Log & rollback armor stand/item frame modifications

This commit is contained in:
Brokkonaut
2018-11-09 05:00:32 +01:00
parent 4e1a79ca0f
commit a5ffa3b709
6 changed files with 221 additions and 61 deletions

View File

@ -5,11 +5,14 @@ import java.sql.SQLException;
import java.util.UUID;
import org.bukkit.Location;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.entity.ArmorStand;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.LivingEntity;
import org.bukkit.inventory.ItemStack;
import de.diddiz.LogBlock.config.Config;
import de.diddiz.util.Utils;
public class EntityChange implements LookupCacheElement {
public static enum EntityChangeType {
@ -75,9 +78,21 @@ public class EntityChange implements LookupCacheElement {
} else if (changeType == EntityChangeType.KILL) {
msg.append(living ? "killed " : "destroyed ");
} else if (changeType == EntityChangeType.ADDEQUIP) {
msg.append("added an item to ");
YamlConfiguration conf = Utils.deserializeYamlConfiguration(data);
ItemStack stack = conf == null ? null : conf.getItemStack("item");
if (stack == null) {
msg.append("added an item to ");
} else {
msg.append("added " + stack.getType() + " to ");
}
} else if (changeType == EntityChangeType.REMOVEEQUIP) {
msg.append("removed an item from ");
YamlConfiguration conf = Utils.deserializeYamlConfiguration(data);
ItemStack stack = conf == null ? null : conf.getItemStack("item");
if (stack == null) {
msg.append("removed an item from ");
} else {
msg.append("removed " + stack.getType() + " from ");
}
} else if (changeType == EntityChangeType.MODIFY) {
msg.append("modified ");
}

View File

@ -19,7 +19,10 @@ 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.ArmorStand;
import org.bukkit.entity.Entity;
import org.bukkit.entity.ItemFrame;
import org.bukkit.inventory.EquipmentSlot;
import org.bukkit.inventory.ItemStack;
import de.diddiz.LogBlock.blockstate.BlockStateCodecs;
@ -201,7 +204,7 @@ public class WorldEditor implements Runnable {
float yaw = (float) deserialized.getDouble("yaw");
float pitch = (float) deserialized.getDouble("pitch");
Location location = new Location(world, x, y, z, yaw, pitch);
Entity existing = Utils.loadChunksForEntity(location.getChunk(), uuid);
Entity existing = BukkitUtils.loadEntityAround(location.getChunk(), uuid);
if (existing != null) {
return PerformResult.NO_ACTION;
}
@ -228,12 +231,60 @@ public class WorldEditor implements Runnable {
float yaw = (float) deserialized.getDouble("yaw");
float pitch = (float) deserialized.getDouble("pitch");
Location location = new Location(world, x, y, z, yaw, pitch);
Entity existing = Utils.loadChunksForEntity(location.getChunk(), uuid);
Entity existing = BukkitUtils.loadEntityAround(location.getChunk(), uuid);
if (existing != null) {
existing.remove();
return PerformResult.SUCCESS;
}
return PerformResult.NO_ACTION; // the entity is not there, so we cannot do anything
} else if (changeType == (rollback ? EntityChangeType.REMOVEEQUIP : EntityChangeType.ADDEQUIP)) {
// set equip
UUID uuid = getReplacedUUID(entityId, entityUUID);
Entity existing = BukkitUtils.loadEntityAround(loc.getChunk(), uuid);
if (existing != null) {
YamlConfiguration deserialized = Utils.deserializeYamlConfiguration(data);
ItemStack item = deserialized.getItemStack("item");
if (item != null && existing instanceof ItemFrame) {
ItemStack old = ((ItemFrame) existing).getItem();
if (old == null || old.getType() == Material.AIR) {
((ItemFrame) existing).setItem(item);
return PerformResult.SUCCESS;
}
} else if (item != null && existing instanceof ArmorStand) {
EquipmentSlot slot = EquipmentSlot.valueOf(deserialized.getString("slot"));
ArmorStand stand = (ArmorStand) existing;
ItemStack old = BukkitUtils.getItemInSlot(stand, slot);
if (old == null || old.getType() == Material.AIR) {
BukkitUtils.setItemInSlot(stand, slot, item);
return PerformResult.SUCCESS;
}
}
}
return PerformResult.NO_ACTION; // the entity is not there, or equip does not match
} else if (changeType == (rollback ? EntityChangeType.ADDEQUIP : EntityChangeType.REMOVEEQUIP)) {
// remove equip
UUID uuid = getReplacedUUID(entityId, entityUUID);
Entity existing = BukkitUtils.loadEntityAround(loc.getChunk(), uuid);
if (existing != null) {
YamlConfiguration deserialized = Utils.deserializeYamlConfiguration(data);
ItemStack item = deserialized.getItemStack("item");
if (item != null && existing instanceof ItemFrame) {
ItemStack old = ((ItemFrame) existing).getItem();
if (old != null && old.isSimilar(item)) {
((ItemFrame) existing).setItem(null);
return PerformResult.SUCCESS;
}
} else if (item != null && existing instanceof ArmorStand) {
EquipmentSlot slot = EquipmentSlot.valueOf(deserialized.getString("slot"));
ArmorStand stand = (ArmorStand) existing;
ItemStack old = BukkitUtils.getItemInSlot(stand, slot);
if (old != null && old.isSimilar(item)) {
BukkitUtils.setItemInSlot(stand, slot, null);
return PerformResult.SUCCESS;
}
}
}
return PerformResult.NO_ACTION; // the entity is not there, or equip does not match
}
return PerformResult.NO_ACTION;
}

View File

@ -3,7 +3,7 @@ package de.diddiz.LogBlock.config;
import de.diddiz.LogBlock.EntityLogging;
import de.diddiz.LogBlock.LogBlock;
import de.diddiz.LogBlock.Logging;
import de.diddiz.util.Utils;
import de.diddiz.util.BukkitUtils;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.entity.Ambient;
@ -90,7 +90,7 @@ public class WorldConfig extends LoggingEnabledMapping {
boolean monsters = false;
boolean living = false;
for (String type : types) {
EntityType et = Utils.matchEntityType(type);
EntityType et = BukkitUtils.matchEntityType(type);
if (et != null) {
logged.add(et);
} else {

View File

@ -8,6 +8,7 @@ import org.bukkit.entity.ArmorStand;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Hanging;
import org.bukkit.entity.IronGolem;
import org.bukkit.entity.ItemFrame;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
import org.bukkit.entity.Snowman;
@ -24,6 +25,7 @@ import org.bukkit.event.entity.EntityDeathEvent;
import org.bukkit.event.hanging.HangingBreakByEntityEvent;
import org.bukkit.event.hanging.HangingBreakEvent;
import org.bukkit.event.hanging.HangingPlaceEvent;
import org.bukkit.event.player.PlayerArmorStandManipulateEvent;
import org.bukkit.event.player.PlayerInteractEntityEvent;
import org.bukkit.event.player.PlayerInteractEvent;
import org.bukkit.inventory.EquipmentSlot;
@ -98,11 +100,26 @@ public class AdvancedEntityLogging extends LoggingListener {
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void onPlayerInteractEntity(PlayerInteractEntityEvent event) {
ItemStack inHand = event.getHand() == EquipmentSlot.HAND ? event.getPlayer().getInventory().getItemInMainHand() : event.getPlayer().getInventory().getItemInOffHand();
if (inHand != null) {
if (inHand != null && inHand.getType() != Material.AIR) {
Material mat = inHand.getType();
if (mat.name().endsWith("_SPAWN_EGG")) {
setLastSpawner(event.getPlayer(), null, true);
}
Entity entity = event.getRightClicked();
if (entity instanceof ItemFrame) {
ItemStack oldItem = ((ItemFrame) entity).getItem();
if (oldItem == null || oldItem.getType() == Material.AIR) {
if (Config.isLogging(entity.getWorld(), EntityLogging.MODIFY, entity)) {
Actor actor = Actor.actorFromEntity(event.getPlayer());
YamlConfiguration data = new YamlConfiguration();
inHand = inHand.clone();
inHand.setAmount(1);
data.set("item", inHand);
consumer.queueEntityModification(actor, entity.getUniqueId(), entity.getType(), entity.getLocation(), EntityChange.EntityChangeType.ADDEQUIP, data);
}
}
}
}
}
@ -169,6 +186,54 @@ public class AdvancedEntityLogging extends LoggingListener {
}
}
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void onEntityDamage(EntityDamageEvent event) {
Entity entity = event.getEntity();
if (entity instanceof ItemFrame) {
ItemStack oldItem = ((ItemFrame) entity).getItem();
if (oldItem != null && oldItem.getType() != Material.AIR) {
if (Config.isLogging(entity.getWorld(), EntityLogging.MODIFY, entity)) {
Actor actor;
if (event instanceof EntityDamageByEntityEvent) {
actor = Actor.actorFromEntity(((EntityDamageByEntityEvent) event).getDamager());
} else {
actor = new Actor(event.getCause().toString());
}
YamlConfiguration data = new YamlConfiguration();
data.set("item", oldItem);
consumer.queueEntityModification(actor, entity.getUniqueId(), entity.getType(), entity.getLocation(), EntityChange.EntityChangeType.REMOVEEQUIP, data);
}
}
}
}
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void onPlayerArmorStandManipulate(PlayerArmorStandManipulateEvent event) {
ArmorStand entity = event.getRightClicked();
ItemStack oldItem = event.getArmorStandItem();
ItemStack newItem = event.getPlayerItem();
boolean oldEmpty = oldItem == null || oldItem.getType() == Material.AIR;
boolean newEmpty = newItem == null || newItem.getType() == Material.AIR;
if ((!oldEmpty || !newEmpty) && Config.isLogging(entity.getWorld(), EntityLogging.MODIFY, entity)) {
Actor actor = Actor.actorFromEntity(event.getPlayer());
if (!oldEmpty && !newEmpty && newItem.getAmount() > 1) {
return;
}
if (!oldEmpty) {
YamlConfiguration data = new YamlConfiguration();
data.set("item", oldItem);
data.set("slot", event.getSlot().name());
consumer.queueEntityModification(actor, entity.getUniqueId(), entity.getType(), entity.getLocation(), EntityChange.EntityChangeType.REMOVEEQUIP, data);
}
if (!newEmpty) {
YamlConfiguration data = new YamlConfiguration();
data.set("item", newItem);
data.set("slot", event.getSlot().name());
consumer.queueEntityModification(actor, entity.getUniqueId(), entity.getType(), entity.getLocation(), EntityChange.EntityChangeType.ADDEQUIP, data);
}
}
}
protected void queueEntitySpawnOrKill(Entity entity, Actor actor, EntityChange.EntityChangeType changeType) {
Location location = entity.getLocation();
YamlConfiguration data = new YamlConfiguration();

View File

@ -12,10 +12,12 @@ import org.bukkit.block.data.type.Slab;
import org.bukkit.block.data.type.Slab.Type;
import org.bukkit.block.data.type.Stairs;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.entity.ArmorStand;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Player;
import org.bukkit.entity.TNTPrimed;
import org.bukkit.inventory.EquipmentSlot;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.InventoryHolder;
import org.bukkit.inventory.ItemStack;
@ -746,4 +748,85 @@ public class BukkitUtils {
}
return null;
}
public static Entity loadEntityAround(Chunk chunk, UUID uuid) {
Entity e = Bukkit.getEntity(uuid);
if (e != null) {
return e;
}
if (!chunk.isLoaded()) {
chunk.load();
e = Bukkit.getEntity(uuid);
if (e != null) {
return e;
}
}
int chunkx = chunk.getX();
int chunkz = chunk.getZ();
for (int i = 0; i < 8; i++) {
int x = i < 3 ? chunkx - 1 : (i < 5 ? chunkx : chunkx + 1);
int z = i == 0 || i == 3 || i == 5 ? chunkz - 1 : (i == 1 || i == 6 ? chunkz : chunkz + 1);
if (!chunk.getWorld().isChunkLoaded(x, z)) {
chunk.getWorld().loadChunk(x, z);
e = Bukkit.getEntity(uuid);
if (e != null) {
return e;
}
}
}
return null;
}
private static final HashMap<String, EntityType> types = new HashMap<>();
static {
for (EntityType t : EntityType.values()) {
types.put(t.name().toLowerCase(), t);
@SuppressWarnings("deprecation")
String typeName = t.getName();
if (typeName != null) {
types.put(typeName.toLowerCase(), t);
}
Class<? extends Entity> ec = t.getEntityClass();
if (ec != null) {
types.put(ec.getSimpleName().toLowerCase(), t);
}
}
}
public static EntityType matchEntityType(String typeName) {
return types.get(typeName.toLowerCase());
}
public static ItemStack getItemInSlot(ArmorStand stand, EquipmentSlot slot) {
if (slot == EquipmentSlot.HAND) {
return stand.getEquipment().getItemInMainHand();
} else if (slot == EquipmentSlot.OFF_HAND) {
return stand.getEquipment().getItemInOffHand();
} else if (slot == EquipmentSlot.FEET) {
return stand.getEquipment().getBoots();
} else if (slot == EquipmentSlot.LEGS) {
return stand.getEquipment().getLeggings();
} else if (slot == EquipmentSlot.CHEST) {
return stand.getEquipment().getChestplate();
} else if (slot == EquipmentSlot.HEAD) {
return stand.getEquipment().getHelmet();
}
return null;
}
public static void setItemInSlot(ArmorStand stand, EquipmentSlot slot, ItemStack stack) {
if (slot == EquipmentSlot.HAND) {
stand.getEquipment().setItemInMainHand(stack);
} else if (slot == EquipmentSlot.OFF_HAND) {
stand.getEquipment().setItemInOffHand(stack);
} else if (slot == EquipmentSlot.FEET) {
stand.getEquipment().setBoots(stack);
} else if (slot == EquipmentSlot.LEGS) {
stand.getEquipment().setLeggings(stack);
} else if (slot == EquipmentSlot.CHEST) {
stand.getEquipment().setChestplate(stack);
} else if (slot == EquipmentSlot.HEAD) {
stand.getEquipment().setHelmet(stack);
}
}
}

View File

@ -10,21 +10,15 @@ import java.io.OutputStreamWriter;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.UUID;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;
import java.util.zip.ZipException;
import org.bukkit.Bukkit;
import org.bukkit.Chunk;
import org.bukkit.configuration.InvalidConfigurationException;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
import org.bukkit.inventory.ItemStack;
import de.diddiz.LogBlock.LogBlock;
@ -290,52 +284,4 @@ public class Utils {
public static String serializeForSQL(YamlConfiguration conf) {
return mysqlPrepareBytesForInsertAllowNull(serializeYamlConfiguration(conf));
}
public static Entity loadChunksForEntity(Chunk chunk, UUID uuid) {
Entity e = Bukkit.getEntity(uuid);
if (e != null) {
return e;
}
if (!chunk.isLoaded()) {
chunk.load();
e = Bukkit.getEntity(uuid);
if (e != null) {
return e;
}
}
int chunkx = chunk.getX();
int chunkz = chunk.getZ();
for (int i = 0; i < 8; i++) {
int x = i < 3 ? chunkx - 1 : (i < 5 ? chunkx : chunkx + 1);
int z = i == 0 || i == 3 || i == 5 ? chunkz - 1 : (i == 1 || i == 6 ? chunkz : chunkz + 1);
if (!chunk.getWorld().isChunkLoaded(x, z)) {
chunk.getWorld().loadChunk(x, z);
e = Bukkit.getEntity(uuid);
if (e != null) {
return e;
}
}
}
return null;
}
private static final HashMap<String, EntityType> types = new HashMap<>();
static {
for (EntityType t : EntityType.values()) {
types.put(t.name().toLowerCase(), t);
@SuppressWarnings("deprecation")
String typeName = t.getName();
if (typeName != null) {
types.put(typeName.toLowerCase(), t);
}
Class<? extends Entity> ec = t.getEntityClass();
if (ec != null) {
types.put(ec.getSimpleName().toLowerCase(), t);
}
}
}
public static EntityType matchEntityType(String typeName) {
return types.get(typeName.toLowerCase());
}
}