From 3a2c1d8d6fb6192e74623dcfb0e5bc27e08fbdd8 Mon Sep 17 00:00:00 2001 From: Brokkonaut Date: Thu, 8 Nov 2018 19:13:13 +0100 Subject: [PATCH] Rollback of killed entities works! --- .../de/diddiz/LogBlock/CommandsHandler.java | 17 ++---- .../java/de/diddiz/LogBlock/WorldEditor.java | 46 ++++++++++++++-- .../diddiz/worldedit/AdvancedKillLogging.java | 4 +- .../de/diddiz/worldedit/WorldEditHelper.java | 53 ++++++++++++++++++- 4 files changed, 101 insertions(+), 19 deletions(-) diff --git a/src/main/java/de/diddiz/LogBlock/CommandsHandler.java b/src/main/java/de/diddiz/LogBlock/CommandsHandler.java index ee22647..9bdf409 100755 --- a/src/main/java/de/diddiz/LogBlock/CommandsHandler.java +++ b/src/main/java/de/diddiz/LogBlock/CommandsHandler.java @@ -690,14 +690,9 @@ public class CommandsHandler implements CommandExecutor { } rs = executeQuery(state, params.getQuery()); final WorldEditor editor = new WorldEditor(logblock, params.world, params.forceReplace); - + WorldEditorEditFactory editFactory = new WorldEditorEditFactory(editor, params, true); while (rs.next()) { - ChestAccess chestaccess = null; - ItemStack stack = Utils.loadItemStack(rs.getBytes("item")); - if (stack != null) { - chestaccess = new ChestAccess(stack, rs.getBoolean("itemremove"), rs.getInt("itemtype")); - } - editor.queueBlockEdit(rs.getInt("x"), rs.getInt("y"), rs.getInt("z"), rs.getInt("replaced"), rs.getInt("replacedData"), rs.getBytes("replacedState"), rs.getInt("type"), rs.getInt("typeData"), rs.getBytes("typeState"), chestaccess); + editFactory.processRow(rs); } final int changes = editor.getSize(); if (changes > 10000) { @@ -781,13 +776,9 @@ public class CommandsHandler implements CommandExecutor { sender.sendMessage(ChatColor.DARK_AQUA + "Searching " + params.getTitle() + ":"); } final WorldEditor editor = new WorldEditor(logblock, params.world, params.forceReplace); + WorldEditorEditFactory editFactory = new WorldEditorEditFactory(editor, params, false); while (rs.next()) { - ChestAccess chestaccess = null; - ItemStack stack = Utils.loadItemStack(rs.getBytes("item")); - if (stack != null) { - chestaccess = new ChestAccess(stack, !rs.getBoolean("itemremove"), rs.getInt("itemtype")); - } - editor.queueBlockEdit(rs.getInt("x"), rs.getInt("y"), rs.getInt("z"), rs.getInt("type"), rs.getInt("typeData"), rs.getBytes("typeState"), rs.getInt("replaced"), rs.getInt("replacedData"), rs.getBytes("replacedState"), chestaccess); + editFactory.processRow(rs); } final int changes = editor.getSize(); if (!params.silent) { diff --git a/src/main/java/de/diddiz/LogBlock/WorldEditor.java b/src/main/java/de/diddiz/LogBlock/WorldEditor.java index 0cf1601..16f5c89 100644 --- a/src/main/java/de/diddiz/LogBlock/WorldEditor.java +++ b/src/main/java/de/diddiz/LogBlock/WorldEditor.java @@ -18,14 +18,19 @@ import org.bukkit.block.data.type.Piston; import org.bukkit.block.data.type.PistonHead; import org.bukkit.block.data.type.TechnicalPiston.Type; import org.bukkit.command.CommandSender; +import org.bukkit.configuration.file.YamlConfiguration; +import org.bukkit.entity.Entity; import org.bukkit.inventory.ItemStack; import de.diddiz.LogBlock.blockstate.BlockStateCodecs; import de.diddiz.util.BukkitUtils; import de.diddiz.util.Utils; +import de.diddiz.worldedit.WorldEditHelper; import java.io.File; import java.io.PrintWriter; +import java.sql.ResultSet; +import java.sql.SQLException; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.List; @@ -87,6 +92,10 @@ public class WorldEditor implements Runnable { edits.add(new BlockEdit(0, new Location(world, x, y, z), null, replaced, replaceData, replacedState, type, typeData, typeState, item)); } + public void queueEntityEdit(ResultSet rs, QueryParams p, boolean rollback) throws SQLException { + edits.add(new EntityEdit(rs, p, rollback)); + } + public long getElapsedTime() { return elapsedTime; } @@ -155,15 +164,46 @@ public class WorldEditor implements Runnable { } } - private static enum PerformResult { + public static enum PerformResult { SUCCESS, BLACKLISTED, NO_ACTION } - private interface Edit { + public interface Edit { PerformResult perform() throws WorldEditorException; } - private class BlockEdit extends BlockChange implements Edit { + public class EntityEdit extends EntityChange implements Edit { + private boolean rollback; + + public EntityEdit(ResultSet rs, QueryParams p, boolean rollback) throws SQLException { + super(rs, p); + this.rollback = rollback; + } + + @Override + public PerformResult perform() throws WorldEditorException { + if (changeType == EntityChangeType.KILL && rollback) { + YamlConfiguration deserialized = Utils.deserializeYamlConfiguration(data); + double x = deserialized.getDouble("x"); + double y = deserialized.getDouble("y"); + double z = deserialized.getDouble("z"); + float yaw = (float) deserialized.getDouble("yaw"); + float pitch = (float) deserialized.getDouble("pitch"); + Location location = new Location(world, x, y, z, yaw, pitch); + byte[] serializedWorldEditEntity = (byte[]) deserialized.get("worldedit"); + if (serializedWorldEditEntity != null) { + Entity result = WorldEditHelper.restoreEntity(location, type, serializedWorldEditEntity); + if (result == null) { + throw new WorldEditorException("Could not restore " + type, location); + } + return PerformResult.SUCCESS; + } + } + return PerformResult.NO_ACTION; + } + } + + public class BlockEdit extends BlockChange implements Edit { public BlockEdit(long time, Location loc, Actor actor, int replaced, int replaceData, byte[] replacedState, int type, int typeData, byte[] typeState, ChestAccess ca) { super(time, loc, actor, replaced, replaceData,replacedState , type, typeData, typeState, ca); } diff --git a/src/main/java/de/diddiz/worldedit/AdvancedKillLogging.java b/src/main/java/de/diddiz/worldedit/AdvancedKillLogging.java index 2c85122..5cbd20f 100644 --- a/src/main/java/de/diddiz/worldedit/AdvancedKillLogging.java +++ b/src/main/java/de/diddiz/worldedit/AdvancedKillLogging.java @@ -38,8 +38,8 @@ public class AdvancedKillLogging extends LoggingListener { Location location = entity.getLocation(); YamlConfiguration data = new YamlConfiguration(); data.set("x", location.getX()); - data.set("y", location.getX()); - data.set("z", location.getX()); + data.set("y", location.getY()); + data.set("z", location.getZ()); data.set("yaw", location.getYaw()); data.set("pitch", location.getPitch()); diff --git a/src/main/java/de/diddiz/worldedit/WorldEditHelper.java b/src/main/java/de/diddiz/worldedit/WorldEditHelper.java index 08441b3..5bfcd33 100644 --- a/src/main/java/de/diddiz/worldedit/WorldEditHelper.java +++ b/src/main/java/de/diddiz/worldedit/WorldEditHelper.java @@ -1,13 +1,27 @@ package de.diddiz.worldedit; +import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; +import java.util.Arrays; +import java.util.LinkedHashMap; +import java.util.UUID; import org.bukkit.Bukkit; +import org.bukkit.Location; import org.bukkit.entity.Entity; +import org.bukkit.entity.EntityType; import org.bukkit.plugin.Plugin; +import com.sk89q.jnbt.CompoundTag; +import com.sk89q.jnbt.DoubleTag; +import com.sk89q.jnbt.FloatTag; +import com.sk89q.jnbt.ListTag; +import com.sk89q.jnbt.NBTInputStream; import com.sk89q.jnbt.NBTOutputStream; +import com.sk89q.jnbt.NamedTag; +import com.sk89q.jnbt.ShortTag; +import com.sk89q.jnbt.Tag; import com.sk89q.worldedit.bukkit.BukkitAdapter; import com.sk89q.worldedit.entity.BaseEntity; @@ -32,6 +46,10 @@ public class WorldEditHelper { return Internal.serializeEntity(entity); } + public static Entity restoreEntity(Location location, EntityType type, byte[] serialized) { + return Internal.restoreEntity(location, type, serialized); + } + private static class Internal { // private static WorldEditPlugin worldEdit; @@ -39,6 +57,33 @@ public class WorldEditHelper { // Internal.worldEdit = (WorldEditPlugin) worldEdit; } + public static Entity restoreEntity(Location location, EntityType type, byte[] serialized) { + com.sk89q.worldedit.world.entity.EntityType weType = BukkitAdapter.adapt(type); + com.sk89q.worldedit.util.Location weLocation = BukkitAdapter.adapt(location); + try { + NBTInputStream nbtis = new NBTInputStream(new ByteArrayInputStream(serialized)); + NamedTag namedTag = nbtis.readNamedTag(); + nbtis.close(); + UUID newUUID = null; + if (namedTag.getName().equals("entity") && namedTag.getTag() instanceof CompoundTag) { + CompoundTag serializedState = (CompoundTag) namedTag.getTag(); + BaseEntity state = new BaseEntity(weType, serializedState); + CompoundTag oldNbt = state.getNbtData(); + UUID oldUUID = new UUID(oldNbt.getLong("UUIDMost"), oldNbt.getLong("UUIDLeast")); + com.sk89q.worldedit.entity.Entity weEntity = weLocation.getExtent().createEntity(weLocation, state); + if (weEntity != null) { + CompoundTag newNbt = weEntity.getState().getNbtData(); + newUUID = new UUID(newNbt.getLong("UUIDMost"), newNbt.getLong("UUIDLeast")); + System.out.println("Old UUID: " + oldUUID); + System.out.println("New UUID: " + newUUID); + } + } + return newUUID == null ? null : Bukkit.getEntity(newUUID); + } catch (IOException e) { + throw new RuntimeException("This IOException should be impossible", e); + } + } + public static byte[] serializeEntity(Entity entity) { com.sk89q.worldedit.entity.Entity weEntity = BukkitAdapter.adapt(entity); BaseEntity state = weEntity.getState(); @@ -46,7 +91,13 @@ public class WorldEditHelper { try { ByteArrayOutputStream baos = new ByteArrayOutputStream(); NBTOutputStream nbtos = new NBTOutputStream(baos); - nbtos.writeNamedTag("entity", state.getNbtData()); + CompoundTag nbt = state.getNbtData(); + LinkedHashMap value = new LinkedHashMap<>(nbt.getValue()); + value.put("Health", new FloatTag(20.0f)); + value.put("Motion", new ListTag(DoubleTag.class, Arrays.asList(new DoubleTag[] {new DoubleTag(0),new DoubleTag(0),new DoubleTag(0)}))); + value.put("Fire", new ShortTag((short) -20)); + value.put("HurtTime", new ShortTag((short) 0)); + nbtos.writeNamedTag("entity", new CompoundTag(value)); nbtos.close(); return baos.toByteArray(); } catch (IOException e) {