mirror of
https://github.com/Xiao-MoMi/craft-engine.git
synced 2025-12-29 20:09:13 +00:00
Merge pull request #388 from jhqwqmc/dev
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;
|
||||
@@ -20,18 +19,16 @@ import net.momirealms.craftengine.bukkit.nms.FastNMS;
|
||||
import net.momirealms.craftengine.bukkit.plugin.BukkitCraftEngine;
|
||||
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.CoreReflections;
|
||||
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MBlockStateProperties;
|
||||
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.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.util.ReflectionUtils;
|
||||
import net.momirealms.craftengine.core.util.VersionHelper;
|
||||
import net.momirealms.craftengine.core.world.World;
|
||||
@@ -42,8 +39,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;
|
||||
@@ -71,27 +66,15 @@ public final class BlockStateGenerator {
|
||||
.method(ElementMatchers.is(CoreReflections.method$StateHolder$setValue))
|
||||
.intercept(MethodDelegation.to(SetPropertyValueInterceptor.INSTANCE))
|
||||
.method(ElementMatchers.is(CoreReflections.method$BlockStateBase$isBlock))
|
||||
.intercept(MethodDelegation.to(IsBlockInterceptor.INSTANCE))
|
||||
.method(ElementMatchers.is(CoreReflections.method$BlockStateBase$isHolderSetBlock))
|
||||
.intercept(MethodDelegation.to(IsHolderSetBlockInterceptor.INSTANCE));
|
||||
if (CoreReflections.method$BlockStateBase$isHolderBlock != null) {
|
||||
stateBuilder = stateBuilder
|
||||
.method(ElementMatchers.is(CoreReflections.method$BlockStateBase$isHolderBlock))
|
||||
.intercept(MethodDelegation.to(IsHolderBlockInterceptor.INSTANCE));
|
||||
}
|
||||
if (CoreReflections.method$BlockStateBase$isResourceKeyBlock != null) {
|
||||
stateBuilder = stateBuilder
|
||||
.method(ElementMatchers.is(CoreReflections.method$BlockStateBase$isResourceKeyBlock))
|
||||
.intercept(MethodDelegation.to(IsResourceKeyBlockInterceptor.INSTANCE));
|
||||
}
|
||||
.intercept(MethodDelegation.to(IsBlockInterceptor.INSTANCE));
|
||||
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,70 +193,15 @@ 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());
|
||||
}
|
||||
}
|
||||
|
||||
public static class IsHolderSetBlockInterceptor {
|
||||
public static final IsHolderSetBlockInterceptor INSTANCE = new IsHolderSetBlockInterceptor();
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@RuntimeType
|
||||
public boolean intercept(@This Object thisObj, @AllArguments Object[] args) {
|
||||
DelegatingBlockState customState = (DelegatingBlockState) thisObj;
|
||||
ImmutableBlockState thisState = customState.blockState();
|
||||
if (thisState == null) return false;
|
||||
CustomBlock thisBlock = thisState.owner().value();
|
||||
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 (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;
|
||||
}
|
||||
}
|
||||
|
||||
public static class IsHolderBlockInterceptor {
|
||||
public static final IsHolderBlockInterceptor INSTANCE = new IsHolderBlockInterceptor();
|
||||
|
||||
@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);
|
||||
}
|
||||
}
|
||||
|
||||
public static class IsResourceKeyBlockInterceptor {
|
||||
public static final IsResourceKeyBlockInterceptor INSTANCE = new IsResourceKeyBlockInterceptor();
|
||||
|
||||
@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);
|
||||
}
|
||||
}
|
||||
|
||||
public static class CreateStateInterceptor {
|
||||
public static final CreateStateInterceptor INSTANCE = new CreateStateInterceptor();
|
||||
|
||||
|
||||
@@ -4419,19 +4419,13 @@ public final class CoreReflections {
|
||||
ReflectionUtils.getDeclaredMethod(clazz$BlockStateBase, boolean.class, new String[]{"is", "a"}, clazz$Block)
|
||||
);
|
||||
|
||||
public static final Method method$BlockStateBase$isHolderSetBlock = requireNonNull(
|
||||
ReflectionUtils.getDeclaredMethod(clazz$BlockStateBase, boolean.class, new String[]{"is", "a"}, clazz$HolderSet)
|
||||
);
|
||||
|
||||
// 1.20.2+
|
||||
public static final Method method$BlockStateBase$isHolderBlock = MiscUtils.requireNonNullIf(
|
||||
ReflectionUtils.getDeclaredMethod(clazz$BlockStateBase, boolean.class, new String[]{"is", "a"}, clazz$Holder),
|
||||
VersionHelper.isOrAbove1_20_2()
|
||||
);
|
||||
|
||||
// 1.20.3+
|
||||
public static final Method method$BlockStateBase$isResourceKeyBlock = MiscUtils.requireNonNullIf(
|
||||
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$Block, boolean.class, new String[]{"propagatesSkylightDown", "a_"}, clazz$BlockState, clazz$BlockGetter, clazz$BlockPos)
|
||||
: ReflectionUtils.getDeclaredMethod(clazz$Block, 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);
|
||||
|
||||
Reference in New Issue
Block a user