9
0
mirror of https://github.com/Xiao-MoMi/craft-engine.git synced 2025-12-26 18:39:20 +00:00

improve waterlogged

This commit is contained in:
XiaoMoMi
2025-03-24 04:46:51 +08:00
parent 0393b89188
commit d3668b855b
20 changed files with 356 additions and 101 deletions

View File

@@ -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<Boolean> waterlogged = (Property<Boolean>) 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<Boolean> waterlogged = (Property<Boolean>) customBlock.getProperty("waterlogged");
// if (waterlogged == null) return;
// ImmutableBlockState nextState = state.with(waterlogged, true);
// CraftEngineBlocks.place(location, nextState, UpdateOption.UPDATE_ALL);
// }
// }
// }
// }
}

View File

@@ -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

View File

@@ -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);
}
}

View File

@@ -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);
}
}

View File

@@ -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<Boolean> waterloggedProperty;
public LeavesBlockBehavior(int maxDistance, Property<Integer> distanceProperty, Property<Boolean> persistentProperty, @Nullable Property<Boolean> 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<Object> 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);
}
}

View File

@@ -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<Boolean> waterloggedProperty;
public WaterLoggedBlockBehavior(@Nullable Property<Boolean> waterloggedProperty) {
this.waterloggedProperty = waterloggedProperty;
}
// TODO create real waterlogged blocks
// @Override
// public Object pickupBlock(Object thisBlock, Object[] args, Callable<Object> 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<Object> 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<Object> superMethod) throws Exception {
// return super.canPlaceLiquid(thisBlock, args, superMethod);
// }
//
// @Override
// public Object getFluidState(Object thisBlock, Object[] args, Callable<Object> 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<String, Object> arguments) {
Property<Boolean> waterlogged = (Property<Boolean>) block.getProperty("waterlogged");
return new WaterLoggedBlockBehavior(waterlogged);
}
}
}

View File

@@ -863,7 +863,7 @@ public class BukkitRecipeManager implements RecipeManager<ItemStack> {
List<Object> itemStacks = new ArrayList<>();
for (Holder<Key> 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<ItemStack> {
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<ItemStack> {
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))
);
}
}

View File

@@ -346,7 +346,7 @@ public class RecipeEventListener implements Listener {
Optional<Object> optionalMCRecipe = (Optional<Object>) 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
);

View File

@@ -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 {

View File

@@ -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<Object> superMethod) {
ObjectHolder<BlockBehavior> 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<Object> superMethod) {
// ObjectHolder<BlockBehavior> 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<Object> superMethod) {
// ObjectHolder<BlockBehavior> 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<Object> superMethod) {
// ObjectHolder<BlockBehavior> 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<Object> superMethod) {
// ObjectHolder<BlockBehavior> holder = ((BehaviorHolder) thisObj).getBehaviorHolder();
// try {
// holder.value().canPlaceLiquid(thisObj, args, superMethod);
// } catch (Exception e) {
// CraftEngine.instance().logger().severe("Failed to run canPlaceLiquid", e);
// }
// }
// }
}

View File

@@ -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<NetWorkUser, NMSPacketEvent, Object> ADD_ENTITY = (user, event, packet) -> {

View File

@@ -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);
}
}
}