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

Merge pull request #352 from ArubikU/preparing-block-entity

Added container and analog
This commit is contained in:
XiaoMoMi
2025-09-04 06:28:18 +08:00
committed by GitHub
4 changed files with 135 additions and 3 deletions

View File

@@ -92,6 +92,18 @@ public class UnsafeCompositeBlockBehavior extends BukkitBlockBehavior {
return previous;
}
@Override
public Object getContainer(Object thisBlock, Object[] args) throws Exception {
for (AbstractBlockBehavior behavior : this.behaviors) {
Object container = behavior.getContainer(thisBlock, args);
if (container != null) {
return container;
}
}
return null;
}
@Override
public void tick(Object thisBlock, Object[] args, Callable<Object> superMethod) throws Exception {
for (AbstractBlockBehavior behavior : this.behaviors) {
@@ -282,6 +294,30 @@ public class UnsafeCompositeBlockBehavior extends BukkitBlockBehavior {
return false;
}
@Override
public boolean hasAnalogOutputSignal(Object thisBlock, Object[] args) throws Exception {
for (AbstractBlockBehavior behavior : this.behaviors) {
if (behavior.hasAnalogOutputSignal(thisBlock, args)) {
return true;
}
}
return false;
}
@Override
public int getAnalogOutputSignal(Object thisBlock, Object[] args) throws Exception {
int signal = 0;
int count = 0;
for (AbstractBlockBehavior behavior : this.behaviors) {
int s = behavior.getAnalogOutputSignal(thisBlock, args);
if (s != 0) {
signal += s;
count++;
}
}
return count == 0 ? 0 : signal / count;
}
@Override
public Object playerWillDestroy(Object thisBlock, Object[] args, Callable<Object> superMethod) throws Exception {
Object previous = args[0];
@@ -300,4 +336,4 @@ public class UnsafeCompositeBlockBehavior extends BukkitBlockBehavior {
behavior.spawnAfterBreak(thisBlock, args, superMethod);
}
}
}
}

View File

@@ -15,6 +15,7 @@ import net.bytebuddy.implementation.bind.annotation.This;
import net.bytebuddy.matcher.ElementMatchers;
import net.momirealms.craftengine.bukkit.block.BukkitBlockShape;
import net.momirealms.craftengine.bukkit.nms.FastNMS;
import net.momirealms.craftengine.bukkit.plugin.injector.BlockGenerator.*;
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.CoreReflections;
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MBlocks;
import net.momirealms.craftengine.bukkit.util.NoteBlockChainUpdateUtils;
@@ -62,6 +63,7 @@ public final class BlockGenerator {
.implement(CoreReflections.clazz$Fallable)
.implement(CoreReflections.clazz$BonemealableBlock)
.implement(CoreReflections.clazz$SimpleWaterloggedBlock)
.implement(CoreReflections.clazz$WorldlyContainerHolder)
// internal interfaces
.method(ElementMatchers.named("behaviorDelegate"))
.intercept(FieldAccessor.ofField("behaviorHolder"))
@@ -89,12 +91,21 @@ public final class BlockGenerator {
// rotate
.method(ElementMatchers.is(CoreReflections.method$BlockBehaviour$rotate))
.intercept(MethodDelegation.to(RotateInterceptor.INSTANCE))
// hasAnalogOutputSignal
.method(ElementMatchers.is(CoreReflections.method$BlockBehaviour$hasAnalogOutputSignal))
.intercept(MethodDelegation.to(HasAnalogOutputSignalInterceptor.INSTANCE))
// getAnalogOutputSignal
.method(ElementMatchers.is(CoreReflections.method$BlockBehaviour$getAnalogOutputSignal))
.intercept(MethodDelegation.to(GetAnalogOutputSignalInterceptor.INSTANCE))
// tick
.method(ElementMatchers.is(CoreReflections.method$BlockBehaviour$tick))
.intercept(MethodDelegation.to(TickInterceptor.INSTANCE))
// isValidBoneMealTarget
.method(ElementMatchers.is(CoreReflections.method$BonemealableBlock$isValidBonemealTarget))
.intercept(MethodDelegation.to(IsValidBoneMealTargetInterceptor.INSTANCE))
// getContainer
.method(ElementMatchers.is(CoreReflections.method$WorldlyContainerHolder$getContainer))
.intercept(MethodDelegation.to(GetContainerInterceptor.INSTANCE))
// isBoneMealSuccess
.method(ElementMatchers.is(CoreReflections.method$BonemealableBlock$isBonemealSuccess))
.intercept(MethodDelegation.to(IsBoneMealSuccessInterceptor.INSTANCE))
@@ -441,6 +452,50 @@ public final class BlockGenerator {
}
}
public static class GetContainerInterceptor {
public static final GetContainerInterceptor INSTANCE = new GetContainerInterceptor();
@RuntimeType
public Object intercept(@This Object thisObj, @AllArguments Object[] args) {
ObjectHolder<BlockBehavior> holder = ((DelegatingBlock) thisObj).behaviorDelegate();
try {
return holder.value().getContainer(thisObj, args);
} catch (Exception e) {
CraftEngine.instance().logger().severe("Failed to run getContainer", e);
return null;
}
}
}
public static class HasAnalogOutputSignalInterceptor {
public static final HasAnalogOutputSignalInterceptor INSTANCE = new HasAnalogOutputSignalInterceptor();
@RuntimeType
public boolean intercept(@This Object thisObj, @AllArguments Object[] args) {
ObjectHolder<BlockBehavior> holder = ((DelegatingBlock) thisObj).behaviorDelegate();
try {
return holder.value().hasAnalogOutputSignal(thisObj, args);
} catch (Exception e) {
CraftEngine.instance().logger().severe("Failed to run hasAnalogOutputSignal", e);
return false;
}
}
}
public static class GetAnalogOutputSignalInterceptor {
public static final GetAnalogOutputSignalInterceptor INSTANCE = new GetAnalogOutputSignalInterceptor();
@RuntimeType
public int intercept(@This Object thisObj, @AllArguments Object[] args) {
ObjectHolder<BlockBehavior> holder = ((DelegatingBlock) thisObj).behaviorDelegate();
try {
return holder.value().getAnalogOutputSignal(thisObj, args);
} catch (Exception e) {
CraftEngine.instance().logger().severe("Failed to run getAnalogOutputSignal", e);
return 0;
}
}
}
public static class PerformBoneMealInterceptor {
public static final PerformBoneMealInterceptor INSTANCE = new PerformBoneMealInterceptor();
@@ -644,4 +699,4 @@ public final class BlockGenerator {
}
}
}
}
}

View File

@@ -1570,6 +1570,14 @@ public final class CoreReflections {
)
);
public static final Method method$BlockBehaviour$hasAnalogOutputSignal = requireNonNull(
ReflectionUtils.getDeclaredMethod(clazz$BlockBehaviour, boolean.class, new String[]{"hasAnalogOutputSignal", "c"}, clazz$BlockState)
);
public static final Method method$BlockBehaviour$getAnalogOutputSignal = requireNonNull(
ReflectionUtils.getDeclaredMethod(clazz$BlockBehaviour, int.class, new String[]{"getAnalogOutputSignal", "a"}, clazz$BlockState, clazz$Level, clazz$BlockPos)
);
public static final Method method$Entity$level = requireNonNull(
ReflectionUtils.getMethod(clazz$Entity, clazz$Level)
);
@@ -2314,12 +2322,30 @@ public final class CoreReflections {
)
);
public static final Class<?> clazz$WorldlyContainerHolder = requireNonNull(
BukkitReflectionUtils.findReobfOrMojmapClass(
"world.IInventoryHolder",
"world.WorldlyContainerHolder"
)
);
public static final Method method$BonemealableBlock$isValidBonemealTarget = requireNonNull(
VersionHelper.isOrAbove1_20_2() ?
ReflectionUtils.getInstanceMethod(clazz$BonemealableBlock, boolean.class, clazz$LevelReader, clazz$BlockPos, clazz$BlockState) :
ReflectionUtils.getInstanceMethod(clazz$BonemealableBlock, boolean.class, clazz$LevelReader, clazz$BlockPos, clazz$BlockState, boolean.class)
);
public static final Class<?> clazz$WorldlyContainer = requireNonNull(
BukkitReflectionUtils.findReobfOrMojmapClass(
"world.IWorldInventory",
"world.WorldlyContainer"
)
);
public static final Method method$WorldlyContainerHolder$getContainer = requireNonNull(
ReflectionUtils.getMethod(clazz$WorldlyContainerHolder, clazz$WorldlyContainer, clazz$BlockState, clazz$LevelAccessor, clazz$BlockPos)
);
public static final Method method$BonemealableBlock$isBonemealSuccess = requireNonNull(
ReflectionUtils.getMethod(clazz$BonemealableBlock, boolean.class, clazz$Level, clazz$RandomSource, clazz$BlockPos, clazz$BlockState)
);

View File

@@ -95,6 +95,21 @@ public abstract class BlockBehavior {
return false;
}
//BlockState state
public boolean hasAnalogOutputSignal(Object thisBlock, Object[] args) throws Exception {
return false;
}
//BlockState state Level level BlockPos pos
public int getAnalogOutputSignal(Object thisBlock, Object[] args) throws Exception {
return 0;
}
// BlockState state, LevelReader world, BlockPos pos
public Object getContainer(Object thisBlock, Object[] args) throws Exception {
return null;
}
// Level level, RandomSource random, BlockPos pos, BlockState state
public boolean isBoneMealSuccess(Object thisBlock, Object[] args) throws Exception {
return false;
@@ -196,4 +211,4 @@ public abstract class BlockBehavior {
}
public abstract CustomBlock block();
}
}