Skip to content

Commit

Permalink
feat: scheduled tick undo
Browse files Browse the repository at this point in the history
  • Loading branch information
zly2006 committed Aug 11, 2023
1 parent 4c02aee commit 9e09ddd
Show file tree
Hide file tree
Showing 6 changed files with 59 additions and 22 deletions.
11 changes: 2 additions & 9 deletions src/main/java/com/github/zly2006/reden/access/PlayerData.kt
Original file line number Diff line number Diff line change
Expand Up @@ -9,22 +9,15 @@ import net.minecraft.world.World


class PlayerData(
player: ServerPlayerEntity,
val player: ServerPlayerEntity,
) {
val undo: MutableList<UndoRecord> = mutableListOf()
val redo: MutableList<UndoRecord> = mutableListOf()
var isRecording: Boolean = false
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(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
@@ -1,26 +1,48 @@
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;
import org.spongepowered.asm.mixin.Mixin;
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 <T> void onRunSchedule(BiConsumer<BlockPos, T> 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 <T> void onRunSchedule(BiConsumer<BlockPos, T> ticker, CallbackInfo ci) {

private void afterRunSchedule(CallbackInfo ci) {
UpdateMonitorHelper.INSTANCE.setRecording(null);
}
@Inject(
method = "scheduleTick",
Expand All @@ -29,6 +51,11 @@ private <T> void onRunSchedule(BiConsumer<BlockPos, T> ticker, CallbackInfo ci)
)
)
private <T> void onAddSchedule(OrderedTick<T> orderedTick, CallbackInfo ci) {

ScheduledTickAccess access = (ScheduledTickAccess) orderedTick;
PlayerData.UndoRecord recording = UpdateMonitorHelper.INSTANCE.getRecording();
if (recording != null) {
// inherit parent id
access.setUndoId(recording.getId());
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ import net.minecraft.world.block.ChainRestrictedNeighborUpdater
object UpdateMonitorHelper {
private val listeners: MutableMap<World.(ChainRestrictedNeighborUpdater.Entry) -> Unit, LifeTime> = mutableMapOf()
private val chainFinishListeners = mutableMapOf<World.() -> Unit, LifeTime>()
private var recordId = 0L
val undoRecordsMap: MutableMap<Long, MutableMap<Long, PlayerData.Entry>> = HashMap()
private var recordId = 20060210L
val undoRecordsMap: MutableMap<Long, PlayerData.UndoRecord> = HashMap()
var recording: PlayerData.UndoRecord? = null
enum class LifeTime {
PERMANENT,
Expand Down Expand Up @@ -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()
Expand All @@ -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
Expand Down
3 changes: 2 additions & 1 deletion src/main/java/com/github/zly2006/reden/network/Rollback.kt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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(
Expand Down
1 change: 1 addition & 0 deletions src/main/resources/reden.accesswidener
Original file line number Diff line number Diff line change
Expand Up @@ -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

0 comments on commit 9e09ddd

Please sign in to comment.