mirror of
https://github.com/Xiao-MoMi/craft-engine.git
synced 2025-12-25 18:09:27 +00:00
@@ -97,7 +97,7 @@ public class DoorBlockBehavior extends AbstractCanSurviveBlockBehavior {
|
||||
ImmutableBlockState immutableBlockState = BukkitBlockManager.instance().getImmutableBlockState(stateId);
|
||||
if (immutableBlockState == null || immutableBlockState.isEmpty()) return blockState;
|
||||
DoubleBlockHalf half = immutableBlockState.get(this.halfProperty);
|
||||
Object direction = VersionHelper.isOrAbove1_21_2() ? args[4] : args[0];
|
||||
Object direction = VersionHelper.isOrAbove1_21_2() ? args[4] : args[1];
|
||||
if (DirectionUtils.isYAxis(direction) && half == DoubleBlockHalf.LOWER == (direction == CoreReflections.instance$Direction$UP)) {
|
||||
ImmutableBlockState neighborState = BukkitBlockManager.instance().getImmutableBlockState(BlockStateUtils.blockStateToId(VersionHelper.isOrAbove1_21_2() ? args[6] : args[2]));
|
||||
if (neighborState == null || neighborState.isEmpty()) {
|
||||
|
||||
@@ -93,7 +93,7 @@ public class FenceGateBlockBehavior extends BukkitBlockBehavior {
|
||||
@Override
|
||||
public Object updateShape(Object thisBlock, Object[] args, Callable<Object> superMethod) throws Exception {
|
||||
Object blockState = args[0];
|
||||
Direction direction = DirectionUtils.fromNMSDirection(VersionHelper.isOrAbove1_21_2() ? args[4] : args[0]);
|
||||
Direction direction = DirectionUtils.fromNMSDirection(VersionHelper.isOrAbove1_21_2() ? args[4] : args[1]);
|
||||
ImmutableBlockState state = BukkitBlockManager.instance().getImmutableBlockState(BlockStateUtils.blockStateToId(blockState));
|
||||
if (state == null || state.isEmpty()) return blockState;
|
||||
if (state.get(this.facingProperty).toDirection().clockWise().axis() != direction.axis()) {
|
||||
|
||||
@@ -1,20 +1,169 @@
|
||||
package net.momirealms.craftengine.bukkit.block.behavior;
|
||||
|
||||
import net.momirealms.craftengine.bukkit.block.BukkitBlockManager;
|
||||
import net.momirealms.craftengine.bukkit.nms.FastNMS;
|
||||
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.CoreReflections;
|
||||
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MBlocks;
|
||||
import net.momirealms.craftengine.bukkit.util.BlockStateUtils;
|
||||
import net.momirealms.craftengine.bukkit.util.DirectionUtils;
|
||||
import net.momirealms.craftengine.bukkit.util.LocationUtils;
|
||||
import net.momirealms.craftengine.bukkit.world.BukkitWorldManager;
|
||||
import net.momirealms.craftengine.core.block.BlockBehavior;
|
||||
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.sound.SoundData;
|
||||
import net.momirealms.craftengine.core.util.Direction;
|
||||
import net.momirealms.craftengine.core.util.PressurePlateSensitivity;
|
||||
import net.momirealms.craftengine.core.util.ResourceConfigUtils;
|
||||
import net.momirealms.craftengine.core.util.VersionHelper;
|
||||
import net.momirealms.craftengine.core.world.World;
|
||||
import org.bukkit.GameEvent;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
public class PressurePlateBlockBehavior extends BukkitBlockBehavior {
|
||||
public static final Factory FACTORY = new Factory();
|
||||
private final Property<Boolean> poweredProperty;
|
||||
private final SoundData onSound;
|
||||
private final SoundData offSound;
|
||||
private final PressurePlateSensitivity pressurePlateSensitivity;
|
||||
|
||||
public PressurePlateBlockBehavior(CustomBlock block, Property<Boolean> poweredProperty) {
|
||||
public PressurePlateBlockBehavior(
|
||||
CustomBlock block,
|
||||
Property<Boolean> poweredProperty,
|
||||
SoundData onSound,
|
||||
SoundData offSound,
|
||||
PressurePlateSensitivity pressurePlateSensitivity
|
||||
) {
|
||||
super(block);
|
||||
this.poweredProperty = poweredProperty;
|
||||
this.onSound = onSound;
|
||||
this.offSound = offSound;
|
||||
this.pressurePlateSensitivity = pressurePlateSensitivity;
|
||||
}
|
||||
|
||||
public Object updateShape(Object thisBlock, Object[] args, Callable<Object> superMethod) throws Exception {
|
||||
Object state = args[0];
|
||||
Object level;
|
||||
Object blockPos;
|
||||
if (VersionHelper.isOrAbove1_21_2()) {
|
||||
level = args[1];
|
||||
blockPos = args[3];
|
||||
} else {
|
||||
level = args[3];
|
||||
blockPos = args[4];
|
||||
}
|
||||
Direction direction = DirectionUtils.fromNMSDirection(VersionHelper.isOrAbove1_21_2() ? args[4] : args[1]);
|
||||
return direction == Direction.DOWN && !FastNMS.INSTANCE.method$BlockStateBase$canSurvive(state, level, blockPos)
|
||||
? MBlocks.AIR$defaultState
|
||||
: superMethod.call();
|
||||
}
|
||||
|
||||
public boolean canSurvive(Object thisBlock, Object[] args, Callable<Object> superMethod) throws Exception {
|
||||
Object blockPos = LocationUtils.below(args[2]);
|
||||
Object level = args[1];
|
||||
return FastNMS.INSTANCE.method$Block$canSupportRigidBlock(level, blockPos)
|
||||
|| FastNMS.INSTANCE.method$Block$canSupportCenter(level, blockPos, CoreReflections.instance$Direction$UP);
|
||||
}
|
||||
|
||||
public void tick(Object thisBlock, Object[] args, Callable<Object> superMethod) throws Exception {
|
||||
Object state = args[0];
|
||||
int signalForState = this.getSignalForState(state);
|
||||
if (signalForState > 0) {
|
||||
this.checkPressed(null, args[1], args[2], state, signalForState, thisBlock);
|
||||
}
|
||||
}
|
||||
|
||||
public void entityInside(Object thisBlock, Object[] args, Callable<Object> superMethod) {
|
||||
Object state = args[0];
|
||||
int signalForState = this.getSignalForState(state);
|
||||
if (signalForState == 0) {
|
||||
this.checkPressed(args[3], args[1], args[2], state, signalForState, thisBlock);
|
||||
}
|
||||
}
|
||||
|
||||
protected int getSignalStrength(Object level, Object pos) {
|
||||
Class<?> clazz = switch (this.pressurePlateSensitivity) {
|
||||
case EVERYTHING -> CoreReflections.clazz$Entity;
|
||||
case MOBS -> CoreReflections.clazz$LivingEntity;
|
||||
};
|
||||
Object box = FastNMS.INSTANCE.method$AABB$move(CoreReflections.instance$BasePressurePlateBlock$TOUCH_AABB, pos);
|
||||
return FastNMS.INSTANCE.method$BasePressurePlateBlock$getEntityCount(level, box, clazz) > 0 ? 15 : 0;
|
||||
}
|
||||
|
||||
private Object setSignalForState(Object state, int strength) {
|
||||
ImmutableBlockState blockState = BukkitBlockManager.instance().getImmutableBlockState(BlockStateUtils.blockStateToId(state));
|
||||
if (blockState == null || blockState.isEmpty()) return state;
|
||||
return blockState.with(this.poweredProperty, strength > 0).customBlockState().handle();
|
||||
}
|
||||
|
||||
private void checkPressed(@Nullable Object entity, Object level, Object pos, Object state, int currentSignal, Object thisBlock) {
|
||||
int signalStrength = this.getSignalStrength(level, pos);
|
||||
boolean flag = currentSignal > 0;
|
||||
boolean flag1 = signalStrength > 0;
|
||||
if (currentSignal != signalStrength) {
|
||||
Object blockState = this.setSignalForState(state, signalStrength);
|
||||
FastNMS.INSTANCE.method$LevelWriter$setBlock(level, pos, blockState, 2);
|
||||
this.updateNeighbours(level, pos, thisBlock);
|
||||
FastNMS.INSTANCE.method$Level$setBlocksDirty(level, pos, state, blockState);
|
||||
}
|
||||
|
||||
if (!flag1 && flag) {
|
||||
World world = BukkitWorldManager.instance().getWorld(FastNMS.INSTANCE.method$Level$getCraftWorld(level)).world();
|
||||
world.playBlockSound(LocationUtils.toVec3d(LocationUtils.fromBlockPos(pos)), this.offSound);
|
||||
FastNMS.INSTANCE.method$Level$getCraftWorld(level).sendGameEvent(FastNMS.INSTANCE.method$Entity$getBukkitEntity(entity),
|
||||
GameEvent.BLOCK_DEACTIVATE,
|
||||
new Vector(FastNMS.INSTANCE.field$Vec3i$x(pos), FastNMS.INSTANCE.field$Vec3i$y(pos), FastNMS.INSTANCE.field$Vec3i$z(pos))
|
||||
);
|
||||
} else if (flag1 && !flag) {
|
||||
World world = BukkitWorldManager.instance().getWorld(FastNMS.INSTANCE.method$Level$getCraftWorld(level)).world();
|
||||
world.playBlockSound(LocationUtils.toVec3d(LocationUtils.fromBlockPos(pos)), this.onSound);
|
||||
FastNMS.INSTANCE.method$Level$getCraftWorld(level).sendGameEvent(FastNMS.INSTANCE.method$Entity$getBukkitEntity(entity),
|
||||
GameEvent.BLOCK_ACTIVATE,
|
||||
new Vector(FastNMS.INSTANCE.field$Vec3i$x(pos), FastNMS.INSTANCE.field$Vec3i$y(pos), FastNMS.INSTANCE.field$Vec3i$z(pos))
|
||||
);
|
||||
}
|
||||
|
||||
if (flag1) {
|
||||
FastNMS.INSTANCE.method$LevelAccessor$scheduleBlockTick(level, pos, thisBlock, 20);
|
||||
}
|
||||
}
|
||||
|
||||
public void affectNeighborsAfterRemoval(Object thisBlock, Object[] args, Callable<Object> superMethod) {
|
||||
boolean movedByPiston = (boolean) args[3];
|
||||
if (!movedByPiston && this.getSignalForState(args[0]) > 0) {
|
||||
this.updateNeighbours(args[1], args[2], thisBlock);
|
||||
}
|
||||
}
|
||||
|
||||
private void updateNeighbours(Object level, Object pos, Object thisBlock) {
|
||||
FastNMS.INSTANCE.method$Level$updateNeighborsAt(level, pos, thisBlock);
|
||||
FastNMS.INSTANCE.method$Level$updateNeighborsAt(level, LocationUtils.below(pos), thisBlock);
|
||||
}
|
||||
|
||||
public int getSignal(Object thisBlock, Object[] args, Callable<Object> superMethod) {
|
||||
return this.getSignalForState(args[0]);
|
||||
}
|
||||
|
||||
private int getSignalForState(Object state) {
|
||||
ImmutableBlockState blockState = BukkitBlockManager.instance().getImmutableBlockState(BlockStateUtils.blockStateToId(state));
|
||||
if (blockState == null || blockState.isEmpty()) return 0;
|
||||
return blockState.get(this.poweredProperty) ? 15 : 0;
|
||||
}
|
||||
|
||||
public int getDirectSignal(Object thisBlock, Object[] args, Callable<Object> superMethod) {
|
||||
Direction direction = DirectionUtils.fromNMSDirection(args[3]);
|
||||
return direction == Direction.UP ? this.getSignalForState(args[0]) : 0;
|
||||
}
|
||||
|
||||
public boolean isSignalSource(Object thisBlock, Object[] args, Callable<Object> superMethod) {
|
||||
return true;
|
||||
}
|
||||
|
||||
public static class Factory implements BlockBehaviorFactory {
|
||||
@@ -23,7 +172,15 @@ public class PressurePlateBlockBehavior extends BukkitBlockBehavior {
|
||||
@Override
|
||||
public BlockBehavior create(CustomBlock block, Map<String, Object> arguments) {
|
||||
Property<Boolean> powered = (Property<Boolean>) ResourceConfigUtils.requireNonNullOrThrow(block.getProperty("powered"), "warning.config.block.behavior.pressure_plate.missing_powered");
|
||||
return new PressurePlateBlockBehavior(block, powered);
|
||||
PressurePlateSensitivity pressurePlateSensitivity = PressurePlateSensitivity.byName(arguments.getOrDefault("pressure-plate-sensitivity", "everything").toString());
|
||||
Map<String, Object> sounds = (Map<String, Object>) arguments.get("sounds");
|
||||
SoundData onSound = null;
|
||||
SoundData offSound = null;
|
||||
if (sounds != null) {
|
||||
onSound = Optional.ofNullable(sounds.get("on")).map(obj -> SoundData.create(obj, SoundData.SoundValue.FIXED_1, SoundData.SoundValue.ranged(0.9f, 1f))).orElse(null);
|
||||
offSound = Optional.ofNullable(sounds.get("off")).map(obj -> SoundData.create(obj, SoundData.SoundValue.FIXED_1, SoundData.SoundValue.ranged(0.9f, 1f))).orElse(null);
|
||||
}
|
||||
return new PressurePlateBlockBehavior(block, powered, onSound, offSound, pressurePlateSensitivity);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -70,7 +70,7 @@ public class StairsBlockBehavior extends BukkitBlockBehavior {
|
||||
if (super.waterloggedProperty != null && immutableBlockState.get(this.waterloggedProperty)) {
|
||||
FastNMS.INSTANCE.method$LevelAccessor$scheduleFluidTick(VersionHelper.isOrAbove1_21_2() ? args[2] : args[3], VersionHelper.isOrAbove1_21_2() ? args[3] : args[4], MFluids.WATER, 5);
|
||||
}
|
||||
Direction direction = DirectionUtils.fromNMSDirection(VersionHelper.isOrAbove1_21_2() ? args[4] : args[0]);
|
||||
Direction direction = DirectionUtils.fromNMSDirection(VersionHelper.isOrAbove1_21_2() ? args[4] : args[1]);
|
||||
StairsShape stairsShape = getStairsShape(immutableBlockState, level, LocationUtils.fromBlockPos(blockPos));
|
||||
return direction.axis().isHorizontal()
|
||||
? immutableBlockState.with(this.shapeProperty, stairsShape).customBlockState().handle()
|
||||
|
||||
@@ -3480,4 +3480,27 @@ public final class CoreReflections {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static final Class<?> clazz$BasePressurePlateBlock = requireNonNull(
|
||||
BukkitReflectionUtils.findReobfOrMojmapClass(
|
||||
"world.level.block.BlockPressurePlateAbstract",
|
||||
"world.level.block.BasePressurePlateBlock"
|
||||
)
|
||||
);
|
||||
|
||||
public static final Field field$BasePressurePlateBlock$TOUCH_AABB = requireNonNull(
|
||||
ReflectionUtils.getDeclaredField(
|
||||
clazz$BasePressurePlateBlock, clazz$AABB, 0
|
||||
)
|
||||
);
|
||||
|
||||
public static final Object instance$BasePressurePlateBlock$TOUCH_AABB;
|
||||
|
||||
static {
|
||||
try {
|
||||
instance$BasePressurePlateBlock$TOUCH_AABB = requireNonNull(field$BasePressurePlateBlock$TOUCH_AABB.get(null));
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -61,6 +61,10 @@ public class LocationUtils {
|
||||
);
|
||||
}
|
||||
|
||||
public static Vec3d toVec3d(BlockPos pos) {
|
||||
return new Vec3d(pos.x(), pos.y(), pos.z());
|
||||
}
|
||||
|
||||
public static double getDistance(Location location1, Location location2) {
|
||||
return Math.sqrt(Math.pow(location2.getX() - location1.getX(), 2) +
|
||||
Math.pow(location2.getY() - location1.getY(), 2) +
|
||||
|
||||
@@ -598,6 +598,10 @@ items:
|
||||
- minecraft:pressure_plates
|
||||
behaviors:
|
||||
type: pressure_plate_block
|
||||
pressure-plate-sensitivity: all
|
||||
sounds:
|
||||
on: minecraft:block.wooden_pressure_plate.click_on
|
||||
off: minecraft:block.wooden_pressure_plate.click_off
|
||||
states:
|
||||
template: default:block_state/pressure_plate
|
||||
arguments:
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
package net.momirealms.craftengine.core.util;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
public enum PressurePlateSensitivity {
|
||||
EVERYTHING("everything", "all"),
|
||||
MOBS("mobs", "mob");
|
||||
|
||||
private final String[] names;
|
||||
|
||||
PressurePlateSensitivity(String... names) {
|
||||
this.names = names;
|
||||
}
|
||||
|
||||
public String[] names() {
|
||||
return names;
|
||||
}
|
||||
|
||||
private static final Map<String, PressurePlateSensitivity> BY_NAME = new HashMap<>();
|
||||
|
||||
static {
|
||||
for (PressurePlateSensitivity trigger : PressurePlateSensitivity.values()) {
|
||||
for (String name : trigger.names()) {
|
||||
BY_NAME.put(name, trigger);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static PressurePlateSensitivity byName(String name) {
|
||||
return Optional.ofNullable(BY_NAME.get(name)).orElseThrow(() -> new IllegalArgumentException("PressurePlateSensitivity not found: " + name));
|
||||
}
|
||||
}
|
||||
@@ -51,7 +51,7 @@ byte_buddy_version=1.17.5
|
||||
ahocorasick_version=0.6.3
|
||||
snake_yaml_version=2.4
|
||||
anti_grief_version=0.17
|
||||
nms_helper_version=0.67.27
|
||||
nms_helper_version=0.67.31
|
||||
evalex_version=3.5.0
|
||||
reactive_streams_version=1.0.4
|
||||
amazon_awssdk_version=2.31.23
|
||||
|
||||
Reference in New Issue
Block a user