Rework undo for Decree

Undo now in a service.
No longer per-player, collective history
We're not worledit - Dan
Removes the need for deprecated offlinePlayer calls as well.
This commit is contained in:
CocoTheOwner 2021-08-19 11:57:56 +02:00
parent db0aeeabbd
commit 7347300f05
4 changed files with 86 additions and 52 deletions

View File

@ -21,6 +21,7 @@ package com.volmit.iris.core.command.object;
import com.volmit.iris.Iris; import com.volmit.iris.Iris;
import com.volmit.iris.core.IrisSettings; import com.volmit.iris.core.IrisSettings;
import com.volmit.iris.core.project.loader.IrisData; import com.volmit.iris.core.project.loader.IrisData;
import com.volmit.iris.core.service.ObjectSVC;
import com.volmit.iris.core.service.StudioSVC; import com.volmit.iris.core.service.StudioSVC;
import com.volmit.iris.core.service.WandSVC; import com.volmit.iris.core.service.WandSVC;
import com.volmit.iris.core.tools.IrisToolbelt; import com.volmit.iris.core.tools.IrisToolbelt;
@ -185,7 +186,7 @@ public class CommandIrisObjectPaste extends MortarCommand {
Map<Block, BlockData> futureChanges = new HashMap<>(); Map<Block, BlockData> futureChanges = new HashMap<>();
obj.place(block.getBlockX(), block.getBlockY() + (int) obj.getCenter().getY(), block.getBlockZ(), createPlacer(sender.player(), block.getWorld(), futureChanges), placement, new RNG(), null); obj.place(block.getBlockX(), block.getBlockY() + (int) obj.getCenter().getY(), block.getBlockZ(), createPlacer(sender.player(), block.getWorld(), futureChanges), placement, new RNG(), null);
CommandIrisObjectUndo.addChanges(sender.player(), futureChanges); Iris.service(ObjectSVC.class).addChanges(futureChanges);
if (intoWand) { if (intoWand) {
ItemStack newWand = WandSVC.createWand(block.clone().subtract(obj.getCenter()).add(obj.getW() - 1, ItemStack newWand = WandSVC.createWand(block.clone().subtract(obj.getCenter()).add(obj.getW() - 1,

View File

@ -20,6 +20,7 @@ package com.volmit.iris.core.command.object;
import com.volmit.iris.Iris; import com.volmit.iris.Iris;
import com.volmit.iris.core.IrisSettings; import com.volmit.iris.core.IrisSettings;
import com.volmit.iris.core.service.ObjectSVC;
import com.volmit.iris.util.collection.KList; import com.volmit.iris.util.collection.KList;
import com.volmit.iris.util.plugin.MortarCommand; import com.volmit.iris.util.plugin.MortarCommand;
import com.volmit.iris.util.plugin.VolmitSender; import com.volmit.iris.util.plugin.VolmitSender;
@ -34,7 +35,6 @@ import java.util.*;
public class CommandIrisObjectUndo extends MortarCommand { public class CommandIrisObjectUndo extends MortarCommand {
private static final Map<UUID, Deque<Map<Block, BlockData>>> undos = new HashMap<>();
public CommandIrisObjectUndo() { public CommandIrisObjectUndo() {
super("undo", "u", "revert"); super("undo", "u", "revert");
@ -101,14 +101,14 @@ public class CommandIrisObjectUndo extends MortarCommand {
sender.sendMessage("Please specify an amount greater than 0!"); sender.sendMessage("Please specify an amount greater than 0!");
return true; return true;
} }
ObjectSVC service = Iris.service(ObjectSVC.class);
if (!undos.containsKey(player) || undos.get(player).size() == 0) { if (service.getUndos().size() == 0) {
sender.sendMessage("No pastes to undo"); sender.sendMessage("No pastes to undo");
return true; return true;
} }
int actualReverts = Math.min(undos.get(player).size(), amount); int actualReverts = Math.min(service.getUndos().size(), amount);
revertChanges(player, amount); service.revertChanges(actualReverts);
sender.sendMessage("Reverted " + actualReverts + " pastes!"); sender.sendMessage("Reverted " + actualReverts + " pastes!");
return true; return true;
@ -118,48 +118,4 @@ public class CommandIrisObjectUndo extends MortarCommand {
protected String getArgsUsage() { protected String getArgsUsage() {
return "[-number [num]] [-user [username]]"; return "[-number [num]] [-user [username]]";
} }
public static void addChanges(Player player, Map<Block, BlockData> oldBlocks) {
if (!undos.containsKey(player.getUniqueId())) {
undos.put(player.getUniqueId(), new ArrayDeque<>());
}
undos.get(player.getUniqueId()).add(oldBlocks);
}
public static void revertChanges(UUID player, int amount) {
loopChange(player, amount);
}
private static void loopChange(UUID uuid, int amount) {
Deque<Map<Block, BlockData>> queue = undos.get(uuid);
if (queue != null && queue.size() > 0) {
revert(queue.pollLast());
if (amount > 1) {
J.s(() -> loopChange(uuid, amount - 1), 2);
}
}
}
/**
* Reverts all the block changes provided, 200 blocks per tick
*
* @param blocks The blocks to remove
*/
private static void revert(Map<Block, BlockData> blocks) {
int amount = 0;
Iterator<Map.Entry<Block, BlockData>> it = blocks.entrySet().iterator();
while (it.hasNext()) {
Map.Entry<Block, BlockData> entry = it.next();
BlockData data = entry.getValue();
entry.getKey().setBlockData(data, false);
it.remove();
amount++;
if (amount > 200) {
J.s(() -> revert(blocks), 1);
}
}
}
} }

View File

@ -3,6 +3,7 @@ package com.volmit.iris.core.decrees;
import com.volmit.iris.Iris; import com.volmit.iris.Iris;
import com.volmit.iris.core.command.object.CommandIrisObjectUndo; import com.volmit.iris.core.command.object.CommandIrisObjectUndo;
import com.volmit.iris.core.project.loader.IrisData; import com.volmit.iris.core.project.loader.IrisData;
import com.volmit.iris.core.service.ObjectSVC;
import com.volmit.iris.core.service.StudioSVC; import com.volmit.iris.core.service.StudioSVC;
import com.volmit.iris.core.service.WandSVC; import com.volmit.iris.core.service.WandSVC;
import com.volmit.iris.engine.object.common.IObjectPlacer; import com.volmit.iris.engine.object.common.IObjectPlacer;
@ -221,7 +222,7 @@ public class DecObject implements DecreeExecutor {
object = object.scaled(scale, interpolator); object = object.scaled(scale, interpolator);
object.place(block.getBlockX(), block.getBlockY() + (int) object.getCenter().getY(), block.getBlockZ(), createPlacer(block.getWorld(), futureChanges), placement, new RNG(), null); object.place(block.getBlockX(), block.getBlockY() + (int) object.getCenter().getY(), block.getBlockZ(), createPlacer(block.getWorld(), futureChanges), placement, new RNG(), null);
CommandIrisObjectUndo.addChanges(player(), futureChanges); Iris.service(ObjectSVC.class).addChanges(futureChanges);
if (edit) { if (edit) {
ItemStack newWand = WandSVC.createWand(block.clone().subtract(object.getCenter()).add(object.getW() - 1, ItemStack newWand = WandSVC.createWand(block.clone().subtract(object.getCenter()).add(object.getW() - 1,
@ -366,5 +367,14 @@ public class DecObject implements DecreeExecutor {
sender().playSound(Sound.ENTITY_ITEM_FRAME_ROTATE_ITEM, 1f, 0.55f); sender().playSound(Sound.ENTITY_ITEM_FRAME_ROTATE_ITEM, 1f, 0.55f);
} }
@Decree(description = "Undo a number of pastes", aliases = "-")
public void undo(
@Param(description = "The amount of pastes to undo", defaultValue = "1")
int amount
){
ObjectSVC service = Iris.service(ObjectSVC.class);
int actualReverts = Math.min(service.getUndos().size(), amount);
service.revertChanges(actualReverts);
sender().sendMessage("Reverted " + actualReverts + " pastes!");
}
} }

View File

@ -0,0 +1,67 @@
package com.volmit.iris.core.service;
import com.volmit.iris.util.collection.KList;
import com.volmit.iris.util.plugin.IrisService;
import com.volmit.iris.util.scheduling.J;
import lombok.Getter;
import org.bukkit.block.Block;
import org.bukkit.block.data.BlockData;
import org.bukkit.entity.Player;
import java.util.*;
public class ObjectSVC implements IrisService {
@Getter
private final Deque<Map<Block, BlockData>> undos = new ArrayDeque<>();
@Override
public void onEnable() {
}
@Override
public void onDisable() {
}
public void addChanges(Map<Block, BlockData> oldBlocks) {
undos.add(oldBlocks);
}
public void revertChanges(int amount) {
loopChange(amount);
}
private void loopChange(int amount) {
if (undos.size() > 0) {
revert(undos.pollLast());
if (amount > 1) {
J.s(() -> loopChange(amount - 1), 2);
}
}
}
/**
* Reverts all the block changes provided, 200 blocks per tick
*
* @param blocks The blocks to remove
*/
private void revert(Map<Block, BlockData> blocks) {
int amount = 0;
Iterator<Map.Entry<Block, BlockData>> it = blocks.entrySet().iterator();
while (it.hasNext()) {
Map.Entry<Block, BlockData> entry = it.next();
BlockData data = entry.getValue();
entry.getKey().setBlockData(data, false);
it.remove();
amount++;
if (amount > 200) {
J.s(() -> revert(blocks), 1);
}
}
}
}