From f06ead2fab0786e66f59af341a786c7dc588b783 Mon Sep 17 00:00:00 2001 From: IzzelAliz Date: Thu, 8 Sep 2022 13:31:21 +0800 Subject: [PATCH] Implement ticking source API --- .../core/server/level/ServerLevelMixin.java | 49 +++++++++++++ .../mod/server/api/DefaultArclightServer.java | 8 +++ .../mod/server/api/DefaultTickingTracker.java | 70 +++++++++++++++++++ .../common/mod/util/ArclightCaptures.java | 40 ++++++++++- build.gradle | 2 +- 5 files changed, 166 insertions(+), 3 deletions(-) create mode 100644 arclight-common/src/main/java/io/izzel/arclight/common/mod/server/api/DefaultTickingTracker.java diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/server/level/ServerLevelMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/server/level/ServerLevelMixin.java index fbfc2be5..0ab7c645 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/server/level/ServerLevelMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/server/level/ServerLevelMixin.java @@ -78,6 +78,7 @@ import org.spongepowered.asm.mixin.Overwrite; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.ModifyVariable; import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; @@ -462,4 +463,52 @@ public abstract class ServerLevelMixin extends LevelMixin implements ServerWorld blockList.updateList(); } } + + @ModifyVariable(method = "tickBlock", ordinal = 0, argsOnly = true, at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/block/state/BlockState;tick(Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/core/BlockPos;Ljava/util/Random;)V")) + private BlockPos arclight$captureTickingBlock(BlockPos pos) { + ArclightCaptures.captureTickingBlock((ServerLevel) (Object) this, pos); + return pos; + } + + @ModifyVariable(method = "tickBlock", ordinal = 0, argsOnly = true, at = @At(value = "INVOKE", shift = At.Shift.AFTER, target = "Lnet/minecraft/world/level/block/state/BlockState;tick(Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/core/BlockPos;Ljava/util/Random;)V")) + private BlockPos arclight$resetTickingBlock(BlockPos pos) { + ArclightCaptures.resetTickingBlock(); + return pos; + } + + @ModifyVariable(method = "tickChunk", ordinal = 0, at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/block/state/BlockState;randomTick(Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/core/BlockPos;Ljava/util/Random;)V")) + private BlockPos arclight$captureRandomTick(BlockPos pos) { + ArclightCaptures.captureTickingBlock((ServerLevel) (Object) this, pos); + return pos; + } + + @ModifyVariable(method = "tickChunk", ordinal = 0, at = @At(value = "INVOKE", shift = At.Shift.AFTER, target = "Lnet/minecraft/world/level/block/state/BlockState;randomTick(Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/core/BlockPos;Ljava/util/Random;)V")) + private BlockPos arclight$resetRandomTick(BlockPos pos) { + ArclightCaptures.resetTickingBlock(); + return pos; + } + + @ModifyVariable(method = "tickNonPassenger", argsOnly = true, ordinal = 0, at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Entity;tick()V")) + private Entity arclight$captureTickingEntity(Entity entity) { + ArclightCaptures.captureTickingEntity(entity); + return entity; + } + + @ModifyVariable(method = "tickNonPassenger", argsOnly = true, ordinal = 0, at = @At(value = "INVOKE", shift = At.Shift.AFTER, target = "Lnet/minecraft/world/entity/Entity;tick()V")) + private Entity arclight$resetTickingEntity(Entity entity) { + ArclightCaptures.resetTickingEntity(); + return entity; + } + + @ModifyVariable(method = "tickPassenger", argsOnly = true, ordinal = 1, at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Entity;rideTick()V")) + private Entity arclight$captureTickingPassenger(Entity entity) { + ArclightCaptures.captureTickingEntity(entity); + return entity; + } + + @ModifyVariable(method = "tickPassenger", argsOnly = true, ordinal = 1, at = @At(value = "INVOKE", shift = At.Shift.AFTER, target = "Lnet/minecraft/world/entity/Entity;rideTick()V")) + private Entity arclight$resetTickingPassenger(Entity entity) { + ArclightCaptures.resetTickingEntity(); + return entity; + } } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mod/server/api/DefaultArclightServer.java b/arclight-common/src/main/java/io/izzel/arclight/common/mod/server/api/DefaultArclightServer.java index 3ad5daf5..6a0cc9ec 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mod/server/api/DefaultArclightServer.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mod/server/api/DefaultArclightServer.java @@ -1,6 +1,7 @@ package io.izzel.arclight.common.mod.server.api; import io.izzel.arclight.api.ArclightServer; +import io.izzel.arclight.api.TickingTracker; import io.izzel.arclight.api.Unsafe; import io.izzel.arclight.common.mod.util.PluginEventHandler; import net.minecraftforge.eventbus.EventBus; @@ -9,6 +10,8 @@ import org.bukkit.plugin.Plugin; public class DefaultArclightServer implements ArclightServer { + private final TickingTracker tickingTracker = new DefaultTickingTracker(); + @Override public void registerForgeEvent(Plugin plugin, IEventBus bus, Object target) { try { @@ -21,4 +24,9 @@ public class DefaultArclightServer implements ArclightServer { Unsafe.throwException(t); } } + + @Override + public TickingTracker getTickingTracker() { + return this.tickingTracker; + } } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mod/server/api/DefaultTickingTracker.java b/arclight-common/src/main/java/io/izzel/arclight/common/mod/server/api/DefaultTickingTracker.java new file mode 100644 index 00000000..45e7e618 --- /dev/null +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mod/server/api/DefaultTickingTracker.java @@ -0,0 +1,70 @@ +package io.izzel.arclight.common.mod.server.api; + +import io.izzel.arclight.api.TickingTracker; +import io.izzel.arclight.common.bridge.core.entity.EntityBridge; +import io.izzel.arclight.common.mod.util.ArclightCaptures; +import org.bukkit.block.Block; +import org.bukkit.block.BlockState; +import org.bukkit.block.TileState; +import org.bukkit.craftbukkit.v.block.CraftBlock; +import org.bukkit.entity.Entity; +import org.jetbrains.annotations.Nullable; + +public class DefaultTickingTracker implements TickingTracker { + + @Nullable + @Override + public Object getTickingSource() { + Entity entity = getTickingEntity(); + if (entity != null) { + return entity; + } + TileState tileState = getTickingBlockEntity(); + if (tileState != null) { + return tileState; + } + Block block = getTickingBlock(); + if (block != null) { + return block; + } + return null; + } + + @Nullable + @Override + public Entity getTickingEntity() { + var tickingEntity = ArclightCaptures.getTickingEntity(); + if (tickingEntity != null) { + return ((EntityBridge) tickingEntity).bridge$getBukkitEntity(); + } + return null; + } + + @Nullable + @Override + public Block getTickingBlock() { + var level = ArclightCaptures.getTickingLevel(); + var pos = ArclightCaptures.getTickingPosition(); + if (level != null && pos != null) { + return CraftBlock.at(level, pos); + } + return null; + } + + @Nullable + @Override + public TileState getTickingBlockEntity() { + var blockEntity = ArclightCaptures.getTickingBlockEntity(); + if (blockEntity != null) { + var level = blockEntity.getLevel(); + if (level != null) { + CraftBlock block = CraftBlock.at(level, blockEntity.getBlockPos()); + BlockState state = block.getState(); + if (state instanceof TileState) { + return (TileState) state; + } + } + } + return null; + } +} diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mod/util/ArclightCaptures.java b/arclight-common/src/main/java/io/izzel/arclight/common/mod/util/ArclightCaptures.java index bd079421..5bb8cd9e 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mod/util/ArclightCaptures.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mod/util/ArclightCaptures.java @@ -4,6 +4,7 @@ import io.izzel.arclight.common.mod.ArclightConstants; import io.izzel.arclight.common.mod.ArclightMod; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; +import net.minecraft.server.level.ServerLevel; import net.minecraft.world.InteractionHand; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.item.ItemEntity; @@ -82,8 +83,7 @@ public class ArclightCaptures { } return eventContext; - } - else { + } else { return null; } } @@ -281,11 +281,47 @@ public class ArclightCaptures { return (T) tickingBlockEntity; } + private static ServerLevel tickingLevel; + private static BlockPos tickingPosition; + + public static void captureTickingBlock(ServerLevel level, BlockPos pos) { + tickingLevel = level; + tickingPosition = pos; + } + + public static ServerLevel getTickingLevel() { + return tickingLevel; + } + + public static BlockPos getTickingPosition() { + return tickingPosition; + } + + public static void resetTickingBlock() { + tickingLevel = null; + tickingPosition = null; + } + + private static Entity tickingEntity; + + public static void captureTickingEntity(Entity entity) { + tickingEntity = entity; + } + + public static Entity getTickingEntity() { + return tickingEntity; + } + + public static void resetTickingEntity() { + tickingEntity = null; + } + private static void recapture(String type) { throw new IllegalStateException("Recapturing " + type); } public static class BlockBreakEventContext { + final private BlockBreakEvent blockBreakEvent; final private ArrayList blockDrops; final private BlockState blockBreakPlayerState; diff --git a/build.gradle b/build.gradle index d1638710..251cca2c 100644 --- a/build.gradle +++ b/build.gradle @@ -15,7 +15,7 @@ allprojects { agpVersion = '1.23' minecraftVersion = '1.18.2' forgeVersion = '40.1.76' - apiVersion = '1.2.6' + apiVersion = '1.4.0' toolsVersion = '1.3.+' mixinVersion = '0.8.5' gitHash = getGitHash()