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

添加支撑形状

This commit is contained in:
XiaoMoMi
2025-05-26 01:44:57 +08:00
parent 0b80a6b592
commit d4086101cf
10 changed files with 80 additions and 9 deletions

View File

@@ -2,12 +2,15 @@ package net.momirealms.craftengine.bukkit.block;
import net.momirealms.craftengine.bukkit.nms.FastNMS;
import net.momirealms.craftengine.shared.block.BlockShape;
import org.jetbrains.annotations.Nullable;
public class BukkitBlockShape implements BlockShape {
private final Object rawBlockState;
private final Object supportBlockState;
public BukkitBlockShape(Object rawBlockState) {
public BukkitBlockShape(Object rawBlockState, @Nullable Object supportBlockState) {
this.rawBlockState = rawBlockState;
this.supportBlockState = supportBlockState == null ? rawBlockState : supportBlockState;
}
@Override
@@ -19,4 +22,9 @@ public class BukkitBlockShape implements BlockShape {
public Object getCollisionShape(Object thisObj, Object[] args) {
return FastNMS.INSTANCE.method$BlockState$getCollisionShape(this.rawBlockState, args[1], args[2], args[3]);
}
@Override
public Object getSupportShape(Object thisObj, Object[] args) {
return FastNMS.INSTANCE.method$BlockState$getBlockSupportShape(this.supportBlockState, args[1], args[2]);
}
}

View File

@@ -21,15 +21,13 @@ import net.momirealms.craftengine.core.util.Tristate;
import net.momirealms.craftengine.core.util.VersionHelper;
import net.momirealms.craftengine.shared.ObjectHolder;
import net.momirealms.craftengine.shared.block.BlockBehavior;
import org.bukkit.Bukkit;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.lang.reflect.Field;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.*;
public class BukkitCustomBlock extends AbstractCustomBlock {
@@ -103,7 +101,16 @@ public class BukkitCustomBlock extends AbstractCustomBlock {
Field shapeField = mcBlock.getClass().getField("shapeHolder");
@SuppressWarnings("unchecked")
ObjectHolder<BukkitBlockShape> shapeHolder = (ObjectHolder<BukkitBlockShape>) shapeField.get(mcBlock);
shapeHolder.bindValue(new BukkitBlockShape(state.vanillaBlockState().handle()));
shapeHolder.bindValue(new BukkitBlockShape(state.vanillaBlockState().handle(), Optional.ofNullable(state.settings().supportShapeBlockState()).map(it -> {
try {
Object blockState = BlockStateUtils.blockDataToBlockState(Bukkit.createBlockData(it));
if (!BlockStateUtils.isVanillaBlock(blockState)) return null;
return blockState;
} catch (IllegalArgumentException e) {
CraftEngine.instance().logger().warn("Illegal shape block state: " + it, e);
return null;
}
}).orElse(null)));
// bind behavior
Field behaviorField = mcBlock.getClass().getField("behaviorHolder");
@SuppressWarnings("unchecked")

View File

@@ -73,7 +73,7 @@ import java.util.function.Consumer;
public class BukkitInjector {
private static final ByteBuddy byteBuddy = new ByteBuddy(ClassFileVersion.JAVA_V17);
private static final BukkitBlockShape STONE_SHAPE = new BukkitBlockShape(Reflections.instance$Blocks$STONE$defaultState);
private static final BukkitBlockShape STONE_SHAPE = new BukkitBlockShape(Reflections.instance$Blocks$STONE$defaultState, Reflections.instance$Blocks$STONE$defaultState);
private static Class<?> clazz$InjectedPalettedContainer;
private static Class<?> clazz$InjectedLevelChunkSection;
@@ -251,6 +251,9 @@ public class BukkitInjector {
// getCollisionShape
.method(ElementMatchers.is(Reflections.method$BlockBehaviour$getCollisionShape))
.intercept(MethodDelegation.to(GetCollisionShapeInterceptor.INSTANCE))
// getSupportShape
.method(ElementMatchers.is(Reflections.method$BlockBehaviour$getBlockSupportShape))
.intercept(MethodDelegation.to(GetSupportShapeInterceptor.INSTANCE))
// mirror
.method(ElementMatchers.is(Reflections.method$BlockBehaviour$mirror))
.intercept(MethodDelegation.to(MirrorInterceptor.INSTANCE))
@@ -941,6 +944,21 @@ public class BukkitInjector {
}
}
public static class GetSupportShapeInterceptor {
public static final GetSupportShapeInterceptor INSTANCE = new GetSupportShapeInterceptor();
@RuntimeType
public Object intercept(@This Object thisObj, @AllArguments Object[] args, @SuperCall Callable<Object> superMethod) throws Exception {
ObjectHolder<BlockShape> holder = ((ShapeHolder) thisObj).getShapeHolder();
try {
return holder.value().getSupportShape(thisObj, args);
} catch (Exception e) {
CraftEngine.instance().logger().severe("Failed to run getSupportShape", e);
return superMethod.call();
}
}
}
public static class MirrorInterceptor {
public static final MirrorInterceptor INSTANCE = new MirrorInterceptor();

View File

@@ -2548,6 +2548,12 @@ public class Reflections {
)
);
public static final Method method$BlockBehaviour$getBlockSupportShape = requireNonNull(
ReflectionUtils.getDeclaredMethod(
clazz$BlockBehaviour, clazz$VoxelShape, new String[]{"getBlockSupportShape", "b_"}, clazz$BlockState, clazz$BlockGetter, clazz$BlockPos
)
);
public static final Method method$BlockBehaviour$tick = requireNonNull(
ReflectionUtils.getDeclaredMethod(
clazz$BlockBehaviour, void.class, new String[]{"tick", "a"}, clazz$BlockState, clazz$ServerLevel, clazz$BlockPos, clazz$RandomSource