9
0
mirror of https://github.com/Xiao-MoMi/craft-engine.git synced 2025-12-19 15:09:15 +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

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

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

View File

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

View File

@@ -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<String, Object> 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);

View File

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

View File

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

View File

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

View File

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

View File

@@ -8,10 +8,6 @@ public abstract class BlockBehavior {
return superMethod.call();
}
public Object getFluidState(Object thisBlock, Object[] args, Callable<Object> superMethod) throws Exception {
return superMethod.call();
}
public void tick(Object thisBlock, Object[] args, Callable<Object> 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<Object> superMethod) throws Exception {
// return superMethod.call();
// }
// public boolean canPlaceLiquid(Object thisBlock, Object[] args, Callable<Object> superMethod) throws Exception {
// return (boolean) superMethod.call();
// }
//
// public boolean placeLiquid(Object thisBlock, Object[] args, Callable<Object> superMethod) throws Exception {
// return (boolean) superMethod.call();
// }
//
// public Object pickupBlock(Object thisBlock, Object[] args, Callable<Object> superMethod) throws Exception {
// return superMethod.call();
// }
}