diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/BukkitNetworkManager.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/BukkitNetworkManager.java index 0763f2f44..e1cdde613 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/BukkitNetworkManager.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/BukkitNetworkManager.java @@ -26,6 +26,7 @@ import org.bukkit.event.HandlerList; import org.bukkit.event.Listener; import org.bukkit.event.player.PlayerJoinEvent; import org.bukkit.event.player.PlayerQuitEvent; +import org.bukkit.event.player.PlayerRegisterChannelEvent; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -158,6 +159,15 @@ public class BukkitNetworkManager implements NetworkManager, Listener { this.onlineUsers.remove(player.getUniqueId()); } + @EventHandler + public void onPlayerRegisterChannel(PlayerRegisterChannelEvent event) { + Player player = event.getPlayer(); + NetWorkUser user = getUser(player); + if (user != null) { + user.setUsingClientMod(true); + } + } + @Override public Collection onlineUsers() { return onlineUsers.values(); diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/PacketConsumers.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/PacketConsumers.java index ab80d70f4..88b142d44 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/PacketConsumers.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/PacketConsumers.java @@ -55,7 +55,8 @@ public class PacketConsumers { BIOME_LIST = new IntIdentityList(RegistryUtils.currentBiomeRegistrySize()); } - public static int remap(int stateId) { + public static int remap(int stateId, NetWorkUser user) { + if (user.usingClientMod() && !BlockStateUtils.isVanillaBlock(stateId)) return stateId; return mappings[stateId]; } @@ -74,11 +75,11 @@ public class PacketConsumers { PalettedContainer container = mcSection.blockStateContainer(); Palette palette = container.data().palette(); if (palette.canRemap()) { - palette.remap(PacketConsumers::remap); + palette.remap(stateId -> remap(stateId, user)); } else { for (int j = 0; j < 4096; j ++) { int state = container.get(j); - int newState = remap(state); + int newState = remap(state, user); if (newState != state) { container.set(j, newState); } @@ -105,7 +106,7 @@ public class PacketConsumers { for (int i = 0; i < blocks; i++) { long k = buf.readVarLong(); positions[i] = (short) ((int) (k & 4095L)); - states[i] = remap((int) (k >>> 12)); + states[i] = remap((int) (k >>> 12), user); } buf.clear(); buf.writeVarInt(event.packetID()); @@ -125,7 +126,7 @@ public class PacketConsumers { FriendlyByteBuf buf = event.getBuffer(); BlockPos pos = buf.readBlockPos(buf); int before = buf.readVarInt(); - int state = remap(before); + int state = remap(before, user); if (state == before) { return; } @@ -147,7 +148,7 @@ public class PacketConsumers { BlockPos blockPos = buf.readBlockPos(buf); int state = buf.readInt(); boolean global = buf.readBoolean(); - int newState = remap(state); + int newState = remap(state, user); if (newState == state) { return; } @@ -181,7 +182,7 @@ public class PacketConsumers { if (!Reflections.clazz$BlockParticleOption.isInstance(option)) return; Object blockState = Reflections.field$BlockParticleOption$blockState.get(option); int id = BlockStateUtils.blockStateToId(blockState); - int remapped = remap(id); + int remapped = remap(id, user); if (remapped == id) return; Reflections.field$BlockParticleOption$blockState.set(option, BlockStateUtils.idToBlockState(remapped)); event.setChanged(true); @@ -523,7 +524,7 @@ public class PacketConsumers { // Falling blocks if (entityType == Reflections.instance$EntityType$FALLING_BLOCK) { int data = Reflections.field$ClientboundAddEntityPacket$data.getInt(packet); - int remapped = remap(data); + int remapped = remap(data, user); if (remapped != data) { Reflections.field$ClientboundAddEntityPacket$data.set(packet, remapped); } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/user/BukkitServerPlayer.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/user/BukkitServerPlayer.java index 07e3fccad..90180937c 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/user/BukkitServerPlayer.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/user/BukkitServerPlayer.java @@ -63,6 +63,8 @@ public class BukkitServerPlayer extends Player { private Key lastUsedRecipe = null; + private boolean usingClientMod = false; + private Map> furnitureView = new ConcurrentHashMap<>(); public BukkitServerPlayer(BukkitCraftEngine plugin, Channel channel) { @@ -616,4 +618,12 @@ public class BukkitServerPlayer extends Player { public void setLastUsedRecipe(Key lastUsedRecipe) { this.lastUsedRecipe = lastUsedRecipe; } + + public boolean usingClientMod() { + return this.usingClientMod; + } + + public void setUsingClientMod(boolean usingClientMod) { + this.usingClientMod = usingClientMod; + } } diff --git a/client-mod/src/client/java/net/momirealms/craftEngineFabricMod/client/CraftEngineFabricModClient.java b/client-mod/src/client/java/net/momirealms/craftEngineFabricMod/client/CraftEngineFabricModClient.java index cd5cafe45..01fffd7dd 100644 --- a/client-mod/src/client/java/net/momirealms/craftEngineFabricMod/client/CraftEngineFabricModClient.java +++ b/client-mod/src/client/java/net/momirealms/craftEngineFabricMod/client/CraftEngineFabricModClient.java @@ -2,15 +2,18 @@ package net.momirealms.craftEngineFabricMod.client; import net.fabricmc.api.ClientModInitializer; import net.fabricmc.fabric.api.blockrenderlayer.v1.BlockRenderLayerMap; +import net.fabricmc.fabric.api.networking.v1.PayloadTypeRegistry; import net.minecraft.client.render.RenderLayer; import net.minecraft.registry.Registries; import net.minecraft.util.Identifier; +import net.momirealms.craftEngineFabricMod.client.network.CraftEnginePayload; public class CraftEngineFabricModClient implements ClientModInitializer { public static final String MOD_ID = "craftengine"; @Override public void onInitializeClient() { + PayloadTypeRegistry.playS2C().register(CraftEnginePayload.ID, CraftEnginePayload.CODEC); Registries.BLOCK.forEach(block -> { Identifier id = Registries.BLOCK.getId(block); if (id.getNamespace().equals(CraftEngineFabricModClient.MOD_ID)) { diff --git a/client-mod/src/client/java/net/momirealms/craftEngineFabricMod/client/network/ByteArrayCodec.java b/client-mod/src/client/java/net/momirealms/craftEngineFabricMod/client/network/ByteArrayCodec.java new file mode 100644 index 000000000..28782f35d --- /dev/null +++ b/client-mod/src/client/java/net/momirealms/craftEngineFabricMod/client/network/ByteArrayCodec.java @@ -0,0 +1,20 @@ +package net.momirealms.craftEngineFabricMod.client.network; + +import net.minecraft.network.RegistryByteBuf; +import net.minecraft.network.codec.PacketCodec; + +public class ByteArrayCodec implements PacketCodec { + + @Override + public void encode(RegistryByteBuf buf, byte[] value) { + buf.writeBytes(value); + } + + @Override + public byte[] decode(RegistryByteBuf buf) { + int length = buf.readableBytes(); + byte[] data = new byte[length]; + buf.readBytes(data); + return data; + } +} \ No newline at end of file diff --git a/client-mod/src/client/java/net/momirealms/craftEngineFabricMod/client/network/CraftEnginePayload.java b/client-mod/src/client/java/net/momirealms/craftEngineFabricMod/client/network/CraftEnginePayload.java new file mode 100644 index 000000000..da4a971f8 --- /dev/null +++ b/client-mod/src/client/java/net/momirealms/craftEngineFabricMod/client/network/CraftEnginePayload.java @@ -0,0 +1,20 @@ +package net.momirealms.craftEngineFabricMod.client.network; + +import net.minecraft.network.RegistryByteBuf; +import net.minecraft.network.codec.PacketCodec; +import net.minecraft.network.packet.CustomPayload; +import net.minecraft.util.Identifier; + +public record CraftEnginePayload(byte[] data) implements CustomPayload { + public static final Identifier ADD_CRAFTENGINE_BLOCK = Identifier.of("craftengine", "payload"); + public static final Id ID = new Id<>(CraftEnginePayload.ADD_CRAFTENGINE_BLOCK); + public static final PacketCodec CODEC = PacketCodec.tuple( + new ByteArrayCodec(), CraftEnginePayload::data, + CraftEnginePayload::new + ); + + @Override + public Id getId() { + return ID; + } +} diff --git a/client-mod/src/main/java/net/momirealms/craftEngineFabricMod/CraftEngineFabricMod.java b/client-mod/src/main/java/net/momirealms/craftEngineFabricMod/CraftEngineFabricMod.java index a8abd3abb..ad91ee19d 100644 --- a/client-mod/src/main/java/net/momirealms/craftEngineFabricMod/CraftEngineFabricMod.java +++ b/client-mod/src/main/java/net/momirealms/craftEngineFabricMod/CraftEngineFabricMod.java @@ -1,7 +1,10 @@ package net.momirealms.craftEngineFabricMod; import net.fabricmc.api.ModInitializer; +import net.minecraft.block.BlockState; import net.minecraft.util.Identifier; +import net.momirealms.craftEngineFabricMod.util.BlockUtils; +import net.momirealms.craftEngineFabricMod.util.LoggerFilter; import net.momirealms.craftEngineFabricMod.util.RegisterBlocks; import net.momirealms.craftEngineFabricMod.util.YamlUtils; @@ -13,6 +16,7 @@ public class CraftEngineFabricMod implements ModInitializer { @Override public void onInitialize() { + LoggerFilter.filter(); try { YamlUtils.ensureConfigFile("additional-real-blocks.yml"); YamlUtils.ensureConfigFile("mappings.yml"); @@ -21,7 +25,11 @@ public class CraftEngineFabricMod implements ModInitializer { for (Map.Entry entry : map.entrySet()) { Identifier replacedBlockId = entry.getKey(); for (int i = 0; i < entry.getValue(); i++) { - RegisterBlocks.register(replacedBlockId.getPath() + "_" + i); + BlockState blockState = YamlUtils.createBlockData("minecraft:" + replacedBlockId.getPath()); + RegisterBlocks.register( + replacedBlockId.getPath() + "_" + i, + BlockUtils.canPassThrough(blockState) + ); } } System.out.println("Registered " + map.size() + " additional real blocks."); diff --git a/client-mod/src/main/java/net/momirealms/craftEngineFabricMod/util/BlockUtils.java b/client-mod/src/main/java/net/momirealms/craftEngineFabricMod/util/BlockUtils.java new file mode 100644 index 000000000..2e58963b5 --- /dev/null +++ b/client-mod/src/main/java/net/momirealms/craftEngineFabricMod/util/BlockUtils.java @@ -0,0 +1,45 @@ +package net.momirealms.craftEngineFabricMod.util; + +import net.minecraft.block.AbstractBlock; +import net.minecraft.block.BlockState; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.lang.reflect.AccessibleObject; +import java.lang.reflect.Field; +import static java.util.Objects.requireNonNull; + +public class BlockUtils { + private final static Field COLLIDABLE_FIELD = requireNonNull(getDeclaredField(AbstractBlock.Settings.class, boolean.class, 0)); + + @Nullable + public static Field getDeclaredField(final Class clazz, final Class type, int index) { + int i = 0; + for (final Field field : clazz.getDeclaredFields()) { + if (field.getType() == type) { + if (index == i) { + return setAccessible(field); + } + i++; + } + } + return null; + } + + @NotNull + public static T setAccessible(@NotNull final T o) { + o.setAccessible(true); + return o; + } + + public static boolean canPassThrough(BlockState state) { + try { + if (state == null) return false; + AbstractBlock.Settings settings = state.getBlock().getSettings(); + boolean collidable = COLLIDABLE_FIELD.getBoolean(settings); + return !collidable; + } catch (IllegalAccessException e) { + throw new RuntimeException("Failed to access 'collidable' field", e); + } + } +} diff --git a/client-mod/src/main/java/net/momirealms/craftEngineFabricMod/util/LoggerFilter.java b/client-mod/src/main/java/net/momirealms/craftEngineFabricMod/util/LoggerFilter.java new file mode 100644 index 000000000..1c6c45c00 --- /dev/null +++ b/client-mod/src/main/java/net/momirealms/craftEngineFabricMod/util/LoggerFilter.java @@ -0,0 +1,21 @@ +package net.momirealms.craftEngineFabricMod.util; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.core.LogEvent; +import org.apache.logging.log4j.core.Logger; +import org.apache.logging.log4j.core.filter.AbstractFilter; + +public class LoggerFilter { + public static void filter() { + Logger rootLogger = (Logger) LogManager.getRootLogger(); + rootLogger.addFilter(new AbstractFilter() { + @Override + public Result filter(LogEvent event) { + if (event.getMessage().getFormattedMessage().contains("Missing model for variant: 'craftengine:")) { + return Result.DENY; + } + return Result.NEUTRAL; + } + }); + } +} diff --git a/client-mod/src/main/java/net/momirealms/craftEngineFabricMod/util/RegisterBlocks.java b/client-mod/src/main/java/net/momirealms/craftEngineFabricMod/util/RegisterBlocks.java index 55f064f4b..9d9f5f079 100644 --- a/client-mod/src/main/java/net/momirealms/craftEngineFabricMod/util/RegisterBlocks.java +++ b/client-mod/src/main/java/net/momirealms/craftEngineFabricMod/util/RegisterBlocks.java @@ -2,6 +2,7 @@ package net.momirealms.craftEngineFabricMod.util; import net.minecraft.block.AbstractBlock; import net.minecraft.block.Block; +import net.minecraft.block.Blocks; import net.minecraft.registry.Registries; import net.minecraft.registry.Registry; import net.minecraft.registry.RegistryKey; @@ -12,8 +13,11 @@ import net.momirealms.craftEngineFabricMod.CraftEngineFabricMod; import java.util.function.Function; public class RegisterBlocks { - public static Block register(String name) { - return register(name, Block::new, Block.Settings.create().nonOpaque()); + @SuppressWarnings("UnusedReturnValue") + public static Block register(String name, boolean canPassThrough) { + AbstractBlock.Settings settings = Block.Settings.create().nonOpaque().strength(-1.0F, 3600000.0F); + if (canPassThrough) settings.noCollision(); + return register(name, Block::new, settings); } public static Block register(String name, Function blockFactory, AbstractBlock.Settings settings) { diff --git a/client-mod/src/main/java/net/momirealms/craftEngineFabricMod/util/YamlUtils.java b/client-mod/src/main/java/net/momirealms/craftEngineFabricMod/util/YamlUtils.java index 985a403c9..3d0e664a7 100644 --- a/client-mod/src/main/java/net/momirealms/craftEngineFabricMod/util/YamlUtils.java +++ b/client-mod/src/main/java/net/momirealms/craftEngineFabricMod/util/YamlUtils.java @@ -102,7 +102,7 @@ public class YamlUtils { } } - private static BlockState createBlockData(String blockState) { + public static BlockState createBlockData(String blockState) { try { StringReader reader = new StringReader(blockState); BlockArgumentParser.BlockResult arg = BlockArgumentParser.block(registryWrapper, reader, true); diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/network/NetWorkUser.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/network/NetWorkUser.java index c70b49362..cb80057c8 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/plugin/network/NetWorkUser.java +++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/network/NetWorkUser.java @@ -36,4 +36,8 @@ public interface NetWorkUser { Object platformPlayer(); Map> furnitureView(); + + boolean usingClientMod(); + + void setUsingClientMod(boolean usingClientMod); }