mirror of
https://github.com/Xiao-MoMi/craft-engine.git
synced 2025-12-19 15:09:15 +00:00
feat(block): 添加瓜藤相关的方块行为并且修复判断方块问题
This commit is contained in:
@@ -0,0 +1,110 @@
|
||||
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;
|
||||
import net.momirealms.craftengine.bukkit.util.DirectionUtils;
|
||||
import net.momirealms.craftengine.core.block.BlockBehavior;
|
||||
import net.momirealms.craftengine.core.block.CustomBlock;
|
||||
import net.momirealms.craftengine.core.block.ImmutableBlockState;
|
||||
import net.momirealms.craftengine.core.block.behavior.BlockBehaviorFactory;
|
||||
import net.momirealms.craftengine.core.block.properties.IntegerProperty;
|
||||
import net.momirealms.craftengine.core.block.properties.Property;
|
||||
import net.momirealms.craftengine.core.util.*;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
public class AttachedStemBlockBehavior extends BushBlockBehavior {
|
||||
public static final Factory FACTORY = new Factory();
|
||||
private final Property<HorizontalDirection> facingProperty;
|
||||
private final Key fruit;
|
||||
private final Key stem;
|
||||
|
||||
public AttachedStemBlockBehavior(CustomBlock customBlock,
|
||||
int delay,
|
||||
boolean blacklist,
|
||||
List<Object> tagsCanSurviveOn,
|
||||
Set<Object> blockStatesCanSurviveOn,
|
||||
Set<String> customBlocksCansSurviveOn,
|
||||
Property<HorizontalDirection> facingProperty,
|
||||
Key fruit,
|
||||
Key stem) {
|
||||
super(customBlock, delay, blacklist, false, tagsCanSurviveOn, blockStatesCanSurviveOn, customBlocksCansSurviveOn);
|
||||
this.facingProperty = facingProperty;
|
||||
this.fruit = fruit;
|
||||
this.stem = stem;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean propagatesSkylightDown(Object thisBlock, Object[] args, Callable<Object> superMethod) {
|
||||
return FastNMS.INSTANCE.field$FluidState$isEmpty(FastNMS.INSTANCE.field$BlockBehaviour$BlockStateBase$fluidState(args[0]));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPathFindable(Object thisBlock, Object[] args, Callable<Object> superMethod) throws Exception {
|
||||
return (VersionHelper.isOrAbove1_20_5() ? args[1] : args[3]).equals(CoreReflections.instance$PathComputationType$AIR)
|
||||
&& !FastNMS.INSTANCE.field$BlockBehavior$hasCollision(thisBlock) || (boolean) superMethod.call();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object updateShape(Object thisBlock, Object[] args, Callable<Object> superMethod) throws Exception {
|
||||
Object state = args[0];
|
||||
HorizontalDirection direction = DirectionUtils.fromNMSDirection(args[updateShape$direction]).toHorizontalDirection();
|
||||
Object neighborState = args[updateShape$neighborState];
|
||||
Optional<ImmutableBlockState> optionalCustomState = BlockStateUtils.getOptionalCustomBlockState(state);
|
||||
if (optionalCustomState.isEmpty() || direction != optionalCustomState.get().get(this.facingProperty)) {
|
||||
return super.updateShape(thisBlock, args, superMethod);
|
||||
}
|
||||
Optional<ImmutableBlockState> optionalCustomNeighborState = BlockStateUtils.getOptionalCustomBlockState(neighborState);
|
||||
if (optionalCustomNeighborState.isPresent()) {
|
||||
ImmutableBlockState customNeighborState = optionalCustomNeighborState.get();
|
||||
if (!customNeighborState.owner().value().id().equals(this.fruit)) {
|
||||
Object stemBlock = resetStemBlock();
|
||||
if (stemBlock != null) return stemBlock;
|
||||
}
|
||||
} else {
|
||||
if (this.stem.namespace().equals("minecraft")) {
|
||||
Key neighborBlockId = BlockStateUtils.getBlockOwnerIdFromState(neighborState);
|
||||
if (!neighborBlockId.equals(this.fruit)) {
|
||||
Object stemBlock = resetStemBlock();
|
||||
if (stemBlock != null) return stemBlock;
|
||||
}
|
||||
} else {
|
||||
Object stemBlock = resetStemBlock();
|
||||
if (stemBlock != null) return stemBlock;
|
||||
}
|
||||
}
|
||||
return super.updateShape(thisBlock, args, superMethod);
|
||||
}
|
||||
|
||||
private Object resetStemBlock() {
|
||||
Optional<CustomBlock> optionalStemBlock = BukkitBlockManager.instance().blockById(this.stem);
|
||||
if (optionalStemBlock.isPresent()) {
|
||||
CustomBlock stemBlock = optionalStemBlock.get();
|
||||
IntegerProperty ageProperty = (IntegerProperty) stemBlock.getProperty("age");
|
||||
if (ageProperty == null) return stemBlock.defaultState().customBlockState().literalObject();
|
||||
return stemBlock.defaultState().with(ageProperty, ageProperty.max).customBlockState().literalObject();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static class Factory implements BlockBehaviorFactory {
|
||||
|
||||
@Override
|
||||
public BlockBehavior create(CustomBlock block, Map<String, Object> arguments) {
|
||||
Tuple<List<Object>, Set<Object>, Set<String>> tuple = readTagsAndState(arguments, false);
|
||||
int delay = ResourceConfigUtils.getAsInt(arguments.getOrDefault("delay", 0), "delay");
|
||||
boolean blacklistMode = ResourceConfigUtils.getAsBoolean(arguments.getOrDefault("blacklist", false), "blacklist");
|
||||
@SuppressWarnings("unchecked")
|
||||
Property<HorizontalDirection> facingProperty = (Property<HorizontalDirection>) ResourceConfigUtils.requireNonNullOrThrow(block.getProperty("facing"), "warning.config.block.behavior.attached_stem.missing_facing");
|
||||
Key fruit = Key.of(ResourceConfigUtils.requireNonEmptyStringOrThrow(arguments.get("fruit"), "warning.config.block.behavior.attached_stem.missing_fruit"));
|
||||
Key stem = Key.of(ResourceConfigUtils.requireNonEmptyStringOrThrow(arguments.get("stem"), "warning.config.block.behavior.attached_stem.missing_stem"));
|
||||
return new AttachedStemBlockBehavior(block, delay, blacklistMode, tuple.left(), tuple.mid(), tuple.right(), facingProperty, fruit, stem);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -39,6 +39,8 @@ public class BukkitBlockBehaviors extends BlockBehaviors {
|
||||
public static final Key FENCE_BLOCK = Key.from("craftengine:fence_block");
|
||||
public static final Key BUTTON_BLOCK = Key.from("craftengine:button_block");
|
||||
public static final Key FACE_ATTACHED_HORIZONTAL_DIRECTIONAL_BLOCK = Key.from("craftengine:face_attached_horizontal_directional_block");
|
||||
public static final Key STEM_BLOCK = Key.from("craftengine:stem_block");
|
||||
public static final Key ATTACHED_STEM_BLOCK = Key.from("craftengine:attached_stem_block");
|
||||
|
||||
public static void init() {
|
||||
register(EMPTY, (block, args) -> EmptyBlockBehavior.INSTANCE);
|
||||
@@ -76,5 +78,7 @@ public class BukkitBlockBehaviors extends BlockBehaviors {
|
||||
register(FENCE_BLOCK, FenceBlockBehavior.FACTORY);
|
||||
register(BUTTON_BLOCK, ButtonBlockBehavior.FACTORY);
|
||||
register(FACE_ATTACHED_HORIZONTAL_DIRECTIONAL_BLOCK, FaceAttachedHorizontalDirectionalBlockBehavior.FACTORY);
|
||||
register(STEM_BLOCK, StemBlockBehavior.FACTORY);
|
||||
register(ATTACHED_STEM_BLOCK, AttachedStemBlockBehavior.FACTORY);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -77,7 +77,7 @@ public class CropBlockBehavior extends BukkitBlockBehavior {
|
||||
return minGrowLight;
|
||||
}
|
||||
|
||||
private static int getRawBrightness(Object level, Object pos) throws InvocationTargetException, IllegalAccessException {
|
||||
public static int getRawBrightness(Object level, Object pos) throws InvocationTargetException, IllegalAccessException {
|
||||
return (int) CoreReflections.method$BlockAndTintGetter$getRawBrightness.invoke(level, pos, 0);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,154 @@
|
||||
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.MBuiltInRegistries;
|
||||
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MRegistries;
|
||||
import net.momirealms.craftengine.bukkit.util.BlockStateUtils;
|
||||
import net.momirealms.craftengine.bukkit.util.DirectionUtils;
|
||||
import net.momirealms.craftengine.bukkit.util.KeyUtils;
|
||||
import net.momirealms.craftengine.core.block.BlockBehavior;
|
||||
import net.momirealms.craftengine.core.block.CustomBlock;
|
||||
import net.momirealms.craftengine.core.block.ImmutableBlockState;
|
||||
import net.momirealms.craftengine.core.block.UpdateOption;
|
||||
import net.momirealms.craftengine.core.block.behavior.BlockBehaviorFactory;
|
||||
import net.momirealms.craftengine.core.block.properties.IntegerProperty;
|
||||
import net.momirealms.craftengine.core.block.properties.Property;
|
||||
import net.momirealms.craftengine.core.util.*;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
public class StemBlockBehavior extends BushBlockBehavior {
|
||||
public static final Factory FACTORY = new Factory();
|
||||
private final IntegerProperty ageProperty;
|
||||
private final Key fruit;
|
||||
private final Key attachedStem;
|
||||
private final int minGrowLight;
|
||||
private final Object tagMayPlaceFruit;
|
||||
private final Object blockMayPlaceFruit;
|
||||
|
||||
public StemBlockBehavior(CustomBlock customBlock,
|
||||
int delay,
|
||||
boolean blacklist,
|
||||
List<Object> tagsCanSurviveOn,
|
||||
Set<Object> blockStatesCanSurviveOn,
|
||||
Set<String> customBlocksCansSurviveOn,
|
||||
IntegerProperty ageProperty,
|
||||
Key fruit,
|
||||
Key attachedStem,
|
||||
int minGrowLight,
|
||||
Object tagMayPlaceFruit,
|
||||
Object blockMayPlaceFruit) {
|
||||
super(customBlock, delay, blacklist, false, tagsCanSurviveOn, blockStatesCanSurviveOn, customBlocksCansSurviveOn);
|
||||
this.ageProperty = ageProperty;
|
||||
this.fruit = fruit;
|
||||
this.attachedStem = attachedStem;
|
||||
this.minGrowLight = minGrowLight;
|
||||
this.tagMayPlaceFruit = tagMayPlaceFruit;
|
||||
this.blockMayPlaceFruit = blockMayPlaceFruit;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean propagatesSkylightDown(Object thisBlock, Object[] args, Callable<Object> superMethod) {
|
||||
return FastNMS.INSTANCE.field$FluidState$isEmpty(FastNMS.INSTANCE.field$BlockBehaviour$BlockStateBase$fluidState(args[0]));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPathFindable(Object thisBlock, Object[] args, Callable<Object> superMethod) throws Exception {
|
||||
return (VersionHelper.isOrAbove1_20_5() ? args[1] : args[3]).equals(CoreReflections.instance$PathComputationType$AIR)
|
||||
&& !FastNMS.INSTANCE.field$BlockBehavior$hasCollision(thisBlock) || (boolean) superMethod.call();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void randomTick(Object thisBlock, Object[] args, Callable<Object> superMethod) throws Exception {
|
||||
Object state = args[0];
|
||||
Object level = args[1];
|
||||
Object pos = args[2];
|
||||
if (CropBlockBehavior.getRawBrightness(level, pos) < this.minGrowLight) return;
|
||||
ImmutableBlockState customState = BlockStateUtils.getOptionalCustomBlockState(state).orElse(null);
|
||||
if (customState == null || customState.isEmpty()) return;
|
||||
int age = customState.get(ageProperty);
|
||||
if (age < ageProperty.max) {
|
||||
FastNMS.INSTANCE.method$LevelWriter$setBlock(level, pos, customState.with(ageProperty, age + 1).customBlockState().literalObject(), 2);
|
||||
return;
|
||||
}
|
||||
Object randomDirection = CoreReflections.instance$Direction$values[RandomUtils.generateRandomInt(2, 6)];
|
||||
Object blockPos = FastNMS.INSTANCE.method$BlockPos$relative(pos, randomDirection);
|
||||
if (!FastNMS.INSTANCE.method$BlockStateBase$isAir(FastNMS.INSTANCE.method$BlockGetter$getBlockState(level, blockPos)))
|
||||
return;
|
||||
Object blockState = FastNMS.INSTANCE.method$BlockGetter$getBlockState(level, FastNMS.INSTANCE.method$BlockPos$relative(blockPos, CoreReflections.instance$Direction$DOWN));
|
||||
if (mayPlaceFruit(blockState)) {
|
||||
Optional<CustomBlock> optionalFruit = BukkitBlockManager.instance().blockById(this.fruit);
|
||||
Object fruitState = null;
|
||||
if (optionalFruit.isPresent()) {
|
||||
fruitState = optionalFruit.get().defaultState().customBlockState().literalObject();
|
||||
} else if (fruit.namespace().equals("minecraft")) {
|
||||
fruitState = FastNMS.INSTANCE.method$Block$defaultState(FastNMS.INSTANCE.method$Registry$getValue(
|
||||
MBuiltInRegistries.BLOCK,
|
||||
FastNMS.INSTANCE.method$ResourceLocation$fromNamespaceAndPath("minecraft", fruit.value())
|
||||
));
|
||||
}
|
||||
Optional<CustomBlock> optionalAttachedStem = BukkitBlockManager.instance().blockById(this.attachedStem);
|
||||
if (fruitState == null || optionalAttachedStem.isEmpty()) return;
|
||||
CustomBlock attachedStem = optionalAttachedStem.get();
|
||||
@SuppressWarnings("unchecked")
|
||||
Property<HorizontalDirection> facing = (Property<HorizontalDirection>) attachedStem.getProperty("facing");
|
||||
if (facing == null) return;
|
||||
FastNMS.INSTANCE.method$LevelWriter$setBlock(level, blockPos, fruitState, UpdateOption.UPDATE_ALL.flags());
|
||||
FastNMS.INSTANCE.method$LevelWriter$setBlock(level, pos, attachedStem.defaultState().with(facing, DirectionUtils.fromNMSDirection(randomDirection).toHorizontalDirection()).customBlockState().literalObject(), UpdateOption.UPDATE_ALL.flags());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValidBoneMealTarget(Object thisBlock, Object[] args) {
|
||||
ImmutableBlockState state = BlockStateUtils.getOptionalCustomBlockState(args[2]).orElse(null);
|
||||
if (state == null || state.isEmpty()) return false;
|
||||
return state.get(ageProperty) != ageProperty.max;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isBoneMealSuccess(Object thisBlock, Object[] args) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void performBoneMeal(Object thisBlock, Object[] args) {
|
||||
ImmutableBlockState state = BlockStateUtils.getOptionalCustomBlockState(args[3]).orElse(null);
|
||||
if (state == null || state.isEmpty()) return;
|
||||
int min = Math.min(7, state.get(ageProperty) + RandomUtils.generateRandomInt(Math.min(ageProperty.min + 2, ageProperty.max), Math.min(ageProperty.max - 2, ageProperty.max)));
|
||||
Object blockState = state.with(ageProperty, min).customBlockState().literalObject();
|
||||
FastNMS.INSTANCE.method$LevelWriter$setBlock(args[0], args[2], blockState, 2);
|
||||
if (min >= ageProperty.max) {
|
||||
FastNMS.INSTANCE.method$BlockBehaviour$BlockStateBase$randomTick(blockState, args[0], args[2]);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean mayPlaceFruit(Object blockState) {
|
||||
boolean flag1 = tagMayPlaceFruit != null && FastNMS.INSTANCE.method$BlockStateBase$is(blockState, tagMayPlaceFruit);
|
||||
boolean flag2 = blockMayPlaceFruit != null && FastNMS.INSTANCE.method$BlockStateBase$isBlock(blockState, blockMayPlaceFruit);
|
||||
if (tagMayPlaceFruit == null && blockMayPlaceFruit == null) return true;
|
||||
return flag1 || flag2;
|
||||
}
|
||||
|
||||
public static class Factory implements BlockBehaviorFactory {
|
||||
|
||||
@Override
|
||||
public BlockBehavior create(CustomBlock block, Map<String, Object> arguments) {
|
||||
Tuple<List<Object>, Set<Object>, Set<String>> tuple = readTagsAndState(arguments, false);
|
||||
int delay = ResourceConfigUtils.getAsInt(arguments.getOrDefault("delay", 0), "delay");
|
||||
boolean blacklistMode = ResourceConfigUtils.getAsBoolean(arguments.getOrDefault("blacklist", false), "blacklist");
|
||||
IntegerProperty ageProperty = (IntegerProperty) ResourceConfigUtils.requireNonNullOrThrow(block.getProperty("age"), "warning.config.block.behavior.stem.missing_age");
|
||||
Key fruit = Key.of(ResourceConfigUtils.requireNonEmptyStringOrThrow(arguments.get("fruit"), "warning.config.block.behavior.stem.missing_fruit"));
|
||||
Key attachedStem = Key.of(ResourceConfigUtils.requireNonEmptyStringOrThrow(arguments.get("attached-stem"), "warning.config.block.behavior.stem.missing_attached_stem"));
|
||||
int minGrowLight = ResourceConfigUtils.getAsInt(arguments.getOrDefault("light-requirement", 9), "light-requirement");
|
||||
Object tagMayPlaceFruit = FastNMS.INSTANCE.method$TagKey$create(MRegistries.BLOCK, KeyUtils.toResourceLocation(Key.of(arguments.getOrDefault("may-place-fruit", "minecraft:dirt").toString())));
|
||||
Object blockMayPlaceFruit = FastNMS.INSTANCE.method$Registry$getValue(MBuiltInRegistries.BLOCK, KeyUtils.toResourceLocation(Key.of(arguments.getOrDefault("may-place-fruit", "minecraft:farmland").toString())));
|
||||
return new StemBlockBehavior(block, delay, blacklistMode, tuple.left(), tuple.mid(), tuple.right(), ageProperty, fruit, attachedStem, minGrowLight, tagMayPlaceFruit, blockMayPlaceFruit);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -381,4 +381,14 @@ public class UnsafeCompositeBlockBehavior extends BukkitBlockBehavior
|
||||
}
|
||||
FallOnBlockBehavior.super.updateEntityMovementAfterFallOn(thisBlock, args, superMethod);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean propagatesSkylightDown(Object thisBlock, Object[] args, Callable<Object> superMethod) throws Exception {
|
||||
for (AbstractBlockBehavior behavior : this.behaviors) {
|
||||
if (!behavior.propagatesSkylightDown(thisBlock, args, superMethod)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return (boolean) superMethod.call();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -170,6 +170,9 @@ public final class BlockGenerator {
|
||||
// stepOn
|
||||
.method(ElementMatchers.is(CoreReflections.method$Block$stepOn))
|
||||
.intercept(MethodDelegation.to(StepOnInterceptor.INSTANCE))
|
||||
// propagatesSkylightDown
|
||||
.method(ElementMatchers.is(CoreReflections.method$BlockBehaviour$propagatesSkylightDown))
|
||||
.intercept(MethodDelegation.to(PropagatesSkylightDownInterceptor.INSTANCE))
|
||||
;
|
||||
// 1.21.5+
|
||||
if (CoreReflections.method$BlockBehaviour$affectNeighborsAfterRemoval != null) {
|
||||
@@ -760,4 +763,19 @@ public final class BlockGenerator {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class PropagatesSkylightDownInterceptor {
|
||||
public static final PropagatesSkylightDownInterceptor INSTANCE = new PropagatesSkylightDownInterceptor();
|
||||
|
||||
@RuntimeType
|
||||
public boolean intercept(@This Object thisObj, @AllArguments Object[] args, @SuperCall Callable<Object> superMethod) {
|
||||
ObjectHolder<BlockBehavior> holder = ((DelegatingBlock) thisObj).behaviorDelegate();
|
||||
try {
|
||||
return holder.value().propagatesSkylightDown(thisObj, args, superMethod);
|
||||
} catch (Exception e) {
|
||||
CraftEngine.instance().logger().severe("Failed to run propagatesSkylightDown", e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -12,7 +12,6 @@ import net.bytebuddy.implementation.FieldAccessor;
|
||||
import net.bytebuddy.implementation.MethodDelegation;
|
||||
import net.bytebuddy.implementation.bind.annotation.AllArguments;
|
||||
import net.bytebuddy.implementation.bind.annotation.RuntimeType;
|
||||
import net.bytebuddy.implementation.bind.annotation.SuperCall;
|
||||
import net.bytebuddy.implementation.bind.annotation.This;
|
||||
import net.bytebuddy.matcher.ElementMatchers;
|
||||
import net.momirealms.craftengine.bukkit.item.BukkitItemManager;
|
||||
@@ -23,15 +22,16 @@ import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MBlockState
|
||||
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MBuiltInRegistries;
|
||||
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MLootContextParams;
|
||||
import net.momirealms.craftengine.bukkit.plugin.user.BukkitServerPlayer;
|
||||
import net.momirealms.craftengine.bukkit.util.BlockStateUtils;
|
||||
import net.momirealms.craftengine.bukkit.world.BukkitWorld;
|
||||
import net.momirealms.craftengine.core.block.*;
|
||||
import net.momirealms.craftengine.core.block.BlockSettings;
|
||||
import net.momirealms.craftengine.core.block.CustomBlock;
|
||||
import net.momirealms.craftengine.core.block.DelegatingBlockState;
|
||||
import net.momirealms.craftengine.core.block.ImmutableBlockState;
|
||||
import net.momirealms.craftengine.core.block.properties.Property;
|
||||
import net.momirealms.craftengine.core.item.Item;
|
||||
import net.momirealms.craftengine.core.plugin.CraftEngine;
|
||||
import net.momirealms.craftengine.core.plugin.context.ContextHolder;
|
||||
import net.momirealms.craftengine.core.plugin.context.parameter.DirectContextParameters;
|
||||
import net.momirealms.craftengine.core.util.ObjectHolder;
|
||||
import net.momirealms.craftengine.core.registry.Holder;
|
||||
import net.momirealms.craftengine.core.util.ReflectionUtils;
|
||||
import net.momirealms.craftengine.core.util.VersionHelper;
|
||||
import net.momirealms.craftengine.core.world.World;
|
||||
@@ -42,8 +42,6 @@ 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;
|
||||
|
||||
public final class BlockStateGenerator {
|
||||
private static MethodHandle constructor$CraftEngineBlockState;
|
||||
@@ -87,11 +85,11 @@ public final class BlockStateGenerator {
|
||||
Class<?> clazz$CraftEngineBlock = stateBuilder.make().load(BlockStateGenerator.class.getClassLoader()).getLoaded();
|
||||
constructor$CraftEngineBlockState = VersionHelper.isOrAbove1_20_5() ?
|
||||
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)) :
|
||||
.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)) :
|
||||
MethodHandles.publicLookup().in(clazz$CraftEngineBlock)
|
||||
.findConstructor(clazz$CraftEngineBlock, MethodType.methodType(void.class, CoreReflections.clazz$Block, ImmutableMap.class, MapCodec.class))
|
||||
.asType(MethodType.methodType(CoreReflections.clazz$BlockState, CoreReflections.clazz$Block, ImmutableMap.class, MapCodec.class));
|
||||
.findConstructor(clazz$CraftEngineBlock, MethodType.methodType(void.class, CoreReflections.clazz$Block, ImmutableMap.class, MapCodec.class))
|
||||
.asType(MethodType.methodType(CoreReflections.clazz$BlockState, CoreReflections.clazz$Block, ImmutableMap.class, MapCodec.class));
|
||||
|
||||
String generatedFactoryClassName = packageWithName.substring(0, packageWithName.lastIndexOf('.')) + ".CraftEngineStateFactory";
|
||||
DynamicType.Builder<?> factoryBuilder = byteBuddy
|
||||
@@ -210,10 +208,12 @@ public final class BlockStateGenerator {
|
||||
DelegatingBlockState customState = (DelegatingBlockState) thisObj;
|
||||
ImmutableBlockState thisState = customState.blockState();
|
||||
if (thisState == null) return false;
|
||||
if (!(args[0] instanceof DelegatingBlock delegatingBlock)) return false;
|
||||
BlockBehavior behavior = delegatingBlock.behaviorDelegate().value();
|
||||
if (behavior == null) return false;
|
||||
return behavior.block().equals(thisState.owner().value());
|
||||
if (FastNMS.INSTANCE.method$Block$defaultState(args[0]) instanceof DelegatingBlockState holder) {
|
||||
ImmutableBlockState holderState = holder.blockState();
|
||||
if (holderState == null) return false;
|
||||
return holderState.owner().equals(thisState.owner());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -226,13 +226,15 @@ public final class BlockStateGenerator {
|
||||
DelegatingBlockState customState = (DelegatingBlockState) thisObj;
|
||||
ImmutableBlockState thisState = customState.blockState();
|
||||
if (thisState == null) return false;
|
||||
CustomBlock thisBlock = thisState.owner().value();
|
||||
Holder<CustomBlock> owner = thisState.owner();
|
||||
for (Object holder : (Iterable<Object>) args[0]) {
|
||||
Object block = FastNMS.INSTANCE.method$Holder$value(holder);
|
||||
if (!(block instanceof DelegatingBlock delegatingBlock)) continue;
|
||||
BlockBehavior behavior = delegatingBlock.behaviorDelegate().value();
|
||||
if (behavior == null) continue;
|
||||
if (behavior.block().equals(thisBlock)) return true;
|
||||
if (block == null) continue;
|
||||
if (!(FastNMS.INSTANCE.method$Block$defaultState(block) instanceof DelegatingBlockState customHolder))
|
||||
continue;
|
||||
ImmutableBlockState holderState = customHolder.blockState();
|
||||
if (holderState == null) continue;
|
||||
return holderState.owner().equals(owner);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -243,15 +245,17 @@ public final class BlockStateGenerator {
|
||||
|
||||
@RuntimeType
|
||||
public boolean intercept(@This Object thisObj, @AllArguments Object[] args) {
|
||||
Object block = FastNMS.INSTANCE.method$Holder$value(args[0]);
|
||||
if (!(block instanceof DelegatingBlock delegatingBlock)) return false;
|
||||
BlockBehavior behavior = delegatingBlock.behaviorDelegate().value();
|
||||
if (behavior == null) return false;
|
||||
DelegatingBlockState customState = (DelegatingBlockState) thisObj;
|
||||
ImmutableBlockState thisState = customState.blockState();
|
||||
if (thisState == null) return false;
|
||||
CustomBlock thisBlock = thisState.owner().value();
|
||||
return behavior.block().equals(thisBlock);
|
||||
Object block = FastNMS.INSTANCE.method$Holder$value(args[0]);
|
||||
if (block == null) return false;
|
||||
if (FastNMS.INSTANCE.method$Block$defaultState(block) instanceof DelegatingBlockState holder) {
|
||||
ImmutableBlockState holderState = holder.blockState();
|
||||
if (holderState == null) return false;
|
||||
return holderState.owner().equals(thisState.owner());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -260,17 +264,19 @@ public final class BlockStateGenerator {
|
||||
|
||||
@RuntimeType
|
||||
public boolean intercept(@This Object thisObj, @AllArguments Object[] args) {
|
||||
Object block = FastNMS.INSTANCE.method$HolderGetter$getResourceKey(MBuiltInRegistries.BLOCK, args[0])
|
||||
.map(FastNMS.INSTANCE::method$Holder$value)
|
||||
.orElse(null);
|
||||
if (!(block instanceof DelegatingBlock delegatingBlock)) return false;
|
||||
BlockBehavior behavior = delegatingBlock.behaviorDelegate().value();
|
||||
if (behavior == null) return false;
|
||||
DelegatingBlockState customState = (DelegatingBlockState) thisObj;
|
||||
ImmutableBlockState thisState = customState.blockState();
|
||||
if (thisState == null) return false;
|
||||
CustomBlock thisBlock = thisState.owner().value();
|
||||
return behavior.block().equals(thisBlock);
|
||||
Object block = FastNMS.INSTANCE.method$HolderGetter$getResourceKey(MBuiltInRegistries.BLOCK, args[0])
|
||||
.map(FastNMS.INSTANCE::method$Holder$value)
|
||||
.orElse(null);
|
||||
if (block == null) return false;
|
||||
if (FastNMS.INSTANCE.method$Block$defaultState(block) instanceof DelegatingBlockState holder) {
|
||||
ImmutableBlockState holderState = holder.blockState();
|
||||
if (holderState == null) return false;
|
||||
return holderState.owner().equals(thisState.owner());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -4434,4 +4434,14 @@ public final class CoreReflections {
|
||||
ReflectionUtils.getDeclaredMethod(clazz$BlockStateBase, boolean.class, new String[]{"is", "a"}, clazz$ResourceKey),
|
||||
VersionHelper.isOrAbove1_20_3()
|
||||
);
|
||||
|
||||
public static final Method method$BlockBehaviour$propagatesSkylightDown = requireNonNull(
|
||||
VersionHelper.isOrAbove1_21_2()
|
||||
? ReflectionUtils.getDeclaredMethod(clazz$BlockBehaviour, boolean.class, new String[]{"propagatesSkylightDown", "e_"}, clazz$BlockState)
|
||||
: VersionHelper.isOrAbove1_20_5()
|
||||
? ReflectionUtils.getDeclaredMethod(clazz$BlockBehaviour, boolean.class, new String[]{"propagatesSkylightDown", "a_"}, clazz$BlockState, clazz$BlockGetter, clazz$BlockPos)
|
||||
: VersionHelper.isOrAbove1_20_4()
|
||||
? ReflectionUtils.getDeclaredMethod(clazz$BlockBehaviour, boolean.class, new String[]{"propagatesSkylightDown", "a_"}, clazz$BlockState, clazz$BlockGetter, clazz$BlockPos)
|
||||
: ReflectionUtils.getDeclaredMethod(clazz$BlockBehaviour, boolean.class, new String[]{"propagatesSkylightDown", "c"}, clazz$BlockState, clazz$BlockGetter, clazz$BlockPos)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -6,54 +6,31 @@ import net.momirealms.craftengine.core.util.VersionHelper;
|
||||
public final class MBlocks {
|
||||
private MBlocks() {}
|
||||
|
||||
public static final Object AIR;
|
||||
public static final Object AIR$defaultState;
|
||||
public static final Object STONE;
|
||||
public static final Object STONE$defaultState;
|
||||
public static final Object FIRE;
|
||||
public static final Object SOUL_FIRE;
|
||||
public static final Object ICE;
|
||||
public static final Object SHORT_GRASS;
|
||||
public static final Object SHORT_GRASS$defaultState;
|
||||
public static final Object SHULKER_BOX;
|
||||
public static final Object COMPOSTER;
|
||||
public static final Object SNOW;
|
||||
public static final Object WATER;
|
||||
public static final Object WATER$defaultState;
|
||||
public static final Object TNT;
|
||||
public static final Object TNT$defaultState;
|
||||
public static final Object BARRIER;
|
||||
public static final Object CARVED_PUMPKIN;
|
||||
public static final Object JACK_O_LANTERN;
|
||||
public static final Object MELON;
|
||||
public static final Object PUMPKIN;
|
||||
public static final Object AIR = getById("air");;
|
||||
public static final Object AIR$defaultState = FastNMS.INSTANCE.method$Block$defaultState(AIR);
|
||||
public static final Object STONE = getById("stone");
|
||||
public static final Object STONE$defaultState = FastNMS.INSTANCE.method$Block$defaultState(STONE);
|
||||
public static final Object FIRE = getById("fire");
|
||||
public static final Object SOUL_FIRE = getById("soul_fire");
|
||||
public static final Object ICE = getById("ice");
|
||||
public static final Object SHORT_GRASS = getById(VersionHelper.isOrAbove1_20_3() ? "short_grass" : "grass");
|
||||
public static final Object SHORT_GRASS$defaultState = FastNMS.INSTANCE.method$Block$defaultState(SHORT_GRASS);
|
||||
public static final Object SHULKER_BOX = getById("shulker_box");
|
||||
public static final Object COMPOSTER = getById("composter");
|
||||
public static final Object SNOW = getById("snow");
|
||||
public static final Object WATER = getById("water");
|
||||
public static final Object WATER$defaultState = FastNMS.INSTANCE.method$Block$defaultState(WATER);
|
||||
public static final Object TNT = getById("tnt");
|
||||
public static final Object TNT$defaultState = FastNMS.INSTANCE.method$Block$defaultState(TNT);
|
||||
public static final Object BARRIER = getById("barrier");
|
||||
public static final Object CARVED_PUMPKIN = getById("carved_pumpkin");
|
||||
public static final Object JACK_O_LANTERN = getById("jack_o_lantern");
|
||||
public static final Object MELON = getById("melon");
|
||||
public static final Object PUMPKIN = getById("pumpkin");
|
||||
public static final Object FARMLAND = getById("farmland");
|
||||
|
||||
private static Object getById(String id) {
|
||||
Object rl = FastNMS.INSTANCE.method$ResourceLocation$fromNamespaceAndPath("minecraft", id);
|
||||
return FastNMS.INSTANCE.method$Registry$getValue(MBuiltInRegistries.BLOCK, rl);
|
||||
}
|
||||
|
||||
static {
|
||||
AIR = getById("air");
|
||||
AIR$defaultState = FastNMS.INSTANCE.method$Block$defaultState(AIR);
|
||||
FIRE = getById("fire");
|
||||
SOUL_FIRE = getById("soul_fire");
|
||||
STONE = getById("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 = FastNMS.INSTANCE.method$Block$defaultState(SHORT_GRASS);
|
||||
SHULKER_BOX = getById("shulker_box");
|
||||
COMPOSTER = getById("composter");
|
||||
SNOW = getById("snow");
|
||||
WATER = getById("water");
|
||||
WATER$defaultState = FastNMS.INSTANCE.method$Block$defaultState(WATER);
|
||||
TNT = getById("tnt");
|
||||
TNT$defaultState = FastNMS.INSTANCE.method$Block$defaultState(TNT);
|
||||
BARRIER = getById("barrier");
|
||||
CARVED_PUMPKIN = getById("carved_pumpkin");
|
||||
JACK_O_LANTERN = getById("jack_o_lantern");
|
||||
MELON = getById("melon");
|
||||
PUMPKIN = getById("pumpkin");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ public final class MTagKeys {
|
||||
public static final Object Block$SHULKER_BOXES = create(MRegistries.BLOCK, "shulker_boxes");
|
||||
public static final Object Block$FENCES = create(MRegistries.BLOCK, "fences");
|
||||
public static final Object Block$WOODEN_FENCES = create(MRegistries.BLOCK, "wooden_fences");
|
||||
public static final Object Block$DIRT = create(MRegistries.BLOCK, "dirt");
|
||||
|
||||
private static Object create(Object registry, String location) {
|
||||
Object resourceLocation = FastNMS.INSTANCE.method$ResourceLocation$fromNamespaceAndPath("minecraft", location);
|
||||
|
||||
@@ -48,13 +48,13 @@ templates#models#block:
|
||||
generation:
|
||||
parent: minecraft:block/cube_column
|
||||
textures:
|
||||
particle: minecraft:block/custom/block_particle
|
||||
down: minecraft:block/custom/block_down
|
||||
up: minecraft:block/custom/block_up
|
||||
north: minecraft:block/custom/block_north
|
||||
east: minecraft:block/custom/block_east
|
||||
south: minecraft:block/custom/block_south
|
||||
west: minecraft:block/custom/block_west
|
||||
particle: ${particle_texture}
|
||||
down: ${down_texture}
|
||||
up: ${up_texture}
|
||||
north: ${north_texture}
|
||||
east: ${east_texture}
|
||||
south: ${south_texture}
|
||||
west: ${west_texture}
|
||||
|
||||
# 2D items
|
||||
templates#models#2d:
|
||||
|
||||
@@ -328,6 +328,12 @@ warning.config.block.behavior.fence.missing_west: "<yellow>Issue found in file <
|
||||
warning.config.block.behavior.face_attached_horizontal_directional.missing_face: "<yellow>Issue found in file <arg:0> - The block '<arg:1>' is missing the required 'face' property for 'face_attached_horizontal_directional_block' behavior.</yellow>"
|
||||
warning.config.block.behavior.face_attached_horizontal_directional.missing_facing: "<yellow>Issue found in file <arg:0> - The block '<arg:1>' is missing the required 'facing' property for 'face_attached_horizontal_directional_block' behavior.</yellow>"
|
||||
warning.config.block.behavior.button.missing_powered: "<yellow>Issue found in file <arg:0> - The block '<arg:1>' is missing the required 'powered' property for 'button_block' behavior.</yellow>"
|
||||
warning.config.block.behavior.stem.missing_age: "<yellow>Issue found in file <arg:0> - The block '<arg:1>' is missing the required 'age' property for 'stem_block' behavior.</yellow>"
|
||||
warning.config.block.behavior.stem.missing_fruit: "<yellow>Issue found in file <arg:0> - The block '<arg:1>' is missing the required 'fruit' argument for 'stem_block' behavior.</yellow>"
|
||||
warning.config.block.behavior.stem.missing_attached_stem: "<yellow>Issue found in file <arg:0> - The block '<arg:1>' is missing the required 'attached_stem' argument for 'stem_block' behavior.</yellow>"
|
||||
warning.config.block.behavior.attached_stem.missing_facing: "<yellow>Issue found in file <arg:0> - The block '<arg:1>' is missing the required 'facing' property for 'attached_stem_block' behavior.</yellow>"
|
||||
warning.config.block.behavior.attached_stem.missing_fruit: "<yellow>Issue found in file <arg:0> - The block '<arg:1>' is missing the required 'fruit' argument for 'attached_stem_block' behavior.</yellow>"
|
||||
warning.config.block.behavior.attached_stem.missing_stem: "<yellow>Issue found in file <arg:0> - The block '<arg:1>' is missing the required 'stem' argument for 'attached_stem_block' behavior.</yellow>"
|
||||
warning.config.model.generation.missing_parent: "<yellow>Issue found in file <arg:0> - The config '<arg:1>' is missing the required 'parent' argument in 'generation' section.</yellow>"
|
||||
warning.config.model.generation.conflict: "<yellow>Issue found in file <arg:0> - Failed to generate model for '<arg:1>' as two or more configurations attempt to generate different json models with the same path: '<arg:2>'.</yellow>"
|
||||
warning.config.model.generation.invalid_display_position: "<yellow>Issue found in file <arg:0> - The config '<arg:1>' is using an invalid display position '<arg:2>' in 'generation.display' section. Allowed display positions: [<arg:3>]</yellow>"
|
||||
|
||||
@@ -322,6 +322,12 @@ warning.config.block.behavior.fence.missing_west: "<yellow>在文件 <arg:0> 发
|
||||
warning.config.block.behavior.face_attached_horizontal_directional.missing_face: "<yellow>在文件 <arg:0> 发现问题 - 方块 '<arg:1>' 的 'face_attached_horizontal_directional_block' 行为缺少必需的 'face' 属性</yellow>"
|
||||
warning.config.block.behavior.face_attached_horizontal_directional.missing_facing: "<yellow>在文件 <arg:0> 发现问题 - 方块 '<arg:1>' 的 'face_attached_horizontal_directional_block' 行为缺少必需的 'facing' 属性</yellow>"
|
||||
warning.config.block.behavior.button.missing_powered: "<yellow>在文件 <arg:0> 发现问题 - 方块 '<arg:1>' 的 'button_block' 行为缺少必需的 'powered' 属性</yellow>"
|
||||
warning.config.block.behavior.stem.missing_age: "<yellow>在文件 <arg:0> 发现问题 - 方块 '<arg:1>' 的 'stem_block' 行为缺少必需的 'age' 属性</yellow>"
|
||||
warning.config.block.behavior.stem.missing_fruit: "<yellow>在文件 <arg:0> 发现问题 - 方块 '<arg:1>' 的 'stem_block' 行为缺少必需的 'fruit' 选项</yellow>"
|
||||
warning.config.block.behavior.stem.missing_attached_stem: "<yellow>在文件 <arg:0> 发现问题 - 方块 '<arg:1>' 的 'stem_block' 行为缺少必需的 'attached_stem' 选项</yellow>"
|
||||
warning.config.block.behavior.attached_stem.missing_facing: "<yellow>在文件 <arg:0> 发现问题 - 方块 '<arg:1>' 的 'attached_stem_block' 行为缺少必需的 'facing' 属性</yellow>"
|
||||
warning.config.block.behavior.attached_stem.missing_fruit: "<yellow>在文件 <arg:0> 发现问题 - 方块 '<arg:1>' 的 'attached_stem_block' 行为缺少必需的 'fruit' 选项</yellow>"
|
||||
warning.config.block.behavior.attached_stem.missing_stem: "<yellow>在文件 <arg:0> 发现问题 - 方块 '<arg:1>' 的 'attached_stem_block' 行为缺少必需的 'stem' 选项</yellow>"
|
||||
warning.config.model.generation.missing_parent: "<yellow>在文件 <arg:0> 发现问题 - 配置项 '<arg:1>' 的 'generation' 段落缺少必需的 'parent' 参数</yellow>"
|
||||
warning.config.model.generation.conflict: "<yellow>在文件 <arg:0> 发现问题 - 无法为 '<arg:1>' 生成模型 存在多个配置尝试使用相同路径 '<arg:2>' 生成不同的 JSON 模型</yellow>"
|
||||
warning.config.model.generation.invalid_display_position: "<yellow>在文件 <arg:0> 发现问题 - 配置项 '<arg:1>' 在 'generation.display' 区域使用了无效的 display 位置类型 '<arg:2>'. 可用展示类型: [<arg:3>]</yellow>"
|
||||
|
||||
@@ -184,6 +184,12 @@ public abstract class BlockBehavior {
|
||||
superMethod.call();
|
||||
}
|
||||
|
||||
// 1.20.1~1.21.1 BlockState state, BlockGetter level, BlockPos pos
|
||||
// 1.21.2+ BlockState state
|
||||
public boolean propagatesSkylightDown(Object thisBlock, Object[] args, Callable<Object> superMethod) throws Exception {
|
||||
return (boolean) superMethod.call();
|
||||
}
|
||||
|
||||
public ImmutableBlockState updateStateForPlacement(BlockPlaceContext context, ImmutableBlockState state) {
|
||||
return state;
|
||||
}
|
||||
@@ -217,4 +223,4 @@ public abstract class BlockBehavior {
|
||||
}
|
||||
|
||||
public abstract CustomBlock block();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ org.gradle.jvmargs=-Xmx1G
|
||||
# Rule: [major update].[feature update].[bug fix]
|
||||
project_version=0.0.63.4
|
||||
config_version=46
|
||||
lang_version=30
|
||||
lang_version=31
|
||||
project_group=net.momirealms
|
||||
latest_supported_version=1.21.8
|
||||
|
||||
@@ -50,7 +50,7 @@ byte_buddy_version=1.17.5
|
||||
ahocorasick_version=0.6.3
|
||||
snake_yaml_version=2.5
|
||||
anti_grief_version=0.20
|
||||
nms_helper_version=1.0.93
|
||||
nms_helper_version=1.0.94
|
||||
evalex_version=3.5.0
|
||||
reactive_streams_version=1.0.4
|
||||
amazon_awssdk_version=2.33.1
|
||||
|
||||
Reference in New Issue
Block a user