mirror of
https://github.com/Xiao-MoMi/craft-engine.git
synced 2025-12-30 12:29:15 +00:00
注入blockstate
This commit is contained in:
@@ -320,7 +320,7 @@ public class BukkitBlockManager extends AbstractBlockManager {
|
||||
for (Object block : (Iterable<Object>) MBuiltInRegistries.BLOCK) {
|
||||
Object soundType = CoreReflections.field$BlockBehaviour$soundType.get(block);
|
||||
if (affectedBlockSounds.contains(soundType)) {
|
||||
Object state = getOnlyBlockState(block);
|
||||
Object state = FastNMS.INSTANCE.method$Block$defaultState(block);
|
||||
if (BlockStateUtils.isVanillaBlock(state)) {
|
||||
affectedBlocks.add(block);
|
||||
}
|
||||
@@ -792,7 +792,7 @@ public class BukkitBlockManager extends AbstractBlockManager {
|
||||
CoreReflections.method$Holder$Reference$bindValue.invoke(blockHolder, newRealBlock);
|
||||
CoreReflections.field$Holder$Reference$tags.set(blockHolder, Set.of());
|
||||
|
||||
newBlockState = getOnlyBlockState(newRealBlock);
|
||||
newBlockState = FastNMS.INSTANCE.method$Block$defaultState(newRealBlock);
|
||||
CoreReflections.method$IdMapper$add.invoke(CoreReflections.instance$Block$BLOCK_STATE_REGISTRY, newBlockState);
|
||||
|
||||
if (isNoteBlock) {
|
||||
@@ -838,13 +838,6 @@ public class BukkitBlockManager extends AbstractBlockManager {
|
||||
return blockProperties;
|
||||
}
|
||||
|
||||
private Object getOnlyBlockState(Object newBlock) throws IllegalAccessException {
|
||||
Object stateDefinition = CoreReflections.field$Block$StateDefinition.get(newBlock);
|
||||
@SuppressWarnings("unchecked")
|
||||
ImmutableList<Object> states = (ImmutableList<Object>) CoreReflections.field$StateDefinition$states.get(stateDefinition);
|
||||
return states.get(0);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private void deceiveBukkit() {
|
||||
try {
|
||||
|
||||
@@ -108,6 +108,7 @@ public class BukkitCraftEngine extends CraftEngine {
|
||||
if (super.blockManager != null) return;
|
||||
try {
|
||||
BlockGenerator.init();
|
||||
BlockStateGenerator.init();
|
||||
super.blockManager = new BukkitBlockManager(this);
|
||||
} catch (Exception e) {
|
||||
throw new InjectionException("Error injecting blocks", e);
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package net.momirealms.craftengine.bukkit.plugin.injector;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import net.bytebuddy.ByteBuddy;
|
||||
import net.bytebuddy.ClassFileVersion;
|
||||
import net.bytebuddy.description.modifier.Visibility;
|
||||
@@ -30,6 +31,7 @@ import java.lang.invoke.MethodType;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.Function;
|
||||
|
||||
public final class BlockGenerator {
|
||||
private static final BukkitBlockShape STONE_SHAPE =
|
||||
@@ -201,6 +203,12 @@ public final class BlockGenerator {
|
||||
field$CraftEngineBlock$shape.set(newBlockInstance, shapeHolder);
|
||||
field$CraftEngineBlock$isNoteBlock.set(newBlockInstance, replacedBlock.equals(BlockKeys.NOTE_BLOCK));
|
||||
field$CraftEngineBlock$isTripwire.set(newBlockInstance, replacedBlock.equals(BlockKeys.TRIPWIRE));
|
||||
|
||||
Object stateDefinitionBuilder = CoreReflections.constructor$StateDefinition$Builder.newInstance(newBlockInstance);
|
||||
Object stateDefinition = CoreReflections.method$StateDefinition$Builder$create.invoke(stateDefinitionBuilder,
|
||||
(Function<Object, Object>) FastNMS.INSTANCE::method$Block$defaultState, BlockStateGenerator.instance$StateDefinition$Factory);
|
||||
CoreReflections.field$Block$StateDefinition.set(newBlockInstance, stateDefinition);
|
||||
CoreReflections.field$Block$defaultBlockState.set(newBlockInstance, ((ImmutableList<?>) CoreReflections.field$StateDefinition$states.get(stateDefinition)).getFirst());
|
||||
return newBlockInstance;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
package net.momirealms.craftengine.bukkit.plugin.injector;
|
||||
|
||||
import com.mojang.serialization.MapCodec;
|
||||
import it.unimi.dsi.fastutil.objects.Reference2ObjectArrayMap;
|
||||
import net.bytebuddy.ByteBuddy;
|
||||
import net.bytebuddy.ClassFileVersion;
|
||||
import net.bytebuddy.dynamic.DynamicType;
|
||||
import net.bytebuddy.dynamic.scaffold.subclass.ConstructorStrategy;
|
||||
import net.bytebuddy.implementation.MethodDelegation;
|
||||
import net.bytebuddy.implementation.bind.annotation.AllArguments;
|
||||
import net.bytebuddy.implementation.bind.annotation.RuntimeType;
|
||||
import net.bytebuddy.matcher.ElementMatchers;
|
||||
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.CoreReflections;
|
||||
import net.momirealms.craftengine.core.block.CustomBlockState;
|
||||
import net.momirealms.craftengine.core.util.ReflectionUtils;
|
||||
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.invoke.MethodType;
|
||||
|
||||
public final class BlockStateGenerator {
|
||||
private static MethodHandle constructor$CraftEngineBlockState;
|
||||
public static Object instance$StateDefinition$Factory;
|
||||
|
||||
public static void init() throws ReflectiveOperationException {
|
||||
ByteBuddy byteBuddy = new ByteBuddy(ClassFileVersion.JAVA_V17);
|
||||
String packageWithName = BlockStateGenerator.class.getName();
|
||||
String generatedStateClassName = packageWithName.substring(0, packageWithName.lastIndexOf('.')) + ".CraftEngineBlockState";
|
||||
DynamicType.Builder<?> stateBuilder = byteBuddy
|
||||
.subclass(CoreReflections.clazz$BlockState, ConstructorStrategy.Default.IMITATE_SUPER_CLASS_OPENING)
|
||||
.name(generatedStateClassName)
|
||||
.implement(CustomBlockState.class);
|
||||
Class<?> clazz$CraftEngineBlock = stateBuilder.make().load(BlockStateGenerator.class.getClassLoader()).getLoaded();
|
||||
constructor$CraftEngineBlockState = MethodHandles.publicLookup().in(clazz$CraftEngineBlock)
|
||||
.findConstructor(clazz$CraftEngineBlock, MethodType.methodType(void.class, CoreReflections.clazz$Block, Reference2ObjectArrayMap.class, MapCodec.class))
|
||||
.asType(MethodType.methodType(CoreReflections.clazz$BlockState, CoreReflections.clazz$Block, Reference2ObjectArrayMap.class, MapCodec.class));
|
||||
|
||||
String generatedFactoryClassName = packageWithName.substring(0, packageWithName.lastIndexOf('.')) + ".CraftEngineStateFactory";
|
||||
DynamicType.Builder<?> factoryBuilder = byteBuddy
|
||||
.subclass(Object.class, ConstructorStrategy.Default.IMITATE_SUPER_CLASS_OPENING)
|
||||
.name(generatedFactoryClassName)
|
||||
.implement(CoreReflections.clazz$StateDefinition$Factory)
|
||||
.method(ElementMatchers.named("create"))
|
||||
.intercept(MethodDelegation.to(CreateStateInterceptor.INSTANCE));
|
||||
|
||||
Class<?> clazz$Factory = factoryBuilder.make().load(BlockStateGenerator.class.getClassLoader()).getLoaded();
|
||||
instance$StateDefinition$Factory = ReflectionUtils.getTheOnlyConstructor(clazz$Factory).newInstance();
|
||||
}
|
||||
|
||||
public static class CreateStateInterceptor {
|
||||
public static final CreateStateInterceptor INSTANCE = new CreateStateInterceptor();
|
||||
|
||||
@RuntimeType
|
||||
public Object intercept(@AllArguments Object[] args) throws Throwable {
|
||||
return constructor$CraftEngineBlockState.invoke(args[0], args[1], args[2]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -22,6 +22,7 @@ import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
|
||||
import static java.util.Objects.requireNonNull;
|
||||
|
||||
@@ -1152,6 +1153,28 @@ public final class CoreReflections {
|
||||
)
|
||||
);
|
||||
|
||||
public static final Class<?> clazz$StateDefinition$Builder = requireNonNull(
|
||||
BukkitReflectionUtils.findReobfOrMojmapClass(
|
||||
"world.level.block.state.BlockStateList$a",
|
||||
"world.level.block.state.StateDefinition$Builder"
|
||||
)
|
||||
);
|
||||
|
||||
public static final Class<?> clazz$StateDefinition$Factory = requireNonNull(
|
||||
BukkitReflectionUtils.findReobfOrMojmapClass(
|
||||
"world.level.block.state.BlockStateList$b",
|
||||
"world.level.block.state.StateDefinition$Factory"
|
||||
)
|
||||
);
|
||||
|
||||
public static final Constructor<?> constructor$StateDefinition$Builder = requireNonNull(
|
||||
ReflectionUtils.getTheOnlyConstructor(clazz$StateDefinition$Builder)
|
||||
);
|
||||
|
||||
public static final Method method$StateDefinition$Builder$create = requireNonNull(
|
||||
ReflectionUtils.getMethod(clazz$StateDefinition$Builder, clazz$StateDefinition, Function.class, clazz$StateDefinition$Factory)
|
||||
);
|
||||
|
||||
public static final Field field$Block$StateDefinition = requireNonNull(
|
||||
ReflectionUtils.getDeclaredField(clazz$Block, clazz$StateDefinition, 0)
|
||||
);
|
||||
@@ -1572,8 +1595,8 @@ public final class CoreReflections {
|
||||
}
|
||||
}
|
||||
|
||||
public static final Method method$Block$defaultBlockState = requireNonNull(
|
||||
ReflectionUtils.getMethod(clazz$Block, clazz$BlockState)
|
||||
public static final Field field$Block$defaultBlockState = requireNonNull(
|
||||
ReflectionUtils.getDeclaredField(clazz$Block, clazz$BlockState, 0)
|
||||
);
|
||||
|
||||
public static final Method method$Entity$getOnPos = requireNonNull(
|
||||
@@ -3503,4 +3526,5 @@ public final class CoreReflections {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -27,14 +27,14 @@ public final class MBlocks {
|
||||
static {
|
||||
try {
|
||||
AIR = getById("air");
|
||||
AIR$defaultState = CoreReflections.method$Block$defaultBlockState.invoke(AIR);
|
||||
AIR$defaultState = FastNMS.INSTANCE.method$Block$defaultState(AIR);
|
||||
FIRE = getById("fire");
|
||||
SOUL_FIRE = getById("soul_fire");
|
||||
STONE = getById("stone");
|
||||
STONE$defaultState = CoreReflections.method$Block$defaultBlockState.invoke(STONE);
|
||||
STONE$defaultState = FastNMS.INSTANCE.method$Block$defaultState(STONE);
|
||||
ICE = getById("ice");
|
||||
SHORT_GRASS = getById(VersionHelper.isOrAbove1_20_3() ? "short_grass" : "grass");
|
||||
SHORT_GRASS$defaultState = CoreReflections.method$Block$defaultBlockState.invoke(SHORT_GRASS);
|
||||
SHORT_GRASS$defaultState = FastNMS.INSTANCE.method$Block$defaultState(SHORT_GRASS);
|
||||
SHULKER_BOX = getById("shulker_box");
|
||||
COMPOSTER = getById("composter");
|
||||
} catch (ReflectiveOperationException e) {
|
||||
|
||||
Reference in New Issue
Block a user