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

再次优化

This commit is contained in:
XiaoMoMi
2025-06-28 04:43:46 +08:00
parent 72238b376b
commit 225cc7e067
30 changed files with 145 additions and 144 deletions

View File

@@ -20,7 +20,6 @@ import net.momirealms.craftengine.core.world.WorldEvents;
import net.momirealms.craftengine.core.world.WorldPosition;
import net.momirealms.sparrow.nbt.CompoundTag;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.SoundCategory;
import org.bukkit.block.Block;
import org.bukkit.block.data.BlockData;
@@ -131,22 +130,20 @@ public final class CraftEngineBlocks {
* @return success or not
*/
public static boolean remove(@NotNull Block block) {
if (!isCustomBlock(block)) return false;
block.setType(Material.AIR, true);
return true;
return remove(block, false);
}
/**
* Removes a block from the world if it's custom
*
* @param block block to remove
* @param applyPhysics whether to apply physics
* @param isMoving is moving
* @return success or not
*/
public static boolean remove(@NotNull Block block,
boolean applyPhysics) {
boolean isMoving) {
if (!isCustomBlock(block)) return false;
block.setType(Material.AIR, applyPhysics);
FastNMS.INSTANCE.method$Level$removeBlock(FastNMS.INSTANCE.field$CraftWorld$ServerLevel(block.getWorld()), LocationUtils.toBlockPos(block.getX(), block.getY(), block.getZ()), isMoving);
return true;
}
@@ -155,15 +152,15 @@ public final class CraftEngineBlocks {
*
* @param block block to remove
* @param player player who breaks the block
* @param applyPhysics whether to apply physics
* @param dropLoot whether to drop block loots
* @param isMoving is moving
* @param playSound whether to play break sounds
* @param sendParticles whether to send break particles
* @return success or not
*/
public static boolean remove(@NotNull Block block,
@Nullable Player player,
boolean applyPhysics,
boolean isMoving,
boolean dropLoot,
boolean playSound,
boolean sendParticles) {
@@ -189,7 +186,7 @@ public final class CraftEngineBlocks {
if (sendParticles) {
FastNMS.INSTANCE.method$Level$levelEvent(world.serverWorld(), WorldEvents.BLOCK_BREAK_EFFECT, LocationUtils.toBlockPos(location.getBlockX(), location.getBlockY(), location.getBlockZ()), state.customBlockState().registryId());
}
block.setType(Material.AIR, applyPhysics);
FastNMS.INSTANCE.method$Level$removeBlock(world.serverWorld(), LocationUtils.toBlockPos(location.getBlockX(), location.getBlockY(), location.getBlockZ()), isMoving);
return true;
}
@@ -200,9 +197,8 @@ public final class CraftEngineBlocks {
* @return is custom block or not
*/
public static boolean isCustomBlock(@NotNull Block block) {
BlockData blockData = block.getBlockData();
int stateId = BlockStateUtils.blockDataToId(blockData);
return !BlockStateUtils.isVanillaBlock(stateId);
Object state = FastNMS.INSTANCE.method$BlockGetter$getBlockState(FastNMS.INSTANCE.field$CraftWorld$ServerLevel(block.getWorld()), LocationUtils.toBlockPos(block.getX(), block.getY(), block.getZ()));
return BlockStateUtils.isCustomBlock(state);
}
/**
@@ -213,9 +209,8 @@ public final class CraftEngineBlocks {
*/
@Nullable
public static ImmutableBlockState getCustomBlockState(@NotNull Block block) {
BlockData blockData = block.getBlockData();
int stateId = BlockStateUtils.blockDataToId(blockData);
return BukkitBlockManager.instance().getImmutableBlockState(stateId);
Object state = FastNMS.INSTANCE.method$BlockGetter$getBlockState(FastNMS.INSTANCE.field$CraftWorld$ServerLevel(block.getWorld()), LocationUtils.toBlockPos(block.getX(), block.getY(), block.getZ()));
return BlockStateUtils.getOptionalCustomBlockState(state).orElse(null);
}
/**
@@ -226,8 +221,8 @@ public final class CraftEngineBlocks {
*/
@Nullable
public static ImmutableBlockState getCustomBlockState(@NotNull BlockData blockData) {
int stateId = BlockStateUtils.blockDataToId(blockData);
return BukkitBlockManager.instance().getImmutableBlockState(stateId);
Object state = BlockStateUtils.blockDataToBlockState(blockData);
return BlockStateUtils.getOptionalCustomBlockState(state).orElse(null);
}
/**

View File

@@ -218,11 +218,10 @@ public class BlockEventListener implements Listener {
@EventHandler(ignoreCancelled = true, priority = EventPriority.MONITOR)
public void onBlockBreakBlock(BlockBreakBlockEvent event) {
Block block = event.getBlock();
Object blockState = BlockStateUtils.blockDataToBlockState(block.getBlockData());
int stateId = BlockStateUtils.blockStateToId(blockState);
if (!BlockStateUtils.isVanillaBlock(stateId)) {
Object blockState = FastNMS.INSTANCE.method$BlockGetter$getBlockState(FastNMS.INSTANCE.field$CraftWorld$ServerLevel(block.getWorld()), LocationUtils.toBlockPos(block.getX(), block.getY(), block.getZ()));
if (BlockStateUtils.isVanillaBlock(blockState)) {
// override vanilla block loots
this.plugin.vanillaLootManager().getBlockLoot(stateId).ifPresent(it -> {
this.plugin.vanillaLootManager().getBlockLoot(BlockStateUtils.blockStateToId(blockState)).ifPresent(it -> {
if (it.override()) {
event.getDrops().clear();
event.setExpToDrop(0);
@@ -249,12 +248,12 @@ public class BlockEventListener implements Listener {
if (!(entity instanceof Player player)) return;
BlockPos pos = EntityUtils.getOnPos(player);
Block block = player.getWorld().getBlockAt(pos.x(), pos.y(), pos.z());
Object blockState = BlockStateUtils.blockDataToBlockState(block.getBlockData());
int stateId = BlockStateUtils.blockStateToId(blockState);
if (!BlockStateUtils.isVanillaBlock(stateId)) {
Object blockState = FastNMS.INSTANCE.method$BlockGetter$getBlockState(FastNMS.INSTANCE.field$CraftWorld$ServerLevel(block.getWorld()), LocationUtils.toBlockPos(block.getX(), block.getY(), block.getZ()));
Optional<ImmutableBlockState> optionalCustomState = BlockStateUtils.getOptionalCustomBlockState(blockState);
if (optionalCustomState.isPresent()) {
Location location = player.getLocation();
ImmutableBlockState state = manager.getImmutableBlockStateUnsafe(stateId);
Cancellable cancellable = Cancellable.dummy();
ImmutableBlockState state = optionalCustomState.get();
Cancellable cancellable = Cancellable.of(event::isCancelled, event::setCancelled);
state.owner().value().execute(PlayerOptionalContext.of(this.plugin.adapt(player), ContextHolder.builder()
.withParameter(DirectContextParameters.EVENT, cancellable)
.withParameter(DirectContextParameters.POSITION, new WorldPosition(new BukkitWorld(event.getWorld()), LocationUtils.toVec3d(location)))
@@ -262,19 +261,18 @@ public class BlockEventListener implements Listener {
.withParameter(DirectContextParameters.CUSTOM_BLOCK_STATE, state)
), EventTrigger.STEP);
if (cancellable.isCancelled()) {
event.setCancelled(true);
return;
}
player.playSound(location, state.sounds().stepSound().id().toString(), SoundCategory.BLOCKS, state.sounds().stepSound().volume().get(), state.sounds().stepSound().pitch().get());
} else if (Config.enableSoundSystem()) {
Object ownerBlock = BlockStateUtils.getBlockOwner(blockState);
if (manager.isBlockSoundRemoved(ownerBlock)) {
if (this.manager.isBlockSoundRemoved(ownerBlock)) {
try {
Object soundType = CoreReflections.field$BlockBehaviour$soundType.get(ownerBlock);
Object stepSound = CoreReflections.field$SoundType$stepSound.get(soundType);
player.playSound(player.getLocation(), FastNMS.INSTANCE.field$SoundEvent$location(stepSound).toString(), SoundCategory.BLOCKS, 0.15f, 1f);
} catch (ReflectiveOperationException e) {
plugin.logger().warn("Failed to get sound type", e);
this.plugin.logger().warn("Failed to get sound type", e);
}
}
}

View File

@@ -14,6 +14,9 @@ import org.bukkit.entity.FallingBlock;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import java.util.Optional;
@SuppressWarnings("DuplicatedCode")
public class FallingBlockRemoveListener implements Listener {
@EventHandler
@@ -24,21 +27,21 @@ public class FallingBlockRemoveListener implements Listener {
boolean cancelDrop = (boolean) CoreReflections.field$FallingBlockEntity$cancelDrop.get(fallingBlockEntity);
if (cancelDrop) return;
Object blockState = CoreReflections.field$FallingBlockEntity$blockState.get(fallingBlockEntity);
int stateId = BlockStateUtils.blockStateToId(blockState);
ImmutableBlockState immutableBlockState = BukkitBlockManager.instance().getImmutableBlockState(stateId);
if (immutableBlockState == null || immutableBlockState.isEmpty()) return;
Optional<ImmutableBlockState> optionalCustomState = BlockStateUtils.getOptionalCustomBlockState(blockState);
if (optionalCustomState.isEmpty()) return;
ImmutableBlockState customState = optionalCustomState.get();
net.momirealms.craftengine.core.world.World world = new BukkitWorld(fallingBlock.getWorld());
WorldPosition position = new WorldPosition(world, CoreReflections.field$Entity$xo.getDouble(fallingBlockEntity), CoreReflections.field$Entity$yo.getDouble(fallingBlockEntity), CoreReflections.field$Entity$zo.getDouble(fallingBlockEntity));
ContextHolder.Builder builder = ContextHolder.builder()
.withParameter(DirectContextParameters.FALLING_BLOCK, true)
.withParameter(DirectContextParameters.POSITION, position);
for (Item<Object> item : immutableBlockState.getDrops(builder, world, null)) {
for (Item<Object> item : customState.getDrops(builder, world, null)) {
world.dropItemNaturally(position, item);
}
Object entityData = CoreReflections.field$Entity$entityData.get(fallingBlockEntity);
boolean isSilent = (boolean) CoreReflections.method$SynchedEntityData$get.invoke(entityData, CoreReflections.instance$Entity$DATA_SILENT);
if (!isSilent) {
world.playBlockSound(position, immutableBlockState.sounds().destroySound());
world.playBlockSound(position, customState.sounds().destroySound());
}
} catch (ReflectiveOperationException e) {
CraftEngine.instance().logger().warn("Failed to handle EntityRemoveEvent", e);

View File

@@ -73,6 +73,7 @@ public class BushBlockBehavior extends AbstractCanSurviveBlockBehavior {
return new Tuple<>(mcTags, mcBlocks, customBlocks);
}
@SuppressWarnings("DuplicatedCode")
@Override
protected boolean canSurvive(Object thisBlock, Object state, Object world, Object blockPos) throws Exception {
int y = FastNMS.INSTANCE.field$Vec3i$y(blockPos);

View File

@@ -34,6 +34,7 @@ import java.util.Map;
import java.util.Optional;
import java.util.concurrent.Callable;
@SuppressWarnings("DuplicatedCode")
public class CropBlockBehavior extends BukkitBlockBehavior {
public static final Factory FACTORY = new Factory();
private final IntegerProperty ageProperty;

View File

@@ -1,6 +1,5 @@
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;
@@ -40,6 +39,7 @@ import java.util.Map;
import java.util.Optional;
import java.util.concurrent.Callable;
@SuppressWarnings("DuplicatedCode")
public class DoorBlockBehavior extends AbstractCanSurviveBlockBehavior {
public static final Factory FACTORY = new Factory();
private final Property<DoubleBlockHalf> halfProperty;
@@ -91,10 +91,11 @@ public class DoorBlockBehavior extends AbstractCanSurviveBlockBehavior {
DoubleBlockHalf half = customState.get(this.halfProperty);
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()) {
Optional<ImmutableBlockState> optionalNeighborState = BlockStateUtils.getOptionalCustomBlockState(args[updateShape$neighborState]);
if (optionalNeighborState.isEmpty()) {
return MBlocks.AIR$defaultState;
}
ImmutableBlockState neighborState = optionalNeighborState.get();
Optional<DoorBlockBehavior> anotherDoorBehavior = neighborState.behavior().getAs(DoorBlockBehavior.class);
if (anotherDoorBehavior.isEmpty()) {
return MBlocks.AIR$defaultState;
@@ -120,8 +121,9 @@ public class DoorBlockBehavior extends AbstractCanSurviveBlockBehavior {
@Override
public void onExplosionHit(Object thisBlock, Object[] args, Callable<Object> superMethod) {
if (this.canOpenByWindCharge && FastNMS.INSTANCE.method$Explosion$canTriggerBlocks(args[3])) {
ImmutableBlockState state = BukkitBlockManager.instance().getImmutableBlockState(BlockStateUtils.blockStateToId(args[0]));
if (state == null || state.isEmpty()) return;
Optional<ImmutableBlockState> optionalCustomState = BlockStateUtils.getOptionalCustomBlockState(args[0]);
if (optionalCustomState.isEmpty()) return;
ImmutableBlockState state = optionalCustomState.get();
if (state.get(this.poweredProperty)) return;
if (state.get(this.halfProperty) == DoubleBlockHalf.LOWER) {
this.setOpen(null, args[1], state, LocationUtils.fromBlockPos(args[2]), !this.isOpen(state));
@@ -193,15 +195,13 @@ public class DoorBlockBehavior extends AbstractCanSurviveBlockBehavior {
}
private boolean isAnotherDoor(Object blockState) {
int id = BlockStateUtils.blockStateToId(blockState);
if (BlockStateUtils.isVanillaBlock(id)) {
Optional<ImmutableBlockState> optionalCustomState = BlockStateUtils.getOptionalCustomBlockState(blockState);
if (optionalCustomState.isEmpty()) {
BlockData blockData = BlockStateUtils.fromBlockData(blockState);
return blockData instanceof Door door && door.getHalf() == Bisected.Half.BOTTOM;
} else {
ImmutableBlockState state = BukkitBlockManager.instance().getImmutableBlockStateUnsafe(id);
if (state.isEmpty()) return false;
Optional<DoorBlockBehavior> optional = state.behavior().getAs(DoorBlockBehavior.class);
return optional.isPresent() && state.get(optional.get().halfProperty) == DoubleBlockHalf.LOWER;
Optional<DoorBlockBehavior> optional = optionalCustomState.get().behavior().getAs(DoorBlockBehavior.class);
return optional.isPresent() && optionalCustomState.get().get(optional.get().halfProperty) == DoubleBlockHalf.LOWER;
}
}
@@ -233,10 +233,10 @@ public class DoorBlockBehavior extends AbstractCanSurviveBlockBehavior {
public boolean isPathFindable(Object thisBlock, Object[] args, Callable<Object> superMethod) {
Object type = VersionHelper.isOrAbove1_20_5() ? args[1] : args[3];
Object blockState = args[0];
ImmutableBlockState state = BukkitBlockManager.instance().getImmutableBlockState(BlockStateUtils.blockStateToId(blockState));
if (state == null || state.isEmpty()) return false;
Optional<ImmutableBlockState> optionalCustomState = BlockStateUtils.getOptionalCustomBlockState(blockState);
if (optionalCustomState.isEmpty()) return false;
if (type == CoreReflections.instance$PathComputationType$LAND || type == CoreReflections.instance$PathComputationType$AIR) {
return state.get(this.openProperty);
return optionalCustomState.get().get(this.openProperty);
}
return false;
}

View File

@@ -73,6 +73,7 @@ public class FallingBlockBehavior extends BukkitBlockBehavior {
}
}
@SuppressWarnings("DuplicatedCode")
@Override
public void onBrokenAfterFall(Object thisBlock, Object[] args) throws Exception {
// Use EntityRemoveEvent for 1.20.3+

View File

@@ -42,6 +42,7 @@ import java.util.Map;
import java.util.Optional;
import java.util.concurrent.Callable;
@SuppressWarnings("DuplicatedCode")
public class FenceGateBlockBehavior extends BukkitBlockBehavior {
public static final Factory FACTORY = new Factory();
private final Property<HorizontalDirection> facingProperty;

View File

@@ -22,6 +22,7 @@ import org.bukkit.block.Block;
import java.util.Map;
import java.util.Optional;
@SuppressWarnings("DuplicatedCode")
public class GrassBlockBehavior extends BukkitBlockBehavior {
public static final Factory FACTORY = new Factory();

View File

@@ -1,6 +1,5 @@
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.util.BlockStateUtils;
import net.momirealms.craftengine.bukkit.util.LocationUtils;
@@ -16,6 +15,7 @@ import java.util.Map;
import java.util.Optional;
import java.util.concurrent.Callable;
@SuppressWarnings("DuplicatedCode")
public class LampBlockBehavior extends BukkitBlockBehavior {
public static final Factory FACTORY = new Factory();
private final Property<Boolean> litProperty;
@@ -51,11 +51,12 @@ public class LampBlockBehavior extends BukkitBlockBehavior {
@Override
public void neighborChanged(Object thisBlock, Object[] args, Callable<Object> superMethod) {
Object blockState = args[0];
ImmutableBlockState state = BukkitBlockManager.instance().getImmutableBlockState(BlockStateUtils.blockStateToId(blockState));
if (state == null || state.isEmpty()) return;
Optional<ImmutableBlockState> optionalCustomState = BlockStateUtils.getOptionalCustomBlockState(blockState);
if (optionalCustomState.isEmpty()) return;
Object world = args[1];
Object blockPos = args[2];
boolean lit = state.get(this.litProperty);
ImmutableBlockState customState = optionalCustomState.get();
boolean lit = customState.get(this.litProperty);
if (lit != FastNMS.INSTANCE.method$SignalGetter$hasNeighborSignal(world, blockPos)) {
if (lit) {
FastNMS.INSTANCE.method$LevelAccessor$scheduleBlockTick(world, blockPos, thisBlock, 4);
@@ -63,7 +64,7 @@ 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, state.cycle(this.litProperty).customBlockState().handle(), 2);
FastNMS.INSTANCE.method$LevelWriter$setBlock(world, blockPos, customState.cycle(this.litProperty).customBlockState().handle(), 2);
}
}
}

View File

@@ -1,6 +1,5 @@
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.util.BlockStateUtils;
@@ -15,7 +14,6 @@ import net.momirealms.craftengine.core.block.properties.Property;
import net.momirealms.craftengine.core.util.Direction;
import net.momirealms.craftengine.core.util.Key;
import net.momirealms.craftengine.core.util.ResourceConfigUtils;
import net.momirealms.craftengine.core.util.VersionHelper;
import net.momirealms.craftengine.core.world.BlockPos;
import org.bukkit.Bukkit;
import org.bukkit.World;
@@ -57,26 +55,17 @@ public class LeavesBlockBehavior extends BukkitBlockBehavior {
@Override
public Object updateShape(Object thisBlock, Object[] args, Callable<Object> superMethod) throws Exception {
Object world;
Object blockPos;
Object neighborState;
Object world = args[updateShape$level];
Object blockPos = args[updateShape$blockPos];
Object neighborState = args[updateShape$neighborState];
Object blockState = args[0];
if (VersionHelper.isOrAbove1_21_2()) {
world = args[1];
neighborState = args[6];
blockPos = args[3];
} else {
world = args[3];
blockPos = args[4];
neighborState = args[2];
}
ImmutableBlockState thisState = BukkitBlockManager.instance().getImmutableBlockState(BlockStateUtils.blockStateToId(blockState));
if (thisState != null) {
Optional<LeavesBlockBehavior> optionalBehavior = thisState.behavior().getAs(LeavesBlockBehavior.class);
Optional<ImmutableBlockState> optionalCustomState = BlockStateUtils.getOptionalCustomBlockState(blockState);
if (optionalCustomState.isPresent()) {
Optional<LeavesBlockBehavior> optionalBehavior = optionalCustomState.get().behavior().getAs(LeavesBlockBehavior.class);
if (optionalBehavior.isPresent()) {
LeavesBlockBehavior behavior = optionalBehavior.get();
int distance = behavior.getDistanceAt(neighborState) + 1;
if (distance != 1 || behavior.getDistance(thisState) != distance) {
if (distance != 1 || behavior.getDistance(optionalCustomState.get()) != distance) {
FastNMS.INSTANCE.method$LevelAccessor$scheduleBlockTick(world, blockPos, thisBlock, 1);
}
}
@@ -89,13 +78,14 @@ public class LeavesBlockBehavior extends BukkitBlockBehavior {
Object blockState = args[0];
Object level = args[1];
Object blockPos = args[2];
ImmutableBlockState currentState = BukkitBlockManager.instance().getImmutableBlockState(BlockStateUtils.blockStateToId(blockState));
if (currentState != null && !currentState.isEmpty()) {
Optional<LeavesBlockBehavior> optionalBehavior = currentState.behavior().getAs(LeavesBlockBehavior.class);
Optional<ImmutableBlockState> optionalCustomState = BlockStateUtils.getOptionalCustomBlockState(blockState);
if (optionalCustomState.isPresent()) {
ImmutableBlockState customState = optionalCustomState.get();
Optional<LeavesBlockBehavior> optionalBehavior = customState.behavior().getAs(LeavesBlockBehavior.class);
if (optionalBehavior.isPresent()) {
LeavesBlockBehavior behavior = optionalBehavior.get();
ImmutableBlockState newState = behavior.updateDistance(currentState, level, blockPos);
if (newState != currentState) {
ImmutableBlockState newState = behavior.updateDistance(customState, level, blockPos);
if (newState != customState) {
if (blockState == newState.customBlockState().handle()) {
CoreReflections.method$BlockStateBase$updateNeighbourShapes.invoke(blockState, level, blockPos, UpdateOption.UPDATE_ALL.flags(), 512);
} else {
@@ -156,14 +146,14 @@ public class LeavesBlockBehavior extends BukkitBlockBehavior {
private int getDistanceAt(Object blockState) throws ReflectiveOperationException {
boolean isLog = FastNMS.INSTANCE.method$BlockStateBase$is(blockState, LOG_TAG);
if (isLog) return 0;
int id = BlockStateUtils.blockStateToId(blockState);
if (BlockStateUtils.isVanillaBlock(id)) {
Optional<ImmutableBlockState> optionalCustomState = BlockStateUtils.getOptionalCustomBlockState(blockState);
if (optionalCustomState.isEmpty()) {
Object distanceProperty = CoreReflections.field$LeavesBlock$DISTANCE.get(null);
boolean hasDistanceProperty = (boolean) CoreReflections.method$StateHolder$hasProperty.invoke(blockState, distanceProperty);
if (!hasDistanceProperty) return this.maxDistance;
return (int) CoreReflections.method$StateHolder$getValue.invoke(blockState, distanceProperty);
} else {
ImmutableBlockState anotherBlockState = BukkitBlockManager.instance().getImmutableBlockStateUnsafe(id);
ImmutableBlockState anotherBlockState = optionalCustomState.get();
Optional<LeavesBlockBehavior> optionalAnotherBehavior = anotherBlockState.behavior().getAs(LeavesBlockBehavior.class);
return optionalAnotherBehavior.map(leavesBlockBehavior -> leavesBlockBehavior.getDistance(anotherBlockState)).orElse(this.maxDistance);
}

View File

@@ -47,6 +47,7 @@ public class OnLiquidBlockBehavior extends AbstractCanSurviveBlockBehavior {
}
}
@SuppressWarnings("DuplicatedCode")
@Override
protected boolean canSurvive(Object thisBlock, Object state, Object world, Object blockPos) {
int y = FastNMS.INSTANCE.field$Vec3i$y(blockPos);

View File

@@ -1,7 +1,6 @@
package net.momirealms.craftengine.bukkit.block.behavior;
import io.papermc.paper.event.entity.EntityInsideBlockEvent;
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;
@@ -54,6 +53,7 @@ public class PressurePlateBlockBehavior extends BukkitBlockBehavior {
this.pressedTime = pressedTime;
}
@SuppressWarnings("DuplicatedCode")
@Override
public Object updateShape(Object thisBlock, Object[] args, Callable<Object> superMethod) throws Exception {
Object state = args[0];
@@ -105,6 +105,7 @@ public class PressurePlateBlockBehavior extends BukkitBlockBehavior {
if (signalForState == 0) {
this.checkPressed(args[3], args[1], args[2], state, signalForState, thisBlock);
} else {
// todo 为什么
FastNMS.INSTANCE.method$LevelAccessor$scheduleBlockTick(args[1], args[2], thisBlock, this.pressedTime);
}
}
@@ -119,9 +120,9 @@ public class PressurePlateBlockBehavior extends BukkitBlockBehavior {
}
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();
Optional<ImmutableBlockState> optionalCustomState = BlockStateUtils.getOptionalCustomBlockState(state);
if (optionalCustomState.isEmpty()) return state;
return optionalCustomState.get().with(this.poweredProperty, strength > 0).customBlockState().handle();
}
private void checkPressed(@Nullable Object entity, Object level, Object pos, Object state, int currentSignal, Object thisBlock) {

View File

@@ -30,6 +30,7 @@ import java.util.Map;
import java.util.Optional;
import java.util.concurrent.Callable;
@SuppressWarnings("DuplicatedCode")
public class SaplingBlockBehavior extends BukkitBlockBehavior {
public static final Factory FACTORY = new Factory();
private final Key feature;

View File

@@ -23,6 +23,7 @@ import java.util.Map;
import java.util.Optional;
import java.util.concurrent.Callable;
@SuppressWarnings("DuplicatedCode")
public class StairsBlockBehavior extends BukkitBlockBehavior {
public static final Factory FACTORY = new Factory();
private final Property<HorizontalDirection> facingProperty;

View File

@@ -39,6 +39,7 @@ import java.util.Map;
import java.util.Optional;
import java.util.concurrent.Callable;
@SuppressWarnings("DuplicatedCode")
public class TrapDoorBlockBehavior extends BukkitBlockBehavior {
public static final Factory FACTORY = new Factory();
private final Property<SingleBlockHalf> halfProperty;

View File

@@ -27,7 +27,6 @@ import net.momirealms.sparrow.nbt.CompoundTag;
import org.bukkit.GameEvent;
import org.bukkit.Material;
import org.bukkit.Statistic;
import org.bukkit.block.data.BlockData;
import org.bukkit.event.entity.EntityChangeBlockEvent;
import org.bukkit.inventory.ItemStack;
import org.bukkit.util.Vector;
@@ -58,15 +57,12 @@ public class AxeItemBehavior extends ItemBehavior {
return InteractionResult.PASS;
}
BukkitBlockInWorld block = (BukkitBlockInWorld) context.getLevel().getBlockAt(context.getClickedPos());
BlockData blockData = block.block().getBlockData();
int stateId = BlockStateUtils.blockDataToId(blockData);
if (BlockStateUtils.isVanillaBlock(stateId)) return InteractionResult.PASS;
Object blockState = FastNMS.INSTANCE.method$BlockGetter$getBlockState(context.getLevel().serverWorld(), LocationUtils.toBlockPos(context.getClickedPos()));
Optional<ImmutableBlockState> optionalCustomState = BlockStateUtils.getOptionalCustomBlockState(blockState);
if (optionalCustomState.isEmpty()) return InteractionResult.PASS;
ImmutableBlockState customBlockState = BukkitBlockManager.instance().getImmutableBlockState(stateId);
if (customBlockState == null || customBlockState.isEmpty()) return InteractionResult.PASS;
Optional<StrippableBlockBehavior> behaviorOptional = customBlockState.behavior().getAs(StrippableBlockBehavior.class);
ImmutableBlockState customState = optionalCustomState.get();
Optional<StrippableBlockBehavior> behaviorOptional = customState.behavior().getAs(StrippableBlockBehavior.class);
if (behaviorOptional.isEmpty()) return InteractionResult.PASS;
Key stripped = behaviorOptional.get().stripped();
Item<ItemStack> offHandItem = (Item<ItemStack>) player.getItemInHand(InteractionHand.OFF_HAND);
@@ -81,7 +77,7 @@ public class AxeItemBehavior extends ItemBehavior {
return InteractionResult.FAIL;
}
CustomBlock newCustomBlock = optionalNewCustomBlock.get();
CompoundTag compoundTag = customBlockState.propertiesNbt();
CompoundTag compoundTag = customState.propertiesNbt();
ImmutableBlockState newState = newCustomBlock.getBlockState(compoundTag);
org.bukkit.entity.Player bukkitPlayer = ((org.bukkit.entity.Player) player.platformPlayer());
@@ -103,7 +99,7 @@ public class AxeItemBehavior extends ItemBehavior {
// resend swing if it's not interactable on client side
if (!InteractUtils.isInteractable(
bukkitPlayer, BlockStateUtils.fromBlockData(customBlockState.vanillaBlockState().handle()),
bukkitPlayer, BlockStateUtils.fromBlockData(customState.vanillaBlockState().handle()),
context.getHitResult(), item
) || player.isSecondaryUseActive()) {
player.swingHand(context.getHand());

View File

@@ -99,13 +99,13 @@ public class BlockItemBehavior extends BlockBoundItemBehavior {
if (player.isAdventureMode()) {
Object againstBlockState = BlockStateUtils.blockDataToBlockState(againstBlock.getBlockData());
int stateId = BlockStateUtils.blockStateToId(againstBlockState);
if (BlockStateUtils.isVanillaBlock(stateId)) {
Optional<ImmutableBlockState> optionalCustomState = BlockStateUtils.getOptionalCustomBlockState(againstBlockState);
if (optionalCustomState.isEmpty()) {
if (!AdventureModeUtils.canPlace(context.getItem(), context.getLevel(), againstPos, againstBlockState)) {
return InteractionResult.FAIL;
}
} else {
ImmutableBlockState customState = BukkitBlockManager.instance().getImmutableBlockStateUnsafe(stateId);
ImmutableBlockState customState = optionalCustomState.get();
// custom block
if (!AdventureModeUtils.canPlace(context.getItem(), context.getLevel(), againstPos, Config.simplifyAdventurePlaceCheck() ? customState.vanillaBlockState().handle() : againstBlockState)) {
return InteractionResult.FAIL;

View File

@@ -2,13 +2,14 @@ package net.momirealms.craftengine.bukkit.item.listener;
import net.kyori.adventure.text.Component;
import net.momirealms.craftengine.bukkit.api.CraftEngineBlocks;
import net.momirealms.craftengine.bukkit.block.BukkitBlockManager;
import net.momirealms.craftengine.bukkit.item.BukkitItemManager;
import net.momirealms.craftengine.bukkit.nms.FastNMS;
import net.momirealms.craftengine.bukkit.plugin.BukkitCraftEngine;
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.NetworkReflections;
import net.momirealms.craftengine.bukkit.plugin.user.BukkitServerPlayer;
import net.momirealms.craftengine.bukkit.util.BlockStateUtils;
import net.momirealms.craftengine.bukkit.util.ComponentUtils;
import net.momirealms.craftengine.bukkit.util.LocationUtils;
import net.momirealms.craftengine.core.block.CustomBlock;
import net.momirealms.craftengine.core.block.ImmutableBlockState;
import net.momirealms.craftengine.core.block.UpdateOption;
@@ -58,13 +59,11 @@ public class DebugStickListener implements Listener {
return;
}
}
Object blockState = BlockStateUtils.blockDataToBlockState(clickedBlock.getBlockData());
int stateId = BlockStateUtils.blockStateToId(blockState);
if (!BlockStateUtils.isVanillaBlock(stateId)) {
Object blockState = FastNMS.INSTANCE.method$BlockGetter$getBlockState(FastNMS.INSTANCE.field$CraftWorld$ServerLevel(clickedBlock.getWorld()), LocationUtils.toBlockPos(clickedBlock.getX(), clickedBlock.getY(), clickedBlock.getZ()));
BlockStateUtils.getOptionalCustomBlockState(blockState).ifPresent(customState -> {
event.setCancelled(true);
boolean update = event.getAction() == Action.RIGHT_CLICK_BLOCK;
ImmutableBlockState clickedCustomBlock = BukkitBlockManager.instance().getImmutableBlockStateUnsafe(stateId);
CustomBlock block = clickedCustomBlock.owner().value();
CustomBlock block = customState.owner().value();
Collection<Property<?>> properties = block.properties();
String blockId = block.id().toString();
try {
@@ -84,7 +83,7 @@ public class DebugStickListener implements Listener {
currentProperty = properties.iterator().next();
}
if (update) {
ImmutableBlockState nextState = cycleState(clickedCustomBlock, currentProperty, player.isSecondaryUseActive());
ImmutableBlockState nextState = cycleState(customState, currentProperty, player.isSecondaryUseActive());
CraftEngineBlocks.place(clickedBlock.getLocation(), nextState, new UpdateOption.Builder().updateClients().updateKnownShape().build(), false);
Object systemChatPacket = NetworkReflections.constructor$ClientboundSystemChatPacket.newInstance(
ComponentUtils.adventureToMinecraft(Component.translatable("item.minecraft.debug_stick.update")
@@ -102,16 +101,16 @@ public class DebugStickListener implements Listener {
ComponentUtils.adventureToMinecraft(Component.translatable("item.minecraft.debug_stick.select")
.arguments(
Component.text(currentProperty.name()),
Component.text(getNameHelper(clickedCustomBlock, currentProperty))
Component.text(getNameHelper(customState, currentProperty))
)), true);
player.sendPacket(systemChatPacket, false);
}
}
}
} catch (ReflectiveOperationException e) {
plugin.logger().warn("Failed to send system chat packet", e);
this.plugin.logger().warn("Failed to send system chat packet", e);
}
}
});
}
private static <T extends Comparable<T>> ImmutableBlockState cycleState(ImmutableBlockState state, Property<T> property, boolean inverse) {

View File

@@ -2,7 +2,6 @@ package net.momirealms.craftengine.bukkit.item.listener;
import io.papermc.paper.event.block.CompostItemEvent;
import net.momirealms.craftengine.bukkit.api.event.CustomBlockInteractEvent;
import net.momirealms.craftengine.bukkit.block.BukkitBlockManager;
import net.momirealms.craftengine.bukkit.item.BukkitCustomItem;
import net.momirealms.craftengine.bukkit.nms.FastNMS;
import net.momirealms.craftengine.bukkit.plugin.BukkitCraftEngine;
@@ -112,8 +111,7 @@ public class ItemEventListener implements Listener {
Block block = Objects.requireNonNull(event.getClickedBlock());
BlockData blockData = block.getBlockData();
Object blockState = BlockStateUtils.blockDataToBlockState(blockData);
ImmutableBlockState immutableBlockState = null;
int stateId = BlockStateUtils.blockStateToId(blockState);
ImmutableBlockState immutableBlockState = BlockStateUtils.getOptionalCustomBlockState(blockState).orElse(null);
Item<ItemStack> itemInHand = serverPlayer.getItemInHand(hand);
Location interactionPoint = event.getInteractionPoint();
@@ -126,8 +124,7 @@ public class ItemEventListener implements Listener {
}
// 处理自定义方块
if (!BlockStateUtils.isVanillaBlock(stateId)) {
immutableBlockState = BukkitBlockManager.instance().getImmutableBlockStateUnsafe(stateId);
if (immutableBlockState != null) {
// call the event if it's custom
CustomBlockInteractEvent interactEvent = new CustomBlockInteractEvent(
player,

View File

@@ -12,7 +12,6 @@ import net.bytebuddy.implementation.bind.annotation.SuperCall;
import net.bytebuddy.implementation.bind.annotation.This;
import net.bytebuddy.implementation.bytecode.assign.Assigner;
import net.bytebuddy.matcher.ElementMatchers;
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.util.BlockStateUtils;
@@ -34,6 +33,7 @@ import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.Callable;
import java.util.function.Consumer;
@@ -217,10 +217,10 @@ public class WorldStorageInjector {
protected static void compareAndUpdateBlockState(int x, int y, int z, Object newState, Object previousState, InjectedHolder holder) {
try {
int stateId = BlockStateUtils.blockStateToId(newState);
Optional<ImmutableBlockState> optionalCustomState = BlockStateUtils.getOptionalCustomBlockState(newState);
CESection section = holder.ceSection();
// 如果是原版方块
if (BlockStateUtils.isVanillaBlock(stateId)) {
if (optionalCustomState.isEmpty()) {
// 那么应该清空自定义块
ImmutableBlockState previous = section.setBlockState(x, y, z, EmptyBlock.STATE);
// 处理 自定义块 -> 原版块
@@ -235,7 +235,7 @@ public class WorldStorageInjector {
}
}
} else {
ImmutableBlockState immutableBlockState = BukkitBlockManager.instance().getImmutableBlockStateUnsafe(stateId);
ImmutableBlockState immutableBlockState = optionalCustomState.get();
ImmutableBlockState previousImmutableBlockState = section.setBlockState(x, y, z, immutableBlockState);
if (previousImmutableBlockState == immutableBlockState) return;
// 处理 自定义块到自定义块或原版块到自定义块

View File

@@ -9,6 +9,7 @@ import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
import it.unimi.dsi.fastutil.ints.IntList;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.TranslationArgument;
import net.momirealms.craftengine.bukkit.api.CraftEngineBlocks;
import net.momirealms.craftengine.bukkit.api.CraftEngineFurniture;
import net.momirealms.craftengine.bukkit.api.event.FurnitureAttemptBreakEvent;
import net.momirealms.craftengine.bukkit.api.event.FurnitureBreakEvent;
@@ -1316,7 +1317,7 @@ public class PacketConsumers {
if (result == null) return;
Block hitBlock = result.getHitBlock();
if (hitBlock == null) return;
ImmutableBlockState state = BukkitBlockManager.instance().getImmutableBlockState(BlockStateUtils.blockDataToId(hitBlock.getBlockData()));
ImmutableBlockState state = CraftEngineBlocks.getCustomBlockState(hitBlock);
// not a custom block
if (state == null || state.isEmpty()) return;
Key itemId = state.settings().itemId();

View File

@@ -1320,7 +1320,6 @@ public final class CoreReflections {
ReflectionUtils.getDeclaredField(clazz$BlockStateBase, boolean.class, 8)
);
public static final Field field$BlockStateBase$lightEmission = requireNonNull(
ReflectionUtils.getDeclaredField(clazz$BlockStateBase, int.class, 0)
);

View File

@@ -5,7 +5,7 @@ import io.netty.buffer.Unpooled;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandler;
import net.kyori.adventure.text.Component;
import net.momirealms.craftengine.bukkit.block.BukkitBlockManager;
import net.momirealms.craftengine.bukkit.api.CraftEngineBlocks;
import net.momirealms.craftengine.bukkit.item.BukkitItemManager;
import net.momirealms.craftengine.bukkit.nms.FastNMS;
import net.momirealms.craftengine.bukkit.plugin.BukkitCraftEngine;
@@ -450,15 +450,15 @@ public class BukkitServerPlayer extends Player {
}
return;
}
int stateId = BlockStateUtils.blockDataToId(hitBlock.getBlockData());
if (BlockStateUtils.isVanillaBlock(stateId)) {
ImmutableBlockState nextBlock = CraftEngineBlocks.getCustomBlockState(hitBlock);
if (nextBlock == null) {
if (!this.clientSideCanBreak) {
setClientSideCanBreakBlock(true);
}
return;
}
if (this.clientSideCanBreak) {
setClientSideCanBreakBlock(false);
} else {
if (this.clientSideCanBreak) {
setClientSideCanBreakBlock(false);
}
}
}
@@ -612,10 +612,10 @@ public class BukkitServerPlayer extends Player {
}
float progressToAdd = getDestroyProgress(destroyedState, hitPos);
int id = BlockStateUtils.blockStateToId(destroyedState);
ImmutableBlockState customState = BukkitBlockManager.instance().getImmutableBlockState(id);
Optional<ImmutableBlockState> optionalCustomState = BlockStateUtils.getOptionalCustomBlockState(destroyedState);
// double check custom block
if (customState != null && !customState.isEmpty()) {
if (optionalCustomState.isPresent()) {
ImmutableBlockState customState = optionalCustomState.get();
BlockSettings blockSettings = customState.settings();
if (blockSettings.requireCorrectTool()) {
if (item != null) {
@@ -666,7 +666,7 @@ public class BukkitServerPlayer extends Player {
CoreReflections.method$ServerPlayerGameMode$destroyBlock.invoke(gameMode, blockPos);
}
// send break particle + (removed sounds)
sendPacket(FastNMS.INSTANCE.constructor$ClientboundLevelEventPacket(WorldEvents.BLOCK_BREAK_EFFECT, blockPos, id, false), false);
sendPacket(FastNMS.INSTANCE.constructor$ClientboundLevelEventPacket(WorldEvents.BLOCK_BREAK_EFFECT, blockPos, customState.customBlockState().registryId(), false), false);
this.lastSuccessfulBreak = currentTick;
this.destroyPos = null;
this.setIsDestroyingBlock(false, false);

View File

@@ -27,8 +27,8 @@ public class LightUtils {
Object chunkPos = FastNMS.INSTANCE.constructor$ChunkPos((int) chunkKey, (int) (chunkKey >> 32));
Object lightPacket = FastNMS.INSTANCE.constructor$ClientboundLightUpdatePacket(chunkPos, lightEngine, entry.getValue(), entry.getValue());
for (Object player : players) {
FastNMS.INSTANCE.method$Connection$send(
FastNMS.INSTANCE.field$ServerGamePacketListenerImpl$connection(FastNMS.INSTANCE.field$ServerGamePacketListenerImpl$connection(player)),
FastNMS.INSTANCE.method$ServerPlayerConnection$send(
FastNMS.INSTANCE.field$Player$connection(player),
lightPacket);
}
}

View File

@@ -1,10 +1,8 @@
package net.momirealms.craftengine.bukkit.world;
import net.momirealms.craftengine.bukkit.api.CraftEngineBlocks;
import net.momirealms.craftengine.bukkit.block.BukkitBlockManager;
import net.momirealms.craftengine.bukkit.nms.FastNMS;
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MFluids;
import net.momirealms.craftengine.bukkit.util.BlockStateUtils;
import net.momirealms.craftengine.bukkit.util.LocationUtils;
import net.momirealms.craftengine.core.block.CustomBlock;
import net.momirealms.craftengine.core.block.ImmutableBlockState;
@@ -23,7 +21,7 @@ public class BukkitBlockInWorld implements BlockInWorld {
@Override
public boolean canBeReplaced(BlockPlaceContext context) {
ImmutableBlockState customState = BukkitBlockManager.instance().getImmutableBlockState(BlockStateUtils.blockDataToId(this.block.getBlockData()));
ImmutableBlockState customState = CraftEngineBlocks.getCustomBlockState(this.block);
if (customState != null && !customState.isEmpty()) {
return customState.behavior().canBeReplaced(context, customState);
}

View File

@@ -32,6 +32,7 @@ import org.jetbrains.annotations.NotNull;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantReadWriteLock;
@@ -338,14 +339,14 @@ public class BukkitWorldManager implements WorldManager, Listener {
boolean requiresSync = false;
if (CoreReflections.clazz$SingleValuePalette.isInstance(palette)) {
Object onlyBlockState = CoreReflections.field$SingleValuePalette$value.get(palette);
if (!BlockStateUtils.isVanillaBlock(BlockStateUtils.blockStateToId(onlyBlockState))) {
if (BlockStateUtils.isCustomBlock(onlyBlockState)) {
requiresSync = true;
}
} else if (CoreReflections.clazz$LinearPalette.isInstance(palette)) {
Object[] blockStates = (Object[]) CoreReflections.field$LinearPalette$values.get(palette);
for (Object blockState : blockStates) {
if (blockState != null) {
if (!BlockStateUtils.isVanillaBlock(BlockStateUtils.blockStateToId(blockState))) {
if (BlockStateUtils.isCustomBlock(blockState)) {
requiresSync = true;
break;
}
@@ -356,7 +357,7 @@ public class BukkitWorldManager implements WorldManager, Listener {
Object[] blockStates = (Object[]) CoreReflections.field$CrudeIncrementalIntIdentityHashBiMap$keys.get(biMap);
for (Object blockState : blockStates) {
if (blockState != null) {
if (!BlockStateUtils.isVanillaBlock(BlockStateUtils.blockStateToId(blockState))) {
if (BlockStateUtils.isCustomBlock(blockState)) {
requiresSync = true;
break;
}
@@ -370,10 +371,9 @@ public class BukkitWorldManager implements WorldManager, Listener {
for (int z = 0; z < 16; z++) {
for (int y = 0; y < 16; y++) {
Object mcState = FastNMS.INSTANCE.method$LevelChunkSection$getBlockState(section, x, y, z);
int stateId = BlockStateUtils.blockStateToId(mcState);
ImmutableBlockState customState = this.plugin.blockManager().getImmutableBlockState(stateId);
if (customState != null) {
ceSection.setBlockState(x, y, z, customState);
Optional<ImmutableBlockState> optionalCustomState = BlockStateUtils.getOptionalCustomBlockState(mcState);
if (optionalCustomState.isPresent()) {
ceSection.setBlockState(x, y, z, optionalCustomState.get());
}
}
}