9
0
mirror of https://github.com/Xiao-MoMi/craft-engine.git synced 2025-12-19 23:19: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: settings:
resistance: 1200.0 resistance: 1200.0
burnable: false burnable: false
fluid-state: water
distance=2,persistent=false,waterlogged=true: distance=2,persistent=false,waterlogged=true:
appearance: "waterlogged" appearance: "waterlogged"
id: "{internal_id}" id: "{internal_id}"
settings: settings:
resistance: 1200.0 resistance: 1200.0
burnable: false burnable: false
fluid-state: water
distance=3,persistent=false,waterlogged=true: distance=3,persistent=false,waterlogged=true:
appearance: "waterlogged" appearance: "waterlogged"
id: "{internal_id}" id: "{internal_id}"
settings: settings:
resistance: 1200.0 resistance: 1200.0
burnable: false burnable: false
fluid-state: water
distance=4,persistent=false,waterlogged=true: distance=4,persistent=false,waterlogged=true:
appearance: "waterlogged" appearance: "waterlogged"
id: "{internal_id}" id: "{internal_id}"
settings: settings:
resistance: 1200.0 resistance: 1200.0
burnable: false burnable: false
fluid-state: water
distance=5,persistent=false,waterlogged=true: distance=5,persistent=false,waterlogged=true:
appearance: "waterlogged" appearance: "waterlogged"
id: "{internal_id}" id: "{internal_id}"
settings: settings:
resistance: 1200.0 resistance: 1200.0
burnable: false burnable: false
fluid-state: water
distance=6,persistent=false,waterlogged=true: distance=6,persistent=false,waterlogged=true:
appearance: "waterlogged" appearance: "waterlogged"
id: "{internal_id}" id: "{internal_id}"
settings: settings:
resistance: 1200.0 resistance: 1200.0
burnable: false burnable: false
fluid-state: water
distance=7,persistent=false,waterlogged=true: distance=7,persistent=false,waterlogged=true:
appearance: "waterlogged" appearance: "waterlogged"
id: "{internal_id}" id: "{internal_id}"
@@ -850,48 +856,56 @@ templates#block_states:
resistance: 1200.0 resistance: 1200.0
burnable: false burnable: false
is-randomly-ticking: true is-randomly-ticking: true
fluid-state: water
distance=1,persistent=true,waterlogged=true: distance=1,persistent=true,waterlogged=true:
appearance: "waterlogged" appearance: "waterlogged"
id: "{internal_id}" id: "{internal_id}"
settings: settings:
resistance: 1200.0 resistance: 1200.0
burnable: false burnable: false
fluid-state: water
distance=2,persistent=true,waterlogged=true: distance=2,persistent=true,waterlogged=true:
appearance: "waterlogged" appearance: "waterlogged"
id: "{internal_id}" id: "{internal_id}"
settings: settings:
resistance: 1200.0 resistance: 1200.0
burnable: false burnable: false
fluid-state: water
distance=3,persistent=true,waterlogged=true: distance=3,persistent=true,waterlogged=true:
appearance: "waterlogged" appearance: "waterlogged"
id: "{internal_id}" id: "{internal_id}"
settings: settings:
resistance: 1200.0 resistance: 1200.0
burnable: false burnable: false
fluid-state: water
distance=4,persistent=true,waterlogged=true: distance=4,persistent=true,waterlogged=true:
appearance: "waterlogged" appearance: "waterlogged"
id: "{internal_id}" id: "{internal_id}"
settings: settings:
resistance: 1200.0 resistance: 1200.0
burnable: false burnable: false
fluid-state: water
distance=5,persistent=true,waterlogged=true: distance=5,persistent=true,waterlogged=true:
appearance: "waterlogged" appearance: "waterlogged"
id: "{internal_id}" id: "{internal_id}"
settings: settings:
resistance: 1200.0 resistance: 1200.0
burnable: false burnable: false
fluid-state: water
distance=6,persistent=true,waterlogged=true: distance=6,persistent=true,waterlogged=true:
appearance: "waterlogged" appearance: "waterlogged"
id: "{internal_id}" id: "{internal_id}"
settings: settings:
resistance: 1200.0 resistance: 1200.0
burnable: false burnable: false
fluid-state: water
distance=7,persistent=true,waterlogged=true: distance=7,persistent=true,waterlogged=true:
appearance: "waterlogged" appearance: "waterlogged"
id: "{internal_id}" id: "{internal_id}"
settings: settings:
resistance: 1200.0 resistance: 1200.0
burnable: false burnable: false
fluid-state: water
# recipes # recipes
templates#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())); Reflections.field$BlockBehaviour$soundType.set(mcBlock, SoundUtils.toSoundType(settings.sounds()));
// init cache // init cache
Reflections.method$BlockStateBase$initCache.invoke(mcBlockState); 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 // set random tick later
BlockStateUtils.setIsRandomlyTicking(mcBlockState, settings.isRandomlyTicking()); BlockStateUtils.setIsRandomlyTicking(mcBlockState, settings.isRandomlyTicking());
// bind tags // 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 STRIPPABLE_BLOCK = Key.from("craftengine:strippable_block");
public static final Key SAPLING_BLOCK = Key.from("craftengine:sapling_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 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 final Key CONCRETE_POWDER_BLOCK = Key.from("craftengine:concrete_powder_block");
public static void init() { public static void init() {
@@ -21,5 +22,6 @@ public class BukkitBlockBehaviors extends BlockBehaviors {
register(STRIPPABLE_BLOCK, StrippableBlockBehavior.FACTORY); register(STRIPPABLE_BLOCK, StrippableBlockBehavior.FACTORY);
register(SAPLING_BLOCK, SaplingBlockBehavior.FACTORY); register(SAPLING_BLOCK, SaplingBlockBehavior.FACTORY);
register(ON_LIQUID_BLOCK, OnLiquidBlockBehavior.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) { public ConcretePowderBlockBehavior(float hurtAmount, int maxHurt) {
super(hurtAmount, 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.Map;
import java.util.concurrent.Callable; import java.util.concurrent.Callable;
public class LeavesBlockBehavior extends BlockBehavior { public class LeavesBlockBehavior extends WaterLoggedBlockBehavior {
public static final Factory FACTORY = new Factory(); public static final Factory FACTORY = new Factory();
private static final Object LOG_TAG = BlockTags.getOrCreate(Key.of("minecraft", "logs")); private static final Object LOG_TAG = BlockTags.getOrCreate(Key.of("minecraft", "logs"));
private final int maxDistance; private final int maxDistance;
@@ -39,6 +39,7 @@ public class LeavesBlockBehavior extends BlockBehavior {
private final Property<Boolean> waterloggedProperty; private final Property<Boolean> waterloggedProperty;
public LeavesBlockBehavior(int maxDistance, Property<Integer> distanceProperty, Property<Boolean> persistentProperty, @Nullable Property<Boolean> waterloggedProperty) { public LeavesBlockBehavior(int maxDistance, Property<Integer> distanceProperty, Property<Boolean> persistentProperty, @Nullable Property<Boolean> waterloggedProperty) {
super(waterloggedProperty);
this.maxDistance = maxDistance; this.maxDistance = maxDistance;
this.distanceProperty = distanceProperty; this.distanceProperty = distanceProperty;
this.persistentProperty = persistentProperty; this.persistentProperty = persistentProperty;
@@ -183,13 +184,4 @@ public class LeavesBlockBehavior extends BlockBehavior {
return new LeavesBlockBehavior(actual, distance, persistent, waterlogged); 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<>(); List<Object> itemStacks = new ArrayList<>();
for (Holder<Key> holder : holders) { for (Holder<Key> holder : holders) {
ItemStack itemStack = BukkitItemManager.instance().getBuildableItem(holder.value()).get().buildItemStack(ItemBuildContext.EMPTY, 1); 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); itemStacks.add(nmsStack);
} }
return itemStacks; return itemStacks;
@@ -994,14 +994,14 @@ public class BukkitRecipeManager implements RecipeManager<ItemStack> {
toOptionalMinecraftIngredient(ceRecipe.template()), toOptionalMinecraftIngredient(ceRecipe.template()),
toOptionalMinecraftIngredient(ceRecipe.base()), toOptionalMinecraftIngredient(ceRecipe.base()),
toOptionalMinecraftIngredient(ceRecipe.addition()), 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()) { } else if (VersionHelper.isVersionNewerThan1_20_2()) {
return Reflections.constructor$SmithingTransformRecipe.newInstance( return Reflections.constructor$SmithingTransformRecipe.newInstance(
toMinecraftIngredient(ceRecipe.template()), toMinecraftIngredient(ceRecipe.template()),
toMinecraftIngredient(ceRecipe.base()), toMinecraftIngredient(ceRecipe.base()),
toMinecraftIngredient(ceRecipe.addition()), toMinecraftIngredient(ceRecipe.addition()),
Reflections.method$CraftItemStack$asNMSMirror.invoke(null, ceRecipe.result(ItemBuildContext.EMPTY)) Reflections.method$CraftItemStack$asNMSCopy.invoke(null, ceRecipe.result(ItemBuildContext.EMPTY))
); );
} else { } else {
return Reflections.constructor$SmithingTransformRecipe.newInstance( return Reflections.constructor$SmithingTransformRecipe.newInstance(
@@ -1009,7 +1009,7 @@ public class BukkitRecipeManager implements RecipeManager<ItemStack> {
toMinecraftIngredient(ceRecipe.template()), toMinecraftIngredient(ceRecipe.template()),
toMinecraftIngredient(ceRecipe.base()), toMinecraftIngredient(ceRecipe.base()),
toMinecraftIngredient(ceRecipe.addition()), 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( Optional<Object> optionalMCRecipe = (Optional<Object>) Reflections.method$RecipeManager$getRecipeFor1.invoke(
BukkitRecipeManager.minecraftRecipeManager(), BukkitRecipeManager.minecraftRecipeManager(),
Reflections.instance$RecipeType$CAMPFIRE_COOKING, 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()), Reflections.field$CraftWorld$ServerLevel.get(event.getPlayer().getWorld()),
null null
); );

View File

@@ -50,7 +50,6 @@ import java.lang.reflect.Field;
import java.nio.file.Path; import java.nio.file.Path;
import java.util.List; import java.util.List;
import java.util.Optional; import java.util.Optional;
import java.util.concurrent.TimeUnit;
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public class BukkitCraftEngine extends CraftEngine { public class BukkitCraftEngine extends CraftEngine {

View File

@@ -183,6 +183,7 @@ public class BukkitInjector {
// should always implement this interface // should always implement this interface
.implement(Reflections.clazz$Fallable) .implement(Reflections.clazz$Fallable)
.implement(Reflections.clazz$BonemealableBlock) .implement(Reflections.clazz$BonemealableBlock)
// TODO .implement(Reflections.clazz$SimpleWaterloggedBlock)
// internal interfaces // internal interfaces
.implement(BehaviorHolder.class) .implement(BehaviorHolder.class)
.implement(ShapeHolder.class) .implement(ShapeHolder.class)
@@ -208,6 +209,15 @@ public class BukkitInjector {
// performBoneMeal // performBoneMeal
.method(ElementMatchers.is(Reflections.method$BonemealableBlock$performBonemeal)) .method(ElementMatchers.is(Reflections.method$BonemealableBlock$performBonemeal))
.intercept(MethodDelegation.to(PerformBoneMealInterceptor.INSTANCE)) .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 // random tick
.method(ElementMatchers.is(Reflections.method$BlockBehaviour$randomTick)) .method(ElementMatchers.is(Reflections.method$BlockBehaviour$randomTick))
.intercept(MethodDelegation.to(RandomTickInterceptor.INSTANCE)) .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.takesArgument(1, Reflections.clazz$LevelReader).or(ElementMatchers.takesArgument(1, Reflections.clazz$Direction)))
.and(ElementMatchers.named("updateShape").or(ElementMatchers.named("a")))) .and(ElementMatchers.named("updateShape").or(ElementMatchers.named("a"))))
.intercept(MethodDelegation.to(UpdateShapeInterceptor.INSTANCE)) .intercept(MethodDelegation.to(UpdateShapeInterceptor.INSTANCE))
// getFluidState // // getFluidState
.method(ElementMatchers.returns(Reflections.clazz$FluidState) // .method(ElementMatchers.returns(Reflections.clazz$FluidState)
.and(ElementMatchers.takesArgument(0, Reflections.clazz$BlockState))) // .and(ElementMatchers.takesArgument(0, Reflections.clazz$BlockState)))
.intercept(MethodDelegation.to(FluidStateInterceptor.INSTANCE)); // .intercept(MethodDelegation.to(FluidStateInterceptor.INSTANCE))
;
clazz$CraftEngineBlock = builder.make().load(BukkitInjector.class.getClassLoader()).getLoaded(); clazz$CraftEngineBlock = builder.make().load(BukkitInjector.class.getClassLoader()).getLoaded();
constructor$CraftEngineBlock = MethodHandles.publicLookup().in(clazz$CraftEngineBlock) constructor$CraftEngineBlock = MethodHandles.publicLookup().in(clazz$CraftEngineBlock)
@@ -647,20 +658,21 @@ public class BukkitInjector {
return newBlockInstance; return newBlockInstance;
} }
public static class FluidStateInterceptor { //
public static final FluidStateInterceptor INSTANCE = new FluidStateInterceptor(); // 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) { // @RuntimeType
ObjectHolder<BlockBehavior> holder = ((BehaviorHolder) thisObj).getBehaviorHolder(); // public Object intercept(@This Object thisObj, @AllArguments Object[] args, @SuperCall Callable<Object> superMethod) {
try { // ObjectHolder<BlockBehavior> holder = ((BehaviorHolder) thisObj).getBehaviorHolder();
return holder.value().getFluidState(thisObj, args, superMethod); // try {
} catch (Exception e) { // return holder.value().getFluidState(thisObj, args, superMethod);
CraftEngine.instance().logger().severe("Failed to run getFluidState", e); // } catch (Exception e) {
return args[0]; // CraftEngine.instance().logger().severe("Failed to run getFluidState", e);
} // return args[0];
} // }
} // }
// }
public static class UpdateShapeInterceptor { public static class UpdateShapeInterceptor {
public static final UpdateShapeInterceptor INSTANCE = new 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.InvocationTargetException;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.util.*; import java.util.*;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.BiConsumer; import java.util.function.BiConsumer;
import java.util.function.Consumer; import java.util.function.Consumer;
@@ -516,7 +514,7 @@ public class PacketConsumers {
} }
assert Reflections.method$ServerGamePacketListenerImpl$tryPickItem != null; assert Reflections.method$ServerGamePacketListenerImpl$tryPickItem != null;
Reflections.method$ServerGamePacketListenerImpl$tryPickItem.invoke( 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) -> { 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( public static final Method method$CraftBlockData$createData = requireNonNull(
ReflectionUtils.getStaticMethod( 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( public static final Method method$CraftBlockData$fromData = requireNonNull(
ReflectionUtils.getStaticMethod( 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( public static final Field field$BlockStateBase$pushReaction = requireNonNull(
ReflectionUtils.getDeclaredField( ReflectionUtils.getDeclaredField(
clazz$BlockStateBase, clazz$PushReaction, 0 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( public static final Field field$ServerboundSetCreativeModeSlotPacket$itemStack = requireNonNull(
ReflectionUtils.getDeclaredField( ReflectionUtils.getDeclaredField(
clazz$ServerboundSetCreativeModeSlotPacket, clazz$ItemStack, 0 clazz$ServerboundSetCreativeModeSlotPacket, clazz$ItemStack, 0
@@ -3176,13 +3196,13 @@ public class Reflections {
public static final Method method$CraftItemStack$asCraftMirror = requireNonNull( public static final Method method$CraftItemStack$asCraftMirror = requireNonNull(
ReflectionUtils.getStaticMethod( 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( 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$AIR;
public static final Object instance$Items$WATER_BUCKET;
public static final Object instance$ItemStack$Air; public static final Object instance$ItemStack$Air;
static { static {
@@ -3659,6 +3680,8 @@ public class Reflections {
Object air = method$ResourceLocation$fromNamespaceAndPath.invoke(null, "minecraft", "air"); Object air = method$ResourceLocation$fromNamespaceAndPath.invoke(null, "minecraft", "air");
instance$Items$AIR = method$Registry$get.invoke(Reflections.instance$BuiltInRegistries$ITEM, air); instance$Items$AIR = method$Registry$get.invoke(Reflections.instance$BuiltInRegistries$ITEM, air);
instance$ItemStack$Air = constructor$ItemStack.newInstance(instance$Items$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) { } catch (ReflectiveOperationException e) {
throw new RuntimeException(e); throw new RuntimeException(e);
} }
@@ -5293,4 +5316,59 @@ public class Reflections {
clazz$ServerboundEditBookPacket, int.class, List.class, Optional.class 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; 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.pack.model.generation.AbstractModelGenerator;
import net.momirealms.craftengine.core.plugin.CraftEngine; 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 { public abstract class AbstractBlockManager extends AbstractModelGenerator implements BlockManager {

View File

@@ -15,6 +15,7 @@ public class BlockSettings {
float hardness = 2f; float hardness = 2f;
float resistance = 2f; float resistance = 2f;
boolean canOcclude; boolean canOcclude;
boolean fluidState;
Tristate isRedstoneConductor = Tristate.UNDEFINED; Tristate isRedstoneConductor = Tristate.UNDEFINED;
Tristate isSuffocating = Tristate.UNDEFINED; Tristate isSuffocating = Tristate.UNDEFINED;
Tristate isViewBlocking = Tristate.UNDEFINED; Tristate isViewBlocking = Tristate.UNDEFINED;
@@ -75,6 +76,7 @@ public class BlockSettings {
newSettings.isSuffocating = settings.isSuffocating; newSettings.isSuffocating = settings.isSuffocating;
newSettings.isViewBlocking = settings.isViewBlocking; newSettings.isViewBlocking = settings.isViewBlocking;
newSettings.correctTools = settings.correctTools; newSettings.correctTools = settings.correctTools;
newSettings.fluidState = settings.fluidState;
return newSettings; return newSettings;
} }
@@ -94,6 +96,10 @@ public class BlockSettings {
return resistance; return resistance;
} }
public boolean fluidState() {
return fluidState;
}
public boolean isRandomlyTicking() { public boolean isRandomlyTicking() {
return isRandomlyTicking; return isRandomlyTicking;
} }
@@ -250,6 +256,11 @@ public class BlockSettings {
return this; return this;
} }
public BlockSettings fluidState(boolean state) {
this.fluidState = state;
return this;
}
public interface Modifier { public interface Modifier {
void apply(BlockSettings settings); void apply(BlockSettings settings);
@@ -332,6 +343,10 @@ public class BlockSettings {
Map<String, Object> soundMap = MiscUtils.castToMap(value, false); Map<String, Object> soundMap = MiscUtils.castToMap(value, false);
return settings -> settings.sounds(BlockSounds.fromMap(soundMap)); 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 -> { registerFactory("can-occlude", (value -> {
boolean booleanValue = (boolean) value; boolean booleanValue = (boolean) value;
return settings -> settings.canOcclude(booleanValue); 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.block.BlockManager;
import net.momirealms.craftengine.core.entity.furniture.FurnitureManager; import net.momirealms.craftengine.core.entity.furniture.FurnitureManager;
import net.momirealms.craftengine.core.font.ImageManager; 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.ItemManager;
import net.momirealms.craftengine.core.item.recipe.RecipeManager; import net.momirealms.craftengine.core.item.recipe.RecipeManager;
import net.momirealms.craftengine.core.loot.VanillaLootManager; 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); Class<?> modClazz = ReflectionUtils.getClazz(CraftEngine.MOD_CLASS);
if (modClazz != null) { 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 { try {
assert setMaxChainMethod != null; assert setMaxChainMethod != null;
setMaxChainMethod.invoke(null, performance$max_block_chain_update_limit); setMaxChainMethod.invoke(null, performance$max_block_chain_update_limit);

View File

@@ -321,7 +321,7 @@ public class ReflectionUtils {
} }
@Nullable @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: outer:
for (Method method : clazz.getMethods()) { for (Method method : clazz.getMethods()) {
if (method.getParameterCount() != parameterTypes.length) { 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.BonemealableBlock;
import net.minecraft.world.level.block.Fallable; import net.minecraft.world.level.block.Fallable;
import net.minecraft.world.level.block.state.BlockState; 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.CollisionContext;
import net.minecraft.world.phys.shapes.VoxelShape; import net.minecraft.world.phys.shapes.VoxelShape;
import net.momirealms.craftengine.mod.util.NoteBlockUtils; import net.momirealms.craftengine.mod.util.NoteBlockUtils;
@@ -23,7 +22,11 @@ import net.momirealms.craftengine.shared.ObjectHolder;
import net.momirealms.craftengine.shared.block.*; import net.momirealms.craftengine.shared.block.*;
import org.jetbrains.annotations.NotNull; 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 static final StoneBlockShape STONE = new StoneBlockShape(Blocks.STONE.defaultBlockState());
private boolean isNoteBlock; private boolean isNoteBlock;
public ObjectHolder<BlockBehavior> behaviorHolder; public ObjectHolder<BlockBehavior> behaviorHolder;
@@ -168,15 +171,15 @@ public class CraftEngineBlock extends Block implements BehaviorHolder, ShapeHold
} }
} }
@Override // @Override
protected @NotNull FluidState getFluidState(@NotNull BlockState state) { // protected @NotNull FluidState getFluidState(@NotNull BlockState state) {
try { // try {
return (FluidState) behaviorHolder.value().getFluidState(this, new Object[]{state}, () -> super.getFluidState(state)); // return (FluidState) behaviorHolder.value().getFluidState(this, new Object[]{state}, () -> super.getFluidState(state));
} catch (Exception e) { // } catch (Exception e) {
e.printStackTrace(); // e.printStackTrace();
return super.getFluidState(state); // return super.getFluidState(state);
} // }
} // }
@Override @Override
public boolean isValidBonemealTarget(@NotNull LevelReader levelReader, @NotNull BlockPos blockPos, @NotNull BlockState blockState) { 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(); 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(); 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 { public void tick(Object thisBlock, Object[] args, Callable<Object> superMethod) throws Exception {
superMethod.call(); superMethod.call();
} }
@@ -48,4 +44,20 @@ public abstract class BlockBehavior {
public Object updateStateForPlacement(Object context, Object state) { public Object updateStateForPlacement(Object context, Object state) {
return 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();
// }
} }