9
0
mirror of https://github.com/Xiao-MoMi/craft-engine.git synced 2025-12-29 20:09:13 +00:00

feat(bukkit): 改进 LampBlockBehavior

This commit is contained in:
jhqwqmc
2025-09-07 08:08:11 +08:00
parent ff4efa13a0
commit 76e1e66308
10 changed files with 94 additions and 16 deletions

View File

@@ -1,6 +1,7 @@
package net.momirealms.craftengine.bukkit.block.behavior;
import net.momirealms.craftengine.bukkit.nms.FastNMS;
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.CoreReflections;
import net.momirealms.craftengine.bukkit.util.BlockStateUtils;
import net.momirealms.craftengine.bukkit.util.LocationUtils;
import net.momirealms.craftengine.core.block.BlockBehavior;
@@ -8,7 +9,9 @@ import net.momirealms.craftengine.core.block.CustomBlock;
import net.momirealms.craftengine.core.block.ImmutableBlockState;
import net.momirealms.craftengine.core.block.behavior.BlockBehaviorFactory;
import net.momirealms.craftengine.core.block.properties.Property;
import net.momirealms.craftengine.core.entity.player.InteractionResult;
import net.momirealms.craftengine.core.item.context.BlockPlaceContext;
import net.momirealms.craftengine.core.item.context.UseOnContext;
import net.momirealms.craftengine.core.util.ResourceConfigUtils;
import java.util.Map;
@@ -19,44 +22,89 @@ import java.util.concurrent.Callable;
public class LampBlockBehavior extends BukkitBlockBehavior {
public static final Factory FACTORY = new Factory();
private final Property<Boolean> litProperty;
private final Property<Boolean> poweredProperty;
private final boolean canOpenWithHand;
private final boolean redstoneToggleMode;
public LampBlockBehavior(CustomBlock block, Property<Boolean> litProperty) {
public LampBlockBehavior(CustomBlock block, Property<Boolean> litProperty, Property<Boolean> poweredProperty, boolean canOpenWithHand, boolean redstoneToggleMode) {
super(block);
this.litProperty = litProperty;
this.poweredProperty = poweredProperty;
this.canOpenWithHand = canOpenWithHand;
this.redstoneToggleMode = redstoneToggleMode;
}
@Override
public InteractionResult useWithoutItem(UseOnContext context, ImmutableBlockState state) {
if (!this.canOpenWithHand) {
return InteractionResult.PASS;
}
LampBlockBehavior behavior = state.behavior().getAs(LampBlockBehavior.class).orElse(null);
if (behavior == null) return InteractionResult.PASS;
FastNMS.INSTANCE.method$LevelWriter$setBlock(
context.getLevel().serverWorld(),
LocationUtils.toBlockPos(context.getClickedPos()),
state.cycle(behavior.litProperty).cycle(behavior.poweredProperty).customBlockState().literalObject(),
2
);
Optional.ofNullable(context.getPlayer()).ifPresent(p -> p.swingHand(context.getHand()));
return InteractionResult.SUCCESS_AND_CANCEL;
}
@Override
public ImmutableBlockState updateStateForPlacement(BlockPlaceContext context, ImmutableBlockState state) {
if (this.canOpenWithHand || this.redstoneToggleMode) return state;
Object level = context.getLevel().serverWorld();
state = state.with(this.litProperty, FastNMS.INSTANCE.method$SignalGetter$hasNeighborSignal(level, LocationUtils.toBlockPos(context.getClickedPos())));
state = state.with(this.poweredProperty, FastNMS.INSTANCE.method$SignalGetter$hasNeighborSignal(level, LocationUtils.toBlockPos(context.getClickedPos())));
return state;
}
@Override
public void tick(Object thisBlock, Object[] args, Callable<Object> superMethod) throws Exception {
Object blockState = args[0];
Object world = args[1];
if (this.canOpenWithHand || this.redstoneToggleMode || !CoreReflections.clazz$ServerLevel.isInstance(world)) return;
Optional<ImmutableBlockState> optionalCustomState = BlockStateUtils.getOptionalCustomBlockState(blockState);
if (optionalCustomState.isEmpty()) return;
Object world = args[1];
Object blockPos = args[2];
ImmutableBlockState customState = optionalCustomState.get();
if (customState.get(this.litProperty) && !FastNMS.INSTANCE.method$SignalGetter$hasNeighborSignal(world, blockPos)) {
if (FastNMS.INSTANCE.method$CraftEventFactory$callRedstoneChange(world, blockPos, 0, 15).getNewCurrent() != 15) {
return;
}
FastNMS.INSTANCE.method$LevelWriter$setBlock(world, blockPos, customState.cycle(this.litProperty).customBlockState().literalObject(), 2);
FastNMS.INSTANCE.method$LevelWriter$setBlock(world, blockPos, customState.cycle(this.litProperty).cycle(this.poweredProperty).customBlockState().literalObject(), 2);
}
}
@Override
public void onPlace(Object thisBlock, Object[] args, Callable<Object> superMethod) {
if (this.canOpenWithHand || !this.redstoneToggleMode) return;
Object state = args[0];
Object level = args[1];
Object pos = args[2];
Object oldState = args[3];
if (FastNMS.INSTANCE.method$BlockState$getBlock(oldState) != FastNMS.INSTANCE.method$BlockState$getBlock(state) && CoreReflections.clazz$ServerLevel.isInstance(level)) {
Optional<ImmutableBlockState> optionalCustomState = BlockStateUtils.getOptionalCustomBlockState(state);
if (optionalCustomState.isEmpty()) return;
checkAndFlip(optionalCustomState.get(), level, pos);
}
}
@Override
public void neighborChanged(Object thisBlock, Object[] args, Callable<Object> superMethod) {
Object blockState = args[0];
Object world = args[1];
if (this.canOpenWithHand || !CoreReflections.clazz$ServerLevel.isInstance(world)) return;
Optional<ImmutableBlockState> optionalCustomState = BlockStateUtils.getOptionalCustomBlockState(blockState);
if (optionalCustomState.isEmpty()) return;
Object world = args[1];
Object blockPos = args[2];
ImmutableBlockState customState = optionalCustomState.get();
boolean lit = customState.get(this.litProperty);
if (this.redstoneToggleMode) {
checkAndFlip(customState, world, blockPos);
return;
}
if (lit != FastNMS.INSTANCE.method$SignalGetter$hasNeighborSignal(world, blockPos)) {
if (lit) {
FastNMS.INSTANCE.method$ScheduledTickAccess$scheduleBlockTick(world, blockPos, thisBlock, 4);
@@ -64,17 +112,33 @@ public class LampBlockBehavior extends BukkitBlockBehavior {
if (FastNMS.INSTANCE.method$CraftEventFactory$callRedstoneChange(world, blockPos, 0, 15).getNewCurrent() != 15) {
return;
}
FastNMS.INSTANCE.method$LevelWriter$setBlock(world, blockPos, customState.cycle(this.litProperty).customBlockState().literalObject(), 2);
FastNMS.INSTANCE.method$LevelWriter$setBlock(world, blockPos, customState.cycle(this.litProperty).cycle(this.poweredProperty).customBlockState().literalObject(), 2);
}
}
}
private void checkAndFlip(ImmutableBlockState customState, Object level, Object pos) {
boolean hasNeighborSignal = FastNMS.INSTANCE.method$SignalGetter$hasNeighborSignal(level, pos);
boolean isPowered = customState.get(this.poweredProperty);
if (hasNeighborSignal != isPowered) {
ImmutableBlockState blockState = customState;
if (!isPowered) {
blockState = blockState.cycle(this.litProperty);
}
FastNMS.INSTANCE.method$LevelWriter$setBlock(level, pos, blockState.with(this.poweredProperty, hasNeighborSignal).customBlockState().literalObject(), 3);
}
}
@SuppressWarnings("unchecked")
public static class Factory implements BlockBehaviorFactory {
@Override
public BlockBehavior create(CustomBlock block, Map<String, Object> arguments) {
Property<Boolean> lit = (Property<Boolean>) ResourceConfigUtils.requireNonNullOrThrow(block.getProperty("lit"), "warning.config.block.behavior.lamp.missing_lit");
return new LampBlockBehavior(block, lit);
Property<Boolean> powered = (Property<Boolean>) ResourceConfigUtils.requireNonNullOrThrow(block.getProperty("powered"), "warning.config.block.behavior.lamp.missing_powered");
boolean canOpenWithHand = ResourceConfigUtils.getAsBoolean(arguments.getOrDefault("can-open-with-hand", false), "can-open-with-hand");
boolean redstoneToggleMode = !canOpenWithHand && ResourceConfigUtils.getAsBoolean(arguments.getOrDefault("redstone-toggle-mode", false), "redstone-toggle-mode");
return new LampBlockBehavior(block, lit, powered, canOpenWithHand, redstoneToggleMode);
}
}
}

View File

@@ -83,7 +83,7 @@ public class VerticalCropBlockBehavior extends BukkitBlockBehavior {
@SuppressWarnings("unchecked")
@Override
public BlockBehavior create(CustomBlock block, Map<String, Object> arguments) {
Property<Integer> ageProperty = (Property<Integer>) ResourceConfigUtils.requireNonNullOrThrow(block.getProperty("age"), "warning.config.block.behavior.sugar_cane.missing_age");
Property<Integer> ageProperty = (Property<Integer>) ResourceConfigUtils.requireNonNullOrThrow(block.getProperty("age"), "warning.config.block.behavior.vertical_crop.missing_age");
int maxHeight = ResourceConfigUtils.getAsInt(arguments.getOrDefault("max-height", 3), "max-height");
boolean direction = arguments.getOrDefault("direction", "up").toString().equalsIgnoreCase("up");
return new VerticalCropBlockBehavior(block, ageProperty, maxHeight,