Implement ticking source API

This commit is contained in:
IzzelAliz 2022-09-08 13:31:21 +08:00
parent 51297084b4
commit f06ead2fab
No known key found for this signature in database
GPG Key ID: EE50E123A11D8338
5 changed files with 166 additions and 3 deletions

View File

@ -78,6 +78,7 @@ import org.spongepowered.asm.mixin.Overwrite;
import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject; 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.Redirect;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
@ -462,4 +463,52 @@ public abstract class ServerLevelMixin extends LevelMixin implements ServerWorld
blockList.updateList(); 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;
}
} }

View File

@ -1,6 +1,7 @@
package io.izzel.arclight.common.mod.server.api; package io.izzel.arclight.common.mod.server.api;
import io.izzel.arclight.api.ArclightServer; import io.izzel.arclight.api.ArclightServer;
import io.izzel.arclight.api.TickingTracker;
import io.izzel.arclight.api.Unsafe; import io.izzel.arclight.api.Unsafe;
import io.izzel.arclight.common.mod.util.PluginEventHandler; import io.izzel.arclight.common.mod.util.PluginEventHandler;
import net.minecraftforge.eventbus.EventBus; import net.minecraftforge.eventbus.EventBus;
@ -9,6 +10,8 @@ import org.bukkit.plugin.Plugin;
public class DefaultArclightServer implements ArclightServer { public class DefaultArclightServer implements ArclightServer {
private final TickingTracker tickingTracker = new DefaultTickingTracker();
@Override @Override
public void registerForgeEvent(Plugin plugin, IEventBus bus, Object target) { public void registerForgeEvent(Plugin plugin, IEventBus bus, Object target) {
try { try {
@ -21,4 +24,9 @@ public class DefaultArclightServer implements ArclightServer {
Unsafe.throwException(t); Unsafe.throwException(t);
} }
} }
@Override
public TickingTracker getTickingTracker() {
return this.tickingTracker;
}
} }

View File

@ -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;
}
}

View File

@ -4,6 +4,7 @@ import io.izzel.arclight.common.mod.ArclightConstants;
import io.izzel.arclight.common.mod.ArclightMod; import io.izzel.arclight.common.mod.ArclightMod;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction; import net.minecraft.core.Direction;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionHand;
import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.item.ItemEntity; import net.minecraft.world.entity.item.ItemEntity;
@ -82,8 +83,7 @@ public class ArclightCaptures {
} }
return eventContext; return eventContext;
} } else {
else {
return null; return null;
} }
} }
@ -281,11 +281,47 @@ public class ArclightCaptures {
return (T) tickingBlockEntity; 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) { private static void recapture(String type) {
throw new IllegalStateException("Recapturing " + type); throw new IllegalStateException("Recapturing " + type);
} }
public static class BlockBreakEventContext { public static class BlockBreakEventContext {
final private BlockBreakEvent blockBreakEvent; final private BlockBreakEvent blockBreakEvent;
final private ArrayList<ItemEntity> blockDrops; final private ArrayList<ItemEntity> blockDrops;
final private BlockState blockBreakPlayerState; final private BlockState blockBreakPlayerState;

View File

@ -15,7 +15,7 @@ allprojects {
agpVersion = '1.23' agpVersion = '1.23'
minecraftVersion = '1.18.2' minecraftVersion = '1.18.2'
forgeVersion = '40.1.76' forgeVersion = '40.1.76'
apiVersion = '1.2.6' apiVersion = '1.4.0'
toolsVersion = '1.3.+' toolsVersion = '1.3.+'
mixinVersion = '0.8.5' mixinVersion = '0.8.5'
gitHash = getGitHash() gitHash = getGitHash()