diff --git a/src/main/java/com/github/zly2006/reden/access/UndoRecordContainerImpl.kt b/src/main/java/com/github/zly2006/reden/access/UndoRecordContainerImpl.kt index f807dc56..126f4f44 100644 --- a/src/main/java/com/github/zly2006/reden/access/UndoRecordContainerImpl.kt +++ b/src/main/java/com/github/zly2006/reden/access/UndoRecordContainerImpl.kt @@ -1,10 +1,12 @@ package com.github.zly2006.reden.access import com.github.zly2006.reden.mixinhelper.UpdateMonitorHelper +import org.jetbrains.annotations.TestOnly class UndoRecordContainerImpl : UndoRecordContainer { override var recording: PlayerData.UndoRecord? = null var id: Long get() = recording?.id ?: 0 set(value) { recording = UpdateMonitorHelper.undoRecordsMap[value] } + @TestOnly @JvmField internal var swapped = false } diff --git a/src/main/java/com/github/zly2006/reden/mixin/undo/MixinExplosion.java b/src/main/java/com/github/zly2006/reden/mixin/undo/MixinExplosion.java index eaa31d91..4ea2f1ed 100644 --- a/src/main/java/com/github/zly2006/reden/mixin/undo/MixinExplosion.java +++ b/src/main/java/com/github/zly2006/reden/mixin/undo/MixinExplosion.java @@ -50,6 +50,7 @@ private void afterAffectWorld(boolean particles, CallbackInfo ci) { DebugKt.debugLogger.invoke("Explosion affect world end, undoID=" + undoId); if (undoId != 0) { UpdateMonitorHelper.INSTANCE.swap(recordContainer); + recordContainer.setRecording(null); } } @@ -67,6 +68,7 @@ private void afterDamageEntities(CallbackInfo ci) { DebugKt.debugLogger.invoke("Explosion damage entities end, undoID=" + undoId); if (undoId != 0) { UpdateMonitorHelper.INSTANCE.swap(recordContainer); + recordContainer.setRecording(null); } } diff --git a/src/main/java/com/github/zly2006/reden/mixin/undo/MixinMovingPiston.java b/src/main/java/com/github/zly2006/reden/mixin/undo/MixinMovingPiston.java index d6bc3d75..871bec00 100644 --- a/src/main/java/com/github/zly2006/reden/mixin/undo/MixinMovingPiston.java +++ b/src/main/java/com/github/zly2006/reden/mixin/undo/MixinMovingPiston.java @@ -41,6 +41,7 @@ public BlockEntityTicker getTicker(World world, if (be instanceof UndoableAccess access) { DebugKt.debugLogger.invoke("After piston block entity tick: " + pos.toShortString() + ", id" + access.getUndoId()); UpdateMonitorHelper.INSTANCE.swap(recordContainer); + recordContainer.setRecording(null); } } } : null; 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 826d218a..a3e2f5fe 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 @@ -48,6 +48,7 @@ private void onRunSchedule(BiConsumer ticker, CallbackInfo ci, private void afterRunSchedule(CallbackInfo ci) { DebugKt.debugLogger.invoke("scheduled tick finished, removing it from record"); UpdateMonitorHelper.INSTANCE.swap(recordContainer); + recordContainer.setRecording(null); } @Inject( method = "scheduleTick", diff --git a/src/main/java/com/github/zly2006/reden/mixin/undo/MixinServerWorld.java b/src/main/java/com/github/zly2006/reden/mixin/undo/MixinServerWorld.java index 81f8df5e..43ce6f65 100644 --- a/src/main/java/com/github/zly2006/reden/mixin/undo/MixinServerWorld.java +++ b/src/main/java/com/github/zly2006/reden/mixin/undo/MixinServerWorld.java @@ -65,5 +65,6 @@ private void beforeProcessBlockEvent(BlockEvent event, CallbackInfoReturnable cir) { DebugKt.debugLogger.invoke("block event end"); UpdateMonitorHelper.INSTANCE.swap(recordContainer); + recordContainer.setRecording(null); } } diff --git a/src/main/java/com/github/zly2006/reden/mixin/undo/MixinTntEntity.java b/src/main/java/com/github/zly2006/reden/mixin/undo/MixinTntEntity.java index 3962f3f8..5f9b35eb 100644 --- a/src/main/java/com/github/zly2006/reden/mixin/undo/MixinTntEntity.java +++ b/src/main/java/com/github/zly2006/reden/mixin/undo/MixinTntEntity.java @@ -50,33 +50,9 @@ private void beforeExplode(CallbackInfo ci) { private void afterExplode(CallbackInfo ci) { DebugKt.debugLogger.invoke("TNT explode end, undoId=" + undoId); UpdateMonitorHelper.INSTANCE.swap(recordContainer); + recordContainer.setRecording(null); } - /* - @Inject(method = "explode", at = @At("HEAD"), cancellable = true) - private void onExplode(CallbackInfo ci) { - Explosion explosion = new Explosion( - this.getWorld(), - this, - null, - null, - this.getX(), - this.getBodyY(0.0625), - this.getZ(), - 4.0f, - false, - this.getWorld().getDestructionType(GameRules.TNT_EXPLOSION_DROP_DECAY) - ); - if (undoId != 0) { - DebugKt.debugLogger.invoke("TNT exploded, adding it into record "+ undoId); - ((UndoableAccess) explosion).setUndoId(undoId); - } - explosion.collectBlocksAndDamageEntities(); - explosion.affectWorld(true); - ci.cancel(); - } - */ - @Override public long getUndoId() { return undoId; 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 658e86d1..bfd04f91 100644 --- a/src/main/java/com/github/zly2006/reden/mixinhelper/UpdateMonitorHelper.kt +++ b/src/main/java/com/github/zly2006/reden/mixinhelper/UpdateMonitorHelper.kt @@ -3,6 +3,7 @@ package com.github.zly2006.reden.mixinhelper import com.github.zly2006.reden.access.PlayerData import com.github.zly2006.reden.access.PlayerData.Companion.data import com.github.zly2006.reden.access.UndoRecordContainer +import com.github.zly2006.reden.access.UndoRecordContainerImpl import com.github.zly2006.reden.carpet.RedenCarpetSettings import com.github.zly2006.reden.utils.debugLogger import com.github.zly2006.reden.utils.server @@ -67,6 +68,17 @@ object UpdateMonitorHelper: UndoRecordContainer { } } + var depth = 0; private set + override fun swap(another: UndoRecordContainer) { + if (another is UndoRecordContainerImpl) { + if (another.swapped) depth-- + else depth++ + another.swapped = !another.swapped + } + debugLogger("swap, depth=$depth") + super.swap(another) + } + @JvmStatic fun onChainFinish(world: World) { //debugLogger("UpdateMonitorHelper.finish") 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 fee09bfc..e419d6d1 100644 --- a/src/main/java/com/github/zly2006/reden/network/Rollback.kt +++ b/src/main/java/com/github/zly2006/reden/network/Rollback.kt @@ -1,5 +1,6 @@ package com.github.zly2006.reden.network +import com.github.zly2006.reden.Reden import com.github.zly2006.reden.access.PlayerData import com.github.zly2006.reden.access.PlayerData.Companion.data import com.github.zly2006.reden.mixinhelper.UpdateMonitorHelper @@ -19,7 +20,6 @@ import net.minecraft.registry.Registries import net.minecraft.server.world.ServerWorld import net.minecraft.text.Text import net.minecraft.util.math.BlockPos -import okhttp3.internal.toImmutableMap private val pType = PacketType.create(ROLLBACK) { Rollback(it.readVarInt()) @@ -46,8 +46,7 @@ class Rollback( world.getBlockEntity(BlockPos.fromLong(pos))?.readNbt(be) } } - // 这里不用forEach是因为要避免ConcurrentModificationException,堆屎山ing - record.entities.toImmutableMap().forEach { + record.entities.forEach { if (it.value != null) { val entry = it.value!! val entity = world.getEntity(it.key) @@ -83,6 +82,11 @@ class Rollback( return@registerGlobalReceiver } UpdateMonitorHelper.playerStopRecording(player) + if (UpdateMonitorHelper.recording != null) { + Reden.LOGGER.warn("Undo when a record is still active, id=" + UpdateMonitorHelper.recording?.id) + // 不取消跟踪会导致undo的更改也被记录,边读边写异常 + UpdateMonitorHelper.recording = null + } when (packet.status) { 0 -> view.undo.lastValid()?.let { undoRecord -> view.undo.removeLast()