mirror of
https://github.com/Xiao-MoMi/craft-engine.git
synced 2025-12-28 11:29:17 +00:00
faster nms
This commit is contained in:
@@ -108,11 +108,11 @@ public final class CraftEngineBlocks {
|
||||
boolean playSound) {
|
||||
boolean success;
|
||||
try {
|
||||
Object worldServer = Reflections.field$CraftWorld$ServerLevel.get(location.getWorld());
|
||||
Object worldServer = FastNMS.INSTANCE.field$CraftWorld$ServerLevel(location.getWorld());
|
||||
Object blockPos = FastNMS.INSTANCE.constructor$BlockPos(location.getBlockX(), location.getBlockY(), location.getBlockZ());
|
||||
Object blockState = block.customBlockState().handle();
|
||||
Object oldBlockState = FastNMS.INSTANCE.method$BlockGetter$getBlockState(worldServer, blockPos);
|
||||
success = (boolean) Reflections.method$LevelWriter$setBlock.invoke(worldServer, blockPos, blockState, option.flags());
|
||||
success = FastNMS.INSTANCE.method$LevelWriter$setBlock(worldServer, blockPos, blockState, option.flags());
|
||||
if (success) {
|
||||
Reflections.method$BlockStateBase$onPlace.invoke(blockState, worldServer, blockPos, oldBlockState, true);
|
||||
if (playSound) {
|
||||
|
||||
@@ -2,6 +2,7 @@ package net.momirealms.craftengine.bukkit.block;
|
||||
|
||||
import io.papermc.paper.event.block.BlockBreakBlockEvent;
|
||||
import net.momirealms.craftengine.bukkit.api.event.CustomBlockBreakEvent;
|
||||
import net.momirealms.craftengine.bukkit.nms.FastNMS;
|
||||
import net.momirealms.craftengine.bukkit.plugin.BukkitCraftEngine;
|
||||
import net.momirealms.craftengine.bukkit.plugin.user.BukkitServerPlayer;
|
||||
import net.momirealms.craftengine.bukkit.util.*;
|
||||
@@ -316,10 +317,10 @@ public class BlockEventListener implements Listener {
|
||||
Block sourceBlock = event.getSourceBlock();
|
||||
BlockFace direction = sourceBlock.getFace(block);
|
||||
if (direction == BlockFace.UP || direction == BlockFace.DOWN) {
|
||||
Object serverLevel = Reflections.field$CraftWorld$ServerLevel.get(world);
|
||||
Object chunkSource = Reflections.field$ServerLevel$chunkSource.get(serverLevel);
|
||||
Object serverLevel = FastNMS.INSTANCE.field$CraftWorld$ServerLevel(world);
|
||||
Object chunkSource = FastNMS.INSTANCE.method$ServerLevel$getChunkSource(serverLevel);
|
||||
Object blockPos = LocationUtils.toBlockPos(location.getBlockX(), location.getBlockY(), location.getBlockZ());
|
||||
Reflections.method$ServerChunkCache$blockChanged.invoke(chunkSource, blockPos);
|
||||
FastNMS.INSTANCE.method$ServerChunkCache$blockChanged(chunkSource, blockPos);
|
||||
if (direction == BlockFace.UP) {
|
||||
NoteBlockChainUpdateUtils.noteBlockChainUpdate(serverLevel, chunkSource, Reflections.instance$Direction$UP, blockPos, 0);
|
||||
} else {
|
||||
|
||||
@@ -0,0 +1,121 @@
|
||||
package net.momirealms.craftengine.bukkit.block.behavior;
|
||||
|
||||
import net.momirealms.craftengine.bukkit.block.BukkitBlockManager;
|
||||
import net.momirealms.craftengine.bukkit.util.BlockStateUtils;
|
||||
import net.momirealms.craftengine.bukkit.util.MirrorUtils;
|
||||
import net.momirealms.craftengine.bukkit.util.RotationUtils;
|
||||
import net.momirealms.craftengine.core.block.CustomBlock;
|
||||
import net.momirealms.craftengine.core.block.ImmutableBlockState;
|
||||
import net.momirealms.craftengine.core.block.behavior.AbstractBlockBehavior;
|
||||
import net.momirealms.craftengine.core.block.properties.Property;
|
||||
import net.momirealms.craftengine.core.util.Direction;
|
||||
import net.momirealms.craftengine.core.util.HorizontalDirection;
|
||||
import net.momirealms.craftengine.core.util.Mirror;
|
||||
import net.momirealms.craftengine.core.util.Rotation;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.function.BiConsumer;
|
||||
|
||||
public class BukkitBlockBehavior extends AbstractBlockBehavior {
|
||||
private static final Map<String, BiConsumer<BukkitBlockBehavior, Property<?>>> HARD_CODED_PROPERTY_DATA = new HashMap<>();
|
||||
static {
|
||||
HARD_CODED_PROPERTY_DATA.put("axis", (behavior, property) -> {
|
||||
@SuppressWarnings("unchecked")
|
||||
Property<Direction.Axis> axisProperty = (Property<Direction.Axis>) property;
|
||||
behavior.rotateFunction = (thisBlock, blockState, rotation) -> {
|
||||
Direction.Axis axis = blockState.get(axisProperty);
|
||||
return switch (rotation) {
|
||||
case COUNTERCLOCKWISE_90, CLOCKWISE_90 -> switch (axis) {
|
||||
case X -> blockState.with(axisProperty, Direction.Axis.Z).customBlockState().handle();
|
||||
case Z -> blockState.with(axisProperty, Direction.Axis.X).customBlockState().handle();
|
||||
default -> blockState.customBlockState().handle();
|
||||
};
|
||||
default -> blockState.customBlockState().handle();
|
||||
};
|
||||
};
|
||||
});
|
||||
HARD_CODED_PROPERTY_DATA.put("facing", (behavior, property) -> {
|
||||
if (property.valueClass() == HorizontalDirection.class) {
|
||||
@SuppressWarnings("unchecked")
|
||||
Property<HorizontalDirection> directionProperty = (Property<HorizontalDirection>) property;
|
||||
behavior.rotateFunction = (thisBlock, blockState, rotation) ->
|
||||
blockState.with(directionProperty, rotation.rotate(blockState.get(directionProperty).toDirection()).toHorizontalDirection())
|
||||
.customBlockState().handle();
|
||||
behavior.mirrorFunction = (thisBlock, blockState, mirror) -> {
|
||||
Rotation rotation = mirror.getRotation(blockState.get(directionProperty).toDirection());
|
||||
return behavior.rotateFunction.rotate(thisBlock, blockState, rotation);
|
||||
};
|
||||
} else if (property.valueClass() == Direction.class) {
|
||||
@SuppressWarnings("unchecked")
|
||||
Property<Direction> directionProperty = (Property<Direction>) property;
|
||||
behavior.rotateFunction = (thisBlock, blockState, rotation) ->
|
||||
blockState.with(directionProperty, rotation.rotate(blockState.get(directionProperty)))
|
||||
.customBlockState().handle();
|
||||
behavior.mirrorFunction = (thisBlock, blockState, mirror) -> {
|
||||
Rotation rotation = mirror.getRotation(blockState.get(directionProperty));
|
||||
return behavior.rotateFunction.rotate(thisBlock, blockState, rotation);
|
||||
};
|
||||
}
|
||||
});
|
||||
HARD_CODED_PROPERTY_DATA.put("facing_clockwise", (behavior, property) -> {
|
||||
if (property.valueClass() == Direction.class) {
|
||||
@SuppressWarnings("unchecked")
|
||||
Property<Direction> directionProperty = (Property<Direction>) property;
|
||||
behavior.rotateFunction = (thisBlock, blockState, rotation) ->
|
||||
blockState.with(directionProperty, rotation.rotate(blockState.get(directionProperty)))
|
||||
.customBlockState().handle();
|
||||
behavior.mirrorFunction = (thisBlock, blockState, mirror) -> {
|
||||
Rotation rotation = mirror.getRotation(blockState.get(directionProperty));
|
||||
return behavior.rotateFunction.rotate(thisBlock, blockState, rotation);
|
||||
};
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private MirrorFunction mirrorFunction;
|
||||
private RotateFunction rotateFunction;
|
||||
|
||||
public BukkitBlockBehavior(CustomBlock customBlock) {
|
||||
super(customBlock);
|
||||
for (Property<?> property : customBlock.properties()) {
|
||||
Optional.ofNullable(HARD_CODED_PROPERTY_DATA.get(property.name())).ifPresent(
|
||||
c -> c.accept(this, property)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object mirror(Object thisBlock, Object[] args, Callable<Object> superMethod) throws Exception {
|
||||
if (this.mirrorFunction != null) {
|
||||
int id = BlockStateUtils.blockStateToId(args[0]);
|
||||
ImmutableBlockState state = BukkitBlockManager.instance().getImmutableBlockState(id);
|
||||
return this.mirrorFunction.mirror(thisBlock, state, MirrorUtils.fromNMSMirror(args[1]));
|
||||
}
|
||||
return super.mirror(thisBlock, args, superMethod);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object rotate(Object thisBlock, Object[] args, Callable<Object> superMethod) throws Exception {
|
||||
if (this.rotateFunction != null) {
|
||||
int id = BlockStateUtils.blockStateToId(args[0]);
|
||||
ImmutableBlockState state = BukkitBlockManager.instance().getImmutableBlockState(id);
|
||||
return this.rotateFunction.rotate(thisBlock, state, RotationUtils.fromNMSRotation(args[1]));
|
||||
}
|
||||
return super.rotate(thisBlock, args, superMethod);
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
interface MirrorFunction {
|
||||
|
||||
Object mirror(Object thisBlock, ImmutableBlockState state, Mirror mirror) throws Exception;
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
interface RotateFunction {
|
||||
|
||||
Object rotate(Object thisBlock, ImmutableBlockState state, Rotation rotation) throws Exception;
|
||||
}
|
||||
}
|
||||
@@ -9,7 +9,6 @@ import net.momirealms.craftengine.bukkit.util.Reflections;
|
||||
import net.momirealms.craftengine.bukkit.world.BukkitWorld;
|
||||
import net.momirealms.craftengine.core.block.CustomBlock;
|
||||
import net.momirealms.craftengine.core.block.ImmutableBlockState;
|
||||
import net.momirealms.craftengine.core.block.behavior.AbstractBlockBehavior;
|
||||
import net.momirealms.craftengine.core.block.behavior.BlockBehaviorFactory;
|
||||
import net.momirealms.craftengine.core.item.Item;
|
||||
import net.momirealms.craftengine.core.loot.parameter.LootParameters;
|
||||
@@ -29,14 +28,15 @@ import org.bukkit.Registry;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
public class BushBlockBehavior extends AbstractBlockBehavior {
|
||||
public class BushBlockBehavior extends BukkitBlockBehavior {
|
||||
public static final Factory FACTORY = new Factory();
|
||||
protected final List<Object> tagsCanSurviveOn;
|
||||
protected final Set<Object> blocksCansSurviveOn;
|
||||
protected final Set<String> customBlocksCansSurviveOn;
|
||||
protected final boolean any;
|
||||
|
||||
public BushBlockBehavior(List<Object> tagsCanSurviveOn, Set<Object> blocksCansSurviveOn, Set<String> customBlocksCansSurviveOn) {
|
||||
public BushBlockBehavior(CustomBlock block, List<Object> tagsCanSurviveOn, Set<Object> blocksCansSurviveOn, Set<String> customBlocksCansSurviveOn) {
|
||||
super(block);
|
||||
this.tagsCanSurviveOn = tagsCanSurviveOn;
|
||||
this.blocksCansSurviveOn = blocksCansSurviveOn;
|
||||
this.customBlocksCansSurviveOn = customBlocksCansSurviveOn;
|
||||
@@ -93,7 +93,7 @@ public class BushBlockBehavior extends AbstractBlockBehavior {
|
||||
@Override
|
||||
public BlockBehavior create(CustomBlock block, Map<String, Object> arguments) {
|
||||
Tuple<List<Object>, Set<Object>, Set<String>> tuple = readTagsAndState(arguments);
|
||||
return new BushBlockBehavior(tuple.left(), tuple.mid(), tuple.right());
|
||||
return new BushBlockBehavior(block, tuple.left(), tuple.mid(), tuple.right());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -32,9 +32,9 @@ public class ConcretePowderBlockBehavior extends FallingBlockBehavior {
|
||||
private Object defaultBlockState;
|
||||
private ImmutableBlockState defaultImmutableBlockState;
|
||||
|
||||
public ConcretePowderBlockBehavior(float hurtAmount, int maxHurt, Key block) {
|
||||
super(hurtAmount, maxHurt);
|
||||
this.targetBlock = block;
|
||||
public ConcretePowderBlockBehavior(CustomBlock block, float hurtAmount, int maxHurt, Key targetBlock) {
|
||||
super(block, hurtAmount, maxHurt);
|
||||
this.targetBlock = targetBlock;
|
||||
}
|
||||
|
||||
public ImmutableBlockState defaultImmutableBlockState() {
|
||||
@@ -161,7 +161,7 @@ public class ConcretePowderBlockBehavior extends FallingBlockBehavior {
|
||||
if (solidBlock == null) {
|
||||
throw new IllegalArgumentException("No `solid-block` specified for concrete powder block behavior");
|
||||
}
|
||||
return new ConcretePowderBlockBehavior(hurtAmount, hurtMax, Key.of(solidBlock));
|
||||
return new ConcretePowderBlockBehavior(block, hurtAmount, hurtMax, Key.of(solidBlock));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,9 +29,9 @@ public class CropBlockBehavior extends BushBlockBehavior {
|
||||
private final float growSpeed;
|
||||
private final int minGrowLight;
|
||||
|
||||
public CropBlockBehavior(List<Object> tagsCanSurviveOn, Set<Object> blocksCansSurviveOn, Set<String> customBlocksCansSurviveOn,
|
||||
public CropBlockBehavior(CustomBlock block, List<Object> tagsCanSurviveOn, Set<Object> blocksCansSurviveOn, Set<String> customBlocksCansSurviveOn,
|
||||
Property<Integer> ageProperty, float growSpeed, int minGrowLight) {
|
||||
super(tagsCanSurviveOn, blocksCansSurviveOn, customBlocksCansSurviveOn);
|
||||
super(block, tagsCanSurviveOn, blocksCansSurviveOn, customBlocksCansSurviveOn);
|
||||
this.ageProperty = (IntegerProperty) ageProperty;
|
||||
this.growSpeed = growSpeed;
|
||||
this.minGrowLight = minGrowLight;
|
||||
@@ -63,7 +63,7 @@ public class CropBlockBehavior extends BushBlockBehavior {
|
||||
if (currentState != null && !currentState.isEmpty()) {
|
||||
int age = this.getAge(currentState);
|
||||
if (age < this.ageProperty.max && RandomUtils.generateRandomFloat(0, 1) < this.growSpeed) {
|
||||
Reflections.method$Level$setBlock.invoke(level, pos, currentState.with(this.ageProperty, age + 1).customBlockState().handle(), UpdateOption.UPDATE_ALL.flags());
|
||||
FastNMS.INSTANCE.method$LevelWriter$setBlock(level, pos, currentState.with(this.ageProperty, age + 1).customBlockState().handle(), UpdateOption.UPDATE_ALL.flags());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -117,7 +117,7 @@ public class CropBlockBehavior extends BushBlockBehavior {
|
||||
if (i > maxAge) {
|
||||
i = maxAge;
|
||||
}
|
||||
Reflections.method$Level$setBlock.invoke(level, pos, immutableBlockState.with(this.ageProperty, i).customBlockState().handle(), UpdateOption.UPDATE_NONE.flags());
|
||||
FastNMS.INSTANCE.method$LevelWriter$setBlock(level, pos, immutableBlockState.with(this.ageProperty, i).customBlockState().handle(), UpdateOption.UPDATE_NONE.flags());
|
||||
if (sendParticles) {
|
||||
World world = FastNMS.INSTANCE.method$Level$getCraftWorld(level);
|
||||
int x = FastNMS.INSTANCE.field$Vec3i$x(pos);
|
||||
@@ -140,7 +140,7 @@ public class CropBlockBehavior extends BushBlockBehavior {
|
||||
// 存活条件是最小生长亮度-1
|
||||
int minGrowLight = MiscUtils.getAsInt(arguments.getOrDefault("light-requirement", 9));
|
||||
float growSpeed = MiscUtils.getAsFloat(arguments.getOrDefault("grow-speed", 0.25f));
|
||||
return new CropBlockBehavior(tuple.left(), tuple.mid(), tuple.right(), ageProperty, growSpeed, minGrowLight);
|
||||
return new CropBlockBehavior(block, tuple.left(), tuple.mid(), tuple.right(), ageProperty, growSpeed, minGrowLight);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,6 @@ import net.momirealms.craftengine.bukkit.util.Reflections;
|
||||
import net.momirealms.craftengine.bukkit.world.BukkitWorld;
|
||||
import net.momirealms.craftengine.core.block.CustomBlock;
|
||||
import net.momirealms.craftengine.core.block.ImmutableBlockState;
|
||||
import net.momirealms.craftengine.core.block.behavior.AbstractBlockBehavior;
|
||||
import net.momirealms.craftengine.core.block.behavior.BlockBehaviorFactory;
|
||||
import net.momirealms.craftengine.core.item.Item;
|
||||
import net.momirealms.craftengine.core.loot.parameter.LootParameters;
|
||||
@@ -21,12 +20,13 @@ import net.momirealms.craftengine.shared.block.BlockBehavior;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
public class FallingBlockBehavior extends AbstractBlockBehavior {
|
||||
public class FallingBlockBehavior extends BukkitBlockBehavior {
|
||||
public static final Factory FACTORY = new Factory();
|
||||
private final float hurtAmount;
|
||||
private final int maxHurt;
|
||||
|
||||
public FallingBlockBehavior(float hurtAmount, int maxHurt) {
|
||||
public FallingBlockBehavior(CustomBlock block, float hurtAmount, int maxHurt) {
|
||||
super(block);
|
||||
this.hurtAmount = hurtAmount;
|
||||
this.maxHurt = maxHurt;
|
||||
}
|
||||
@@ -131,7 +131,7 @@ public class FallingBlockBehavior extends AbstractBlockBehavior {
|
||||
public BlockBehavior create(CustomBlock block, Map<String, Object> arguments) {
|
||||
float hurtAmount = MiscUtils.getAsFloat(arguments.getOrDefault("hurt-amount", -1f));
|
||||
int hurtMax = MiscUtils.getAsInt(arguments.getOrDefault("max-hurt", -1));
|
||||
return new FallingBlockBehavior(hurtAmount, hurtMax);
|
||||
return new FallingBlockBehavior(block, hurtAmount, hurtMax);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,8 +13,8 @@ import java.util.Set;
|
||||
public class HangingBlockBehavior extends BushBlockBehavior {
|
||||
public static final Factory FACTORY = new Factory();
|
||||
|
||||
public HangingBlockBehavior(List<Object> tagsCanSurviveOn, Set<Object> blocksCansSurviveOn, Set<String> customBlocksCansSurviveOn) {
|
||||
super(tagsCanSurviveOn, blocksCansSurviveOn, customBlocksCansSurviveOn);
|
||||
public HangingBlockBehavior(CustomBlock block, List<Object> tagsCanSurviveOn, Set<Object> blocksCansSurviveOn, Set<String> customBlocksCansSurviveOn) {
|
||||
super(block, tagsCanSurviveOn, blocksCansSurviveOn, customBlocksCansSurviveOn);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -32,7 +32,7 @@ public class HangingBlockBehavior extends BushBlockBehavior {
|
||||
@Override
|
||||
public BlockBehavior create(CustomBlock block, Map<String, Object> arguments) {
|
||||
Tuple<List<Object>, Set<Object>, Set<String>> tuple = readTagsAndState(arguments);
|
||||
return new HangingBlockBehavior(tuple.left(), tuple.mid(), tuple.right());
|
||||
return new HangingBlockBehavior(block, tuple.left(), tuple.mid(), tuple.right());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,8 +39,8 @@ public class LeavesBlockBehavior extends WaterLoggedBlockBehavior {
|
||||
@Nullable
|
||||
private final Property<Boolean> waterloggedProperty;
|
||||
|
||||
public LeavesBlockBehavior(int maxDistance, Property<Integer> distanceProperty, Property<Boolean> persistentProperty, @Nullable Property<Boolean> waterloggedProperty) {
|
||||
super(waterloggedProperty);
|
||||
public LeavesBlockBehavior(CustomBlock block, int maxDistance, Property<Integer> distanceProperty, Property<Boolean> persistentProperty, @Nullable Property<Boolean> waterloggedProperty) {
|
||||
super(block, waterloggedProperty);
|
||||
this.maxDistance = maxDistance;
|
||||
this.distanceProperty = distanceProperty;
|
||||
this.persistentProperty = persistentProperty;
|
||||
@@ -97,7 +97,7 @@ public class LeavesBlockBehavior extends WaterLoggedBlockBehavior {
|
||||
if (blockState == newState.customBlockState().handle()) {
|
||||
Reflections.method$BlockStateBase$updateNeighbourShapes.invoke(blockState, level, blockPos, UpdateOption.UPDATE_ALL.flags(), 512);
|
||||
} else {
|
||||
Reflections.method$Level$setBlock.invoke(level, blockPos, newState.customBlockState().handle(), UpdateOption.UPDATE_ALL.flags());
|
||||
FastNMS.INSTANCE.method$LevelWriter$setBlock(level, blockPos, newState.customBlockState().handle(), UpdateOption.UPDATE_ALL.flags());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -182,7 +182,7 @@ public class LeavesBlockBehavior extends WaterLoggedBlockBehavior {
|
||||
}
|
||||
Property<Boolean> waterlogged = (Property<Boolean>) block.getProperty("waterlogged");
|
||||
int actual = distance.possibleValues().get(distance.possibleValues().size() - 1);
|
||||
return new LeavesBlockBehavior(actual, distance, persistent, waterlogged);
|
||||
return new LeavesBlockBehavior(block, actual, distance, persistent, waterlogged);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,8 +16,8 @@ public class OnLiquidBlockBehavior extends BushBlockBehavior {
|
||||
private final boolean onWater;
|
||||
private final boolean onLava;
|
||||
|
||||
public OnLiquidBlockBehavior(boolean onWater, boolean onLava) {
|
||||
super(List.of(), Set.of(), Set.of());
|
||||
public OnLiquidBlockBehavior(CustomBlock block, boolean onWater, boolean onLava) {
|
||||
super(block, List.of(), Set.of(), Set.of());
|
||||
this.onWater = onWater;
|
||||
this.onLava = onLava;
|
||||
}
|
||||
@@ -34,7 +34,7 @@ public class OnLiquidBlockBehavior extends BushBlockBehavior {
|
||||
@Override
|
||||
public BlockBehavior create(CustomBlock block, Map<String, Object> arguments) {
|
||||
List<String> liquidTypes = MiscUtils.getAsStringList(arguments.getOrDefault("liquid-type", List.of("water")));
|
||||
return new OnLiquidBlockBehavior(liquidTypes.contains("water"), liquidTypes.contains("lava"));
|
||||
return new OnLiquidBlockBehavior(block, liquidTypes.contains("water"), liquidTypes.contains("lava"));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -31,8 +31,8 @@ public class SaplingBlockBehavior extends BushBlockBehavior {
|
||||
private final double boneMealSuccessChance;
|
||||
private final float growSpeed;
|
||||
|
||||
public SaplingBlockBehavior(Key feature, Property<Integer> stageProperty, List<Object> tagsCanSurviveOn, Set<Object> blocksCansSurviveOn, Set<String> customBlocksCansSurviveOn, double boneMealSuccessChance, float growSpeed) {
|
||||
super(tagsCanSurviveOn, blocksCansSurviveOn, customBlocksCansSurviveOn);
|
||||
public SaplingBlockBehavior(CustomBlock block, Key feature, Property<Integer> stageProperty, List<Object> tagsCanSurviveOn, Set<Object> blocksCansSurviveOn, Set<String> customBlocksCansSurviveOn, double boneMealSuccessChance, float growSpeed) {
|
||||
super(block, tagsCanSurviveOn, blocksCansSurviveOn, customBlocksCansSurviveOn);
|
||||
this.feature = feature;
|
||||
this.stageProperty = stageProperty;
|
||||
this.boneMealSuccessChance = boneMealSuccessChance;
|
||||
@@ -79,18 +79,18 @@ public class SaplingBlockBehavior extends BushBlockBehavior {
|
||||
CraftEngine.instance().logger().warn("Configured feature not found: " + treeFeature());
|
||||
return;
|
||||
}
|
||||
Object chunkGenerator = Reflections.method$ServerChunkCache$getGenerator.invoke(Reflections.field$ServerLevel$chunkSource.get(world));
|
||||
Object chunkGenerator = Reflections.method$ServerChunkCache$getGenerator.invoke(FastNMS.INSTANCE.method$ServerLevel$getChunkSource(world));
|
||||
Object configuredFeature = Reflections.method$Holder$value.invoke(holder.get());
|
||||
Object fluidState = Reflections.method$Level$getFluidState.invoke(world, blockPos);
|
||||
Object legacyState = Reflections.method$FluidState$createLegacyBlock.invoke(fluidState);
|
||||
Reflections.method$Level$setBlock.invoke(world, blockPos, legacyState, UpdateOption.UPDATE_NONE.flags());
|
||||
FastNMS.INSTANCE.method$LevelWriter$setBlock(world, blockPos, legacyState, UpdateOption.UPDATE_NONE.flags());
|
||||
if ((boolean) Reflections.method$ConfiguredFeature$place.invoke(configuredFeature, world, chunkGenerator, randomSource, blockPos)) {
|
||||
if (FastNMS.INSTANCE.method$BlockGetter$getBlockState(world, blockPos) == legacyState) {
|
||||
Reflections.method$ServerLevel$sendBlockUpdated.invoke(world, blockPos, blockState, legacyState, 2);
|
||||
}
|
||||
} else {
|
||||
// failed to place, rollback changes
|
||||
Reflections.method$Level$setBlock.invoke(world, blockPos, blockState, UpdateOption.UPDATE_NONE.flags());
|
||||
FastNMS.INSTANCE.method$LevelWriter$setBlock(world, blockPos, blockState, UpdateOption.UPDATE_NONE.flags());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -150,7 +150,7 @@ public class SaplingBlockBehavior extends BushBlockBehavior {
|
||||
}
|
||||
double boneMealSuccessChance = MiscUtils.getAsDouble(arguments.getOrDefault("bone-meal-success-chance", 0.45));
|
||||
Tuple<List<Object>, Set<Object>, Set<String>> tuple = readTagsAndState(arguments);
|
||||
return new SaplingBlockBehavior(Key.of(feature), stageProperty, tuple.left(), tuple.mid(), tuple.right(), boneMealSuccessChance,
|
||||
return new SaplingBlockBehavior(block, Key.of(feature), stageProperty, tuple.left(), tuple.mid(), tuple.right(), boneMealSuccessChance,
|
||||
MiscUtils.getAsFloat(arguments.getOrDefault("grow-speed", 1.0 / 7.0)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
package net.momirealms.craftengine.bukkit.block.behavior;
|
||||
|
||||
import net.momirealms.craftengine.core.block.CustomBlock;
|
||||
import net.momirealms.craftengine.core.block.behavior.AbstractBlockBehavior;
|
||||
import net.momirealms.craftengine.core.block.behavior.BlockBehaviorFactory;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
import net.momirealms.craftengine.shared.block.BlockBehavior;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public class StrippableBlockBehavior extends AbstractBlockBehavior {
|
||||
public class StrippableBlockBehavior extends BukkitBlockBehavior {
|
||||
public static final Factory FACTORY = new Factory();
|
||||
private final Key stripped;
|
||||
|
||||
public StrippableBlockBehavior(Key stripped) {
|
||||
public StrippableBlockBehavior(CustomBlock block, Key stripped) {
|
||||
super(block);
|
||||
this.stripped = stripped;
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ public class StrippableBlockBehavior extends AbstractBlockBehavior {
|
||||
if (stripped == null) {
|
||||
throw new IllegalArgumentException("stripped is null");
|
||||
}
|
||||
return new StrippableBlockBehavior(Key.of(stripped));
|
||||
return new StrippableBlockBehavior(block, Key.of(stripped));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,17 +38,15 @@ public class SugarCaneBlockBehavior extends BushBlockBehavior {
|
||||
private final boolean nearLava;
|
||||
private final IntegerProperty ageProperty;
|
||||
private final float growSpeed;
|
||||
private final CustomBlock customBlock;
|
||||
|
||||
public SugarCaneBlockBehavior(CustomBlock customBlock, List<Object> tagsCanSurviveOn, Set<Object> blocksCansSurviveOn, Set<String> customBlocksCansSurviveOn, Property<Integer> ageProperty,
|
||||
int maxHeight, boolean nearWater, boolean nearLava, float growSpeed) {
|
||||
super(tagsCanSurviveOn, blocksCansSurviveOn, customBlocksCansSurviveOn);
|
||||
super(customBlock, tagsCanSurviveOn, blocksCansSurviveOn, customBlocksCansSurviveOn);
|
||||
this.nearWater = nearWater;
|
||||
this.nearLava = nearLava;
|
||||
this.maxHeight = maxHeight;
|
||||
this.ageProperty = (IntegerProperty) ageProperty;
|
||||
this.growSpeed = growSpeed;
|
||||
this.customBlock = customBlock;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -120,13 +118,13 @@ public class SugarCaneBlockBehavior extends BushBlockBehavior {
|
||||
if (age >= this.ageProperty.max || RandomUtils.generateRandomFloat(0, 1) < this.growSpeed) {
|
||||
Object abovePos = LocationUtils.above(blockPos);
|
||||
if (VersionHelper.isVersionNewerThan1_21_5()) {
|
||||
Reflections.method$CraftEventFactory$handleBlockGrowEvent.invoke(null, level, abovePos, customBlock.defaultState().customBlockState().handle(), UpdateOption.UPDATE_ALL.flags());
|
||||
Reflections.method$CraftEventFactory$handleBlockGrowEvent.invoke(null, level, abovePos, super.customBlock.defaultState().customBlockState().handle(), UpdateOption.UPDATE_ALL.flags());
|
||||
} else {
|
||||
Reflections.method$CraftEventFactory$handleBlockGrowEvent.invoke(null, level, abovePos, customBlock.defaultState().customBlockState().handle());
|
||||
Reflections.method$CraftEventFactory$handleBlockGrowEvent.invoke(null, level, abovePos, super.customBlock.defaultState().customBlockState().handle());
|
||||
}
|
||||
Reflections.method$Level$setBlock.invoke(level, blockPos, currentState.with(this.ageProperty, this.ageProperty.min).customBlockState().handle(), UpdateOption.UPDATE_NONE.flags());
|
||||
FastNMS.INSTANCE.method$LevelWriter$setBlock(level, blockPos, currentState.with(this.ageProperty, this.ageProperty.min).customBlockState().handle(), UpdateOption.UPDATE_NONE.flags());
|
||||
} else if (RandomUtils.generateRandomFloat(0, 1) < this.growSpeed) {
|
||||
Reflections.method$Level$setBlock.invoke(level, blockPos, currentState.with(this.ageProperty, age + 1).customBlockState().handle(), UpdateOption.UPDATE_NONE.flags());
|
||||
FastNMS.INSTANCE.method$LevelWriter$setBlock(level, blockPos, currentState.with(this.ageProperty, age + 1).customBlockState().handle(), UpdateOption.UPDATE_NONE.flags());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -143,7 +141,7 @@ public class SugarCaneBlockBehavior extends BushBlockBehavior {
|
||||
// 如果下方是同种方块
|
||||
if (!BlockStateUtils.isVanillaBlock(id)) {
|
||||
ImmutableBlockState immutableBlockState = BukkitBlockManager.instance().getImmutableBlockStateUnsafe(id);
|
||||
if (immutableBlockState.owner().value() == this.customBlock) {
|
||||
if (immutableBlockState.owner().value() == super.customBlock) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package net.momirealms.craftengine.bukkit.block.behavior;
|
||||
|
||||
import net.momirealms.craftengine.core.block.CustomBlock;
|
||||
import net.momirealms.craftengine.core.block.behavior.AbstractBlockBehavior;
|
||||
import net.momirealms.craftengine.core.block.behavior.BlockBehaviorFactory;
|
||||
import net.momirealms.craftengine.core.block.properties.Property;
|
||||
import net.momirealms.craftengine.shared.block.BlockBehavior;
|
||||
@@ -9,12 +8,13 @@ import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public class WaterLoggedBlockBehavior extends AbstractBlockBehavior {
|
||||
public class WaterLoggedBlockBehavior extends BukkitBlockBehavior {
|
||||
public static final Factory FACTORY = new Factory();
|
||||
@Nullable
|
||||
private final Property<Boolean> waterloggedProperty;
|
||||
|
||||
public WaterLoggedBlockBehavior(@Nullable Property<Boolean> waterloggedProperty) {
|
||||
public WaterLoggedBlockBehavior(CustomBlock block, @Nullable Property<Boolean> waterloggedProperty) {
|
||||
super(block);
|
||||
this.waterloggedProperty = waterloggedProperty;
|
||||
}
|
||||
|
||||
@@ -82,7 +82,7 @@ public class WaterLoggedBlockBehavior extends AbstractBlockBehavior {
|
||||
@Override
|
||||
public BlockBehavior create(CustomBlock block, Map<String, Object> arguments) {
|
||||
Property<Boolean> waterlogged = (Property<Boolean>) block.getProperty("waterlogged");
|
||||
return new WaterLoggedBlockBehavior(waterlogged);
|
||||
return new WaterLoggedBlockBehavior(block, waterlogged);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -112,9 +112,9 @@ public class LoadedFurniture {
|
||||
});
|
||||
}
|
||||
try {
|
||||
this.cachedSpawnPacket = Reflections.constructor$ClientboundBundlePacket.newInstance(packets);
|
||||
this.cachedSpawnPacket = FastNMS.INSTANCE.constructor$ClientboundBundlePacket(packets);
|
||||
if (this.minimized) {
|
||||
this.cachedMinimizedSpawnPacket = Reflections.constructor$ClientboundBundlePacket.newInstance(minimizedPackets);
|
||||
this.cachedMinimizedSpawnPacket = FastNMS.INSTANCE.constructor$ClientboundBundlePacket(minimizedPackets);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
CraftEngine.instance().logger().warn("Failed to init spawn packets for furniture " + id, e);
|
||||
|
||||
@@ -150,7 +150,7 @@ public class BlockItemBehavior extends ItemBehavior {
|
||||
Object blockState = state.customBlockState().handle();
|
||||
Object blockPos = LocationUtils.toBlockPos(context.getClickedPos());
|
||||
Object voxelShape = Reflections.method$CollisionContext$of.invoke(null, player);
|
||||
Object world = Reflections.field$CraftWorld$ServerLevel.get(context.getLevel().platformWorld());
|
||||
Object world = FastNMS.INSTANCE.field$CraftWorld$ServerLevel((World) context.getLevel().platformWorld());
|
||||
boolean defaultReturn = ((!this.checkStatePlacement() || (boolean) Reflections.method$BlockStateBase$canSurvive.invoke(blockState, world, blockPos))
|
||||
&& (boolean) Reflections.method$ServerLevel$checkEntityCollision.invoke(world, blockState, player, voxelShape, blockPos, true));
|
||||
Block block = FastNMS.INSTANCE.method$CraftBlock$at(world, blockPos);
|
||||
|
||||
@@ -3,6 +3,7 @@ package net.momirealms.craftengine.bukkit.item.recipe;
|
||||
import com.destroystokyo.paper.event.inventory.PrepareResultEvent;
|
||||
import net.kyori.adventure.text.Component;
|
||||
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.injector.BukkitInjector;
|
||||
import net.momirealms.craftengine.bukkit.plugin.user.BukkitServerPlayer;
|
||||
@@ -347,7 +348,7 @@ public class RecipeEventListener implements Listener {
|
||||
BukkitRecipeManager.minecraftRecipeManager(),
|
||||
Reflections.instance$RecipeType$CAMPFIRE_COOKING,
|
||||
Reflections.constructor$SingleRecipeInput.newInstance(Reflections.method$CraftItemStack$asNMSCopy.invoke(null, itemStack)),
|
||||
Reflections.field$CraftWorld$ServerLevel.get(event.getPlayer().getWorld()),
|
||||
FastNMS.INSTANCE.field$CraftWorld$ServerLevel(event.getPlayer().getWorld()),
|
||||
null
|
||||
);
|
||||
if (optionalMCRecipe.isEmpty()) {
|
||||
|
||||
@@ -1,9 +1,6 @@
|
||||
package net.momirealms.craftengine.bukkit.plugin.command.feature;
|
||||
|
||||
import net.momirealms.craftengine.bukkit.nms.CollisionEntity;
|
||||
import net.momirealms.craftengine.bukkit.nms.FastNMS;
|
||||
import net.momirealms.craftengine.bukkit.plugin.command.BukkitCommandFeature;
|
||||
import net.momirealms.craftengine.bukkit.util.Reflections;
|
||||
import net.momirealms.craftengine.core.plugin.CraftEngine;
|
||||
import net.momirealms.craftengine.core.plugin.command.CraftEngineCommandManager;
|
||||
import org.bukkit.Location;
|
||||
@@ -25,11 +22,7 @@ public class TestCommand extends BukkitCommandFeature<CommandSender> {
|
||||
Player player = context.sender();
|
||||
Location location = player.getLocation();
|
||||
try {
|
||||
Object level = Reflections.field$CraftWorld$ServerLevel.get(player.getWorld());
|
||||
Object aabb = FastNMS.INSTANCE.constructor$AABB(location.getBlockX(), location.getBlockY(), location.getBlockZ(),
|
||||
location.getBlockX() + 1, location.getBlockY() + 1, location.getBlockZ() + 1);
|
||||
CollisionEntity nmsEntity = FastNMS.INSTANCE.createCollisionEntity(level, aabb, location.getBlockX() + 0.5, location.getBlockY(), location.getBlockZ() + 0.5, false);
|
||||
FastNMS.INSTANCE.method$LevelWriter$addFreshEntity(level, nmsEntity);
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
@@ -174,6 +174,12 @@ public class BukkitInjector {
|
||||
// getShape
|
||||
.method(ElementMatchers.is(Reflections.method$BlockBehaviour$getShape))
|
||||
.intercept(MethodDelegation.to(GetShapeInterceptor.INSTANCE))
|
||||
// mirror
|
||||
.method(ElementMatchers.is(Reflections.method$BlockBehaviour$mirror))
|
||||
.intercept(MethodDelegation.to(MirrorInterceptor.INSTANCE))
|
||||
// rotate
|
||||
.method(ElementMatchers.is(Reflections.method$BlockBehaviour$rotate))
|
||||
.intercept(MethodDelegation.to(RotateInterceptor.INSTANCE))
|
||||
// tick
|
||||
.method(ElementMatchers.is(Reflections.method$BlockBehaviour$tick))
|
||||
.intercept(MethodDelegation.to(TickInterceptor.INSTANCE))
|
||||
@@ -711,8 +717,8 @@ public class BukkitInjector {
|
||||
int id = (int) Reflections.field$Direction$data3d.get(direction);
|
||||
// Y axis
|
||||
if (id == 0 || id == 1) {
|
||||
Object chunkSource = Reflections.field$ServerLevel$chunkSource.get(serverLevel);
|
||||
Reflections.method$ServerChunkCache$blockChanged.invoke(chunkSource, blockPos);
|
||||
Object chunkSource = FastNMS.INSTANCE.method$ServerLevel$getChunkSource(serverLevel);
|
||||
FastNMS.INSTANCE.method$ServerChunkCache$blockChanged(chunkSource, blockPos);
|
||||
if (id == 1) {
|
||||
NoteBlockChainUpdateUtils.noteBlockChainUpdate(serverLevel, chunkSource, Reflections.instance$Direction$DOWN, blockPos, 0);
|
||||
} else {
|
||||
@@ -736,6 +742,36 @@ public class BukkitInjector {
|
||||
}
|
||||
}
|
||||
|
||||
public static class MirrorInterceptor {
|
||||
public static final MirrorInterceptor INSTANCE = new MirrorInterceptor();
|
||||
|
||||
@RuntimeType
|
||||
public Object intercept(@This Object thisObj, @AllArguments Object[] args, @SuperCall Callable<Object> superMethod) throws Exception {
|
||||
ObjectHolder<BlockBehavior> holder = ((BehaviorHolder) thisObj).getBehaviorHolder();
|
||||
try {
|
||||
return holder.value().mirror(thisObj, args, superMethod);
|
||||
} catch (Exception e) {
|
||||
CraftEngine.instance().logger().severe("Failed to run mirror", e);
|
||||
return superMethod.call();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class RotateInterceptor {
|
||||
public static final RotateInterceptor INSTANCE = new RotateInterceptor();
|
||||
|
||||
@RuntimeType
|
||||
public Object intercept(@This Object thisObj, @AllArguments Object[] args, @SuperCall Callable<Object> superMethod) throws Exception {
|
||||
ObjectHolder<BlockBehavior> holder = ((BehaviorHolder) thisObj).getBehaviorHolder();
|
||||
try {
|
||||
return holder.value().rotate(thisObj, args, superMethod);
|
||||
} catch (Exception e) {
|
||||
CraftEngine.instance().logger().severe("Failed to run rotate", e);
|
||||
return superMethod.call();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class RandomTickInterceptor {
|
||||
public static final RandomTickInterceptor INSTANCE = new RandomTickInterceptor();
|
||||
|
||||
|
||||
@@ -92,31 +92,19 @@ public class BukkitNetworkManager implements NetworkManager, Listener, PluginMes
|
||||
}
|
||||
this.registerConsumers();
|
||||
this.packetsConsumer = ((serverPlayer, packets) -> {
|
||||
try {
|
||||
Object bundle = Reflections.constructor$ClientboundBundlePacket.newInstance(packets);
|
||||
Reflections.method$ServerGamePacketListenerImpl$sendPacket.invoke(
|
||||
Reflections.field$ServerPlayer$connection.get(serverPlayer), bundle);
|
||||
} catch (ReflectiveOperationException e) {
|
||||
plugin.logger().warn("Failed to create bundle packet", e);
|
||||
}
|
||||
Object bundle = FastNMS.INSTANCE.constructor$ClientboundBundlePacket(packets);
|
||||
FastNMS.INSTANCE.sendPacket(serverPlayer, bundle);
|
||||
});
|
||||
this.delayedPacketConsumer = (serverPlayer, packet) -> {
|
||||
try {
|
||||
Reflections.method$ServerGamePacketListenerImpl$sendPacket.invoke(
|
||||
Reflections.field$ServerPlayer$connection.get(serverPlayer), packet);
|
||||
} catch (ReflectiveOperationException e) {
|
||||
plugin.logger().warn("Failed to invoke send packet", e);
|
||||
}
|
||||
};
|
||||
this.delayedPacketConsumer = FastNMS.INSTANCE::sendPacket;
|
||||
this.immediatePacketConsumer = (serverPlayer, packet) -> {
|
||||
try {
|
||||
Reflections.method$Connection$sendPacketImmediate.invoke(Reflections.field$ServerCommonPacketListenerImpl$connection.get(Reflections.field$ServerPlayer$connection.get(serverPlayer)), packet, null, true);
|
||||
Reflections.method$Connection$sendPacketImmediate.invoke(FastNMS.INSTANCE.field$Player$connection$connection(serverPlayer), packet, null, true);
|
||||
} catch (ReflectiveOperationException e) {
|
||||
plugin.logger().warn("Failed to invoke send packet", e);
|
||||
}
|
||||
};
|
||||
this.active = true;
|
||||
this.hasModelEngine = Bukkit.getPluginManager().getPlugin("ModelEngine") != null;
|
||||
hasModelEngine = Bukkit.getPluginManager().getPlugin("ModelEngine") != null;
|
||||
instance = this;
|
||||
}
|
||||
|
||||
@@ -258,17 +246,7 @@ public class BukkitNetworkManager implements NetworkManager, Listener, PluginMes
|
||||
}
|
||||
|
||||
public Channel getChannel(Player player) {
|
||||
try {
|
||||
return (Channel) Reflections.field$Channel.get(
|
||||
Reflections.field$NetworkManager.get(
|
||||
Reflections.field$ServerPlayer$connection.get(
|
||||
FastNMS.INSTANCE.method$CraftPlayer$getHandle(player)
|
||||
)
|
||||
)
|
||||
);
|
||||
} catch (ReflectiveOperationException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
return (Channel) FastNMS.INSTANCE.field$Player$connection$connection$channel(FastNMS.INSTANCE.method$CraftPlayer$getHandle(player));
|
||||
}
|
||||
|
||||
public void sendPacket(@NotNull Player player, @NotNull Object packet) {
|
||||
|
||||
@@ -291,7 +291,7 @@ public class PacketConsumers {
|
||||
private static void handlePlayerActionPacketOnMainThread(BukkitServerPlayer player, World world, BlockPos pos, Object packet) throws Exception {
|
||||
Object action = Reflections.field$ServerboundPlayerActionPacket$action.get(packet);
|
||||
if (action == Reflections.instance$ServerboundPlayerActionPacket$Action$START_DESTROY_BLOCK) {
|
||||
Object serverLevel = Reflections.field$CraftWorld$ServerLevel.get(world);
|
||||
Object serverLevel = FastNMS.INSTANCE.field$CraftWorld$ServerLevel(world);
|
||||
Object blockState = FastNMS.INSTANCE.method$BlockGetter$getBlockState(serverLevel, LocationUtils.toBlockPos(pos));
|
||||
int stateId = BlockStateUtils.blockStateToId(blockState);
|
||||
// not a custom block
|
||||
@@ -546,7 +546,7 @@ public class PacketConsumers {
|
||||
};
|
||||
|
||||
private static void handlePickItemFromBlockPacketOnMainThread(Player player, Object pos) throws Exception {
|
||||
Object serverLevel = Reflections.field$CraftWorld$ServerLevel.get(player.getWorld());
|
||||
Object serverLevel = FastNMS.INSTANCE.field$CraftWorld$ServerLevel(player.getWorld());
|
||||
Object blockState = FastNMS.INSTANCE.method$BlockGetter$getBlockState(serverLevel, pos);
|
||||
ImmutableBlockState state = BukkitBlockManager.instance().getImmutableBlockState(BlockStateUtils.blockStateToId(blockState));
|
||||
if (state == null) return;
|
||||
|
||||
@@ -40,4 +40,13 @@ public class DirectionUtils {
|
||||
case EAST -> Reflections.instance$Direction$EAST;
|
||||
};
|
||||
}
|
||||
|
||||
public static Direction fromNMSDirection(Object direction) {
|
||||
try {
|
||||
int index = (int) Reflections.method$Direction$ordinal.invoke(direction);
|
||||
return Direction.values()[index];
|
||||
} catch (ReflectiveOperationException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package net.momirealms.craftengine.bukkit.util;
|
||||
|
||||
import net.momirealms.craftengine.bukkit.nms.FastNMS;
|
||||
import net.momirealms.craftengine.core.plugin.CraftEngine;
|
||||
import org.bukkit.World;
|
||||
|
||||
@@ -11,30 +12,25 @@ public class LightUtils {
|
||||
|
||||
private LightUtils() {}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static void updateChunkLight(World world, Map<Long, BitSet> sectionPosSet) {
|
||||
try {
|
||||
Object serverLevel = Reflections.field$CraftWorld$ServerLevel.get(world);
|
||||
Object chunkSource = Reflections.field$ServerLevel$chunkSource.get(serverLevel);
|
||||
Object serverLevel = FastNMS.INSTANCE.field$CraftWorld$ServerLevel(world);
|
||||
Object chunkSource = FastNMS.INSTANCE.method$ServerLevel$getChunkSource(serverLevel);
|
||||
for (Map.Entry<Long, BitSet> entry : sectionPosSet.entrySet()) {
|
||||
long chunkKey = entry.getKey();
|
||||
Object chunkHolder = Reflections.method$ServerChunkCache$getVisibleChunkIfPresent.invoke(chunkSource, chunkKey);
|
||||
Object chunkHolder = FastNMS.INSTANCE.method$ServerChunkCache$getVisibleChunkIfPresent(chunkSource, chunkKey);
|
||||
if (chunkHolder == null) continue;
|
||||
List<Object> players;
|
||||
if (Reflections.method$ChunkHolder$getPlayers != null) {
|
||||
players = (List<Object>) Reflections.method$ChunkHolder$getPlayers.invoke(chunkHolder, false);
|
||||
} else {
|
||||
Object chunkHolder$PlayerProvider = Reflections.field$ChunkHolder$playerProvider.get(chunkHolder);
|
||||
players = (List<Object>) Reflections.method$ChunkHolder$PlayerProvider$getPlayers.invoke(chunkHolder$PlayerProvider, false);
|
||||
}
|
||||
List<Object> players = FastNMS.INSTANCE.method$ChunkHolder$getPlayers(chunkHolder);
|
||||
if (players.isEmpty()) continue;
|
||||
Object lightEngine = Reflections.field$ChunkHolder$lightEngine.get(chunkHolder);
|
||||
BitSet blockChangedLightSectionFilter = (BitSet) Reflections.field$ChunkHolder$blockChangedLightSectionFilter.get(chunkHolder);
|
||||
blockChangedLightSectionFilter.or(entry.getValue());
|
||||
BitSet skyChangedLightSectionFilter = (BitSet) Reflections.field$ChunkHolder$skyChangedLightSectionFilter.get(chunkHolder);
|
||||
Object chunkPos = Reflections.constructor$ChunkPos.newInstance((int) chunkKey, (int) (chunkKey >> 32));
|
||||
Object lightPacket = Reflections.constructor$ClientboundLightUpdatePacket.newInstance(chunkPos, lightEngine, skyChangedLightSectionFilter, blockChangedLightSectionFilter);
|
||||
Reflections.method$ChunkHolder$broadcast.invoke(chunkHolder, players, lightPacket);
|
||||
Object chunkPos = FastNMS.INSTANCE.constructor$ChunkPos((int) chunkKey, (int) (chunkKey >> 32));
|
||||
Object lightPacket = FastNMS.INSTANCE.constructor$ClientboundLightUpdatePacket(chunkPos, lightEngine, skyChangedLightSectionFilter, blockChangedLightSectionFilter);
|
||||
for (Object player : players) {
|
||||
FastNMS.INSTANCE.sendPacket(player, lightPacket);
|
||||
}
|
||||
blockChangedLightSectionFilter.clear();
|
||||
skyChangedLightSectionFilter.clear();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
package net.momirealms.craftengine.bukkit.util;
|
||||
|
||||
import net.momirealms.craftengine.core.util.Mirror;
|
||||
|
||||
public class MirrorUtils {
|
||||
|
||||
private MirrorUtils() {}
|
||||
|
||||
public static Mirror fromNMSMirror(Object mirror) {
|
||||
try {
|
||||
int index = (int) Reflections.method$Mirror$ordinal.invoke(mirror);
|
||||
return Mirror.values()[index];
|
||||
} catch (ReflectiveOperationException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static Object toNMSMirror(Mirror mirror) {
|
||||
switch (mirror) {
|
||||
case FRONT_BACK -> {
|
||||
return Reflections.instance$Mirror$FRONT_BACK;
|
||||
}
|
||||
case LEFT_RIGHT -> {
|
||||
return Reflections.instance$Mirror$LEFT_RIGHT;
|
||||
}
|
||||
default -> {
|
||||
return Reflections.instance$Mirror$NONE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -12,7 +12,7 @@ public class NoteBlockChainUpdateUtils {
|
||||
Object relativePos = Reflections.method$BlockPos$relative.invoke(blockPos, direction);
|
||||
Object state = FastNMS.INSTANCE.method$BlockGetter$getBlockState(level, relativePos);
|
||||
if (BlockStateUtils.isClientSideNoteBlock(state)) {
|
||||
Reflections.method$ServerChunkCache$blockChanged.invoke(chunkSource, relativePos);
|
||||
FastNMS.INSTANCE.method$ServerChunkCache$blockChanged(chunkSource, relativePos);
|
||||
noteBlockChainUpdate(level, chunkSource, direction, relativePos, times+1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -421,9 +421,9 @@ public class Reflections {
|
||||
)
|
||||
);
|
||||
|
||||
public static final Constructor<?> constructor$ClientboundBundlePacket = requireNonNull(
|
||||
ReflectionUtils.getConstructor(clazz$ClientboundBundlePacket, Iterable.class)
|
||||
);
|
||||
// public static final Constructor<?> constructor$ClientboundBundlePacket = requireNonNull(
|
||||
// ReflectionUtils.getConstructor(clazz$ClientboundBundlePacket, Iterable.class)
|
||||
// );
|
||||
|
||||
public static final Class<?> clazz$Packet = requireNonNull(
|
||||
ReflectionUtils.getClazz(
|
||||
@@ -494,12 +494,6 @@ public class Reflections {
|
||||
)
|
||||
);
|
||||
|
||||
public static final Field field$NetworkManager = requireNonNull(
|
||||
VersionHelper.isVersionNewerThan1_20_2() ?
|
||||
ReflectionUtils.getDeclaredField(clazz$ServerGamePacketListenerImpl.getSuperclass(), clazz$Connection, 0) :
|
||||
ReflectionUtils.getDeclaredField(clazz$ServerGamePacketListenerImpl, clazz$Connection, 0)
|
||||
);
|
||||
|
||||
public static final Field field$Channel = requireNonNull(
|
||||
ReflectionUtils.getDeclaredField(
|
||||
clazz$Connection, Channel.class, 0
|
||||
@@ -1053,11 +1047,12 @@ public class Reflections {
|
||||
)
|
||||
);
|
||||
|
||||
public static final Field field$CraftWorld$ServerLevel = requireNonNull(
|
||||
ReflectionUtils.getDeclaredField(
|
||||
clazz$CraftWorld, clazz$ServerLevel, 0
|
||||
)
|
||||
);
|
||||
// @Deprecated
|
||||
// public static final Field field$CraftWorld$ServerLevel = requireNonNull(
|
||||
// ReflectionUtils.getDeclaredField(
|
||||
// clazz$CraftWorld, clazz$ServerLevel, 0
|
||||
// )
|
||||
// );
|
||||
|
||||
public static final Method method$ServerLevel$getNoiseBiome = requireNonNull(
|
||||
ReflectionUtils.getMethod(
|
||||
@@ -1806,17 +1801,18 @@ public class Reflections {
|
||||
)
|
||||
);
|
||||
|
||||
public static final Field field$ServerLevel$chunkSource = requireNonNull(
|
||||
ReflectionUtils.getDeclaredField(
|
||||
clazz$ServerLevel, clazz$ServerChunkCache, 0
|
||||
)
|
||||
);
|
||||
@Deprecated
|
||||
// public static final Field field$ServerLevel$chunkSource = requireNonNull(
|
||||
// ReflectionUtils.getDeclaredField(
|
||||
// clazz$ServerLevel, clazz$ServerChunkCache, 0
|
||||
// )
|
||||
// );
|
||||
|
||||
public static final Method method$ServerChunkCache$blockChanged = requireNonNull(
|
||||
ReflectionUtils.getMethod(
|
||||
clazz$ServerChunkCache, void.class, clazz$BlockPos
|
||||
)
|
||||
);
|
||||
// public static final Method method$ServerChunkCache$blockChanged = requireNonNull(
|
||||
// ReflectionUtils.getMethod(
|
||||
// clazz$ServerChunkCache, void.class, clazz$BlockPos
|
||||
// )
|
||||
// );
|
||||
|
||||
// public static final Method method$ServerChunkCache$getChunkAtIfLoadedMainThread = requireNonNull(
|
||||
// ReflectionUtils.getMethod(
|
||||
@@ -2644,6 +2640,7 @@ public class Reflections {
|
||||
)
|
||||
);
|
||||
|
||||
@Deprecated
|
||||
public static final Constructor<?> constructor$ChunkPos = requireNonNull(
|
||||
ReflectionUtils.getConstructor(
|
||||
clazz$ChunkPos, int.class, int.class
|
||||
@@ -2695,7 +2692,7 @@ public class Reflections {
|
||||
)
|
||||
);
|
||||
|
||||
// 1.20 ~ 1.21.4
|
||||
// 1.20 ~ 1.21.4 moonrise
|
||||
public static final Method method$ChunkHolder$getPlayers =
|
||||
ReflectionUtils.getMethod(
|
||||
clazz$ChunkHolder, List.class, boolean.class
|
||||
@@ -2725,6 +2722,7 @@ public class Reflections {
|
||||
)
|
||||
);
|
||||
|
||||
@Deprecated
|
||||
public static final Method method$ServerChunkCache$getVisibleChunkIfPresent = requireNonNull(
|
||||
ReflectionUtils.getDeclaredMethod(
|
||||
clazz$ServerChunkCache, clazz$ChunkHolder, long.class
|
||||
@@ -3577,12 +3575,6 @@ public class Reflections {
|
||||
)
|
||||
);
|
||||
|
||||
public static final Method method$Level$setBlock = requireNonNull(
|
||||
ReflectionUtils.getMethod(
|
||||
clazz$Level, boolean.class, clazz$BlockPos, clazz$BlockState, int.class
|
||||
)
|
||||
);
|
||||
|
||||
public static final Method method$Block$updateFromNeighbourShapes = requireNonNull(
|
||||
ReflectionUtils.getStaticMethod(
|
||||
clazz$Block, clazz$BlockState, clazz$BlockState, clazz$LevelAccessor, clazz$BlockPos
|
||||
@@ -3735,6 +3727,7 @@ public class Reflections {
|
||||
)
|
||||
);
|
||||
|
||||
@Deprecated
|
||||
public static final Method method$LevelWriter$setBlock = requireNonNull(
|
||||
ReflectionUtils.getMethod(
|
||||
clazz$LevelWriter, boolean.class, clazz$BlockPos, clazz$BlockState, int.class
|
||||
@@ -5963,4 +5956,86 @@ public class Reflections {
|
||||
clazz$ClientboundSetEntityMotionPacket, int.class, 0
|
||||
)
|
||||
);
|
||||
|
||||
public static final Class<?> clazz$Rotation = requireNonNull(
|
||||
ReflectionUtils.getClazz(
|
||||
BukkitReflectionUtils.assembleMCClass("world.level.block.Rotation"),
|
||||
BukkitReflectionUtils.assembleMCClass("world.level.block.EnumBlockRotation")
|
||||
)
|
||||
);
|
||||
|
||||
public static final Method method$Rotation$values = requireNonNull(
|
||||
ReflectionUtils.getStaticMethod(
|
||||
clazz$Rotation, clazz$Rotation.arrayType()
|
||||
)
|
||||
);
|
||||
|
||||
public static final Object instance$Rotation$NONE;
|
||||
public static final Object instance$Rotation$CLOCKWISE_90;
|
||||
public static final Object instance$Rotation$CLOCKWISE_180;
|
||||
public static final Object instance$Rotation$COUNTERCLOCKWISE_90;
|
||||
|
||||
static {
|
||||
try {
|
||||
Object[] values = (Object[]) method$Rotation$values.invoke(null);
|
||||
instance$Rotation$NONE = values[0];
|
||||
instance$Rotation$CLOCKWISE_90 = values[1];
|
||||
instance$Rotation$CLOCKWISE_180 = values[2];
|
||||
instance$Rotation$COUNTERCLOCKWISE_90 = values[3];
|
||||
} catch (ReflectiveOperationException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static final Method method$Rotation$ordinal = requireNonNull(
|
||||
ReflectionUtils.getMethod(
|
||||
clazz$Rotation, int.class, new String[]{"ordinal"}
|
||||
)
|
||||
);
|
||||
|
||||
public static final Class<?> clazz$Mirror = requireNonNull(
|
||||
ReflectionUtils.getClazz(
|
||||
BukkitReflectionUtils.assembleMCClass("world.level.block.Mirror"),
|
||||
BukkitReflectionUtils.assembleMCClass("world.level.block.EnumBlockMirror")
|
||||
)
|
||||
);
|
||||
|
||||
public static final Method method$Mirror$values = requireNonNull(
|
||||
ReflectionUtils.getStaticMethod(
|
||||
clazz$Mirror, clazz$Mirror.arrayType()
|
||||
)
|
||||
);
|
||||
|
||||
public static final Object instance$Mirror$NONE;
|
||||
public static final Object instance$Mirror$LEFT_RIGHT;
|
||||
public static final Object instance$Mirror$FRONT_BACK;
|
||||
|
||||
static {
|
||||
try {
|
||||
Object[] values = (Object[]) method$Mirror$values.invoke(null);
|
||||
instance$Mirror$NONE = values[0];
|
||||
instance$Mirror$LEFT_RIGHT = values[1];
|
||||
instance$Mirror$FRONT_BACK = values[2];
|
||||
} catch (ReflectiveOperationException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static final Method method$Mirror$ordinal = requireNonNull(
|
||||
ReflectionUtils.getMethod(
|
||||
clazz$Mirror, int.class, new String[]{"ordinal"}
|
||||
)
|
||||
);
|
||||
|
||||
public static final Method method$BlockBehaviour$rotate = requireNonNull(
|
||||
ReflectionUtils.getDeclaredMethod(
|
||||
clazz$BlockBehaviour, clazz$BlockState, clazz$BlockState, clazz$Rotation
|
||||
)
|
||||
);
|
||||
|
||||
public static final Method method$BlockBehaviour$mirror = requireNonNull(
|
||||
ReflectionUtils.getDeclaredMethod(
|
||||
clazz$BlockBehaviour, clazz$BlockState, clazz$BlockState, clazz$Mirror
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
package net.momirealms.craftengine.bukkit.util;
|
||||
|
||||
import net.momirealms.craftengine.core.util.Rotation;
|
||||
|
||||
public class RotationUtils {
|
||||
|
||||
private RotationUtils() {}
|
||||
|
||||
public static Rotation fromNMSRotation(Object rotation) {
|
||||
try {
|
||||
int index = (int) Reflections.method$Rotation$ordinal.invoke(rotation);
|
||||
return Rotation.values()[index];
|
||||
} catch (ReflectiveOperationException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static Object toNMSRotation(Rotation rotation) {
|
||||
switch (rotation) {
|
||||
case CLOCKWISE_90 -> {
|
||||
return Reflections.instance$Rotation$CLOCKWISE_90;
|
||||
}
|
||||
case CLOCKWISE_180 -> {
|
||||
return Reflections.instance$Rotation$CLOCKWISE_180;
|
||||
}
|
||||
case COUNTERCLOCKWISE_90 -> {
|
||||
return Reflections.instance$Rotation$COUNTERCLOCKWISE_90;
|
||||
}
|
||||
default -> {
|
||||
return Reflections.instance$Rotation$NONE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,8 @@
|
||||
package net.momirealms.craftengine.bukkit.world;
|
||||
|
||||
import net.momirealms.craftengine.bukkit.nms.FastNMS;
|
||||
import net.momirealms.craftengine.bukkit.util.EntityUtils;
|
||||
import net.momirealms.craftengine.bukkit.util.ItemUtils;
|
||||
import net.momirealms.craftengine.bukkit.util.Reflections;
|
||||
import net.momirealms.craftengine.core.item.Item;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
import net.momirealms.craftengine.core.util.VersionHelper;
|
||||
@@ -36,7 +36,7 @@ public class BukkitWorld implements World {
|
||||
@Override
|
||||
public Object serverWorld() {
|
||||
try {
|
||||
return Reflections.field$CraftWorld$ServerLevel.get(platformWorld());
|
||||
return FastNMS.INSTANCE.field$CraftWorld$ServerLevel(platformWorld());
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("Failed to get server world", e);
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package net.momirealms.craftengine.bukkit.world;
|
||||
import net.momirealms.craftengine.bukkit.block.BukkitBlockManager;
|
||||
import net.momirealms.craftengine.bukkit.item.BukkitItemManager;
|
||||
import net.momirealms.craftengine.bukkit.item.behavior.BlockItemBehavior;
|
||||
import net.momirealms.craftengine.bukkit.nms.FastNMS;
|
||||
import net.momirealms.craftengine.bukkit.util.BlockStateUtils;
|
||||
import net.momirealms.craftengine.bukkit.util.LocationUtils;
|
||||
import net.momirealms.craftengine.bukkit.util.Reflections;
|
||||
@@ -51,7 +52,7 @@ public class BukkitWorldBlock implements WorldBlock {
|
||||
public boolean isWaterSource(BlockPlaceContext blockPlaceContext) {
|
||||
try {
|
||||
Location location = block.getLocation();
|
||||
Object serverLevel = Reflections.field$CraftWorld$ServerLevel.get(block.getWorld());
|
||||
Object serverLevel = FastNMS.INSTANCE.field$CraftWorld$ServerLevel(block.getWorld());
|
||||
Object fluidData = Reflections.method$Level$getFluidState.invoke(serverLevel, LocationUtils.toBlockPos(location.getBlockX(), location.getBlockY(), location.getBlockZ()));
|
||||
if (fluidData == null) return false;
|
||||
return (boolean) Reflections.method$FluidState$isSource.invoke(fluidData);
|
||||
|
||||
@@ -1,10 +1,16 @@
|
||||
package net.momirealms.craftengine.core.block.behavior;
|
||||
|
||||
import net.momirealms.craftengine.core.block.CustomBlock;
|
||||
import net.momirealms.craftengine.core.block.ImmutableBlockState;
|
||||
import net.momirealms.craftengine.core.item.context.BlockPlaceContext;
|
||||
import net.momirealms.craftengine.shared.block.BlockBehavior;
|
||||
|
||||
public abstract class AbstractBlockBehavior extends BlockBehavior {
|
||||
protected CustomBlock customBlock;
|
||||
|
||||
public AbstractBlockBehavior(CustomBlock customBlock) {
|
||||
this.customBlock = customBlock;
|
||||
}
|
||||
|
||||
public ImmutableBlockState updateStateForPlacement(BlockPlaceContext context, ImmutableBlockState state) {
|
||||
return state;
|
||||
|
||||
@@ -49,7 +49,7 @@ mojang_brigadier_version=1.0.18
|
||||
byte_buddy_version=1.15.11
|
||||
snake_yaml_version=2.3
|
||||
anti_grief_version=0.13
|
||||
nms_helper_version=0.29
|
||||
nms_helper_version=0.32
|
||||
# Ignite Dependencies
|
||||
mixinextras_version=0.4.1
|
||||
mixin_version=0.15.2+mixin.0.8.7
|
||||
|
||||
@@ -10,10 +10,7 @@ import net.minecraft.world.level.BlockGetter;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.LevelReader;
|
||||
import net.minecraft.world.level.ScheduledTickAccess;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.Blocks;
|
||||
import net.minecraft.world.level.block.BonemealableBlock;
|
||||
import net.minecraft.world.level.block.Fallable;
|
||||
import net.minecraft.world.level.block.*;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.phys.shapes.CollisionContext;
|
||||
import net.minecraft.world.phys.shapes.VoxelShape;
|
||||
@@ -68,10 +65,30 @@ public class CraftEngineBlock
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @NotNull BlockState rotate(@NotNull BlockState state, @NotNull Rotation rotation) {
|
||||
try {
|
||||
return (BlockState) this.behaviorHolder.value().rotate(this, new Object[]{state, rotation}, () -> super.rotate(state, rotation));
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return super.rotate(state, rotation);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @NotNull BlockState mirror(@NotNull BlockState state, @NotNull Mirror mirror) {
|
||||
try {
|
||||
return (BlockState) this.behaviorHolder.value().mirror(this, new Object[]{state, mirror}, () -> super.mirror(state, mirror));
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return super.mirror(state, mirror);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void tick(@NotNull BlockState state, @NotNull ServerLevel level, @NotNull BlockPos pos, @NotNull RandomSource random) {
|
||||
try {
|
||||
behaviorHolder.value().tick(this, new Object[]{state, level, pos, random}, () -> {
|
||||
this.behaviorHolder.value().tick(this, new Object[]{state, level, pos, random}, () -> {
|
||||
super.tick(state, level, pos, random);
|
||||
return null;
|
||||
});
|
||||
|
||||
@@ -4,6 +4,14 @@ import java.util.concurrent.Callable;
|
||||
|
||||
public abstract class BlockBehavior {
|
||||
|
||||
public Object rotate(Object thisBlock, Object[] args, Callable<Object> superMethod) throws Exception {
|
||||
return superMethod.call();
|
||||
}
|
||||
|
||||
public Object mirror(Object thisBlock, Object[] args, Callable<Object> superMethod) throws Exception {
|
||||
return superMethod.call();
|
||||
}
|
||||
|
||||
public Object updateShape(Object thisBlock, Object[] args, Callable<Object> superMethod) throws Exception {
|
||||
return superMethod.call();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user