diff --git a/build.gradle b/build.gradle index 52e7778..175956c 100755 --- a/build.gradle +++ b/build.gradle @@ -27,6 +27,9 @@ repositories { url = "https://api.modrinth.com/maven" } maven { url 'https://maven.nucleoid.xyz' } + maven { + url = uri("https://repo.opencollab.dev/main/") + } } dependencies { @@ -47,6 +50,7 @@ dependencies { modImplementation ("eu.pb4:polymer-virtual-entity:${polymer_version}") modImplementation ("eu.pb4:polymer-autohost:${polymer_version}") modImplementation ("eu.pb4:factorytools:${factorytools_version}") + compileOnly('org.geysermc.geyser:api:2.4.2-SNAPSHOT') } processResources { diff --git a/src/main/java/eu/midnightdust/motschen/rocks/RocksMain.java b/src/main/java/eu/midnightdust/motschen/rocks/RocksMain.java index 932ce0e..cd72b41 100755 --- a/src/main/java/eu/midnightdust/motschen/rocks/RocksMain.java +++ b/src/main/java/eu/midnightdust/motschen/rocks/RocksMain.java @@ -11,6 +11,7 @@ import eu.midnightdust.motschen.rocks.config.RocksConfig; import eu.midnightdust.motschen.rocks.networking.HelloPayload; import eu.midnightdust.motschen.rocks.util.RockType; import eu.midnightdust.motschen.rocks.util.StickType; +import eu.midnightdust.motschen.rocks.util.geyser.GeyserUtil; import eu.midnightdust.motschen.rocks.util.polymer.PolyUtil; import eu.midnightdust.motschen.rocks.world.*; import net.fabricmc.api.ModInitializer; @@ -19,6 +20,7 @@ import net.fabricmc.fabric.api.networking.v1.PayloadTypeRegistry; import net.fabricmc.fabric.api.networking.v1.ServerPlayConnectionEvents; import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking; import net.minecraft.block.Block; +import net.minecraft.entity.player.PlayerEntity; import net.minecraft.item.Item; import net.minecraft.item.ItemGroup; import net.minecraft.item.ItemStack; @@ -43,6 +45,7 @@ import static eu.midnightdust.motschen.rocks.util.polymer.PolyUtil.*; public class RocksMain implements ModInitializer { public static final String MOD_ID = "rocks"; public static boolean polymerMode = hasRequiredPolymerModules(); + public static boolean hasGeyserMC = PlatformFunctions.isModLoaded("geyser-fabric") || PlatformFunctions.isModLoaded("geyser-neoforge"); public static List playersWithMod = new ArrayList<>(); public static final EnumProperty ROCK_VARIATION = EnumProperty.of("variation", RockVariation.class); @@ -85,6 +88,7 @@ public class RocksMain implements ModInitializer { }); if (polymerMode) PolyUtil.init(); + if (hasGeyserMC) GeyserUtil.init(this); for (RockType type : RockType.values()) { Identifier id = id(type.getName()); @@ -136,4 +140,7 @@ public class RocksMain implements ModInitializer { Registry.register(Registries.ITEM_GROUP, ROCKS_GROUP, RocksGroup); } } + public static boolean isOnBedrock(PlayerEntity player) { + return player != null && hasGeyserMC && GeyserUtil.isOnBedrock(player.getUuid()); + } } diff --git a/src/main/java/eu/midnightdust/motschen/rocks/util/geyser/GeyserBlocks.java b/src/main/java/eu/midnightdust/motschen/rocks/util/geyser/GeyserBlocks.java new file mode 100644 index 0000000..96d2464 --- /dev/null +++ b/src/main/java/eu/midnightdust/motschen/rocks/util/geyser/GeyserBlocks.java @@ -0,0 +1,104 @@ +package eu.midnightdust.motschen.rocks.util.geyser; + +import eu.midnightdust.motschen.rocks.RocksMain; +import eu.midnightdust.motschen.rocks.blockstates.RockVariation; +import eu.midnightdust.motschen.rocks.util.RockType; +import net.minecraft.block.Block; +import net.minecraft.block.BlockState; +import net.minecraft.registry.Registries; +import net.minecraft.state.property.Properties; +import org.geysermc.event.subscribe.Subscribe; +import org.geysermc.geyser.api.block.custom.CustomBlockData; +import org.geysermc.geyser.api.block.custom.CustomBlockPermutation; +import org.geysermc.geyser.api.block.custom.NonVanillaCustomBlockData; +import org.geysermc.geyser.api.block.custom.component.BoxComponent; +import org.geysermc.geyser.api.block.custom.component.CustomBlockComponents; +import org.geysermc.geyser.api.block.custom.component.GeometryComponent; +import org.geysermc.geyser.api.block.custom.component.MaterialInstance; +import org.geysermc.geyser.api.block.custom.nonvanilla.JavaBlockState; +import org.geysermc.geyser.api.event.lifecycle.GeyserDefineCustomBlocksEvent; +import org.geysermc.geyser.api.extension.Extension; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Locale; +import java.util.stream.Collectors; + +import static eu.midnightdust.motschen.rocks.RocksMain.*; + +public class GeyserBlocks implements Extension { + static final BoxComponent SHAPE = new BoxComponent(-8, 0, -8, 8, 2, 8); + static final BoxComponent SHAPE_LARGE = new BoxComponent(-8, 0, -8, 8, 3, 8); + + /* + Bedrock follows a very different design than Java. + A rock here will contain a property that defines its stone material type, rather than the variation. + Each variation will be registered as one such rock block. + */ + @Subscribe + public void onDefineCustomBlocks(GeyserDefineCustomBlocksEvent event) { + for (RockVariation variation : RockVariation.values()) { + CustomBlockComponents components = CustomBlockComponents.builder() + .collisionBox(BoxComponent.emptyBox()) + .selectionBox(variation == RockVariation.LARGE ? SHAPE_LARGE : SHAPE) + .geometry(GeometryComponent.builder() + .identifier(String.format("geometry.rocks.%s_rock", variation.asString())) + .build()) + .lightEmission(0) + .lightDampening(0) + .friction(1f) + .build(); + + CustomBlockData rockVariant = NonVanillaCustomBlockData.builder() + .name(variation.asString()+"_rock") + .namespace(MOD_ID) + .stringProperty("TYPE", Arrays.stream(RockType.values()).map(RockType::getName).collect(Collectors.toList())) + .components(components) + .permutations(createRockPermutations()) + .includedInCreativeInventory(true) + .build(); + + event.register(rockVariant); + event.registerItemOverride(id(RockType.STONE.getName()).toString(), rockVariant); + + for (RockType type : RockType.values()) { + String javaIdentifier = String.format("%s:%s[variation=%s]", MOD_ID, type.getName(), variation.asString()); + BlockState state = RocksMain.rocksByType.get(type).getDefaultState().with(ROCK_VARIATION, variation); + + JavaBlockState javaBlockState = JavaBlockState.builder() + .javaId(Block.getRawIdFromState(state)) + .identifier(javaIdentifier) + .stateGroupId(Registries.BLOCK.getRawId(rocksByType.get(type))) + .waterlogged(state.contains(Properties.WATERLOGGED) && state.get(Properties.WATERLOGGED)) + .canBreakWithHand(true) + .build(); + event.registerOverride(javaBlockState, rockVariant.blockStateBuilder() + .stringProperty("TYPE", type.getName()) + .build()); + } + } + } + + private List createRockPermutations() { + List permutations = new ArrayList<>(); + for (RockType type : RockType.values()) { + MaterialInstance material = MaterialInstance.builder() + .texture(String.format("minecraft.%s", type.name().toLowerCase(Locale.ROOT))) + .renderMethod("opaque") + .ambientOcclusion(true) + .build(); + CustomBlockComponents components = CustomBlockComponents.builder() + .materialInstance("up", material) + .materialInstance("down", material) + .materialInstance("north", material) + .materialInstance("south", material) + .materialInstance("east", material) + .materialInstance("west", material) + .build(); + String condition = String.format("query.block_property('%s') == %s", "TYPE", type.getName()); + permutations.add(new CustomBlockPermutation(components, condition)); + } + return permutations; + } +} \ No newline at end of file diff --git a/src/main/java/eu/midnightdust/motschen/rocks/util/geyser/GeyserUtil.java b/src/main/java/eu/midnightdust/motschen/rocks/util/geyser/GeyserUtil.java new file mode 100644 index 0000000..0fa0118 --- /dev/null +++ b/src/main/java/eu/midnightdust/motschen/rocks/util/geyser/GeyserUtil.java @@ -0,0 +1,40 @@ +package eu.midnightdust.motschen.rocks.util.geyser; + +import eu.midnightdust.motschen.rocks.RocksMain; +import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents; +import net.fabricmc.loader.api.FabricLoader; +import org.geysermc.event.subscribe.Subscribe; +import org.geysermc.geyser.api.GeyserApi; +import org.geysermc.geyser.api.connection.GeyserConnection; +import org.geysermc.geyser.api.event.EventRegistrar; +import org.geysermc.geyser.api.event.lifecycle.GeyserLoadResourcePacksEvent; + +import java.net.URI; +import java.nio.file.Path; +import java.util.UUID; + +import static eu.midnightdust.motschen.rocks.RocksMain.MOD_ID; + +public class GeyserUtil implements EventRegistrar { + static GeyserApi geyser; + + public static void init(RocksMain mainEntryPoint) { + //GeyserConnection connection = GeyserApi.api().connectionByUuid(uuid); + ServerLifecycleEvents.SERVER_STARTING.register((server) -> { + geyser = GeyserApi.api(); + EventRegistrar registrar = new GeyserUtil(); + geyser.eventBus().register(registrar, registrar); + geyser.eventBus().register(registrar, new GeyserBlocks()); // register your mod & this class instance as a listener + }); + } + @Subscribe + public void onGeyserLoadResourcePacksEvent(GeyserLoadResourcePacksEvent event) { + //logger().info("Loading: " + event.resourcePacks().size() + " resource packs."); + event.resourcePacks().add(FabricLoader.getInstance().getModContainer(MOD_ID).get().findPath("bedrock/rocks.zip").get()); + // you could add a resource pack with event.resourcePacks().add(path-to-pack) + } + public static boolean isOnBedrock(UUID uuid) { + if (geyser == null) return false; + return geyser.isBedrockPlayer(uuid); + } +} diff --git a/src/main/java/eu/midnightdust/motschen/rocks/util/polymer/PolyUtil.java b/src/main/java/eu/midnightdust/motschen/rocks/util/polymer/PolyUtil.java index 4efced8..7b1ce08 100644 --- a/src/main/java/eu/midnightdust/motschen/rocks/util/polymer/PolyUtil.java +++ b/src/main/java/eu/midnightdust/motschen/rocks/util/polymer/PolyUtil.java @@ -69,7 +69,7 @@ public class PolyUtil { } public static boolean hasModOnClient(ServerPlayerEntity player) { - return playersWithMod.contains(player); + return playersWithMod.contains(player) || isOnBedrock(player); } public static Item polymerBlockItem(Block block, Identifier id) { diff --git a/src/main/resources/bedrock/rocks.zip b/src/main/resources/bedrock/rocks.zip new file mode 100644 index 0000000..5eac68d Binary files /dev/null and b/src/main/resources/bedrock/rocks.zip differ diff --git a/src/main/resources/bedrock/rocks_base/manifest.json b/src/main/resources/bedrock/rocks_base/manifest.json new file mode 100644 index 0000000..a22f8e7 --- /dev/null +++ b/src/main/resources/bedrock/rocks_base/manifest.json @@ -0,0 +1,17 @@ +{ + "format_version": 2, + "header": { + "name": "pack.rocks", + "description": "pack.description", + "uuid": "420e8521-598a-428d-9a44-ed3e2f1b303d", + "version": [1, 0, 0], + "min_engine_version": [1, 16, 0] + }, + "modules": [ + { + "type": "resources", + "uuid": "517e7279-6a76-4956-b34d-f2e126d3187a", + "version": [1, 0, 0] + } + ] +} \ No newline at end of file diff --git a/src/main/resources/bedrock/rocks_base/models/block/large_rock.json b/src/main/resources/bedrock/rocks_base/models/block/large_rock.json new file mode 100644 index 0000000..ba0fcf5 --- /dev/null +++ b/src/main/resources/bedrock/rocks_base/models/block/large_rock.json @@ -0,0 +1,59 @@ +{ + "format_version": "1.12.0", + "minecraft:geometry": [ + { + "description": { + "identifier": "geometry.large_rock", + "texture_width": 16, + "texture_height": 16, + "visible_bounds_width": 2, + "visible_bounds_height": 1.5, + "visible_bounds_offset": [0, 0.25, 0] + }, + "bones": [ + { + "name": "bb_main", + "pivot": [0, 0, 0], + "cubes": [ + { + "origin": [-5, 0, -3], + "size": [12, 3, 7], + "uv": { + "north": {"uv": [0, 0], "uv_size": [12, 3]}, + "east": {"uv": [0, 0], "uv_size": [7, 3]}, + "south": {"uv": [0, 0], "uv_size": [12, 3]}, + "west": {"uv": [0, 0], "uv_size": [7, 3]}, + "up": {"uv": [12, 7], "uv_size": [-12, -7]}, + "down": {"uv": [12, 7], "uv_size": [-12, -7]} + } + }, + { + "origin": [-1, 3, -1], + "size": [7, 1, 4], + "uv": { + "north": {"uv": [0, 0], "uv_size": [7, 1]}, + "east": {"uv": [0, 0], "uv_size": [4, 1]}, + "south": {"uv": [0, 0], "uv_size": [7, 1]}, + "west": {"uv": [0, 0], "uv_size": [4, 1]}, + "up": {"uv": [7, 4], "uv_size": [-7, -4]}, + "down": {"uv": [7, 4], "uv_size": [-7, -4]} + } + }, + { + "origin": [-4, 0, -5], + "size": [8, 1, 10], + "uv": { + "north": {"uv": [0, 0], "uv_size": [8, 1]}, + "east": {"uv": [0, 0], "uv_size": [10, 1]}, + "south": {"uv": [0, 0], "uv_size": [8, 1]}, + "west": {"uv": [0, 0], "uv_size": [10, 1]}, + "up": {"uv": [8, 10], "uv_size": [-8, -10]}, + "down": {"uv": [8, 10], "uv_size": [-8, -10]} + } + } + ] + } + ] + } + ] +} \ No newline at end of file diff --git a/src/main/resources/bedrock/rocks_base/pack_icon.png b/src/main/resources/bedrock/rocks_base/pack_icon.png new file mode 100755 index 0000000..f54e752 Binary files /dev/null and b/src/main/resources/bedrock/rocks_base/pack_icon.png differ diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index a63ecff..a2325e9 100755 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -30,7 +30,6 @@ ] }, - "accessWidener" : "thisrocks.accesswidener", "mixins": [ "rocks.mixins.json" ],