mirror of
https://github.com/Xiao-MoMi/craft-engine.git
synced 2025-12-25 18:09:27 +00:00
feat(bukkit): 实现弹跳方块行为
This commit is contained in:
@@ -0,0 +1,68 @@
|
||||
package net.momirealms.craftengine.bukkit.block.behavior;
|
||||
|
||||
import net.momirealms.craftengine.bukkit.nms.FastNMS;
|
||||
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.CoreReflections;
|
||||
import net.momirealms.craftengine.core.block.BlockBehavior;
|
||||
import net.momirealms.craftengine.core.block.CustomBlock;
|
||||
import net.momirealms.craftengine.core.block.behavior.BlockBehaviorFactory;
|
||||
import net.momirealms.craftengine.core.util.ResourceConfigUtils;
|
||||
import net.momirealms.craftengine.core.util.VersionHelper;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
public class BouncingBlockBehavior extends BukkitBlockBehavior {
|
||||
public static final Factory FACTORY = new Factory();
|
||||
private final double bounceHeight;
|
||||
|
||||
public BouncingBlockBehavior(CustomBlock customBlock, double bounceHeight) {
|
||||
super(customBlock);
|
||||
this.bounceHeight = bounceHeight;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fallOn(Object thisBlock, Object[] args, Callable<Object> superMethod) throws Exception {
|
||||
Object entity = args[3];
|
||||
Object finalFallDistance;
|
||||
if (VersionHelper.isOrAbove1_21_5()) {
|
||||
double fallDistance = (double) args[4];
|
||||
finalFallDistance = fallDistance * 0.5;
|
||||
} else {
|
||||
finalFallDistance = (float) args[4] * 0.5F;
|
||||
}
|
||||
FastNMS.INSTANCE.method$Entity$causeFallDamage(
|
||||
entity, finalFallDistance, 1.0F,
|
||||
FastNMS.INSTANCE.method$DamageSources$fall(FastNMS.INSTANCE.method$Entity$damageSources(entity))
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateEntityMovementAfterFallOn(Object thisBlock, Object[] args, Callable<Object> superMethod) throws Exception {
|
||||
Object entity = args[1];
|
||||
if (FastNMS.INSTANCE.method$Entity$getSharedFlag(entity, 1)) {
|
||||
bounceUp(entity);
|
||||
}
|
||||
}
|
||||
|
||||
private void bounceUp(Object entity) {
|
||||
Object deltaMovement = FastNMS.INSTANCE.method$Entity$getDeltaMovement(entity);
|
||||
if (FastNMS.INSTANCE.field$Vec3$y(deltaMovement) < 0.0) {
|
||||
double d = CoreReflections.clazz$LivingEntity.isInstance(entity) ? 1.0 : 0.8;
|
||||
FastNMS.INSTANCE.method$Entity$setDeltaMovement(
|
||||
entity,
|
||||
FastNMS.INSTANCE.field$Vec3$x(deltaMovement),
|
||||
-FastNMS.INSTANCE.field$Vec3$y(deltaMovement) * this.bounceHeight * d,
|
||||
FastNMS.INSTANCE.field$Vec3$z(deltaMovement)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public static class Factory implements BlockBehaviorFactory {
|
||||
|
||||
@Override
|
||||
public BlockBehavior create(CustomBlock block, Map<String, Object> arguments) {
|
||||
double bounceHeight = ResourceConfigUtils.getAsDouble(arguments.getOrDefault("bounce-height", 0.66), "bounce-height");
|
||||
return new BouncingBlockBehavior(block, bounceHeight);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -31,6 +31,7 @@ public class BukkitBlockBehaviors extends BlockBehaviors {
|
||||
public static final Key SIMPLE_STORAGE_BLOCK = Key.from("craftengine:simple_storage_block");
|
||||
public static final Key TOGGLEABLE_LAMP_BLOCK = Key.from("craftengine:toggleable_lamp_block");
|
||||
public static final Key SOFA_BLOCK = Key.from("craftengine:sofa_block");
|
||||
public static final Key BOUNCING_BLOCK = Key.from("craftengine:bouncing_block");
|
||||
|
||||
public static void init() {
|
||||
register(EMPTY, (block, args) -> EmptyBlockBehavior.INSTANCE);
|
||||
@@ -60,5 +61,6 @@ public class BukkitBlockBehaviors extends BlockBehaviors {
|
||||
register(SIMPLE_STORAGE_BLOCK, SimpleStorageBlockBehavior.FACTORY);
|
||||
register(TOGGLEABLE_LAMP_BLOCK, ToggleableLampBlockBehavior.FACTORY);
|
||||
register(SOFA_BLOCK, SofaBlockBehavior.FACTORY);
|
||||
register(BOUNCING_BLOCK, BouncingBlockBehavior.FACTORY);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -336,4 +336,18 @@ public class UnsafeCompositeBlockBehavior extends BukkitBlockBehavior {
|
||||
behavior.spawnAfterBreak(thisBlock, args, superMethod);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fallOn(Object thisBlock, Object[] args, Callable<Object> superMethod) throws Exception {
|
||||
for (AbstractBlockBehavior behavior : this.behaviors) {
|
||||
behavior.fallOn(thisBlock, args, superMethod);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateEntityMovementAfterFallOn(Object thisBlock, Object[] args, Callable<Object> superMethod) throws Exception {
|
||||
for (AbstractBlockBehavior behavior : this.behaviors) {
|
||||
behavior.updateEntityMovementAfterFallOn(thisBlock, args, superMethod);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -159,7 +159,14 @@ public final class BlockGenerator {
|
||||
.intercept(MethodDelegation.to(PlayerWillDestroyInterceptor.INSTANCE))
|
||||
// spawnAfterBreak
|
||||
.method(ElementMatchers.is(CoreReflections.method$BlockBehaviour$spawnAfterBreak))
|
||||
.intercept(MethodDelegation.to(SpawnAfterBreakInterceptor.INSTANCE));
|
||||
.intercept(MethodDelegation.to(SpawnAfterBreakInterceptor.INSTANCE))
|
||||
// fallOn
|
||||
.method(ElementMatchers.is(CoreReflections.method$Block$fallOn))
|
||||
.intercept(MethodDelegation.to(FallOnInterceptor.INSTANCE))
|
||||
// updateEntityMovementAfterFallOn
|
||||
.method(ElementMatchers.is(CoreReflections.method$Block$updateEntityMovementAfterFallOn))
|
||||
.intercept(MethodDelegation.to(UpdateEntityMovementAfterFallOnInterceptor.INSTANCE))
|
||||
;
|
||||
// 1.21.5+
|
||||
if (CoreReflections.method$BlockBehaviour$affectNeighborsAfterRemoval != null) {
|
||||
builder = builder.method(ElementMatchers.is(CoreReflections.method$BlockBehaviour$affectNeighborsAfterRemoval))
|
||||
@@ -699,4 +706,32 @@ public final class BlockGenerator {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class FallOnInterceptor {
|
||||
public static final FallOnInterceptor INSTANCE = new FallOnInterceptor();
|
||||
|
||||
@RuntimeType
|
||||
public void intercept(@This Object thisObj, @AllArguments Object[] args, @SuperCall Callable<Object> superMethod) {
|
||||
ObjectHolder<BlockBehavior> holder = ((DelegatingBlock) thisObj).behaviorDelegate();
|
||||
try {
|
||||
holder.value().fallOn(thisObj, args, superMethod);
|
||||
} catch (Exception e) {
|
||||
CraftEngine.instance().logger().severe("Failed to run fallOn", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class UpdateEntityMovementAfterFallOnInterceptor {
|
||||
public static final UpdateEntityMovementAfterFallOnInterceptor INSTANCE = new UpdateEntityMovementAfterFallOnInterceptor();
|
||||
|
||||
@RuntimeType
|
||||
public void intercept(@This Object thisObj, @AllArguments Object[] args, @SuperCall Callable<Object> superMethod) {
|
||||
ObjectHolder<BlockBehavior> holder = ((DelegatingBlock) thisObj).behaviorDelegate();
|
||||
try {
|
||||
holder.value().updateEntityMovementAfterFallOn(thisObj, args, superMethod);
|
||||
} catch (Exception e) {
|
||||
CraftEngine.instance().logger().severe("Failed to run updateEntityMovementAfterFallOn", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4209,4 +4209,12 @@ public final class CoreReflections {
|
||||
public static final Method method$BlockAndTintGetter$getLightEngine = requireNonNull(
|
||||
ReflectionUtils.getDeclaredMethod(clazz$BlockAndTintGetter, clazz$LevelLightEngine)
|
||||
);
|
||||
|
||||
public static final Method method$Block$fallOn = requireNonNull(
|
||||
ReflectionUtils.getDeclaredMethod(clazz$Block, void.class, clazz$Level, clazz$BlockState, clazz$BlockPos, clazz$Entity, VersionHelper.isOrAbove1_21_5() ? double.class : float.class)
|
||||
);
|
||||
|
||||
public static final Method method$Block$updateEntityMovementAfterFallOn = requireNonNull(
|
||||
ReflectionUtils.getDeclaredMethod(clazz$Block, void.class, clazz$BlockGetter, clazz$Entity)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -585,6 +585,9 @@ items#misc:
|
||||
hit: minecraft:block.wood.hit
|
||||
place: minecraft:block.wood.place
|
||||
step: minecraft:block.wood.step
|
||||
behavior:
|
||||
type: bouncing_block
|
||||
bounce-height: 0.66
|
||||
state:
|
||||
id: 0
|
||||
state: white_bed[facing=west,occupied=false,part=foot]
|
||||
|
||||
@@ -178,6 +178,15 @@ public abstract class BlockBehavior {
|
||||
public void spawnAfterBreak(Object thisBlock, Object[] args, Callable<Object> superMethod) throws Exception {
|
||||
}
|
||||
|
||||
// 1.20.1~1.21.4 Level world, BlockState state, BlockPos pos, Entity entity, float fallDistance
|
||||
// 1.21.5+ Level level, BlockState state, BlockPos pos, Entity entity, double fallDistance
|
||||
public void fallOn(Object thisBlock, Object[] args, Callable<Object> superMethod) throws Exception {
|
||||
}
|
||||
|
||||
// BlockGetter level, Entity entity
|
||||
public void updateEntityMovementAfterFallOn(Object thisBlock, Object[] args, Callable<Object> superMethod) throws Exception {
|
||||
}
|
||||
|
||||
public ImmutableBlockState updateStateForPlacement(BlockPlaceContext context, ImmutableBlockState state) {
|
||||
return state;
|
||||
}
|
||||
|
||||
@@ -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.80
|
||||
nms_helper_version=1.0.81
|
||||
evalex_version=3.5.0
|
||||
reactive_streams_version=1.0.4
|
||||
amazon_awssdk_version=2.33.1
|
||||
|
||||
Reference in New Issue
Block a user