diff --git a/bukkit-loader/src/main/resources/resources/default/configuration/templates.yml b/bukkit-loader/src/main/resources/resources/default/configuration/templates.yml index d8c84f87f..bb2ba0d64 100644 --- a/bukkit-loader/src/main/resources/resources/default/configuration/templates.yml +++ b/bukkit-loader/src/main/resources/resources/default/configuration/templates.yml @@ -813,36 +813,42 @@ templates#block_states: settings: resistance: 1200.0 burnable: false + fluid-state: water distance=2,persistent=false,waterlogged=true: appearance: "waterlogged" id: "{internal_id}" settings: resistance: 1200.0 burnable: false + fluid-state: water distance=3,persistent=false,waterlogged=true: appearance: "waterlogged" id: "{internal_id}" settings: resistance: 1200.0 burnable: false + fluid-state: water distance=4,persistent=false,waterlogged=true: appearance: "waterlogged" id: "{internal_id}" settings: resistance: 1200.0 burnable: false + fluid-state: water distance=5,persistent=false,waterlogged=true: appearance: "waterlogged" id: "{internal_id}" settings: resistance: 1200.0 burnable: false + fluid-state: water distance=6,persistent=false,waterlogged=true: appearance: "waterlogged" id: "{internal_id}" settings: resistance: 1200.0 burnable: false + fluid-state: water distance=7,persistent=false,waterlogged=true: appearance: "waterlogged" id: "{internal_id}" @@ -850,48 +856,56 @@ templates#block_states: resistance: 1200.0 burnable: false is-randomly-ticking: true + fluid-state: water distance=1,persistent=true,waterlogged=true: appearance: "waterlogged" id: "{internal_id}" settings: resistance: 1200.0 burnable: false + fluid-state: water distance=2,persistent=true,waterlogged=true: appearance: "waterlogged" id: "{internal_id}" settings: resistance: 1200.0 burnable: false + fluid-state: water distance=3,persistent=true,waterlogged=true: appearance: "waterlogged" id: "{internal_id}" settings: resistance: 1200.0 burnable: false + fluid-state: water distance=4,persistent=true,waterlogged=true: appearance: "waterlogged" id: "{internal_id}" settings: resistance: 1200.0 burnable: false + fluid-state: water distance=5,persistent=true,waterlogged=true: appearance: "waterlogged" id: "{internal_id}" settings: resistance: 1200.0 burnable: false + fluid-state: water distance=6,persistent=true,waterlogged=true: appearance: "waterlogged" id: "{internal_id}" settings: resistance: 1200.0 burnable: false + fluid-state: water distance=7,persistent=true,waterlogged=true: appearance: "waterlogged" id: "{internal_id}" settings: resistance: 1200.0 burnable: false + fluid-state: water # recipes templates#recipes: 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 b166a2175..b9c370a51 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 @@ -332,41 +332,4 @@ public class BlockEventListener implements Listener { } } } - - // TODO Is there a way to deceive the server? -// @SuppressWarnings("unchecked") -// @EventHandler(ignoreCancelled = true) -// public void onDispenserWork(BlockDispenseEvent event) { -// ItemStack itemStack = event.getItem(); -// Material type = itemStack.getType(); -// Block block = event.getBlock(); -// if (type == Material.BUCKET) { -// if (block.getBlockData() instanceof Dispenser dispenser) { -// Block against = block.getRelative(dispenser.getFacing()); -// ImmutableBlockState state = this.manager.getImmutableBlockState(BlockStateUtils.blockDataToId(against.getBlockData())); -// if (state != null && !state.isEmpty()) { -// Location location = against.getLocation(); -// CustomBlock customBlock = state.owner().value(); -// Property waterlogged = (Property) customBlock.getProperty("waterlogged"); -// if (waterlogged == null) return; -// if (!state.get(waterlogged)) return; -// ImmutableBlockState nextState = state.with(waterlogged, false); -// CraftEngineBlocks.place(location, nextState, UpdateOption.UPDATE_ALL); -// } -// } -// } else if (WATER_BUCKETS.contains(type)) { -// if (block.getBlockData() instanceof Dispenser dispenser) { -// Block against = block.getRelative(dispenser.getFacing()); -// ImmutableBlockState state = this.manager.getImmutableBlockState(BlockStateUtils.blockDataToId(against.getBlockData())); -// if (state != null && !state.isEmpty()) { -// Location location = against.getLocation(); -// CustomBlock customBlock = state.owner().value(); -// Property waterlogged = (Property) customBlock.getProperty("waterlogged"); -// if (waterlogged == null) return; -// ImmutableBlockState nextState = state.with(waterlogged, true); -// CraftEngineBlocks.place(location, nextState, UpdateOption.UPDATE_ALL); -// } -// } -// } -// } } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/BukkitCustomBlock.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/BukkitCustomBlock.java index 6cd231677..3c8f16e6b 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/BukkitCustomBlock.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/BukkitCustomBlock.java @@ -103,6 +103,12 @@ public class BukkitCustomBlock extends CustomBlock { Reflections.field$BlockBehaviour$soundType.set(mcBlock, SoundUtils.toSoundType(settings.sounds())); // init cache Reflections.method$BlockStateBase$initCache.invoke(mcBlockState); + // set fluid later + if (settings.fluidState()) { + Reflections.field$BlockStateBase$fluidState.set(mcBlockState, Reflections.method$FlowingFluid$getSource.invoke(Reflections.instance$Fluids$WATER, false)); + } else { + Reflections.field$BlockStateBase$fluidState.set(mcBlockState, Reflections.instance$Fluid$EMPTY$defaultState); + } // set random tick later BlockStateUtils.setIsRandomlyTicking(mcBlockState, settings.isRandomlyTicking()); // bind tags diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/BukkitBlockBehaviors.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/BukkitBlockBehaviors.java index 2e414eacf..c4ca15763 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/BukkitBlockBehaviors.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/BukkitBlockBehaviors.java @@ -11,6 +11,7 @@ public class BukkitBlockBehaviors extends BlockBehaviors { public static final Key STRIPPABLE_BLOCK = Key.from("craftengine:strippable_block"); public static final Key SAPLING_BLOCK = Key.from("craftengine:sapling_block"); public static final Key ON_LIQUID_BLOCK = Key.from("craftengine:on_liquid_block"); + public static final Key WATERLOGGED_BLOCK = Key.from("craftengine:waterlogged_block"); public static final Key CONCRETE_POWDER_BLOCK = Key.from("craftengine:concrete_powder_block"); public static void init() { @@ -21,5 +22,6 @@ public class BukkitBlockBehaviors extends BlockBehaviors { register(STRIPPABLE_BLOCK, StrippableBlockBehavior.FACTORY); register(SAPLING_BLOCK, SaplingBlockBehavior.FACTORY); register(ON_LIQUID_BLOCK, OnLiquidBlockBehavior.FACTORY); + register(WATERLOGGED_BLOCK, WaterLoggedBlockBehavior.FACTORY); } } 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 6d2dad7cb..563eac99d 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 @@ -5,4 +5,9 @@ public class ConcretePowderBlockBehavior extends FallingBlockBehavior { public ConcretePowderBlockBehavior(float hurtAmount, int maxHurt) { super(hurtAmount, maxHurt); } + + @Override + public void onLand(Object thisBlock, Object[] args) throws Exception { + super.onLand(thisBlock, args); + } } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/LeavesBlockBehavior.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/LeavesBlockBehavior.java index 7fc3f83ba..34dd0d031 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/LeavesBlockBehavior.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/LeavesBlockBehavior.java @@ -29,7 +29,7 @@ import org.jetbrains.annotations.Nullable; import java.util.Map; import java.util.concurrent.Callable; -public class LeavesBlockBehavior extends BlockBehavior { +public class LeavesBlockBehavior extends WaterLoggedBlockBehavior { public static final Factory FACTORY = new Factory(); private static final Object LOG_TAG = BlockTags.getOrCreate(Key.of("minecraft", "logs")); private final int maxDistance; @@ -39,6 +39,7 @@ public class LeavesBlockBehavior extends BlockBehavior { private final Property waterloggedProperty; public LeavesBlockBehavior(int maxDistance, Property distanceProperty, Property persistentProperty, @Nullable Property waterloggedProperty) { + super(waterloggedProperty); this.maxDistance = maxDistance; this.distanceProperty = distanceProperty; this.persistentProperty = persistentProperty; @@ -183,13 +184,4 @@ public class LeavesBlockBehavior extends BlockBehavior { return new LeavesBlockBehavior(actual, distance, persistent, waterlogged); } } - - @Override - public Object getFluidState(Object thisBlock, Object[] args, Callable superMethod) throws Exception { - Object blockState = args[0]; - ImmutableBlockState state = BukkitBlockManager.instance().getImmutableBlockState(BlockStateUtils.blockStateToId(blockState)); - if (state == null || state.isEmpty() || waterloggedProperty == null) return super.getFluidState(thisBlock, args, superMethod); - boolean waterlogged = state.get(waterloggedProperty); - return waterlogged ? Reflections.method$FlowingFluid$getSource.invoke(Reflections.instance$Fluids$WATER, false) : super.getFluidState(thisBlock, args, superMethod); - } } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/WaterLoggedBlockBehavior.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/WaterLoggedBlockBehavior.java new file mode 100644 index 000000000..1f77a5a10 --- /dev/null +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/WaterLoggedBlockBehavior.java @@ -0,0 +1,88 @@ +package net.momirealms.craftengine.bukkit.block.behavior; + +import net.momirealms.craftengine.core.block.CustomBlock; +import net.momirealms.craftengine.core.block.behavior.BlockBehaviorFactory; +import net.momirealms.craftengine.core.block.properties.Property; +import net.momirealms.craftengine.shared.block.BlockBehavior; +import org.jetbrains.annotations.Nullable; + +import java.util.Map; + +public class WaterLoggedBlockBehavior extends BlockBehavior { + public static final Factory FACTORY = new Factory(); + @Nullable + private final Property waterloggedProperty; + + public WaterLoggedBlockBehavior(@Nullable Property waterloggedProperty) { + this.waterloggedProperty = waterloggedProperty; + } + + // TODO create real waterlogged blocks +// @Override +// public Object pickupBlock(Object thisBlock, Object[] args, Callable superMethod) throws Exception { +// if (this.waterloggedProperty == null) return Reflections.instance$ItemStack$EMPTY; +// Object blockState; +// Object world; +// Object pos; +// if (VersionHelper.isVersionNewerThan1_20_2()) { +// world = args[1]; +// pos = args[2]; +// blockState = args[3]; +// } else { +// world = args[0]; +// pos = args[1]; +// blockState = args[2]; +// } +// ImmutableBlockState immutableBlockState = BukkitBlockManager.instance().getImmutableBlockState(BlockStateUtils.blockStateToId(blockState)); +// if (immutableBlockState != null) { +// if (immutableBlockState.get(this.waterloggedProperty)) { +// Reflections.method$LevelWriter$setBlock.invoke(world, pos, immutableBlockState.with(this.waterloggedProperty, false).customBlockState().handle(), 3); +// // TODO check can survive +// Object itemStack = Reflections.constructor$ItemStack.newInstance(Reflections.instance$Items$WATER_BUCKET); +// System.out.println(itemStack); +// return itemStack; +// } +// } +// return Reflections.instance$ItemStack$EMPTY; +// } +// +// @Override +// public boolean placeLiquid(Object thisBlock, Object[] args, Callable superMethod) throws Exception { +// if (this.waterloggedProperty == null) return false; +// Object blockState = args[2]; +// ImmutableBlockState immutableBlockState = BukkitBlockManager.instance().getImmutableBlockState(BlockStateUtils.blockStateToId(blockState)); +// if (immutableBlockState != null) { +// Object fluidType = Reflections.method$FluidState$getType.invoke(args[3]); +// if (!immutableBlockState.get(this.waterloggedProperty) && fluidType == Reflections.instance$Fluids$WATER) { +// Reflections.method$LevelWriter$setBlock.invoke(args[0], args[1], immutableBlockState.with(this.waterloggedProperty, true).customBlockState().handle(), 3); +// Reflections.method$LevelAccessor$scheduleTick.invoke(args[0], fluidType, Reflections.method$Fluid$getTickDelay.invoke(fluidType, args[0])); +// return true; +// } +// } +// return false; +// } +// +// // use water +// @Override +// public boolean canPlaceLiquid(Object thisBlock, Object[] args, Callable superMethod) throws Exception { +// return super.canPlaceLiquid(thisBlock, args, superMethod); +// } +// +// @Override +// public Object getFluidState(Object thisBlock, Object[] args, Callable superMethod) throws Exception { +// Object blockState = args[0]; +// ImmutableBlockState state = BukkitBlockManager.instance().getImmutableBlockState(BlockStateUtils.blockStateToId(blockState)); +// if (state == null || state.isEmpty() || this.waterloggedProperty == null) return super.getFluidState(thisBlock, args, superMethod); +// boolean waterlogged = state.get(this.waterloggedProperty); +// return waterlogged ? Reflections.method$FlowingFluid$getSource.invoke(Reflections.instance$Fluids$WATER, false) : super.getFluidState(thisBlock, args, superMethod); +// } + + @SuppressWarnings("unchecked") + public static class Factory implements BlockBehaviorFactory { + @Override + public BlockBehavior create(CustomBlock block, Map arguments) { + Property waterlogged = (Property) block.getProperty("waterlogged"); + return new WaterLoggedBlockBehavior(waterlogged); + } + } +} diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/recipe/BukkitRecipeManager.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/recipe/BukkitRecipeManager.java index 729e2a607..07fc4fab6 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/recipe/BukkitRecipeManager.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/recipe/BukkitRecipeManager.java @@ -863,7 +863,7 @@ public class BukkitRecipeManager implements RecipeManager { List itemStacks = new ArrayList<>(); for (Holder holder : holders) { ItemStack itemStack = BukkitItemManager.instance().getBuildableItem(holder.value()).get().buildItemStack(ItemBuildContext.EMPTY, 1); - Object nmsStack = Reflections.method$CraftItemStack$asNMSMirror.invoke(null, itemStack); + Object nmsStack = Reflections.method$CraftItemStack$asNMSCopy.invoke(null, itemStack); itemStacks.add(nmsStack); } return itemStacks; @@ -994,14 +994,14 @@ public class BukkitRecipeManager implements RecipeManager { toOptionalMinecraftIngredient(ceRecipe.template()), toOptionalMinecraftIngredient(ceRecipe.base()), toOptionalMinecraftIngredient(ceRecipe.addition()), - Reflections.method$CraftItemStack$asNMSMirror.invoke(null, ceRecipe.result(ItemBuildContext.EMPTY)) + Reflections.method$CraftItemStack$asNMSCopy.invoke(null, ceRecipe.result(ItemBuildContext.EMPTY)) ); } else if (VersionHelper.isVersionNewerThan1_20_2()) { return Reflections.constructor$SmithingTransformRecipe.newInstance( toMinecraftIngredient(ceRecipe.template()), toMinecraftIngredient(ceRecipe.base()), toMinecraftIngredient(ceRecipe.addition()), - Reflections.method$CraftItemStack$asNMSMirror.invoke(null, ceRecipe.result(ItemBuildContext.EMPTY)) + Reflections.method$CraftItemStack$asNMSCopy.invoke(null, ceRecipe.result(ItemBuildContext.EMPTY)) ); } else { return Reflections.constructor$SmithingTransformRecipe.newInstance( @@ -1009,7 +1009,7 @@ public class BukkitRecipeManager implements RecipeManager { toMinecraftIngredient(ceRecipe.template()), toMinecraftIngredient(ceRecipe.base()), toMinecraftIngredient(ceRecipe.addition()), - Reflections.method$CraftItemStack$asNMSMirror.invoke(null, ceRecipe.result(ItemBuildContext.EMPTY)) + Reflections.method$CraftItemStack$asNMSCopy.invoke(null, ceRecipe.result(ItemBuildContext.EMPTY)) ); } } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/recipe/RecipeEventListener.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/recipe/RecipeEventListener.java index f6b0518cb..c513dc9b1 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/recipe/RecipeEventListener.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/recipe/RecipeEventListener.java @@ -346,7 +346,7 @@ public class RecipeEventListener implements Listener { Optional optionalMCRecipe = (Optional) Reflections.method$RecipeManager$getRecipeFor1.invoke( BukkitRecipeManager.minecraftRecipeManager(), Reflections.instance$RecipeType$CAMPFIRE_COOKING, - Reflections.constructor$SingleRecipeInput.newInstance(Reflections.method$CraftItemStack$asNMSMirror.invoke(null, itemStack)), + Reflections.constructor$SingleRecipeInput.newInstance(Reflections.method$CraftItemStack$asNMSCopy.invoke(null, itemStack)), Reflections.field$CraftWorld$ServerLevel.get(event.getPlayer().getWorld()), null ); diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/BukkitCraftEngine.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/BukkitCraftEngine.java index 19571f6b8..423bdd269 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/BukkitCraftEngine.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/BukkitCraftEngine.java @@ -50,7 +50,6 @@ import java.lang.reflect.Field; import java.nio.file.Path; import java.util.List; import java.util.Optional; -import java.util.concurrent.TimeUnit; @SuppressWarnings("unchecked") public class BukkitCraftEngine extends CraftEngine { diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/injector/BukkitInjector.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/injector/BukkitInjector.java index 4e835a00f..f375fb7bb 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/injector/BukkitInjector.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/injector/BukkitInjector.java @@ -183,6 +183,7 @@ public class BukkitInjector { // should always implement this interface .implement(Reflections.clazz$Fallable) .implement(Reflections.clazz$BonemealableBlock) + // TODO .implement(Reflections.clazz$SimpleWaterloggedBlock) // internal interfaces .implement(BehaviorHolder.class) .implement(ShapeHolder.class) @@ -208,6 +209,15 @@ public class BukkitInjector { // performBoneMeal .method(ElementMatchers.is(Reflections.method$BonemealableBlock$performBonemeal)) .intercept(MethodDelegation.to(PerformBoneMealInterceptor.INSTANCE)) +// // pickupBlock +// .method(ElementMatchers.is(Reflections.method$SimpleWaterloggedBlock$pickupBlock)) +// .intercept(MethodDelegation.to(PickUpBlockInterceptor.INSTANCE)) +// // placeLiquid +// .method(ElementMatchers.is(Reflections.method$SimpleWaterloggedBlock$placeLiquid)) +// .intercept(MethodDelegation.to(PlaceLiquidInterceptor.INSTANCE)) +// // canPlaceLiquid +// .method(ElementMatchers.is(Reflections.method$SimpleWaterloggedBlock$canPlaceLiquid)) +// .intercept(MethodDelegation.to(CanPlaceLiquidInterceptor.INSTANCE)) // random tick .method(ElementMatchers.is(Reflections.method$BlockBehaviour$randomTick)) .intercept(MethodDelegation.to(RandomTickInterceptor.INSTANCE)) @@ -251,10 +261,11 @@ public class BukkitInjector { .and(ElementMatchers.takesArgument(1, Reflections.clazz$LevelReader).or(ElementMatchers.takesArgument(1, Reflections.clazz$Direction))) .and(ElementMatchers.named("updateShape").or(ElementMatchers.named("a")))) .intercept(MethodDelegation.to(UpdateShapeInterceptor.INSTANCE)) - // getFluidState - .method(ElementMatchers.returns(Reflections.clazz$FluidState) - .and(ElementMatchers.takesArgument(0, Reflections.clazz$BlockState))) - .intercept(MethodDelegation.to(FluidStateInterceptor.INSTANCE)); +// // getFluidState +// .method(ElementMatchers.returns(Reflections.clazz$FluidState) +// .and(ElementMatchers.takesArgument(0, Reflections.clazz$BlockState))) +// .intercept(MethodDelegation.to(FluidStateInterceptor.INSTANCE)) + ; clazz$CraftEngineBlock = builder.make().load(BukkitInjector.class.getClassLoader()).getLoaded(); constructor$CraftEngineBlock = MethodHandles.publicLookup().in(clazz$CraftEngineBlock) @@ -647,20 +658,21 @@ public class BukkitInjector { return newBlockInstance; } - public static class FluidStateInterceptor { - public static final FluidStateInterceptor INSTANCE = new FluidStateInterceptor(); - - @RuntimeType - public Object intercept(@This Object thisObj, @AllArguments Object[] args, @SuperCall Callable superMethod) { - ObjectHolder holder = ((BehaviorHolder) thisObj).getBehaviorHolder(); - try { - return holder.value().getFluidState(thisObj, args, superMethod); - } catch (Exception e) { - CraftEngine.instance().logger().severe("Failed to run getFluidState", e); - return args[0]; - } - } - } +// +// public static class FluidStateInterceptor { +// public static final FluidStateInterceptor INSTANCE = new FluidStateInterceptor(); +// +// @RuntimeType +// public Object intercept(@This Object thisObj, @AllArguments Object[] args, @SuperCall Callable superMethod) { +// ObjectHolder holder = ((BehaviorHolder) thisObj).getBehaviorHolder(); +// try { +// return holder.value().getFluidState(thisObj, args, superMethod); +// } catch (Exception e) { +// CraftEngine.instance().logger().severe("Failed to run getFluidState", e); +// return args[0]; +// } +// } +// } public static class UpdateShapeInterceptor { public static final UpdateShapeInterceptor INSTANCE = new UpdateShapeInterceptor(); @@ -849,4 +861,46 @@ public class BukkitInjector { } } } +// +// public static class PickUpBlockInterceptor { +// public static final PickUpBlockInterceptor INSTANCE = new PickUpBlockInterceptor(); +// +// @RuntimeType +// public void intercept(@This Object thisObj, @AllArguments Object[] args, @SuperCall Callable superMethod) { +// ObjectHolder holder = ((BehaviorHolder) thisObj).getBehaviorHolder(); +// try { +// holder.value().pickupBlock(thisObj, args, superMethod); +// } catch (Exception e) { +// CraftEngine.instance().logger().severe("Failed to run pickupBlock", e); +// } +// } +// } +// +// public static class PlaceLiquidInterceptor { +// public static final PlaceLiquidInterceptor INSTANCE = new PlaceLiquidInterceptor(); +// +// @RuntimeType +// public void intercept(@This Object thisObj, @AllArguments Object[] args, @SuperCall Callable superMethod) { +// ObjectHolder holder = ((BehaviorHolder) thisObj).getBehaviorHolder(); +// try { +// holder.value().placeLiquid(thisObj, args, superMethod); +// } catch (Exception e) { +// CraftEngine.instance().logger().severe("Failed to run placeLiquid", e); +// } +// } +// } +// +// public static class CanPlaceLiquidInterceptor { +// public static final CanPlaceLiquidInterceptor INSTANCE = new CanPlaceLiquidInterceptor(); +// +// @RuntimeType +// public void intercept(@This Object thisObj, @AllArguments Object[] args, @SuperCall Callable superMethod) { +// ObjectHolder holder = ((BehaviorHolder) thisObj).getBehaviorHolder(); +// try { +// holder.value().canPlaceLiquid(thisObj, args, superMethod); +// } catch (Exception e) { +// CraftEngine.instance().logger().severe("Failed to run canPlaceLiquid", e); +// } +// } +// } } 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 b45e8c83b..ab80d70f4 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 @@ -34,8 +34,6 @@ import org.bukkit.util.RayTraceResult; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.*; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.atomic.AtomicReference; import java.util.function.BiConsumer; import java.util.function.Consumer; @@ -516,7 +514,7 @@ public class PacketConsumers { } assert Reflections.method$ServerGamePacketListenerImpl$tryPickItem != null; Reflections.method$ServerGamePacketListenerImpl$tryPickItem.invoke( - Reflections.field$ServerPlayer$connection.get(Reflections.method$CraftPlayer$getHandle.invoke(player)), Reflections.method$CraftItemStack$asNMSMirror.invoke(null, itemStack)); + Reflections.field$ServerPlayer$connection.get(Reflections.method$CraftPlayer$getHandle.invoke(player)), Reflections.method$CraftItemStack$asNMSCopy.invoke(null, itemStack)); } public static final TriConsumer ADD_ENTITY = (user, event, packet) -> { 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 ca7482e16..d0819e6b6 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 @@ -1537,13 +1537,13 @@ public class Reflections { public static final Method method$CraftBlockData$createData = requireNonNull( ReflectionUtils.getStaticMethod( - clazz$CraftBlockData, new String[]{"createData"}, clazz$CraftBlockData, clazz$BlockState + clazz$CraftBlockData, clazz$CraftBlockData, new String[]{"createData"}, clazz$BlockState ) ); public static final Method method$CraftBlockData$fromData = requireNonNull( ReflectionUtils.getStaticMethod( - clazz$CraftBlockData, new String[]{"fromData"}, clazz$CraftBlockData, clazz$BlockState + clazz$CraftBlockData, clazz$CraftBlockData, new String[]{"fromData"}, clazz$BlockState ) ); @@ -2230,6 +2230,12 @@ public class Reflections { ) ); + public static final Field field$BlockStateBase$fluidState = requireNonNull( + ReflectionUtils.getDeclaredField( + clazz$BlockStateBase, clazz$FluidState, 0 + ) + ); + public static final Field field$BlockStateBase$pushReaction = requireNonNull( ReflectionUtils.getDeclaredField( clazz$BlockStateBase, clazz$PushReaction, 0 @@ -3162,6 +3168,20 @@ public class Reflections { ) ); + public static final Object instance$ItemStack$EMPTY; + + static { + try { + instance$ItemStack$EMPTY = requireNonNull( + ReflectionUtils.getDeclaredField( + clazz$ItemStack, clazz$ItemStack, 0 + ).get(null) + ); + } catch (ReflectiveOperationException e) { + throw new RuntimeException(e); + } + } + public static final Field field$ServerboundSetCreativeModeSlotPacket$itemStack = requireNonNull( ReflectionUtils.getDeclaredField( clazz$ServerboundSetCreativeModeSlotPacket, clazz$ItemStack, 0 @@ -3176,13 +3196,13 @@ public class Reflections { public static final Method method$CraftItemStack$asCraftMirror = requireNonNull( ReflectionUtils.getStaticMethod( - clazz$CraftItemStack, new String[]{"asCraftMirror"}, clazz$CraftItemStack, clazz$ItemStack + clazz$CraftItemStack, clazz$CraftItemStack, new String[]{"asCraftMirror"}, clazz$ItemStack ) ); - public static final Method method$CraftItemStack$asNMSMirror = requireNonNull( + public static final Method method$CraftItemStack$asNMSCopy = requireNonNull( ReflectionUtils.getStaticMethod( - clazz$CraftItemStack, new String[]{"asNMSCopy"}, clazz$ItemStack, ItemStack.class + clazz$CraftItemStack, clazz$ItemStack, new String[]{"asNMSCopy"}, ItemStack.class ) ); @@ -3652,6 +3672,7 @@ public class Reflections { ); public static final Object instance$Items$AIR; + public static final Object instance$Items$WATER_BUCKET; public static final Object instance$ItemStack$Air; static { @@ -3659,6 +3680,8 @@ public class Reflections { Object air = method$ResourceLocation$fromNamespaceAndPath.invoke(null, "minecraft", "air"); instance$Items$AIR = method$Registry$get.invoke(Reflections.instance$BuiltInRegistries$ITEM, air); instance$ItemStack$Air = constructor$ItemStack.newInstance(instance$Items$AIR); + Object waterBucket = method$ResourceLocation$fromNamespaceAndPath.invoke(null, "minecraft", "water_bucket"); + instance$Items$WATER_BUCKET = method$Registry$get.invoke(Reflections.instance$BuiltInRegistries$ITEM, waterBucket); } catch (ReflectiveOperationException e) { throw new RuntimeException(e); } @@ -5293,4 +5316,59 @@ public class Reflections { clazz$ServerboundEditBookPacket, int.class, List.class, Optional.class ) ); + + public static final Class clazz$SimpleWaterloggedBlock = requireNonNull( + ReflectionUtils.getClazz( + BukkitReflectionUtils.assembleMCClass("world.level.block.SimpleWaterloggedBlock"), + BukkitReflectionUtils.assembleMCClass("world.level.block.IBlockWaterlogged") + ) + ); + + public static final Method method$SimpleWaterloggedBlock$canPlaceLiquid = requireNonNull( + VersionHelper.isVersionNewerThan1_20_2() ? + ReflectionUtils.getMethod( + clazz$SimpleWaterloggedBlock, boolean.class, clazz$Player, clazz$BlockGetter, clazz$BlockPos, clazz$BlockState, clazz$Fluid + ) : + ReflectionUtils.getMethod( + clazz$SimpleWaterloggedBlock, boolean.class, clazz$BlockGetter, clazz$BlockPos, clazz$BlockState, clazz$Fluid + ) + ); + + public static final Method method$SimpleWaterloggedBlock$placeLiquid = requireNonNull( + ReflectionUtils.getMethod( + clazz$SimpleWaterloggedBlock, boolean.class, clazz$LevelAccessor, clazz$BlockPos, clazz$BlockState, clazz$FluidState + ) + ); + + public static final Method method$SimpleWaterloggedBlock$pickupBlock = requireNonNull( + VersionHelper.isVersionNewerThan1_20_2() ? + ReflectionUtils.getMethod( + clazz$SimpleWaterloggedBlock, clazz$ItemStack, clazz$Player, clazz$LevelAccessor, clazz$BlockPos, clazz$BlockState + ) : + ReflectionUtils.getMethod( + clazz$SimpleWaterloggedBlock, clazz$ItemStack, clazz$LevelAccessor, clazz$BlockPos, clazz$BlockState + ) + ); + + public static final Method method$Fluid$getTickDelay = requireNonNull( + ReflectionUtils.getMethod( + clazz$Fluid, int.class, clazz$LevelReader + ) + ); + + public static final Method method$Fluid$defaultFluidState = requireNonNull( + ReflectionUtils.getMethod( + clazz$Fluid, clazz$FluidState, 0 + ) + ); + + public static final Object instance$Fluid$EMPTY$defaultState; + + static { + try { + instance$Fluid$EMPTY$defaultState = method$Fluid$defaultFluidState.invoke(instance$Fluids$EMPTY); + } catch (ReflectiveOperationException e) { + throw new RuntimeException(e); + } + } } diff --git a/core/src/main/java/net/momirealms/craftengine/core/block/AbstractBlockManager.java b/core/src/main/java/net/momirealms/craftengine/core/block/AbstractBlockManager.java index 329b1170e..a1046b6e7 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/block/AbstractBlockManager.java +++ b/core/src/main/java/net/momirealms/craftengine/core/block/AbstractBlockManager.java @@ -1,11 +1,7 @@ package net.momirealms.craftengine.core.block; -import com.google.gson.JsonElement; import net.momirealms.craftengine.core.pack.model.generation.AbstractModelGenerator; import net.momirealms.craftengine.core.plugin.CraftEngine; -import net.momirealms.craftengine.core.util.Key; - -import java.util.Map; public abstract class AbstractBlockManager extends AbstractModelGenerator implements BlockManager { diff --git a/core/src/main/java/net/momirealms/craftengine/core/block/BlockSettings.java b/core/src/main/java/net/momirealms/craftengine/core/block/BlockSettings.java index 42c66df96..183ab46a5 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/block/BlockSettings.java +++ b/core/src/main/java/net/momirealms/craftengine/core/block/BlockSettings.java @@ -15,6 +15,7 @@ public class BlockSettings { float hardness = 2f; float resistance = 2f; boolean canOcclude; + boolean fluidState; Tristate isRedstoneConductor = Tristate.UNDEFINED; Tristate isSuffocating = Tristate.UNDEFINED; Tristate isViewBlocking = Tristate.UNDEFINED; @@ -75,6 +76,7 @@ public class BlockSettings { newSettings.isSuffocating = settings.isSuffocating; newSettings.isViewBlocking = settings.isViewBlocking; newSettings.correctTools = settings.correctTools; + newSettings.fluidState = settings.fluidState; return newSettings; } @@ -94,6 +96,10 @@ public class BlockSettings { return resistance; } + public boolean fluidState() { + return fluidState; + } + public boolean isRandomlyTicking() { return isRandomlyTicking; } @@ -250,6 +256,11 @@ public class BlockSettings { return this; } + public BlockSettings fluidState(boolean state) { + this.fluidState = state; + return this; + } + public interface Modifier { void apply(BlockSettings settings); @@ -332,6 +343,10 @@ public class BlockSettings { Map soundMap = MiscUtils.castToMap(value, false); return settings -> settings.sounds(BlockSounds.fromMap(soundMap)); })); + registerFactory("fluid-state", (value -> { + String state = (String) value; + return settings -> settings.fluidState(state.equals("water")); + })); registerFactory("can-occlude", (value -> { boolean booleanValue = (boolean) value; return settings -> settings.canOcclude(booleanValue); diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/CraftEngine.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/CraftEngine.java index 62626b2c3..d31706cac 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/plugin/CraftEngine.java +++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/CraftEngine.java @@ -3,7 +3,6 @@ package net.momirealms.craftengine.core.plugin; import net.momirealms.craftengine.core.block.BlockManager; import net.momirealms.craftengine.core.entity.furniture.FurnitureManager; import net.momirealms.craftengine.core.font.ImageManager; -import net.momirealms.craftengine.core.font.AbstractImageManager; import net.momirealms.craftengine.core.item.ItemManager; import net.momirealms.craftengine.core.item.recipe.RecipeManager; import net.momirealms.craftengine.core.loot.VanillaLootManager; diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/config/ConfigManager.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/config/ConfigManager.java index a50439999..9e7e4f18e 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/plugin/config/ConfigManager.java +++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/config/ConfigManager.java @@ -249,7 +249,7 @@ public class ConfigManager implements Reloadable { Class modClazz = ReflectionUtils.getClazz(CraftEngine.MOD_CLASS); if (modClazz != null) { - Method setMaxChainMethod = ReflectionUtils.getStaticMethod(modClazz, new String[] {"setMaxChainUpdate"}, void.class, int.class); + Method setMaxChainMethod = ReflectionUtils.getStaticMethod(modClazz, void.class, new String[] {"setMaxChainUpdate"}, int.class); try { assert setMaxChainMethod != null; setMaxChainMethod.invoke(null, performance$max_block_chain_update_limit); diff --git a/core/src/main/java/net/momirealms/craftengine/core/util/ReflectionUtils.java b/core/src/main/java/net/momirealms/craftengine/core/util/ReflectionUtils.java index 491ca6264..77b5c2d1e 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/util/ReflectionUtils.java +++ b/core/src/main/java/net/momirealms/craftengine/core/util/ReflectionUtils.java @@ -321,7 +321,7 @@ public class ReflectionUtils { } @Nullable - public static Method getStaticMethod(final Class clazz, String[] possibleNames, Class returnType, final Class... parameterTypes) { + 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) { diff --git a/server-mod/src/main/java/net/momirealms/craftengine/mod/CraftEngineBlock.java b/server-mod/src/main/java/net/momirealms/craftengine/mod/CraftEngineBlock.java index 24e8c1533..54effc4b0 100644 --- a/server-mod/src/main/java/net/momirealms/craftengine/mod/CraftEngineBlock.java +++ b/server-mod/src/main/java/net/momirealms/craftengine/mod/CraftEngineBlock.java @@ -15,7 +15,6 @@ import net.minecraft.world.level.block.Blocks; import net.minecraft.world.level.block.BonemealableBlock; import net.minecraft.world.level.block.Fallable; import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.material.FluidState; import net.minecraft.world.phys.shapes.CollisionContext; import net.minecraft.world.phys.shapes.VoxelShape; import net.momirealms.craftengine.mod.util.NoteBlockUtils; @@ -23,7 +22,11 @@ import net.momirealms.craftengine.shared.ObjectHolder; import net.momirealms.craftengine.shared.block.*; import org.jetbrains.annotations.NotNull; -public class CraftEngineBlock extends Block implements BehaviorHolder, ShapeHolder, NoteBlockIndicator, Fallable, BonemealableBlock { +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; @@ -168,15 +171,15 @@ public class CraftEngineBlock extends Block implements BehaviorHolder, ShapeHold } } - @Override - protected @NotNull FluidState getFluidState(@NotNull BlockState state) { - try { - return (FluidState) behaviorHolder.value().getFluidState(this, new Object[]{state}, () -> super.getFluidState(state)); - } catch (Exception e) { - e.printStackTrace(); - return super.getFluidState(state); - } - } +// @Override +// protected @NotNull FluidState getFluidState(@NotNull BlockState state) { +// try { +// return (FluidState) behaviorHolder.value().getFluidState(this, new Object[]{state}, () -> super.getFluidState(state)); +// } catch (Exception e) { +// e.printStackTrace(); +// return super.getFluidState(state); +// } +// } @Override public boolean isValidBonemealTarget(@NotNull LevelReader levelReader, @NotNull BlockPos blockPos, @NotNull BlockState blockState) { @@ -215,4 +218,35 @@ public class CraftEngineBlock extends Block implements BehaviorHolder, ShapeHold 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/shared/src/main/java/net/momirealms/craftengine/shared/block/BlockBehavior.java b/shared/src/main/java/net/momirealms/craftengine/shared/block/BlockBehavior.java index c263301b2..c96ae499e 100644 --- a/shared/src/main/java/net/momirealms/craftengine/shared/block/BlockBehavior.java +++ b/shared/src/main/java/net/momirealms/craftengine/shared/block/BlockBehavior.java @@ -8,10 +8,6 @@ public abstract class BlockBehavior { return superMethod.call(); } - public Object getFluidState(Object thisBlock, Object[] args, Callable superMethod) throws Exception { - return superMethod.call(); - } - public void tick(Object thisBlock, Object[] args, Callable superMethod) throws Exception { superMethod.call(); } @@ -48,4 +44,20 @@ public abstract class BlockBehavior { public Object updateStateForPlacement(Object context, Object state) { return state; } + +// +// public Object getFluidState(Object thisBlock, Object[] args, Callable superMethod) throws Exception { +// return superMethod.call(); +// } +// public boolean canPlaceLiquid(Object thisBlock, Object[] args, Callable superMethod) throws Exception { +// return (boolean) superMethod.call(); +// } +// +// public boolean placeLiquid(Object thisBlock, Object[] args, Callable superMethod) throws Exception { +// return (boolean) superMethod.call(); +// } +// +// public Object pickupBlock(Object thisBlock, Object[] args, Callable superMethod) throws Exception { +// return superMethod.call(); +// } }