diff --git a/src/main/java/com/github/zly2006/reden/access/PlayerData.kt b/src/main/java/com/github/zly2006/reden/access/PlayerData.kt index 09ae06be..fccab85d 100644 --- a/src/main/java/com/github/zly2006/reden/access/PlayerData.kt +++ b/src/main/java/com/github/zly2006/reden/access/PlayerData.kt @@ -9,7 +9,7 @@ import net.minecraft.world.World class PlayerData( - player: ServerPlayerEntity, + val player: ServerPlayerEntity, ) { val undo: MutableList = mutableListOf() val redo: MutableList = mutableListOf() @@ -17,14 +17,7 @@ class PlayerData( var pearlListening: Boolean = false fun stopRecording(world: World) { - isRecording = false - redo.clear() - if (undo.lastOrNull() != null) { - if (undo.last().data.isEmpty()) { - UpdateMonitorHelper.removeRecord(undo.last().id) - undo.removeLast() - } - } + UpdateMonitorHelper.playerStopRecording(player) } data class Entry( diff --git a/src/main/java/com/github/zly2006/reden/malilib/KeyCallbacks.kt b/src/main/java/com/github/zly2006/reden/malilib/KeyCallbacks.kt index c76a93bb..33356463 100644 --- a/src/main/java/com/github/zly2006/reden/malilib/KeyCallbacks.kt +++ b/src/main/java/com/github/zly2006/reden/malilib/KeyCallbacks.kt @@ -44,7 +44,7 @@ fun configureKeyCallbacks(mc: MinecraftClient) { if (mc.interactionManager?.currentGameMode == GameMode.CREATIVE) { BlockBorder.tags.clear() val view = mc.server!!.playerManager.playerList[0].data() - view.undo.lastOrNull()?.keys?.forEach { + view.undo.lastOrNull()?.data?.keys?.forEach { BlockBorder.tags[it] = 1 } return@setCallback true diff --git a/src/main/java/com/github/zly2006/reden/mixin/undo/MixinSchedule.java b/src/main/java/com/github/zly2006/reden/mixin/undo/MixinSchedule.java index 4bc857c8..7f0c46db 100644 --- a/src/main/java/com/github/zly2006/reden/mixin/undo/MixinSchedule.java +++ b/src/main/java/com/github/zly2006/reden/mixin/undo/MixinSchedule.java @@ -1,5 +1,8 @@ package com.github.zly2006.reden.mixin.undo; +import com.github.zly2006.reden.access.PlayerData; +import com.github.zly2006.reden.access.ScheduledTickAccess; +import com.github.zly2006.reden.mixinhelper.UpdateMonitorHelper; import net.minecraft.util.math.BlockPos; import net.minecraft.world.tick.OrderedTick; import net.minecraft.world.tick.WorldTickScheduler; @@ -7,20 +10,39 @@ import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.spongepowered.asm.mixin.injection.callback.LocalCapture; import java.util.function.BiConsumer; @Mixin(WorldTickScheduler.class) public class MixinSchedule { + @SuppressWarnings("rawtypes") @Inject( method = "tick(Ljava/util/function/BiConsumer;)V", at = @At( value = "INVOKE", - target = "Ljava/util/Queue;poll()Ljava/lang/Object;" + target = "Ljava/util/List;add(Ljava/lang/Object;)Z" + ), + locals = LocalCapture.CAPTURE_FAILSOFT + ) + private void onRunSchedule(BiConsumer ticker, CallbackInfo ci, OrderedTick orderedTick) { + UpdateMonitorHelper.INSTANCE.setRecording( + UpdateMonitorHelper.INSTANCE.getUndoRecordsMap().get( + ((ScheduledTickAccess) orderedTick).getUndoId() + // this is null safe + ) + ); + } + @Inject( + method = "tick(Ljava/util/function/BiConsumer;)V", + at = @At( + value = "INVOKE", + shift = At.Shift.AFTER, + target = "Ljava/util/function/BiConsumer;accept(Ljava/lang/Object;Ljava/lang/Object;)V" ) ) - private void onRunSchedule(BiConsumer ticker, CallbackInfo ci) { - + private void afterRunSchedule(CallbackInfo ci) { + UpdateMonitorHelper.INSTANCE.setRecording(null); } @Inject( method = "scheduleTick", @@ -29,6 +51,11 @@ private void onRunSchedule(BiConsumer ticker, CallbackInfo ci) ) ) private void onAddSchedule(OrderedTick orderedTick, CallbackInfo ci) { - + ScheduledTickAccess access = (ScheduledTickAccess) orderedTick; + PlayerData.UndoRecord recording = UpdateMonitorHelper.INSTANCE.getRecording(); + if (recording != null) { + // inherit parent id + access.setUndoId(recording.getId()); + } } } diff --git a/src/main/java/com/github/zly2006/reden/mixinhelper/UpdateMonitorHelper.kt b/src/main/java/com/github/zly2006/reden/mixinhelper/UpdateMonitorHelper.kt index 68be2723..fe1944fe 100644 --- a/src/main/java/com/github/zly2006/reden/mixinhelper/UpdateMonitorHelper.kt +++ b/src/main/java/com/github/zly2006/reden/mixinhelper/UpdateMonitorHelper.kt @@ -15,8 +15,8 @@ import net.minecraft.world.block.ChainRestrictedNeighborUpdater object UpdateMonitorHelper { private val listeners: MutableMap Unit, LifeTime> = mutableMapOf() private val chainFinishListeners = mutableMapOf Unit, LifeTime>() - private var recordId = 0L - val undoRecordsMap: MutableMap> = HashMap() + private var recordId = 20060210L + val undoRecordsMap: MutableMap = HashMap() var recording: PlayerData.UndoRecord? = null enum class LifeTime { PERMANENT, @@ -85,16 +85,16 @@ object UpdateMonitorHelper { * 此缓存可能在没有确认的情况下不经检查直接调用 */ private fun addRecord(): PlayerData.UndoRecord { - undoRecordsMap[recordId] = hashMapOf() - recordId++ recording = PlayerData.UndoRecord( - recordId - 1, - undoRecordsMap[recordId - 1]!! + recordId, + hashMapOf() ) + undoRecordsMap[recordId] = recording!! + recordId++ return recording!! } - fun removeRecord(id: Long) = undoRecordsMap.remove(id) + private fun removeRecord(id: Long) = undoRecordsMap.remove(id) @JvmStatic fun playerStartRecord(player: ServerPlayerEntity) { val playerView = player.data() @@ -104,6 +104,21 @@ object UpdateMonitorHelper { } } + fun playerStopRecording(player: ServerPlayerEntity) { + val playerView = player.data() + if (playerView.isRecording) { + playerView.isRecording = false + recording = null + playerView.redo.clear() + if (playerView.undo.lastOrNull() != null) { + if (playerView.undo.last().data.isEmpty()) { + removeRecord(playerView.undo.last().id) + playerView.undo.removeLast() + } + } + } + } + @JvmStatic fun isPlayerRecording(): Boolean { return monitoringPlayerCache?.data()?.isRecording == true diff --git a/src/main/java/com/github/zly2006/reden/network/Rollback.kt b/src/main/java/com/github/zly2006/reden/network/Rollback.kt index f411f956..e3c0996c 100644 --- a/src/main/java/com/github/zly2006/reden/network/Rollback.kt +++ b/src/main/java/com/github/zly2006/reden/network/Rollback.kt @@ -3,6 +3,7 @@ package com.github.zly2006.reden.network import com.github.zly2006.reden.access.PlayerData import com.github.zly2006.reden.access.PlayerData.Companion.data import com.github.zly2006.reden.malilib.DEBUG_LOGGER +import com.github.zly2006.reden.mixinhelper.UpdateMonitorHelper import com.github.zly2006.reden.utils.isClient import com.github.zly2006.reden.utils.sendMessage import com.github.zly2006.reden.utils.setBlockNoPP @@ -32,7 +33,7 @@ class Rollback( fun register() { ServerPlayNetworking.registerGlobalReceiver(pType) { packet, player, res -> val view = player.data() - view.isRecording = false + UpdateMonitorHelper.playerStopRecording(player) fun operate(record: PlayerData.UndoRecord): PlayerData.UndoRecord { val ret = PlayerData.UndoRecord(record.id, record.data.keys.associateWith { PlayerData.Entry.fromWorld( diff --git a/src/main/resources/reden.accesswidener b/src/main/resources/reden.accesswidener index af89e2b6..49375d67 100644 --- a/src/main/resources/reden.accesswidener +++ b/src/main/resources/reden.accesswidener @@ -25,3 +25,4 @@ mutable field net/minecraft/util/math/Vec3d z D accessible field net/minecraft/entity/vehicle/AbstractMinecartEntity clientX D accessible field net/minecraft/entity/vehicle/AbstractMinecartEntity clientY D accessible field net/minecraft/entity/vehicle/AbstractMinecartEntity clientZ D +extendable class net/minecraft/world/tick/OrderedTick