diff --git a/bukkit/loader/src/main/resources/config.yml b/bukkit/loader/src/main/resources/config.yml index 252604a20..7883f4776 100644 --- a/bukkit/loader/src/main/resources/config.yml +++ b/bukkit/loader/src/main/resources/config.yml @@ -167,7 +167,7 @@ furniture: - "xxx:invalid_furniture" # Converts the invalid furniture to a valid one convert: - "xxx:invalid_furniture": "xxx:valid_furniture" + "namespace:furniture_a": "namespace:furniture_b" # Hide technical entities used for storing furniture metadata. # NOTE: diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/BlockEventListener.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/BlockEventListener.java index c23e2774d..e919ede53 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/BlockEventListener.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/BlockEventListener.java @@ -342,25 +342,21 @@ public class BlockEventListener implements Listener { if (!this.enableNoteBlockCheck) return; // for vanilla blocks if (event.getChangedType() == Material.NOTE_BLOCK) { - try { - Block block = event.getBlock(); - World world = block.getWorld(); - Location location = block.getLocation(); - Block sourceBlock = event.getSourceBlock(); - BlockFace direction = sourceBlock.getFace(block); - if (direction == BlockFace.UP || direction == BlockFace.DOWN) { - Object serverLevel = FastNMS.INSTANCE.field$CraftWorld$ServerLevel(world); - Object chunkSource = FastNMS.INSTANCE.method$ServerLevel$getChunkSource(serverLevel); - Object blockPos = LocationUtils.toBlockPos(location.getBlockX(), location.getBlockY(), location.getBlockZ()); - FastNMS.INSTANCE.method$ServerChunkCache$blockChanged(chunkSource, blockPos); - if (direction == BlockFace.UP) { - NoteBlockChainUpdateUtils.noteBlockChainUpdate(serverLevel, chunkSource, Reflections.instance$Direction$UP, blockPos, 0); - } else { - NoteBlockChainUpdateUtils.noteBlockChainUpdate(serverLevel, chunkSource, Reflections.instance$Direction$DOWN, blockPos, 0); - } + Block block = event.getBlock(); + World world = block.getWorld(); + Location location = block.getLocation(); + Block sourceBlock = event.getSourceBlock(); + BlockFace direction = sourceBlock.getFace(block); + if (direction == BlockFace.UP || direction == BlockFace.DOWN) { + Object serverLevel = FastNMS.INSTANCE.field$CraftWorld$ServerLevel(world); + Object chunkSource = FastNMS.INSTANCE.method$ServerLevel$getChunkSource(serverLevel); + Object blockPos = LocationUtils.toBlockPos(location.getBlockX(), location.getBlockY(), location.getBlockZ()); + FastNMS.INSTANCE.method$ServerChunkCache$blockChanged(chunkSource, blockPos); + if (direction == BlockFace.UP) { + NoteBlockChainUpdateUtils.noteBlockChainUpdate(serverLevel, chunkSource, Reflections.instance$Direction$UP, blockPos, 0); + } else { + NoteBlockChainUpdateUtils.noteBlockChainUpdate(serverLevel, chunkSource, Reflections.instance$Direction$DOWN, blockPos, 0); } - } catch (ReflectiveOperationException e) { - plugin.logger().warn("Failed to sync note block states", e); } } } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/BukkitBlockManager.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/BukkitBlockManager.java index 01b2c7495..a2e40a287 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/BukkitBlockManager.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/BukkitBlockManager.java @@ -794,7 +794,7 @@ public class BukkitBlockManager extends AbstractBlockManager { newBlockState = getOnlyBlockState(newRealBlock); @SuppressWarnings("unchecked") - Optional optionalHolder = (Optional) Reflections.method$Registry$getHolder0.invoke(Reflections.instance$BuiltInRegistries$BLOCK, resourceLocation); + Optional optionalHolder = (Optional) Reflections.method$Registry$getHolder1.invoke(Reflections.instance$BuiltInRegistries$BLOCK, Reflections.method$ResourceKey$create.invoke(null, Reflections.instance$Registries$BLOCK, resourceLocation)); blockHolder = optionalHolder.get(); } else { try { diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/ConcretePowderBlockBehavior.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/ConcretePowderBlockBehavior.java index 451c60f5e..99ec57099 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/ConcretePowderBlockBehavior.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/ConcretePowderBlockBehavior.java @@ -142,7 +142,7 @@ public class ConcretePowderBlockBehavior extends FallingBlockBehavior { if (direction != Reflections.instance$Direction$DOWN || canSolidify(blockState)) { Reflections.method$MutableBlockPos$setWithOffset.invoke(mutablePos, pos, direction); blockState = FastNMS.INSTANCE.method$BlockGetter$getBlockState(level, mutablePos); - if (canSolidify(blockState) && !(boolean) Reflections.method$BlockStateBase$isFaceSturdy.invoke(blockState, level, pos, Reflections.getOppositeDirection(direction), Reflections.instance$SupportType$FULL)) { + if (canSolidify(blockState) && !(boolean) Reflections.method$BlockStateBase$isFaceSturdy.invoke(blockState, level, pos, FastNMS.INSTANCE.method$Direction$getOpposite(direction), Reflections.instance$SupportType$FULL)) { flag = true; break; } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/BukkitItemManager.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/BukkitItemManager.java index b2baff59b..0cafce423 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/BukkitItemManager.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/BukkitItemManager.java @@ -76,7 +76,7 @@ public class BukkitItemManager extends AbstractItemManager { this.debugStickListener = new DebugStickListener(plugin); this.itemParser = new ItemParser(); this.registerAllVanillaItems(); - if (plugin.hasMod() && VersionHelper.isVersionNewerThan1_20_5()) { + if (plugin.hasMod()) { Class clazz$CustomStreamCodec = ReflectionUtils.getClazz("net.momirealms.craftengine.mod.item.CustomStreamCodec"); if (clazz$CustomStreamCodec != null) { Field s2cProcessor = ReflectionUtils.getDeclaredField(clazz$CustomStreamCodec, Function.class, 0); diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/NoteBlockChainUpdateUtils.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/NoteBlockChainUpdateUtils.java index 78ed33dc9..39d85f954 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/NoteBlockChainUpdateUtils.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/NoteBlockChainUpdateUtils.java @@ -7,9 +7,9 @@ public class NoteBlockChainUpdateUtils { private NoteBlockChainUpdateUtils() {} - public static void noteBlockChainUpdate(Object level, Object chunkSource, Object direction, Object blockPos, int times) throws ReflectiveOperationException { + public static void noteBlockChainUpdate(Object level, Object chunkSource, Object direction, Object blockPos, int times) { if (times >= Config.maxChainUpdate()) return; - Object relativePos = Reflections.method$BlockPos$relative.invoke(blockPos, direction); + Object relativePos = FastNMS.INSTANCE.method$BlockPos$relative(blockPos, direction); Object state = FastNMS.INSTANCE.method$BlockGetter$getBlockState(level, relativePos); if (BlockStateUtils.isClientSideNoteBlock(state)) { FastNMS.INSTANCE.method$ServerChunkCache$blockChanged(chunkSource, relativePos); diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/Reflections.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/Reflections.java index af1e49bae..0ce455beb 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/Reflections.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/Reflections.java @@ -1522,7 +1522,6 @@ public class Reflections { public static final Object instance$Direction$WEST; public static final Object instance$Direction$EAST; public static final Object[] instance$Directions; - private static final Map oppositeDirections = new HashMap<>(); static { try { @@ -1533,20 +1532,14 @@ public class Reflections { instance$Direction$SOUTH = instance$Directions[3]; instance$Direction$WEST = instance$Directions[4]; instance$Direction$EAST = instance$Directions[5]; - oppositeDirections.put(instance$Direction$DOWN, instance$Direction$UP); - oppositeDirections.put(instance$Direction$UP, instance$Direction$DOWN); - oppositeDirections.put(instance$Direction$NORTH, instance$Direction$SOUTH); - oppositeDirections.put(instance$Direction$SOUTH, instance$Direction$NORTH); - oppositeDirections.put(instance$Direction$WEST, instance$Direction$EAST); - oppositeDirections.put(instance$Direction$EAST, instance$Direction$WEST); } catch (ReflectiveOperationException e) { throw new RuntimeException(e); } } - public static Object getOppositeDirection(Object direction) { - return oppositeDirections.get(direction); - } +// public static Object getOppositeDirection(Object direction) { +// return oppositeDirections.get(direction); +// } public static final Class clazz$CraftBlock = requireNonNull( ReflectionUtils.getClazz( diff --git a/client-mod/build.gradle.kts b/client-mod/build.gradle.kts index 0b2b01c08..df2efc2e3 100644 --- a/client-mod/build.gradle.kts +++ b/client-mod/build.gradle.kts @@ -40,7 +40,7 @@ tasks.remapJar { inputFile.set(tasks.shadowJar.get().archiveFile) destinationDirectory.set(file("$rootDir/target")) - archiveFileName.set("${base.archivesName.get()}-${project.version}+${rootProject.properties["latest_minecraft_version"]}.jar") + archiveFileName.set("${base.archivesName.get()}-${project.version}+mc${rootProject.properties["latest_minecraft_version"]}.jar") } loom { diff --git a/gradle.properties b/gradle.properties index 72593c134..d7349e4e7 100644 --- a/gradle.properties +++ b/gradle.properties @@ -51,7 +51,7 @@ byte_buddy_version=1.17.5 ahocorasick_version=0.6.3 snake_yaml_version=2.4 anti_grief_version=0.13 -nms_helper_version=0.58.8 +nms_helper_version=0.59 # Ignite Dependencies mixinextras_version=0.4.1 mixin_version=0.15.2+mixin.0.8.7 diff --git a/server-mod/v1_20_1/build.gradle.kts b/server-mod/v1_20_1/build.gradle.kts new file mode 100644 index 000000000..8589cbe10 --- /dev/null +++ b/server-mod/v1_20_1/build.gradle.kts @@ -0,0 +1,46 @@ +plugins { + id("java-library") + id("com.gradleup.shadow") version "9.0.0-beta11" + id("io.papermc.paperweight.userdev") version "2.0.0-beta.16" +} + +repositories { + mavenCentral() + maven("https://maven.fabricmc.net/") + maven("https://oss.sonatype.org/content/groups/public/") + maven("https://repo.papermc.io/repository/maven-public/") + maven("https://repo.spongepowered.org/maven/") +} + +dependencies { + implementation(project(":shared")) + remapper("net.fabricmc:tiny-remapper:${rootProject.properties["tiny_remapper_version"]}:fat") + paperweightDevelopmentBundle("io.papermc.paper:dev-bundle:1.20.1-R0.1-SNAPSHOT") + compileOnly("space.vectrix.ignite:ignite-api:${rootProject.properties["ignite_version"]}") + compileOnly("net.fabricmc:sponge-mixin:${rootProject.properties["mixin_version"]}") + compileOnly("io.github.llamalad7:mixinextras-common:${rootProject.properties["mixinextras_version"]}") +} + +java { + sourceCompatibility = JavaVersion.VERSION_21 + targetCompatibility = JavaVersion.VERSION_21 + toolchain { + languageVersion = JavaLanguageVersion.of(21) + } +} + +tasks.withType { + options.encoding = "UTF-8" + options.release.set(21) + dependsOn(tasks.clean) +} + +artifacts { + archives(tasks.reobfJar) +} + +tasks { + reobfJar { + outputJar.set(file("$rootDir/target/${rootProject.name}-ignite-mod-${rootProject.properties["project_version"]}+mc1.20.1-reobf.jar")) + } +} diff --git a/server-mod/v1_20_1/src/main/java/net/momirealms/craftengine/mod/CraftEnginePlugin.java b/server-mod/v1_20_1/src/main/java/net/momirealms/craftengine/mod/CraftEnginePlugin.java new file mode 100644 index 000000000..99848d288 --- /dev/null +++ b/server-mod/v1_20_1/src/main/java/net/momirealms/craftengine/mod/CraftEnginePlugin.java @@ -0,0 +1,107 @@ +package net.momirealms.craftengine.mod; + +import io.netty.buffer.Unpooled; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.world.item.ItemStack; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.objectweb.asm.tree.ClassNode; +import org.spongepowered.asm.mixin.extensibility.IMixinConfigPlugin; +import org.spongepowered.asm.mixin.extensibility.IMixinInfo; + +import java.net.URISyntaxException; +import java.net.URL; +import java.nio.Buffer; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.security.CodeSource; +import java.security.ProtectionDomain; +import java.util.List; +import java.util.Set; +import java.util.logging.Logger; + +public final class CraftEnginePlugin implements IMixinConfigPlugin { + public static final Logger LOGGER = Logger.getLogger(CraftEnginePlugin.class.getName()); + private static int vanillaRegistrySize; + private static boolean isSuccessfullyRegistered = false; + private static int maxChainUpdate = 32; + + public static void setVanillaRegistrySize(int vanillaRegistrySize) { + CraftEnginePlugin.vanillaRegistrySize = vanillaRegistrySize; + } + + public static void setIsSuccessfullyRegistered(boolean isSuccessfullyRegistered) { + CraftEnginePlugin.isSuccessfullyRegistered = isSuccessfullyRegistered; + } + + public static int maxChainUpdate() { + return maxChainUpdate; + } + + public static void setMaxChainUpdate(int maxChainUpdate) { + CraftEnginePlugin.maxChainUpdate = maxChainUpdate; + } + + @Override + public void onLoad(final @NotNull String mixinPackage) { + } + + @Override + public @Nullable String getRefMapperConfig() { + return null; + } + + @Override + public boolean shouldApplyMixin(@NotNull String targetClassName, + @NotNull String mixinClassName) { + return true; + } + + @Override + public void acceptTargets(@NotNull Set myTargets, + @NotNull Set otherTargets) { + } + + @Override + public @Nullable List getMixins() { + return null; + } + + @Override + public void preApply(@NotNull String targetClassName, + @NotNull ClassNode targetClass, + @NotNull String mixinClassName, + @NotNull IMixinInfo mixinInfo) { + } + + @Override + public void postApply(@NotNull String targetClassName, + @NotNull ClassNode targetClass, + @NotNull String mixinClassName, + @NotNull IMixinInfo mixinInfo) { + } + + public static Path getPluginFolderPath() { + ProtectionDomain protectionDomain = CraftEnginePlugin.class.getProtectionDomain(); + CodeSource codeSource = protectionDomain.getCodeSource(); + URL jarUrl = codeSource.getLocation(); + try { + return Paths.get(jarUrl.toURI()).getParent().getParent().resolve("plugins"); + } catch (URISyntaxException e) { + e.printStackTrace(); + } + return null; + } + + public static Path getCraftEngineMappingsPath() { + return getPluginFolderPath() + .resolve("CraftEngine") + .resolve("mappings.yml"); + } + + public static Path getCraftEngineAdditionalBlocksPath() { + return getPluginFolderPath() + .resolve("CraftEngine") + .resolve("additional-real-blocks.yml"); + } +} diff --git a/server-mod/v1_20_1/src/main/java/net/momirealms/craftengine/mod/block/CraftEngineBlock.java b/server-mod/v1_20_1/src/main/java/net/momirealms/craftengine/mod/block/CraftEngineBlock.java new file mode 100644 index 000000000..09f390769 --- /dev/null +++ b/server-mod/v1_20_1/src/main/java/net/momirealms/craftengine/mod/block/CraftEngineBlock.java @@ -0,0 +1,259 @@ +package net.momirealms.craftengine.mod.block; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.server.level.ServerChunkCache; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.util.RandomSource; +import net.minecraft.world.entity.item.FallingBlockEntity; +import net.minecraft.world.level.BlockGetter; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.LevelAccessor; +import net.minecraft.world.level.LevelReader; +import net.minecraft.world.level.block.*; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.shapes.CollisionContext; +import net.minecraft.world.phys.shapes.VoxelShape; +import net.momirealms.craftengine.mod.CraftEnginePlugin; +import net.momirealms.craftengine.mod.util.NoteBlockUtils; +import net.momirealms.craftengine.shared.ObjectHolder; +import net.momirealms.craftengine.shared.block.*; +import org.jetbrains.annotations.NotNull; + +@SuppressWarnings("deprecation") +public class CraftEngineBlock + extends Block + implements BehaviorHolder, ShapeHolder, NoteBlockIndicator, Fallable, BonemealableBlock + //TODO , SimpleWaterloggedBlock +{ + private static final StoneBlockShape STONE = new StoneBlockShape(Blocks.STONE.defaultBlockState()); + private boolean isNoteBlock; + public ObjectHolder behaviorHolder; + public ObjectHolder shapeHolder; + public boolean isClientSideNoteBlock; + + public CraftEngineBlock(Properties properties) { + super(properties); + this.behaviorHolder = new ObjectHolder<>(EmptyBlockBehavior.INSTANCE); + this.shapeHolder = new ObjectHolder<>(STONE); + } + + public void setNoteBlock(boolean noteBlock) { + isNoteBlock = noteBlock; + } + + @Override + public ObjectHolder getBehaviorHolder() { + return behaviorHolder; + } + + @Override + public ObjectHolder getShapeHolder() { + return shapeHolder; + } + + @Override + public boolean isNoteBlock() { + return isClientSideNoteBlock; + } + + @Override + public @NotNull VoxelShape getShape(@NotNull BlockState state, @NotNull BlockGetter level, @NotNull BlockPos pos, @NotNull CollisionContext context) { + try { + return (VoxelShape) shapeHolder.value().getShape(this, new Object[]{state, level, pos, context}); + } catch (Exception e) { + e.printStackTrace(); + return super.getShape(state, level, pos, context); + } + } + + @Override + public @NotNull BlockState rotate(@NotNull BlockState state, @NotNull Rotation rotation) { + try { + return (BlockState) this.behaviorHolder.value().rotate(this, new Object[]{state, rotation}, () -> super.rotate(state, rotation)); + } catch (Exception e) { + e.printStackTrace(); + return super.rotate(state, rotation); + } + } + + @Override + public @NotNull BlockState mirror(@NotNull BlockState state, @NotNull Mirror mirror) { + try { + return (BlockState) this.behaviorHolder.value().mirror(this, new Object[]{state, mirror}, () -> super.mirror(state, mirror)); + } catch (Exception e) { + e.printStackTrace(); + return super.mirror(state, mirror); + } + } + + @Override + public void tick(@NotNull BlockState state, @NotNull ServerLevel level, @NotNull BlockPos pos, @NotNull RandomSource random) { + try { + this.behaviorHolder.value().tick(this, new Object[]{state, level, pos, random}, () -> { + super.tick(state, level, pos, random); + return null; + }); + } catch (Exception e) { + e.printStackTrace(); + super.tick(state, level, pos, random); + } + } + + @Override + public void randomTick(@NotNull BlockState state, @NotNull ServerLevel level, @NotNull BlockPos pos, @NotNull RandomSource random) { + try { + behaviorHolder.value().randomTick(this, new Object[]{state, level, pos, random}, () -> { + super.randomTick(state, level, pos, random); + return null; + }); + } catch (Exception e) { + e.printStackTrace(); + super.randomTick(state, level, pos, random); + } + } + + @Override + public void onPlace(@NotNull BlockState state, @NotNull Level level, @NotNull BlockPos pos, @NotNull BlockState oldState, boolean movedByPiston) { + try { + behaviorHolder.value().onPlace(this, new Object[]{state, level, pos, oldState, movedByPiston}, () -> { + super.onPlace(state, level, pos, oldState, movedByPiston); + return null; + }); + } catch (Exception e) { + e.printStackTrace(); + super.onPlace(state, level, pos, oldState, movedByPiston); + } + } + + @Override + public void onBrokenAfterFall(@NotNull Level level, @NotNull BlockPos pos, @NotNull FallingBlockEntity fallingBlock) { + try { + behaviorHolder.value().onBrokenAfterFall(this, new Object[]{level, pos, fallingBlock}); + } catch (Exception e) { + e.printStackTrace(); + Fallable.super.onBrokenAfterFall(level, pos, fallingBlock); + } + } + + @Override + public boolean canSurvive(@NotNull BlockState state, @NotNull LevelReader level, @NotNull BlockPos pos) { + try { + return behaviorHolder.value().canSurvive(this, new Object[]{state, level, pos}, () -> super.canSurvive(state, level, pos)); + } catch (Exception e) { + e.printStackTrace(); + return super.canSurvive(state, level, pos); + } + } + + @Override + public BlockState updateShape(@NotNull BlockState state, + @NotNull Direction direction, + @NotNull BlockState neighborState, + @NotNull LevelAccessor world, + @NotNull BlockPos pos, + @NotNull BlockPos neighborPos) { + try { + if (isNoteBlock && world instanceof ServerLevel serverLevel) { + startNoteBlockChain(direction, serverLevel, pos); + } + return (BlockState) behaviorHolder.value().updateShape(this, new Object[]{state, direction, neighborState, world, pos, neighborPos}, () -> super.updateShape(state, direction, neighborState, world, pos, neighborPos)); + } catch (Exception e) { + e.printStackTrace(); + return super.updateShape(state, direction, neighborState, world, pos, neighborPos); + } + } + + private static void startNoteBlockChain(Direction direction, ServerLevel serverLevel, BlockPos blockPos) { + int id = direction.get3DDataValue(); + // Y axis + if (id == 0 || id == 1) { + ServerChunkCache chunkSource = serverLevel.chunkSource; + chunkSource.blockChanged(blockPos); + if (id == 1) { + noteBlockChainUpdate(serverLevel, chunkSource, Direction.DOWN, blockPos, 0); + } else { + noteBlockChainUpdate(serverLevel, chunkSource, Direction.UP, blockPos, 0); + } + } + } + + public static void noteBlockChainUpdate(ServerLevel level, ServerChunkCache chunkSource, Direction direction, BlockPos blockPos, int times) { + if (times >= CraftEnginePlugin.maxChainUpdate()) return; + BlockPos relativePos = blockPos.relative(direction); + BlockState state = level.getBlockState(relativePos); + if (NoteBlockUtils.CLIENT_SIDE_NOTE_BLOCKS.contains(state)) { + chunkSource.blockChanged(relativePos); + noteBlockChainUpdate(level, chunkSource, direction, relativePos, times+1); + } + } + + @Override + public boolean isValidBonemealTarget(@NotNull LevelReader world, @NotNull BlockPos pos, @NotNull BlockState state, boolean isClient) { + try { + return behaviorHolder.value().isValidBoneMealTarget(this, new Object[]{world, pos, state, isClient}); + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + @Override + public boolean isBonemealSuccess(@NotNull Level level, @NotNull RandomSource randomSource, @NotNull BlockPos blockPos, @NotNull BlockState blockState) { + try { + return behaviorHolder.value().isBoneMealSuccess(this, new Object[]{level, randomSource, blockPos, blockState}); + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + @Override + public void performBonemeal(@NotNull ServerLevel serverLevel, @NotNull RandomSource randomSource, @NotNull BlockPos blockPos, @NotNull BlockState blockState) { + try { + behaviorHolder.value().performBoneMeal(this, new Object[]{serverLevel, randomSource, blockPos, blockState}); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Override + public void onLand(@NotNull Level level, @NotNull BlockPos pos, @NotNull BlockState state, @NotNull BlockState replaceableState, @NotNull FallingBlockEntity fallingBlock) { + try { + behaviorHolder.value().onLand(this, new Object[]{level, pos, state, replaceableState, fallingBlock}); + } catch (Exception e) { + e.printStackTrace(); + } + } + +// @Override +// public boolean canPlaceLiquid(@Nullable Player player, @NotNull BlockGetter level, @NotNull BlockPos pos, @NotNull BlockState state, @NotNull Fluid fluid) { +// try { +// return behaviorHolder.value().canPlaceLiquid(this, new Object[]{player, level, pos, state, fluid}, () -> SimpleWaterloggedBlock.super.canPlaceLiquid(player, level, pos, state, fluid)); +// } catch (Exception e) { +// e.printStackTrace(); +// return SimpleWaterloggedBlock.super.canPlaceLiquid(player, level, pos, state, fluid); +// } +// } +// +// @Override +// public boolean placeLiquid(@NotNull LevelAccessor level, @NotNull BlockPos pos, @NotNull BlockState state, @NotNull FluidState fluidState) { +// try { +// return behaviorHolder.value().placeLiquid(this, new Object[]{level, pos, state, fluidState}, () -> SimpleWaterloggedBlock.super.placeLiquid(level, pos, state, fluidState)); +// } catch (Exception e) { +// e.printStackTrace(); +// return SimpleWaterloggedBlock.super.placeLiquid(level, pos, state, fluidState); +// } +// } +// +// @NotNull +// @Override +// public ItemStack pickupBlock(@Nullable Player player, @NotNull LevelAccessor level, @NotNull BlockPos pos, @NotNull BlockState state) { +// try { +// return (ItemStack) behaviorHolder.value().pickupBlock(this, new Object[]{player, level, pos, state}, () -> SimpleWaterloggedBlock.super.pickupBlock(player, level, pos, state)); +// } catch (Exception e) { +// e.printStackTrace(); +// return SimpleWaterloggedBlock.super.pickupBlock(player, level, pos, state); +// } +// } +} diff --git a/server-mod/v1_20_1/src/main/java/net/momirealms/craftengine/mod/block/CustomBlocks.java b/server-mod/v1_20_1/src/main/java/net/momirealms/craftengine/mod/block/CustomBlocks.java new file mode 100644 index 000000000..31d32631c --- /dev/null +++ b/server-mod/v1_20_1/src/main/java/net/momirealms/craftengine/mod/block/CustomBlocks.java @@ -0,0 +1,121 @@ +package net.momirealms.craftengine.mod.block; + +import net.minecraft.commands.arguments.blocks.BlockStateParser; +import net.minecraft.core.Registry; +import net.minecraft.core.registries.BuiltInRegistries; +import net.minecraft.core.registries.Registries; +import net.minecraft.resources.ResourceKey; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.state.BlockBehaviour; +import net.minecraft.world.level.block.state.BlockState; +import net.momirealms.craftengine.mod.CraftEnginePlugin; +import net.momirealms.craftengine.mod.util.NoteBlockUtils; +import org.bukkit.configuration.file.YamlConfiguration; + +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.Map; + +public class CustomBlocks { + + public static void register() { + CraftEnginePlugin.setVanillaRegistrySize(Block.BLOCK_STATE_REGISTRY.size()); + ResourceLocation noteBlock = new ResourceLocation("minecraft", "note_block"); + Map map = loadMappingsAndAdditionalBlocks(); + for (Map.Entry entry : map.entrySet()) { + ResourceLocation replacedBlockId = entry.getKey(); + boolean isNoteBlock = replacedBlockId.equals(noteBlock); + Block replacedBlock = BuiltInRegistries.BLOCK.get(replacedBlockId); + for (int i = 0; i < entry.getValue(); i++) { + ResourceLocation location = new ResourceLocation("craftengine", replacedBlockId.getPath() + "_" + i); + ResourceKey resourceKey = ResourceKey.create(Registries.BLOCK, location); + BlockBehaviour.Properties properties = BlockBehaviour.Properties.of(); + if (!replacedBlock.hasCollision) { + properties.noCollission(); + } + CraftEngineBlock block = new CraftEngineBlock(properties); + if (isNoteBlock) { + block.setNoteBlock(true); + NoteBlockUtils.CLIENT_SIDE_NOTE_BLOCKS.add(block.defaultBlockState()); + } + Registry.register(BuiltInRegistries.BLOCK, location, block); + Block.BLOCK_STATE_REGISTRY.add(block.defaultBlockState()); + } + } + NoteBlockUtils.CLIENT_SIDE_NOTE_BLOCKS.addAll(net.minecraft.world.level.block.Blocks.NOTE_BLOCK.getStateDefinition().getPossibleStates()); + if (!map.isEmpty()) { + CraftEnginePlugin.setIsSuccessfullyRegistered(true); + } + } + + private static Map loadMappingsAndAdditionalBlocks() { + Path mappingPath = CraftEnginePlugin.getCraftEngineMappingsPath(); + if (!Files.exists(mappingPath)) return Map.of(); + YamlConfiguration mappings = YamlConfiguration.loadConfiguration(mappingPath.toFile()); + Map blockStateMappings = loadBlockStateMappings(mappings); + validateBlockStateMappings(blockStateMappings); + Map blockTypeCounter = new LinkedHashMap<>(); + Map appearanceMapper = new HashMap<>(); + for (Map.Entry entry : blockStateMappings.entrySet()) { + processBlockStateMapping(entry, appearanceMapper, blockTypeCounter); + } + YamlConfiguration additionalYaml = YamlConfiguration.loadConfiguration(CraftEnginePlugin.getCraftEngineAdditionalBlocksPath().toFile()); + return buildRegisteredRealBlockSlots(blockTypeCounter, additionalYaml); + } + + private static Map loadBlockStateMappings(YamlConfiguration mappings) { + Map blockStateMappings = new LinkedHashMap<>(); + for (Map.Entry entry : mappings.getValues(false).entrySet()) { + if (entry.getValue() instanceof String afterValue) { + blockStateMappings.put(entry.getKey(), afterValue); + } + } + return blockStateMappings; + } + + private static void validateBlockStateMappings(Map blockStateMappings) { + Map temp = new HashMap<>(blockStateMappings); + for (Map.Entry entry : temp.entrySet()) { + String state = entry.getValue(); + blockStateMappings.remove(state); + } + } + + private static LinkedHashMap buildRegisteredRealBlockSlots(Map counter, YamlConfiguration additionalYaml) { + LinkedHashMap map = new LinkedHashMap<>(); + for (Map.Entry entry : counter.entrySet()) { + String id = entry.getKey().toString(); + int additionalStates = additionalYaml.getInt(id, 0); + int internalIds = entry.getValue() + additionalStates; + map.put(entry.getKey(), internalIds); + } + return map; + } + + private static void processBlockStateMapping(Map.Entry entry, Map mapper, Map counter) { + BlockState before = createBlockData(entry.getKey()); + BlockState after = createBlockData(entry.getValue()); + if (before == null || after == null) return; + + int beforeId = Block.BLOCK_STATE_REGISTRY.getId(before); + int afterId = Block.BLOCK_STATE_REGISTRY.getId(after); + + Integer previous = mapper.put(beforeId, afterId); + if (previous == null) { + counter.compute(BuiltInRegistries.BLOCK.getKey(before.getBlock()), (k, count) -> count == null ? 1 : count + 1); + } + } + + private static BlockState createBlockData(String blockState) { + try { + BlockStateParser.BlockResult result = BlockStateParser.parseForBlock(BuiltInRegistries.BLOCK.asLookup(), blockState, false); + return result.blockState(); + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } +} diff --git a/server-mod/v1_20_1/src/main/java/net/momirealms/craftengine/mod/block/StoneBlockShape.java b/server-mod/v1_20_1/src/main/java/net/momirealms/craftengine/mod/block/StoneBlockShape.java new file mode 100644 index 000000000..6ebc977a6 --- /dev/null +++ b/server-mod/v1_20_1/src/main/java/net/momirealms/craftengine/mod/block/StoneBlockShape.java @@ -0,0 +1,20 @@ +package net.momirealms.craftengine.mod.block; + +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.BlockGetter; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.shapes.CollisionContext; +import net.momirealms.craftengine.shared.block.BlockShape; + +public class StoneBlockShape implements BlockShape { + private final BlockState rawBlockState; + + public StoneBlockShape(BlockState rawBlockState) { + this.rawBlockState = rawBlockState; + } + + @Override + public Object getShape(Object thisObj, Object[] args) { + return rawBlockState.getShape((BlockGetter) args[1], (BlockPos) args[2], (CollisionContext) args[3]); + } +} diff --git a/server-mod/v1_20_1/src/main/java/net/momirealms/craftengine/mod/item/CustomStreamCodec.java b/server-mod/v1_20_1/src/main/java/net/momirealms/craftengine/mod/item/CustomStreamCodec.java new file mode 100644 index 000000000..4fae02230 --- /dev/null +++ b/server-mod/v1_20_1/src/main/java/net/momirealms/craftengine/mod/item/CustomStreamCodec.java @@ -0,0 +1,25 @@ +package net.momirealms.craftengine.mod.item; + +import net.minecraft.world.item.ItemStack; +import org.jetbrains.annotations.NotNull; + +import java.util.function.Function; + +public class CustomStreamCodec { + public static Function clientBoundDataProcessor; + public static Function serverBoundDataProcessor; + + public static @NotNull ItemStack s2c(@NotNull ItemStack itemStack) { + if (clientBoundDataProcessor != null) { + itemStack = clientBoundDataProcessor.apply(itemStack); + } + return itemStack; + } + + public static @NotNull ItemStack c2s(@NotNull ItemStack itemStack) { + if (serverBoundDataProcessor != null) { + itemStack = serverBoundDataProcessor.apply(itemStack); + } + return itemStack; + } +} \ No newline at end of file diff --git a/server-mod/v1_20_1/src/main/java/net/momirealms/craftengine/mod/mixin/BlocksMixin.java b/server-mod/v1_20_1/src/main/java/net/momirealms/craftengine/mod/mixin/BlocksMixin.java new file mode 100644 index 000000000..a14af758c --- /dev/null +++ b/server-mod/v1_20_1/src/main/java/net/momirealms/craftengine/mod/mixin/BlocksMixin.java @@ -0,0 +1,17 @@ +package net.momirealms.craftengine.mod.mixin; + +import net.minecraft.world.level.block.Blocks; +import net.momirealms.craftengine.mod.block.CustomBlocks; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(value = Blocks.class) +public abstract class BlocksMixin { + + @Inject(method = "", at = @At("RETURN")) + private static void onBlocksInit(CallbackInfo ci) { + CustomBlocks.register(); + } +} diff --git a/server-mod/v1_20_1/src/main/java/net/momirealms/craftengine/mod/mixin/FriendlyByteBufMixin.java b/server-mod/v1_20_1/src/main/java/net/momirealms/craftengine/mod/mixin/FriendlyByteBufMixin.java new file mode 100644 index 000000000..2e3fae0e7 --- /dev/null +++ b/server-mod/v1_20_1/src/main/java/net/momirealms/craftengine/mod/mixin/FriendlyByteBufMixin.java @@ -0,0 +1,30 @@ +package net.momirealms.craftengine.mod.mixin; + +import com.llamalad7.mixinextras.injector.ModifyReturnValue; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.world.item.ItemStack; +import net.momirealms.craftengine.mod.item.CustomStreamCodec; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.ModifyVariable; + +@Mixin(value = FriendlyByteBuf.class) +public class FriendlyByteBufMixin { + + @ModifyVariable( + method = "a(Lnet/minecraft/world/item/ItemStack;)Lnet/minecraft/network/PacketDataSerializer;", + at = @At("HEAD"), + argsOnly = true + ) + private ItemStack modifyWriteItemParam(ItemStack stack) { + return stack.isEmpty() ? stack : CustomStreamCodec.s2c(stack); + } + + @ModifyReturnValue( + method = "r()Lnet/minecraft/world/item/ItemStack;", + at = @At("RETURN") + ) + private ItemStack modifyReadItemStack(ItemStack original) { + return original.isEmpty() ? original : CustomStreamCodec.c2s(original); + } +} diff --git a/server-mod/v1_20_1/src/main/java/net/momirealms/craftengine/mod/util/NoteBlockUtils.java b/server-mod/v1_20_1/src/main/java/net/momirealms/craftengine/mod/util/NoteBlockUtils.java new file mode 100644 index 000000000..8deebf538 --- /dev/null +++ b/server-mod/v1_20_1/src/main/java/net/momirealms/craftengine/mod/util/NoteBlockUtils.java @@ -0,0 +1,11 @@ +package net.momirealms.craftengine.mod.util; + +import net.minecraft.world.level.block.state.BlockState; + +import java.util.HashSet; +import java.util.Set; + +public class NoteBlockUtils { + + public static final Set CLIENT_SIDE_NOTE_BLOCKS = new HashSet<>(); +} diff --git a/server-mod/v1_20_1/src/main/resources/ignite.mod.json b/server-mod/v1_20_1/src/main/resources/ignite.mod.json new file mode 100644 index 000000000..a353e9e4d --- /dev/null +++ b/server-mod/v1_20_1/src/main/resources/ignite.mod.json @@ -0,0 +1,7 @@ +{ + "id": "craftengine", + "version": "${project_version}", + "mixins": [ + "mixins.craftengine.json" + ] +} diff --git a/server-mod/v1_20_1/src/main/resources/mixins.craftengine.json b/server-mod/v1_20_1/src/main/resources/mixins.craftengine.json new file mode 100644 index 000000000..b6396bab4 --- /dev/null +++ b/server-mod/v1_20_1/src/main/resources/mixins.craftengine.json @@ -0,0 +1,12 @@ +{ + "required": true, + "minVersion": "0.8.7", + "package": "net.momirealms.craftengine.mod.mixin", + "plugin": "net.momirealms.craftengine.mod.CraftEnginePlugin", + "target": "@env(DEFAULT)", + "compatibilityLevel": "JAVA_21", + "server": [ + "BlocksMixin", + "FriendlyByteBufMixin" + ] +} diff --git a/server-mod/v1_21_5/src/main/java/net/momirealms/craftengine/mod/block/CustomBlocks.java b/server-mod/v1_21_5/src/main/java/net/momirealms/craftengine/mod/block/CustomBlocks.java index 36af40eab..132c9e72d 100644 --- a/server-mod/v1_21_5/src/main/java/net/momirealms/craftengine/mod/block/CustomBlocks.java +++ b/server-mod/v1_21_5/src/main/java/net/momirealms/craftengine/mod/block/CustomBlocks.java @@ -11,10 +11,8 @@ import net.minecraft.world.level.block.state.BlockBehaviour; import net.minecraft.world.level.block.state.BlockState; import net.momirealms.craftengine.mod.CraftEnginePlugin; import net.momirealms.craftengine.mod.util.NoteBlockUtils; -import net.momirealms.craftengine.mod.util.Reflections; import org.bukkit.configuration.file.YamlConfiguration; -import java.lang.reflect.InvocationTargetException; import java.nio.file.Files; import java.nio.file.Path; import java.util.HashMap; @@ -30,28 +28,22 @@ public class CustomBlocks { for (Map.Entry entry : map.entrySet()) { ResourceLocation replacedBlockId = entry.getKey(); boolean isNoteBlock = replacedBlockId.equals(noteBlock); - try { - Block replacedBlock = (Block) Reflections.method$DefaultedRegistry$get.invoke(BuiltInRegistries.BLOCK, replacedBlockId); - for (int i = 0; i < entry.getValue(); i++) { - ResourceLocation location = ResourceLocation.fromNamespaceAndPath("craftengine", replacedBlockId.getPath() + "_" + i); - ResourceKey resourceKey = ResourceKey.create(Registries.BLOCK, location); - BlockBehaviour.Properties properties = BlockBehaviour.Properties.of(); - if (Reflections.field$BlockBehaviour$Properties$id != null) { - Reflections.field$BlockBehaviour$Properties$id.set(properties, resourceKey); - } - if (!replacedBlock.hasCollision) { - properties.noCollission(); - } - CraftEngineBlock block = new CraftEngineBlock(properties); - if (isNoteBlock) { - block.setNoteBlock(true); - NoteBlockUtils.CLIENT_SIDE_NOTE_BLOCKS.add(block.defaultBlockState()); - } - Registry.register(BuiltInRegistries.BLOCK, location, block); - Block.BLOCK_STATE_REGISTRY.add(block.defaultBlockState()); + Block replacedBlock = BuiltInRegistries.BLOCK.getValue(replacedBlockId); + for (int i = 0; i < entry.getValue(); i++) { + ResourceLocation location = ResourceLocation.fromNamespaceAndPath("craftengine", replacedBlockId.getPath() + "_" + i); + ResourceKey resourceKey = ResourceKey.create(Registries.BLOCK, location); + BlockBehaviour.Properties properties = BlockBehaviour.Properties.of(); + properties.setId(resourceKey); + if (!replacedBlock.hasCollision) { + properties.noCollission(); } - } catch (IllegalAccessException | InvocationTargetException e) { - e.printStackTrace(); + CraftEngineBlock block = new CraftEngineBlock(properties); + if (isNoteBlock) { + block.setNoteBlock(true); + NoteBlockUtils.CLIENT_SIDE_NOTE_BLOCKS.add(block.defaultBlockState()); + } + Registry.register(BuiltInRegistries.BLOCK, location, block); + Block.BLOCK_STATE_REGISTRY.add(block.defaultBlockState()); } } NoteBlockUtils.CLIENT_SIDE_NOTE_BLOCKS.addAll(net.minecraft.world.level.block.Blocks.NOTE_BLOCK.getStateDefinition().getPossibleStates()); @@ -120,11 +112,7 @@ public class CustomBlocks { private static BlockState createBlockData(String blockState) { try { - Object holderLookUp = BuiltInRegistries.BLOCK; - if (Reflections.method$Registry$asLookup != null) { - holderLookUp = Reflections.method$Registry$asLookup.invoke(holderLookUp); - } - BlockStateParser.BlockResult result = (BlockStateParser.BlockResult) Reflections.method$BlockStateParser$parseForBlock.invoke(null, holderLookUp, blockState, false); + BlockStateParser.BlockResult result = BlockStateParser.parseForBlock(BuiltInRegistries.BLOCK, blockState, false); return result.blockState(); } catch (Exception e) { e.printStackTrace(); diff --git a/server-mod/v1_21_5/src/main/java/net/momirealms/craftengine/mod/util/BukkitReflectionUtils.java b/server-mod/v1_21_5/src/main/java/net/momirealms/craftengine/mod/util/BukkitReflectionUtils.java deleted file mode 100644 index 5353b5e8d..000000000 --- a/server-mod/v1_21_5/src/main/java/net/momirealms/craftengine/mod/util/BukkitReflectionUtils.java +++ /dev/null @@ -1,68 +0,0 @@ -package net.momirealms.craftengine.mod.util; - -import org.bukkit.Bukkit; - -import java.lang.reflect.Method; -import java.util.Objects; - -public final class BukkitReflectionUtils { - private static final String PREFIX_MC = "net.minecraft."; - private static final String PREFIX_CRAFTBUKKIT = "org.bukkit.craftbukkit"; - private static final String CRAFT_SERVER = "CraftServer"; - private static final String CB_PKG_VERSION; - public static final int MAJOR_REVISION; - - private BukkitReflectionUtils() {} - - static { - final Class serverClass; - if (Bukkit.getServer() == null) { - // Paper plugin Bootstrapper 1.20.6+ - serverClass = Objects.requireNonNull(ReflectionUtils.getClazz("org.bukkit.craftbukkit.CraftServer")); - } else { - serverClass = Bukkit.getServer().getClass(); - } - final String pkg = serverClass.getPackage().getName(); - final String nmsVersion = pkg.substring(pkg.lastIndexOf(".") + 1); - if (!nmsVersion.contains("_")) { - int fallbackVersion = -1; - if (Bukkit.getServer() != null) { - try { - final Method getMinecraftVersion = serverClass.getDeclaredMethod("getMinecraftVersion"); - fallbackVersion = Integer.parseInt(getMinecraftVersion.invoke(Bukkit.getServer()).toString().split("\\.")[1]); - } catch (final Exception ignored) { - } - } else { - // Paper plugin bootstrapper 1.20.6+ - try { - final Class sharedConstants = Objects.requireNonNull(ReflectionUtils.getClazz("net.minecraft.SharedConstants")); - final Method getCurrentVersion = sharedConstants.getDeclaredMethod("getCurrentVersion"); - final Object currentVersion = getCurrentVersion.invoke(null); - final Method getName = currentVersion.getClass().getDeclaredMethod("getName"); - final String versionName = (String) getName.invoke(currentVersion); - try { - fallbackVersion = Integer.parseInt(versionName.split("\\.")[1]); - } catch (final Exception ignored) { - } - } catch (final ReflectiveOperationException e) { - throw new RuntimeException(e); - } - } - MAJOR_REVISION = fallbackVersion; - } else { - MAJOR_REVISION = Integer.parseInt(nmsVersion.split("_")[1]); - } - String name = serverClass.getName(); - name = name.substring(PREFIX_CRAFTBUKKIT.length()); - name = name.substring(0, name.length() - CRAFT_SERVER.length()); - CB_PKG_VERSION = name; - } - - public static String assembleCBClass(String className) { - return PREFIX_CRAFTBUKKIT + CB_PKG_VERSION + className; - } - - public static String assembleMCClass(String className) { - return PREFIX_MC + className; - } -} diff --git a/server-mod/v1_21_5/src/main/java/net/momirealms/craftengine/mod/util/ReflectionUtils.java b/server-mod/v1_21_5/src/main/java/net/momirealms/craftengine/mod/util/ReflectionUtils.java deleted file mode 100644 index f76d59ebc..000000000 --- a/server-mod/v1_21_5/src/main/java/net/momirealms/craftengine/mod/util/ReflectionUtils.java +++ /dev/null @@ -1,489 +0,0 @@ -package net.momirealms.craftengine.mod.util; - -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.lang.invoke.MethodHandle; -import java.lang.invoke.MethodHandles; -import java.lang.invoke.VarHandle; -import java.lang.reflect.*; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -public class ReflectionUtils { - private static final MethodHandles.Lookup LOOKUP = MethodHandles.lookup(); - - private ReflectionUtils() {} - - public static Class getClazz(String... classes) { - for (String className : classes) { - Class clazz = getClazz(className); - if (clazz != null) { - return clazz; - } - } - return null; - } - - public static Class getClazz(String clazz) { - try { - return Class.forName(clazz); - } catch (Throwable e) { - return null; - } - } - - public static boolean classExists(@NotNull final String clazz) { - try { - Class.forName(clazz); - return true; - } catch (Throwable e) { - return false; - } - } - - public static boolean methodExists(@NotNull final Class clazz, @NotNull final String method, @NotNull final Class... parameterTypes) { - try { - clazz.getMethod(method, parameterTypes); - return true; - } catch (NoSuchMethodException e) { - return false; - } - } - - @Nullable - public static Field getDeclaredField(final Class clazz, final String field) { - try { - return setAccessible(clazz.getDeclaredField(field)); - } catch (NoSuchFieldException e) { - return null; - } - } - - @NotNull - public static Field getDeclaredField(@NotNull Class clazz, @NotNull String... possibleNames) { - List possibleNameList = Arrays.asList(possibleNames); - for (Field field : clazz.getDeclaredFields()) { - if (possibleNameList.contains(field.getName())) { - return field; - } - } - throw new RuntimeException("Class " + clazz.getName() + " does not contain a field with possible names " + Arrays.toString(possibleNames)); - } - - @Nullable - public static Field getDeclaredField(final Class clazz, final int index) { - int i = 0; - for (final Field field : clazz.getDeclaredFields()) { - if (index == i) { - return setAccessible(field); - } - i++; - } - return null; - } - - @Nullable - public static Field getInstanceDeclaredField(final Class clazz, final int index) { - int i = 0; - for (final Field field : clazz.getDeclaredFields()) { - if (!Modifier.isStatic(field.getModifiers())) { - if (index == i) { - return setAccessible(field); - } - i++; - } - } - return null; - } - - @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; - } - - @Nullable - public static Field getDeclaredFieldBackwards(final Class clazz, final Class type, int index) { - int i = 0; - Field[] fields = clazz.getDeclaredFields(); - for (int j = fields.length - 1; j >= 0; j--) { - Field field = fields[j]; - if (field.getType() == type) { - if (index == i) { - return setAccessible(field); - } - i++; - } - } - return null; - } - - @Nullable - public static Field getInstanceDeclaredField(@NotNull Class clazz, final Class type, int index) { - int i = 0; - for (final Field field : clazz.getDeclaredFields()) { - if (field.getType() == type && !Modifier.isStatic(field.getModifiers())) { - if (index == i) { - return setAccessible(field); - } - i++; - } - } - return null; - } - - @NotNull - public static List getDeclaredFields(final Class clazz) { - List fields = new ArrayList<>(); - for (Field field : clazz.getDeclaredFields()) { - fields.add(setAccessible(field)); - } - return fields; - } - - @NotNull - public static List getInstanceDeclaredFields(@NotNull Class clazz) { - List list = new ArrayList<>(); - for (Field field : clazz.getDeclaredFields()) { - if (!Modifier.isStatic(field.getModifiers())) { - list.add(setAccessible(field)); - } - } - return list; - } - - @NotNull - public static List getDeclaredFields(@NotNull final Class clazz, @NotNull final Class type) { - List fields = new ArrayList<>(); - for (Field field : clazz.getDeclaredFields()) { - if (field.getType() == type) { - fields.add(setAccessible(field)); - } - } - return fields; - } - - @NotNull - public static List getInstanceDeclaredFields(@NotNull Class clazz, @NotNull Class type) { - List list = new ArrayList<>(); - for (Field field : clazz.getDeclaredFields()) { - if (field.getType() == type && !Modifier.isStatic(field.getModifiers())) { - list.add(setAccessible(field)); - } - } - return list; - } - - @Nullable - public static Method getMethod(final Class clazz, Class returnType, final String[] possibleMethodNames, final Class... parameterTypes) { - outer: - for (Method method : clazz.getMethods()) { - if (method.getParameterCount() != parameterTypes.length) { - continue; - } - Class[] types = method.getParameterTypes(); - for (int i = 0; i < types.length; i++) { - if (types[i] != parameterTypes[i]) { - continue outer; - } - } - for (String name : possibleMethodNames) { - if (name.equals(method.getName())) { - if (returnType.isAssignableFrom(method.getReturnType())) { - return method; - } - } - } - } - return null; - } - - @Nullable - public static Method getMethod(final Class clazz, final String[] possibleMethodNames, final Class... parameterTypes) { - outer: - for (Method method : clazz.getMethods()) { - if (method.getParameterCount() != parameterTypes.length) { - continue; - } - Class[] types = method.getParameterTypes(); - for (int i = 0; i < types.length; i++) { - if (types[i] != parameterTypes[i]) { - continue outer; - } - } - for (String name : possibleMethodNames) { - if (name.equals(method.getName())) return method; - } - } - return null; - } - - @Nullable - public static Method getMethod(final Class clazz, Class returnType, final Class... parameterTypes) { - outer: - for (Method method : clazz.getMethods()) { - if (method.getParameterCount() != parameterTypes.length) { - continue; - } - Class[] types = method.getParameterTypes(); - for (int i = 0; i < types.length; i++) { - if (types[i] != parameterTypes[i]) { - continue outer; - } - } - if (returnType.isAssignableFrom(method.getReturnType())) return method; - } - return null; - } - - @Nullable - public static Method getDeclaredMethod(final Class clazz, Class returnType, final String[] possibleMethodNames, final Class... parameterTypes) { - outer: - for (Method method : clazz.getDeclaredMethods()) { - if (method.getParameterCount() != parameterTypes.length) { - continue; - } - Class[] types = method.getParameterTypes(); - for (int i = 0; i < types.length; i++) { - if (types[i] != parameterTypes[i]) { - continue outer; - } - } - for (String name : possibleMethodNames) { - if (name.equals(method.getName())) { - if (returnType.isAssignableFrom(method.getReturnType())) { - return setAccessible(method); - } - } - } - } - return null; - } - - @Nullable - public static Method getDeclaredMethod(final Class clazz, Class returnType, final Class... parameterTypes) { - outer: - for (Method method : clazz.getDeclaredMethods()) { - if (method.getParameterCount() != parameterTypes.length) { - continue; - } - Class[] types = method.getParameterTypes(); - for (int i = 0; i < types.length; i++) { - if (types[i] != parameterTypes[i]) { - continue outer; - } - } - if (returnType.isAssignableFrom(method.getReturnType())) return setAccessible(method); - } - return null; - } - - @Nullable - public static Method getMethod(final Class clazz, Class returnType, int index) { - int i = 0; - for (Method method : clazz.getMethods()) { - if (returnType.isAssignableFrom(method.getReturnType())) { - if (i == index) { - return setAccessible(method); - } - i++; - } - } - return null; - } - - @Nullable - public static Method getStaticMethod(final Class clazz, Class returnType, final Class... parameterTypes) { - outer: - for (Method method : clazz.getMethods()) { - if (method.getParameterCount() != parameterTypes.length) { - continue; - } - if (!Modifier.isStatic(method.getModifiers())) { - continue; - } - Class[] types = method.getParameterTypes(); - for (int i = 0; i < types.length; i++) { - if (types[i] != parameterTypes[i]) { - continue outer; - } - } - if (returnType.isAssignableFrom(method.getReturnType())) - return setAccessible(method); - } - return null; - } - - @Nullable - public static Method getStaticMethod(final Class clazz, Class returnType, String[] possibleNames, final Class... parameterTypes) { - outer: - for (Method method : clazz.getMethods()) { - if (method.getParameterCount() != parameterTypes.length) { - continue; - } - if (!Modifier.isStatic(method.getModifiers())) { - continue; - } - Class[] types = method.getParameterTypes(); - for (int i = 0; i < types.length; i++) { - if (types[i] != parameterTypes[i]) { - continue outer; - } - } - if (returnType.isAssignableFrom(method.getReturnType())) { - for (String name : possibleNames) { - if (name.equals(method.getName())) { - return setAccessible(method); - } - } - } - } - return null; - } - - public static Method getStaticMethod(final Class clazz, int index) { - int i = 0; - for (Method method : clazz.getMethods()) { - if (Modifier.isStatic(method.getModifiers())) { - if (i == index) { - return setAccessible(method); - } - i++; - } - } - return null; - } - - @Nullable - public static Method getMethod(final Class clazz, int index) { - int i = 0; - for (Method method : clazz.getMethods()) { - if (i == index) { - return setAccessible(method); - } - i++; - } - return null; - } - - public static Method getMethodOrElseThrow(final Class clazz, final String[] possibleMethodNames, final Class[] parameterTypes) throws NoSuchMethodException { - Method method = getMethod(clazz, possibleMethodNames, parameterTypes); - if (method == null) { - throw new NoSuchMethodException("No method found with possible names " + Arrays.toString(possibleMethodNames) + " with parameters " + - Arrays.toString(parameterTypes) + " in class " + clazz.getName()); - } - return method; - } - - @NotNull - public static List getMethods(@NotNull Class clazz, @NotNull Class returnType, @NotNull Class... parameterTypes) { - List list = new ArrayList<>(); - for (Method method : clazz.getMethods()) { - if (!returnType.isAssignableFrom(method.getReturnType()) // check type - || method.getParameterCount() != parameterTypes.length // check length - ) continue; - Class[] types = method.getParameterTypes(); - outer: { - for (int i = 0; i < types.length; i++) { - if (types[i] != parameterTypes[i]) { - break outer; - } - } - list.add(method); - } - } - return list; - } - - @NotNull - public static T setAccessible(@NotNull final T o) { - o.setAccessible(true); - return o; - } - - @Nullable - public static Constructor getConstructor(Class clazz, Class... parameterTypes) { - try { - return clazz.getConstructor(parameterTypes); - } catch (NoSuchMethodException | SecurityException ignore) { - return null; - } - } - - @Nullable - public static Constructor getDeclaredConstructor(Class clazz, Class... parameterTypes) { - try { - return setAccessible(clazz.getDeclaredConstructor(parameterTypes)); - } catch (NoSuchMethodException | SecurityException ignore) { - return null; - } - } - - @Nullable - public static Constructor getConstructor(Class clazz, int index) { - try { - Constructor[] constructors = clazz.getDeclaredConstructors(); - if (index < 0 || index >= constructors.length) { - throw new IndexOutOfBoundsException("Invalid constructor index: " + index); - } - return setAccessible(constructors[index]); - } catch (SecurityException e) { - return null; - } - } - - @NotNull - public static Constructor getTheOnlyConstructor(Class clazz) { - Constructor[] constructors = clazz.getConstructors(); - if (constructors.length != 1) { - throw new RuntimeException("This class is expected to have only one constructor but it has " + constructors.length); - } - return constructors[0]; - } - - public static MethodHandle unreflectGetter(Field field) throws IllegalAccessException { - try { - return LOOKUP.unreflectGetter(field); - } catch (IllegalAccessException e) { - field.setAccessible(true); - return LOOKUP.unreflectGetter(field); - } - } - - public static MethodHandle unreflectMethod(Method method) throws IllegalAccessException { - try { - return LOOKUP.unreflect(method); - } catch (IllegalAccessException e) { - method.setAccessible(true); - return LOOKUP.unreflect(method); - } - } - - public static VarHandle findVarHandle(Class clazz, String name, Class type) { - try { - return MethodHandles.privateLookupIn(clazz, LOOKUP) - .findVarHandle(clazz, name, type); - } catch (NoSuchFieldException | SecurityException | IllegalAccessException e) { - return null; - } - } - - public static VarHandle findVarHandle(Field field) { - try { - return MethodHandles.privateLookupIn(field.getDeclaringClass(), LOOKUP) - .findVarHandle(field.getDeclaringClass(), field.getName(), field.getType()); - } catch (IllegalAccessException | NoSuchFieldException e) { - return null; - } - } -} diff --git a/server-mod/v1_21_5/src/main/java/net/momirealms/craftengine/mod/util/Reflections.java b/server-mod/v1_21_5/src/main/java/net/momirealms/craftengine/mod/util/Reflections.java deleted file mode 100644 index 001f3a736..000000000 --- a/server-mod/v1_21_5/src/main/java/net/momirealms/craftengine/mod/util/Reflections.java +++ /dev/null @@ -1,37 +0,0 @@ -package net.momirealms.craftengine.mod.util; - -import net.minecraft.commands.arguments.blocks.BlockStateParser; -import net.minecraft.core.DefaultedRegistry; -import net.minecraft.core.HolderLookup; -import net.minecraft.core.Registry; -import net.minecraft.resources.ResourceKey; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.level.block.state.BlockBehaviour; - -import java.lang.reflect.Field; -import java.lang.reflect.Method; - -import static java.util.Objects.requireNonNull; - -public class Reflections { - - public static final Method method$DefaultedRegistry$get = requireNonNull( - ReflectionUtils.getMethod( - DefaultedRegistry.class, Object.class, ResourceLocation.class - ) - ); - - public static final Field field$BlockBehaviour$Properties$id = ReflectionUtils.getDeclaredField( - BlockBehaviour.Properties.class, ResourceKey.class, 0 - ); - - public static final Method method$BlockStateParser$parseForBlock = requireNonNull( - ReflectionUtils.getStaticMethod( - BlockStateParser.class, BlockStateParser.BlockResult.class, new String[]{"parseForBlock"}, HolderLookup.class, String.class, boolean.class - ) - ); - - public static final Method method$Registry$asLookup = ReflectionUtils.getMethod( - Registry.class, new String[]{"asLookup"} - ); -} diff --git a/settings.gradle.kts b/settings.gradle.kts index a06e0cb2c..d75ce83fd 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -5,6 +5,7 @@ include(":bukkit") include(":bukkit:legacy") include(":bukkit:compatibility") include(":bukkit:loader") +include(":server-mod:v1_20_1") include(":server-mod:v1_20_5") include(":server-mod:v1_21_5") include(":client-mod")