diff --git a/src/main/java/net/coreprotect/CoreProtectAPI.java b/src/main/java/net/coreprotect/CoreProtectAPI.java index e76502f..2235f72 100755 --- a/src/main/java/net/coreprotect/CoreProtectAPI.java +++ b/src/main/java/net/coreprotect/CoreProtectAPI.java @@ -25,7 +25,7 @@ import net.coreprotect.config.Config; import net.coreprotect.consumer.Queue; import net.coreprotect.database.Database; import net.coreprotect.database.Lookup; -import net.coreprotect.database.Rollback; +import net.coreprotect.database.rollback.Rollback; import net.coreprotect.language.Phrase; import net.coreprotect.listener.player.InventoryChangeListener; import net.coreprotect.utility.Chat; diff --git a/src/main/java/net/coreprotect/command/RollbackRestoreCommand.java b/src/main/java/net/coreprotect/command/RollbackRestoreCommand.java index 856c437..2c98a14 100755 --- a/src/main/java/net/coreprotect/command/RollbackRestoreCommand.java +++ b/src/main/java/net/coreprotect/command/RollbackRestoreCommand.java @@ -23,8 +23,8 @@ import net.coreprotect.config.Config; import net.coreprotect.config.ConfigHandler; import net.coreprotect.database.ContainerRollback; import net.coreprotect.database.Database; -import net.coreprotect.database.Rollback; import net.coreprotect.database.lookup.PlayerLookup; +import net.coreprotect.database.rollback.Rollback; import net.coreprotect.language.Phrase; import net.coreprotect.language.Selector; import net.coreprotect.utility.Chat; diff --git a/src/main/java/net/coreprotect/database/ContainerRollback.java b/src/main/java/net/coreprotect/database/ContainerRollback.java index 61ea742..df61d23 100644 --- a/src/main/java/net/coreprotect/database/ContainerRollback.java +++ b/src/main/java/net/coreprotect/database/ContainerRollback.java @@ -21,13 +21,15 @@ import net.coreprotect.CoreProtect; import net.coreprotect.config.ConfigHandler; import net.coreprotect.consumer.Queue; import net.coreprotect.consumer.process.Process; +import net.coreprotect.database.rollback.Rollback; +import net.coreprotect.database.rollback.RollbackComplete; import net.coreprotect.language.Phrase; import net.coreprotect.model.BlockGroup; import net.coreprotect.thread.Scheduler; import net.coreprotect.utility.Chat; import net.coreprotect.utility.Util; -public class ContainerRollback extends Queue { +public class ContainerRollback extends Rollback { public static void performContainerRollbackRestore(Statement statement, CommandSender user, List checkUuids, List checkUsers, String timeString, List restrictList, Map excludeList, List excludeUserList, List actionList, final Location location, Integer[] radius, long startTime, long endTime, boolean restrictWorld, boolean lookup, boolean verbose, final int rollbackType) { try { @@ -176,7 +178,7 @@ public class ContainerRollback extends Queue { int itemCount = 0; int entityCount = 0; - Rollback.finishRollbackRestore(user, location, checkUsers, restrictList, excludeList, excludeUserList, actionList, timeString, file, totalSeconds, itemCount, blockCount, entityCount, rollbackType, radius, verbose, restrictWorld, 0); + RollbackComplete.output(user, location, checkUsers, restrictList, excludeList, excludeUserList, actionList, timeString, file, totalSeconds, itemCount, blockCount, entityCount, rollbackType, radius, verbose, restrictWorld, 0); } } catch (Exception e) { diff --git a/src/main/java/net/coreprotect/database/Lookup.java b/src/main/java/net/coreprotect/database/Lookup.java index 93b9b2b..1668464 100755 --- a/src/main/java/net/coreprotect/database/Lookup.java +++ b/src/main/java/net/coreprotect/database/Lookup.java @@ -29,7 +29,7 @@ import net.coreprotect.utility.Util; public class Lookup extends Queue { - static List convertRawLookup(Statement statement, List list) { + protected static List convertRawLookup(Statement statement, List list) { List newList = new ArrayList<>(); if (list == null) { @@ -122,7 +122,7 @@ public class Lookup extends Queue { return newList; } - static List performLookupRaw(Statement statement, CommandSender user, List checkUuids, List checkUsers, List restrictList, Map excludeList, List excludeUserList, List actionList, Location location, Integer[] radius, Long[] rowData, long startTime, long endTime, int limitOffset, int limitCount, boolean restrictWorld, boolean lookup) { + protected static List performLookupRaw(Statement statement, CommandSender user, List checkUuids, List checkUsers, List restrictList, Map excludeList, List excludeUserList, List actionList, Location location, Integer[] radius, Long[] rowData, long startTime, long endTime, int limitOffset, int limitCount, boolean restrictWorld, boolean lookup) { List list = new ArrayList<>(); List invalidRollbackActions = new ArrayList<>(); invalidRollbackActions.add(2); diff --git a/src/main/java/net/coreprotect/database/Rollback.java b/src/main/java/net/coreprotect/database/rollback/Rollback.java similarity index 69% rename from src/main/java/net/coreprotect/database/Rollback.java rename to src/main/java/net/coreprotect/database/rollback/Rollback.java index 1dabe44..666f462 100644 --- a/src/main/java/net/coreprotect/database/Rollback.java +++ b/src/main/java/net/coreprotect/database/rollback/Rollback.java @@ -1,10 +1,7 @@ -package net.coreprotect.database; +package net.coreprotect.database.rollback; import java.io.ByteArrayInputStream; -import java.math.BigDecimal; -import java.math.RoundingMode; import java.sql.Statement; -import java.text.NumberFormat; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; @@ -20,14 +17,9 @@ import java.util.UUID; import org.bukkit.Bukkit; import org.bukkit.DyeColor; -import org.bukkit.FireworkEffect; -import org.bukkit.FireworkEffect.Builder; import org.bukkit.Location; import org.bukkit.Material; -import org.bukkit.Tag; import org.bukkit.World; -import org.bukkit.attribute.Attribute; -import org.bukkit.attribute.AttributeModifier; import org.bukkit.block.Banner; import org.bukkit.block.Block; import org.bukkit.block.BlockFace; @@ -35,7 +27,6 @@ import org.bukkit.block.BlockState; import org.bukkit.block.CommandBlock; import org.bukkit.block.CreatureSpawner; import org.bukkit.block.Jukebox; -import org.bukkit.block.ShulkerBox; import org.bukkit.block.banner.Pattern; import org.bukkit.block.data.Bisected; import org.bukkit.block.data.Bisected.Half; @@ -65,18 +56,6 @@ import org.bukkit.entity.Player; import org.bukkit.inventory.EntityEquipment; import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; -import org.bukkit.inventory.PlayerInventory; -import org.bukkit.inventory.meta.BannerMeta; -import org.bukkit.inventory.meta.BlockStateMeta; -import org.bukkit.inventory.meta.CrossbowMeta; -import org.bukkit.inventory.meta.FireworkEffectMeta; -import org.bukkit.inventory.meta.FireworkMeta; -import org.bukkit.inventory.meta.ItemMeta; -import org.bukkit.inventory.meta.LeatherArmorMeta; -import org.bukkit.inventory.meta.MapMeta; -import org.bukkit.inventory.meta.PotionMeta; -import org.bukkit.inventory.meta.SuspiciousStewMeta; -import org.bukkit.potion.PotionEffect; import org.bukkit.util.io.BukkitObjectInputStream; import net.coreprotect.CoreProtect; @@ -85,6 +64,7 @@ import net.coreprotect.config.Config; import net.coreprotect.config.ConfigHandler; import net.coreprotect.consumer.Queue; import net.coreprotect.consumer.process.Process; +import net.coreprotect.database.Lookup; import net.coreprotect.database.logger.ItemLogger; import net.coreprotect.database.statement.UserStatement; import net.coreprotect.language.Phrase; @@ -100,7 +80,7 @@ import net.coreprotect.utility.Teleport; import net.coreprotect.utility.Util; import net.coreprotect.utility.entity.HangingUtil; -public class Rollback extends Queue { +public class Rollback extends RollbackUtil { public static List performRollbackRestore(Statement statement, CommandSender user, List checkUuids, List checkUsers, String timeString, List restrictList, Map excludeList, List excludeUserList, List actionList, Location location, Integer[] radius, long startTime, long endTime, boolean restrictWorld, boolean lookup, boolean verbose, final int rollbackType, final int preview) { List list = new ArrayList<>(); @@ -1337,7 +1317,7 @@ public class Rollback extends Queue { double totalSeconds = (timeFinish - timeStart) / 1000.0; if (user != null) { - finishRollbackRestore(user, location, checkUsers, restrictList, excludeList, excludeUserList, actionList, timeString, chunkCount, totalSeconds, itemCount, blockCount, entityCount, rollbackType, radius, verbose, restrictWorld, preview); + RollbackComplete.output(user, location, checkUsers, restrictList, excludeList, excludeUserList, actionList, timeString, chunkCount, totalSeconds, itemCount, blockCount, entityCount, rollbackType, radius, verbose, restrictWorld, preview); } list = Lookup.convertRawLookup(statement, lookupList); @@ -1350,733 +1330,4 @@ public class Rollback extends Queue { return null; } - static void finishRollbackRestore(CommandSender user, Location location, List checkUsers, List restrictList, Map excludeList, List excludeUserList, List actionList, String timeString, Integer chunkCount, Double seconds, Integer itemCount, Integer blockCount, Integer entityCount, int rollbackType, Integer[] radius, boolean verbose, boolean restrictWorld, int preview) { - try { - if (preview == 2) { - Chat.sendMessage(user, Color.DARK_AQUA + "CoreProtect " + Color.WHITE + "- " + Phrase.build(Phrase.PREVIEW_CANCELLED)); - return; - } - - Chat.sendMessage(user, "-----"); - - StringBuilder usersBuilder = new StringBuilder(); - for (String value : checkUsers) { - if (usersBuilder.length() == 0) { - usersBuilder = usersBuilder.append("" + value + ""); - } - else { - usersBuilder.append(", ").append(value); - } - } - String users = usersBuilder.toString(); - - if (users.equals("#global") && restrictWorld) { - users = "#" + location.getWorld().getName(); - } - - if (preview > 0) { - Chat.sendMessage(user, Color.DARK_AQUA + "CoreProtect " + Color.WHITE + "- " + Phrase.build(Phrase.ROLLBACK_COMPLETED, users, Selector.THIRD)); // preview - } - else if (rollbackType == 0) { - Chat.sendMessage(user, Color.DARK_AQUA + "CoreProtect " + Color.WHITE + "- " + Phrase.build(Phrase.ROLLBACK_COMPLETED, users, Selector.FIRST)); // rollback - } - else if (rollbackType == 1) { - Chat.sendMessage(user, Color.DARK_AQUA + "CoreProtect " + Color.WHITE + "- " + Phrase.build(Phrase.ROLLBACK_COMPLETED, users, Selector.SECOND)); // restore - } - - if (preview == 1 || rollbackType == 0 || rollbackType == 1) { - Chat.sendMessage(user, Color.DARK_AQUA + "CoreProtect " + Color.WHITE + "- " + Phrase.build(Phrase.ROLLBACK_TIME, timeString)); - } - - if (radius != null) { - int worldedit = radius[7]; - if (worldedit == 0) { - Integer rollbackRadius = radius[0]; - Chat.sendMessage(user, Color.DARK_AQUA + "CoreProtect " + Color.WHITE + "- " + Phrase.build(Phrase.ROLLBACK_RADIUS, rollbackRadius.toString(), (rollbackRadius == 1 ? Selector.FIRST : Selector.SECOND))); - } - else { - Chat.sendMessage(user, Color.DARK_AQUA + "CoreProtect " + Color.WHITE + "- " + Phrase.build(Phrase.ROLLBACK_SELECTION, "#worldedit")); - } - } - - if (restrictWorld && radius == null) { - if (location != null) { - Chat.sendMessage(user, Color.DARK_AQUA + "CoreProtect " + Color.WHITE + "- " + Phrase.build(Phrase.ROLLBACK_WORLD_ACTION, location.getWorld().getName(), Selector.FIRST)); - } - } - - if (actionList.contains(4) && actionList.contains(11)) { - if (actionList.contains(0)) { - Chat.sendMessage(user, Color.DARK_AQUA + "CoreProtect " + Color.WHITE + "- " + Phrase.build(Phrase.ROLLBACK_WORLD_ACTION, "+inventory", Selector.SECOND)); - } - else if (actionList.contains(1)) { - Chat.sendMessage(user, Color.DARK_AQUA + "CoreProtect " + Color.WHITE + "- " + Phrase.build(Phrase.ROLLBACK_WORLD_ACTION, "-inventory", Selector.SECOND)); - } - else { - Chat.sendMessage(user, Color.DARK_AQUA + "CoreProtect " + Color.WHITE + "- " + Phrase.build(Phrase.ROLLBACK_WORLD_ACTION, "inventory", Selector.SECOND)); - } - } - else if (actionList.contains(4)) { - if (actionList.contains(0)) { - Chat.sendMessage(user, Color.DARK_AQUA + "CoreProtect " + Color.WHITE + "- " + Phrase.build(Phrase.ROLLBACK_WORLD_ACTION, "-container", Selector.SECOND)); - } - else if (actionList.contains(1)) { - Chat.sendMessage(user, Color.DARK_AQUA + "CoreProtect " + Color.WHITE + "- " + Phrase.build(Phrase.ROLLBACK_WORLD_ACTION, "+container", Selector.SECOND)); - } - else { - Chat.sendMessage(user, Color.DARK_AQUA + "CoreProtect " + Color.WHITE + "- " + Phrase.build(Phrase.ROLLBACK_WORLD_ACTION, "container", Selector.SECOND)); - } - } - else if (actionList.contains(0) && actionList.contains(1)) { - Chat.sendMessage(user, Color.DARK_AQUA + "CoreProtect " + Color.WHITE + "- " + Phrase.build(Phrase.ROLLBACK_WORLD_ACTION, "block", Selector.SECOND)); - } - else if (actionList.contains(0)) { - Chat.sendMessage(user, Color.DARK_AQUA + "CoreProtect " + Color.WHITE + "- " + Phrase.build(Phrase.ROLLBACK_WORLD_ACTION, "-block", Selector.SECOND)); - } - else if (actionList.contains(1)) { - Chat.sendMessage(user, Color.DARK_AQUA + "CoreProtect " + Color.WHITE + "- " + Phrase.build(Phrase.ROLLBACK_WORLD_ACTION, "+block", Selector.SECOND)); - } - else if (actionList.contains(3)) { - Chat.sendMessage(user, Color.DARK_AQUA + "CoreProtect " + Color.WHITE + "- " + Phrase.build(Phrase.ROLLBACK_WORLD_ACTION, "kill", Selector.SECOND)); - } - - if (restrictList.size() > 0) { - StringBuilder restrictTargets = new StringBuilder(); - boolean material = false; - boolean item = false; - boolean entity = false; - - int targetCount = 0; - for (Object restrictTarget : restrictList) { - String targetName = ""; - - if (restrictTarget instanceof Material) { - targetName = ((Material) restrictTarget).name().toLowerCase(Locale.ROOT); - item = (!item ? !(((Material) restrictTarget).isBlock()) : item); - material = true; - } - else if (restrictTarget instanceof EntityType) { - targetName = ((EntityType) restrictTarget).name().toLowerCase(Locale.ROOT); - entity = true; - } - - if (targetCount == 0) { - restrictTargets = restrictTargets.append("" + targetName + ""); - } - else { - restrictTargets.append(", ").append(targetName); - } - - targetCount++; - } - - String targetType = Selector.THIRD; - if (material && !item && !entity) { - targetType = Selector.FIRST; - } - else if (material && item && !entity) { - targetType = Selector.THIRD; - } - else if (entity && !material) { - targetType = Selector.SECOND; - } - - Chat.sendMessage(user, Color.DARK_AQUA + "CoreProtect " + Color.WHITE + "- " + Phrase.build(Phrase.ROLLBACK_INCLUDE, restrictTargets.toString(), Selector.FIRST, targetType, (targetCount == 1 ? Selector.FIRST : Selector.SECOND))); // include - } - - if (excludeList.size() > 0) { - StringBuilder excludeTargets = new StringBuilder(); - boolean material = false; - boolean item = false; - boolean entity = false; - - int excludeCount = 0; - for (Map.Entry entry : excludeList.entrySet()) { - Object excludeTarget = entry.getKey(); - Boolean excludeTargetInternal = entry.getValue(); - - // don't display default block excludes - if (Boolean.TRUE.equals(excludeTargetInternal)) { - continue; - } - - // don't display that excluded water/fire/farmland in inventory rollbacks - if (actionList.contains(4) && actionList.contains(11)) { - if (excludeTarget.equals(Material.FIRE) || excludeTarget.equals(Material.WATER) || excludeTarget.equals(Material.FARMLAND)) { - continue; - } - } - - String targetName = ""; - if (excludeTarget instanceof Material) { - targetName = ((Material) excludeTarget).name().toLowerCase(Locale.ROOT); - item = (!item ? !(((Material) excludeTarget).isBlock()) : item); - material = true; - } - else if (excludeTarget instanceof EntityType) { - targetName = ((EntityType) excludeTarget).name().toLowerCase(Locale.ROOT); - entity = true; - } - - if (excludeCount == 0) { - excludeTargets = excludeTargets.append("" + targetName + ""); - } - else { - excludeTargets.append(", ").append(targetName); - } - - excludeCount++; - } - - String targetType = Selector.THIRD; - if (material && !item && !entity) { - targetType = Selector.FIRST; - } - else if (material && item && !entity) { - targetType = Selector.THIRD; - } - else if (entity && !material) { - targetType = Selector.SECOND; - } - - if (excludeCount > 0) { - Chat.sendMessage(user, Color.DARK_AQUA + "CoreProtect " + Color.WHITE + "- " + Phrase.build(Phrase.ROLLBACK_INCLUDE, excludeTargets.toString(), Selector.SECOND, targetType, (excludeCount == 1 ? Selector.FIRST : Selector.SECOND))); // exclude - } - } - - if (excludeUserList.size() > 0) { - StringBuilder excludeUsers = new StringBuilder(); - - int excludeCount = 0; - for (String excludeUser : excludeUserList) { - // don't display that excluded #hopper in inventory rollbacks - if (actionList.contains(4) && actionList.contains(11)) { - if (excludeUser.equals("#hopper")) { - continue; - } - } - - if (excludeCount == 0) { - excludeUsers = excludeUsers.append("" + excludeUser + ""); - } - else { - excludeUsers.append(", ").append(excludeUser); - } - - excludeCount++; - } - - if (excludeCount > 0) { - Chat.sendMessage(user, Color.DARK_AQUA + "CoreProtect " + Color.WHITE + "- " + Phrase.build(Phrase.ROLLBACK_EXCLUDED_USERS, excludeUsers.toString(), (excludeCount == 1 ? Selector.FIRST : Selector.SECOND))); - } - } - - StringBuilder modifiedData = new StringBuilder(); - Integer modifyCount = 0; - if (actionList.contains(5)) { - modifiedData = modifiedData.append(Phrase.build(Phrase.AMOUNT_ITEM, NumberFormat.getInstance().format(blockCount), (blockCount == 1 ? Selector.FIRST : Selector.SECOND))); - modifyCount++; - } - else { - if (itemCount > 0 || actionList.contains(4)) { - modifiedData = modifiedData.append(Phrase.build(Phrase.AMOUNT_ITEM, NumberFormat.getInstance().format(itemCount), (itemCount == 1 ? Selector.FIRST : Selector.SECOND))); - modifyCount++; - } - - if (entityCount > 0) { - if (modifyCount > 0) { - modifiedData.append(", "); - } - modifiedData.append(Phrase.build(Phrase.AMOUNT_ENTITY, NumberFormat.getInstance().format(entityCount), (entityCount == 1 ? Selector.FIRST : Selector.SECOND))); - modifyCount++; - } - - if (blockCount > 0 || !actionList.contains(4) || preview > 0) { - if (modifyCount > 0) { - modifiedData.append(", "); - } - modifiedData.append(Phrase.build(Phrase.AMOUNT_BLOCK, NumberFormat.getInstance().format(blockCount), (blockCount == 1 ? Selector.FIRST : Selector.SECOND))); - modifyCount++; - } - } - - StringBuilder modifiedDataVerbose = new StringBuilder(); - if (verbose && preview == 0 && !actionList.contains(11)) { - if (chunkCount > -1 && modifyCount < 3) { - if (modifyCount > 0) { - modifiedData.append(", "); - } - modifiedData.append(Phrase.build(Phrase.AMOUNT_CHUNK, NumberFormat.getInstance().format(chunkCount), (chunkCount == 1 ? Selector.FIRST : Selector.SECOND))); - modifyCount++; - } - else if (chunkCount > 1) { - modifiedDataVerbose.append(Phrase.build(Phrase.AMOUNT_CHUNK, NumberFormat.getInstance().format(chunkCount), (chunkCount == 1 ? Selector.FIRST : Selector.SECOND))); - } - } - - Chat.sendMessage(user, Color.DARK_AQUA + "CoreProtect " + Color.WHITE + "- " + Phrase.build(Phrase.ROLLBACK_MODIFIED, modifiedData.toString(), (preview == 0 ? Selector.FIRST : Selector.SECOND))); - if (modifiedDataVerbose.length() > 0) { - Chat.sendMessage(user, Color.DARK_AQUA + "CoreProtect " + Color.WHITE + "- " + Phrase.build(Phrase.ROLLBACK_MODIFIED, modifiedDataVerbose.toString(), (preview == 0 ? Selector.FIRST : Selector.SECOND))); - } - - if (preview == 0) { - BigDecimal decimalSeconds = new BigDecimal(seconds).setScale(1, RoundingMode.HALF_EVEN); - Chat.sendMessage(user, Color.DARK_AQUA + "CoreProtect " + Color.WHITE + "- " + Phrase.build(Phrase.ROLLBACK_LENGTH, decimalSeconds.stripTrailingZeros().toPlainString(), (decimalSeconds.doubleValue() == 1 ? Selector.FIRST : Selector.SECOND))); - } - - Chat.sendMessage(user, "-----"); - if (preview > 0) { - Chat.sendMessage(user, Color.DARK_AQUA + "CoreProtect " + Color.WHITE + "- " + Phrase.build(Phrase.PLEASE_SELECT, "/co apply", "/co cancel")); - } - } - catch (Exception e) { - e.printStackTrace(); - } - } - - static int modifyContainerItems(Material type, Object container, int slot, ItemStack itemstack, int action) { - int modifiedArmor = -1; - try { - ItemStack[] contents = null; - - if (type != null && type.equals(Material.ARMOR_STAND)) { - EntityEquipment equipment = (EntityEquipment) container; - if (equipment != null) { - if (action == 1) { - itemstack.setAmount(1); - } - else { - itemstack.setType(Material.AIR); - itemstack.setAmount(0); - } - - if (slot < 4) { - contents = equipment.getArmorContents(); - if (slot >= 0) { - contents[slot] = itemstack; - } - equipment.setArmorContents(contents); - } - else { - ArmorStand armorStand = (ArmorStand) equipment.getHolder(); - armorStand.setArms(true); - switch (slot) { - case 4: - equipment.setItemInMainHand(itemstack); - break; - case 5: - equipment.setItemInOffHand(itemstack); - break; - } - } - } - } - else if (type != null && type.equals(Material.ITEM_FRAME)) { - ItemFrame frame = (ItemFrame) container; - if (frame != null) { - if (action == 1) { - itemstack.setAmount(1); - } - else { - itemstack.setType(Material.AIR); - itemstack.setAmount(0); - } - - frame.setItem(itemstack); - } - } - else if (type != null && type.equals(Material.JUKEBOX)) { - Jukebox jukebox = (Jukebox) container; - if (jukebox != null) { - if (action == 1 && Tag.ITEMS_MUSIC_DISCS.isTagged(itemstack.getType())) { - itemstack.setAmount(1); - } - else { - itemstack.setType(Material.AIR); - itemstack.setAmount(0); - } - - jukebox.setRecord(itemstack); - jukebox.update(); - } - } - else { - Inventory inventory = (Inventory) container; - if (inventory != null) { - boolean isPlayerInventory = (inventory instanceof PlayerInventory); - if (action == 1) { - int count = 0; - int amount = itemstack.getAmount(); - itemstack.setAmount(1); - - while (count < amount) { - boolean addedItem = false; - if (isPlayerInventory) { - int setArmor = Util.setPlayerArmor((PlayerInventory) inventory, itemstack); - addedItem = (setArmor > -1); - modifiedArmor = addedItem ? setArmor : modifiedArmor; - } - if (!addedItem) { - if (BukkitAdapter.ADAPTER.isChiseledBookshelf(type)) { - ItemStack[] inventoryContents = inventory.getStorageContents(); - int i = 0; - for (ItemStack stack : inventoryContents) { - if (stack == null) { - inventoryContents[i] = itemstack; - addedItem = true; - break; - } - i++; - } - if (addedItem) { - inventory.setStorageContents(inventoryContents); - } - else { - addedItem = (inventory.addItem(itemstack).size() == 0); - } - } - else { - addedItem = (inventory.addItem(itemstack).size() == 0); - } - } - if (!addedItem && isPlayerInventory) { - PlayerInventory playerInventory = (PlayerInventory) inventory; - ItemStack offhand = playerInventory.getItemInOffHand(); - if (offhand == null || offhand.getType() == Material.AIR || (itemstack.isSimilar(offhand) && offhand.getAmount() < offhand.getMaxStackSize())) { - ItemStack setOffhand = itemstack.clone(); - if (itemstack.isSimilar(offhand)) { - setOffhand.setAmount(offhand.getAmount() + 1); - } - - playerInventory.setItemInOffHand(setOffhand); - } - } - count++; - } - } - else { - int removeAmount = itemstack.getAmount(); - ItemStack removeMatch = itemstack.clone(); - removeMatch.setAmount(1); - - ItemStack[] inventoryContents = (isPlayerInventory ? inventory.getContents() : inventory.getStorageContents()).clone(); - for (int i = inventoryContents.length - 1; i >= 0; i--) { - if (inventoryContents[i] != null) { - ItemStack itemStack = inventoryContents[i].clone(); - int maxAmount = itemStack.getAmount(); - int currentAmount = maxAmount; - itemStack.setAmount(1); - - if (itemStack.toString().equals(removeMatch.toString())) { - for (int scan = 0; scan < maxAmount; scan++) { - if (removeAmount > 0) { - currentAmount--; - itemStack.setAmount(currentAmount); - removeAmount--; - } - else { - break; - } - } - } - else { - itemStack.setAmount(maxAmount); - } - - if (itemStack.getAmount() == 0) { - inventoryContents[i] = null; - } - else { - inventoryContents[i] = itemStack; - } - } - - if (removeAmount == 0) { - break; - } - } - - if (isPlayerInventory) { - inventory.setContents(inventoryContents); - } - else { - inventory.setStorageContents(inventoryContents); - } - - int count = 0; - while (count < removeAmount) { - inventory.removeItem(removeMatch); - count++; - } - } - } - } - } - catch (Exception e) { - e.printStackTrace(); - } - - return modifiedArmor; - } - - public static void sortContainerItems(PlayerInventory inventory, List modifiedArmorSlots) { - try { - ItemStack[] armorContents = inventory.getArmorContents(); - ItemStack[] storageContents = inventory.getStorageContents(); - - for (int armor = 0; armor < armorContents.length; armor++) { - ItemStack armorItem = armorContents[armor]; - if (armorItem == null || !modifiedArmorSlots.contains(armor)) { - continue; - } - - for (int storage = 0; storage < storageContents.length; storage++) { - ItemStack storageItem = storageContents[storage]; - if (storageItem == null) { - storageContents[storage] = armorItem; - armorContents[armor] = null; - break; - } - } - } - - inventory.setArmorContents(armorContents); - inventory.setStorageContents(storageContents); - } - catch (Exception e) { - e.printStackTrace(); - } - } - - private static void buildFireworkEffect(Builder effectBuilder, Material rowType, ItemStack itemstack) { - try { - FireworkEffect effect = effectBuilder.build(); - if ((rowType == Material.FIREWORK_ROCKET)) { - FireworkMeta meta = (FireworkMeta) itemstack.getItemMeta(); - meta.addEffect(effect); - itemstack.setItemMeta(meta); - } - else if ((rowType == Material.FIREWORK_STAR)) { - FireworkEffectMeta meta = (FireworkEffectMeta) itemstack.getItemMeta(); - meta.setEffect(effect); - itemstack.setItemMeta(meta); - } - } - catch (Exception e) { - e.printStackTrace(); - } - } - - @SuppressWarnings("unchecked") - public static Object[] populateItemStack(ItemStack itemstack, Object list) { - int slot = 0; - String faceData = ""; - - try { - /* - if (list instanceof Object[]) { - slot = (int) ((Object[]) list)[0]; - ItemMeta itemMeta = (ItemMeta) ((Object[]) list)[1]; - itemstack.setItemMeta(itemMeta); - return new Object[] { slot, itemstack }; - } - */ - - Material rowType = itemstack.getType(); - List metaList = (List) list; - if (metaList.size() > 0 && !(metaList.get(0) instanceof List)) { - if (rowType.name().endsWith("_BANNER")) { - BannerMeta meta = (BannerMeta) itemstack.getItemMeta(); - for (Object value : metaList) { - if (value instanceof Map) { - Pattern pattern = new Pattern((Map) value); - meta.addPattern(pattern); - } - } - itemstack.setItemMeta(meta); - } - else if (BlockGroup.SHULKER_BOXES.contains(rowType)) { - BlockStateMeta meta = (BlockStateMeta) itemstack.getItemMeta(); - ShulkerBox shulkerBox = (ShulkerBox) meta.getBlockState(); - for (Object value : metaList) { - ItemStack item = Util.unserializeItemStackLegacy(value); - if (item != null) { - shulkerBox.getInventory().addItem(item); - } - } - meta.setBlockState(shulkerBox); - itemstack.setItemMeta(meta); - } - - return new Object[] { slot, faceData, itemstack }; - } - - int itemCount = 0; - Builder effectBuilder = FireworkEffect.builder(); - for (List> map : (List>>) list) { - if (map.size() == 0) { - if (itemCount == 3 && (rowType == Material.FIREWORK_ROCKET || rowType == Material.FIREWORK_STAR)) { - buildFireworkEffect(effectBuilder, rowType, itemstack); - itemCount = 0; - } - - itemCount++; - continue; - } - Map mapData = map.get(0); - - if (mapData.get("slot") != null) { - slot = (Integer) mapData.get("slot"); - } - else if (mapData.get("facing") != null) { - faceData = (String) mapData.get("facing"); - } - else if (mapData.get("modifiers") != null) { - ItemMeta itemMeta = itemstack.getItemMeta(); - if (itemMeta.hasAttributeModifiers()) { - for (Map.Entry entry : itemMeta.getAttributeModifiers().entries()) { - itemMeta.removeAttributeModifier(entry.getKey(), entry.getValue()); - } - } - - List modifiers = (List) mapData.get("modifiers"); - - for (Object item : modifiers) { - Map> modifiersMap = (Map>) item; - for (Map.Entry> entry : modifiersMap.entrySet()) { - try { - Attribute attribute = entry.getKey(); - AttributeModifier modifier = AttributeModifier.deserialize(entry.getValue()); - itemMeta.addAttributeModifier(attribute, modifier); - } - catch (IllegalArgumentException e) { - // AttributeModifier already exists - } - } - } - - itemstack.setItemMeta(itemMeta); - } - else if (itemCount == 0) { - ItemMeta meta = Util.deserializeItemMeta(itemstack.getItemMeta().getClass(), map.get(0)); - itemstack.setItemMeta(meta); - - if (map.size() > 1 && (rowType == Material.POTION)) { - PotionMeta subMeta = (PotionMeta) itemstack.getItemMeta(); - org.bukkit.Color color = org.bukkit.Color.deserialize(map.get(1)); - subMeta.setColor(color); - itemstack.setItemMeta(subMeta); - } - } - else { - if ((rowType == Material.LEATHER_HORSE_ARMOR) || (rowType == Material.LEATHER_HELMET) || (rowType == Material.LEATHER_CHESTPLATE) || (rowType == Material.LEATHER_LEGGINGS) || (rowType == Material.LEATHER_BOOTS)) { // leather armor - for (Map colorData : map) { - LeatherArmorMeta meta = (LeatherArmorMeta) itemstack.getItemMeta(); - org.bukkit.Color color = org.bukkit.Color.deserialize(colorData); - meta.setColor(color); - itemstack.setItemMeta(meta); - } - } - else if ((rowType == Material.POTION)) { // potion - for (Map potionData : map) { - PotionMeta meta = (PotionMeta) itemstack.getItemMeta(); - PotionEffect effect = new PotionEffect(potionData); - meta.addCustomEffect(effect, true); - itemstack.setItemMeta(meta); - } - } - else if (rowType.name().endsWith("_BANNER")) { - for (Map patternData : map) { - BannerMeta meta = (BannerMeta) itemstack.getItemMeta(); - Pattern pattern = new Pattern(patternData); - meta.addPattern(pattern); - itemstack.setItemMeta(meta); - } - } - else if ((rowType == Material.CROSSBOW)) { - CrossbowMeta meta = (CrossbowMeta) itemstack.getItemMeta(); - for (Map itemData : map) { - ItemStack crossbowItem = Util.unserializeItemStack(itemData); - if (crossbowItem != null) { - meta.addChargedProjectile(crossbowItem); - } - } - itemstack.setItemMeta(meta); - } - else if (rowType == Material.MAP || rowType == Material.FILLED_MAP) { - for (Map colorData : map) { - MapMeta meta = (MapMeta) itemstack.getItemMeta(); - org.bukkit.Color color = org.bukkit.Color.deserialize(colorData); - meta.setColor(color); - itemstack.setItemMeta(meta); - } - } - else if ((rowType == Material.FIREWORK_ROCKET) || (rowType == Material.FIREWORK_STAR)) { - if (itemCount == 1) { - effectBuilder = FireworkEffect.builder(); - for (Map fireworkData : map) { - org.bukkit.FireworkEffect.Type type = (org.bukkit.FireworkEffect.Type) fireworkData.getOrDefault("type", org.bukkit.FireworkEffect.Type.BALL); - boolean hasFlicker = (Boolean) fireworkData.get("flicker"); - boolean hasTrail = (Boolean) fireworkData.get("trail"); - effectBuilder.with(type); - effectBuilder.flicker(hasFlicker); - effectBuilder.trail(hasTrail); - } - } - else if (itemCount == 2) { - for (Map colorData : map) { - org.bukkit.Color color = org.bukkit.Color.deserialize(colorData); - effectBuilder.withColor(color); - } - } - else if (itemCount == 3) { - for (Map colorData : map) { - org.bukkit.Color color = org.bukkit.Color.deserialize(colorData); - effectBuilder.withFade(color); - } - buildFireworkEffect(effectBuilder, rowType, itemstack); - itemCount = 0; - } - } - else if ((rowType == Material.SUSPICIOUS_STEW)) { - for (Map suspiciousStewData : map) { - SuspiciousStewMeta meta = (SuspiciousStewMeta) itemstack.getItemMeta(); - PotionEffect effect = new PotionEffect(suspiciousStewData); - meta.addCustomEffect(effect, true); - itemstack.setItemMeta(meta); - } - } - else { - BukkitAdapter.ADAPTER.setItemMeta(rowType, itemstack, map); - } - } - - itemCount++; - } - } - catch (Exception e) { - e.printStackTrace(); - } - return new Object[] { slot, faceData, itemstack }; - } - - public static Object[] populateItemStack(ItemStack itemstack, byte[] metadata) { - if (metadata != null) { - try { - ByteArrayInputStream metaByteStream = new ByteArrayInputStream(metadata); - BukkitObjectInputStream metaObjectStream = new BukkitObjectInputStream(metaByteStream); - Object metaList = metaObjectStream.readObject(); - metaObjectStream.close(); - metaByteStream.close(); - - return populateItemStack(itemstack, metaList); - } - catch (Exception e) { - e.printStackTrace(); - } - } - - return new Object[] { 0, "", itemstack }; - } - } diff --git a/src/main/java/net/coreprotect/database/rollback/RollbackComplete.java b/src/main/java/net/coreprotect/database/rollback/RollbackComplete.java new file mode 100644 index 0000000..451bea3 --- /dev/null +++ b/src/main/java/net/coreprotect/database/rollback/RollbackComplete.java @@ -0,0 +1,306 @@ +package net.coreprotect.database.rollback; + +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.text.NumberFormat; +import java.util.List; +import java.util.Locale; +import java.util.Map; + +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.EntityType; + +import net.coreprotect.language.Phrase; +import net.coreprotect.language.Selector; +import net.coreprotect.utility.Chat; +import net.coreprotect.utility.Color; + +public class RollbackComplete { + + public static void output(CommandSender user, Location location, List checkUsers, List restrictList, Map excludeList, List excludeUserList, List actionList, String timeString, Integer chunkCount, Double seconds, Integer itemCount, Integer blockCount, Integer entityCount, int rollbackType, Integer[] radius, boolean verbose, boolean restrictWorld, int preview) { + try { + if (preview == 2) { + Chat.sendMessage(user, Color.DARK_AQUA + "CoreProtect " + Color.WHITE + "- " + Phrase.build(Phrase.PREVIEW_CANCELLED)); + return; + } + + Chat.sendMessage(user, "-----"); + + StringBuilder usersBuilder = new StringBuilder(); + for (String value : checkUsers) { + if (usersBuilder.length() == 0) { + usersBuilder = usersBuilder.append("" + value + ""); + } + else { + usersBuilder.append(", ").append(value); + } + } + String users = usersBuilder.toString(); + + if (users.equals("#global") && restrictWorld) { + users = "#" + location.getWorld().getName(); + } + + if (preview > 0) { + Chat.sendMessage(user, Color.DARK_AQUA + "CoreProtect " + Color.WHITE + "- " + Phrase.build(Phrase.ROLLBACK_COMPLETED, users, Selector.THIRD)); // preview + } + else if (rollbackType == 0) { + Chat.sendMessage(user, Color.DARK_AQUA + "CoreProtect " + Color.WHITE + "- " + Phrase.build(Phrase.ROLLBACK_COMPLETED, users, Selector.FIRST)); // rollback + } + else if (rollbackType == 1) { + Chat.sendMessage(user, Color.DARK_AQUA + "CoreProtect " + Color.WHITE + "- " + Phrase.build(Phrase.ROLLBACK_COMPLETED, users, Selector.SECOND)); // restore + } + + if (preview == 1 || rollbackType == 0 || rollbackType == 1) { + Chat.sendMessage(user, Color.DARK_AQUA + "CoreProtect " + Color.WHITE + "- " + Phrase.build(Phrase.ROLLBACK_TIME, timeString)); + } + + if (radius != null) { + int worldedit = radius[7]; + if (worldedit == 0) { + Integer rollbackRadius = radius[0]; + Chat.sendMessage(user, Color.DARK_AQUA + "CoreProtect " + Color.WHITE + "- " + Phrase.build(Phrase.ROLLBACK_RADIUS, rollbackRadius.toString(), (rollbackRadius == 1 ? Selector.FIRST : Selector.SECOND))); + } + else { + Chat.sendMessage(user, Color.DARK_AQUA + "CoreProtect " + Color.WHITE + "- " + Phrase.build(Phrase.ROLLBACK_SELECTION, "#worldedit")); + } + } + + if (restrictWorld && radius == null) { + if (location != null) { + Chat.sendMessage(user, Color.DARK_AQUA + "CoreProtect " + Color.WHITE + "- " + Phrase.build(Phrase.ROLLBACK_WORLD_ACTION, location.getWorld().getName(), Selector.FIRST)); + } + } + + if (actionList.contains(4) && actionList.contains(11)) { + if (actionList.contains(0)) { + Chat.sendMessage(user, Color.DARK_AQUA + "CoreProtect " + Color.WHITE + "- " + Phrase.build(Phrase.ROLLBACK_WORLD_ACTION, "+inventory", Selector.SECOND)); + } + else if (actionList.contains(1)) { + Chat.sendMessage(user, Color.DARK_AQUA + "CoreProtect " + Color.WHITE + "- " + Phrase.build(Phrase.ROLLBACK_WORLD_ACTION, "-inventory", Selector.SECOND)); + } + else { + Chat.sendMessage(user, Color.DARK_AQUA + "CoreProtect " + Color.WHITE + "- " + Phrase.build(Phrase.ROLLBACK_WORLD_ACTION, "inventory", Selector.SECOND)); + } + } + else if (actionList.contains(4)) { + if (actionList.contains(0)) { + Chat.sendMessage(user, Color.DARK_AQUA + "CoreProtect " + Color.WHITE + "- " + Phrase.build(Phrase.ROLLBACK_WORLD_ACTION, "-container", Selector.SECOND)); + } + else if (actionList.contains(1)) { + Chat.sendMessage(user, Color.DARK_AQUA + "CoreProtect " + Color.WHITE + "- " + Phrase.build(Phrase.ROLLBACK_WORLD_ACTION, "+container", Selector.SECOND)); + } + else { + Chat.sendMessage(user, Color.DARK_AQUA + "CoreProtect " + Color.WHITE + "- " + Phrase.build(Phrase.ROLLBACK_WORLD_ACTION, "container", Selector.SECOND)); + } + } + else if (actionList.contains(0) && actionList.contains(1)) { + Chat.sendMessage(user, Color.DARK_AQUA + "CoreProtect " + Color.WHITE + "- " + Phrase.build(Phrase.ROLLBACK_WORLD_ACTION, "block", Selector.SECOND)); + } + else if (actionList.contains(0)) { + Chat.sendMessage(user, Color.DARK_AQUA + "CoreProtect " + Color.WHITE + "- " + Phrase.build(Phrase.ROLLBACK_WORLD_ACTION, "-block", Selector.SECOND)); + } + else if (actionList.contains(1)) { + Chat.sendMessage(user, Color.DARK_AQUA + "CoreProtect " + Color.WHITE + "- " + Phrase.build(Phrase.ROLLBACK_WORLD_ACTION, "+block", Selector.SECOND)); + } + else if (actionList.contains(3)) { + Chat.sendMessage(user, Color.DARK_AQUA + "CoreProtect " + Color.WHITE + "- " + Phrase.build(Phrase.ROLLBACK_WORLD_ACTION, "kill", Selector.SECOND)); + } + + if (restrictList.size() > 0) { + StringBuilder restrictTargets = new StringBuilder(); + boolean material = false; + boolean item = false; + boolean entity = false; + + int targetCount = 0; + for (Object restrictTarget : restrictList) { + String targetName = ""; + + if (restrictTarget instanceof Material) { + targetName = ((Material) restrictTarget).name().toLowerCase(Locale.ROOT); + item = (!item ? !(((Material) restrictTarget).isBlock()) : item); + material = true; + } + else if (restrictTarget instanceof EntityType) { + targetName = ((EntityType) restrictTarget).name().toLowerCase(Locale.ROOT); + entity = true; + } + + if (targetCount == 0) { + restrictTargets = restrictTargets.append("" + targetName + ""); + } + else { + restrictTargets.append(", ").append(targetName); + } + + targetCount++; + } + + String targetType = Selector.THIRD; + if (material && !item && !entity) { + targetType = Selector.FIRST; + } + else if (material && item && !entity) { + targetType = Selector.THIRD; + } + else if (entity && !material) { + targetType = Selector.SECOND; + } + + Chat.sendMessage(user, Color.DARK_AQUA + "CoreProtect " + Color.WHITE + "- " + Phrase.build(Phrase.ROLLBACK_INCLUDE, restrictTargets.toString(), Selector.FIRST, targetType, (targetCount == 1 ? Selector.FIRST : Selector.SECOND))); // include + } + + if (excludeList.size() > 0) { + StringBuilder excludeTargets = new StringBuilder(); + boolean material = false; + boolean item = false; + boolean entity = false; + + int excludeCount = 0; + for (Map.Entry entry : excludeList.entrySet()) { + Object excludeTarget = entry.getKey(); + Boolean excludeTargetInternal = entry.getValue(); + + // don't display default block excludes + if (Boolean.TRUE.equals(excludeTargetInternal)) { + continue; + } + + // don't display that excluded water/fire/farmland in inventory rollbacks + if (actionList.contains(4) && actionList.contains(11)) { + if (excludeTarget.equals(Material.FIRE) || excludeTarget.equals(Material.WATER) || excludeTarget.equals(Material.FARMLAND)) { + continue; + } + } + + String targetName = ""; + if (excludeTarget instanceof Material) { + targetName = ((Material) excludeTarget).name().toLowerCase(Locale.ROOT); + item = (!item ? !(((Material) excludeTarget).isBlock()) : item); + material = true; + } + else if (excludeTarget instanceof EntityType) { + targetName = ((EntityType) excludeTarget).name().toLowerCase(Locale.ROOT); + entity = true; + } + + if (excludeCount == 0) { + excludeTargets = excludeTargets.append("" + targetName + ""); + } + else { + excludeTargets.append(", ").append(targetName); + } + + excludeCount++; + } + + String targetType = Selector.THIRD; + if (material && !item && !entity) { + targetType = Selector.FIRST; + } + else if (material && item && !entity) { + targetType = Selector.THIRD; + } + else if (entity && !material) { + targetType = Selector.SECOND; + } + + if (excludeCount > 0) { + Chat.sendMessage(user, Color.DARK_AQUA + "CoreProtect " + Color.WHITE + "- " + Phrase.build(Phrase.ROLLBACK_INCLUDE, excludeTargets.toString(), Selector.SECOND, targetType, (excludeCount == 1 ? Selector.FIRST : Selector.SECOND))); // exclude + } + } + + if (excludeUserList.size() > 0) { + StringBuilder excludeUsers = new StringBuilder(); + + int excludeCount = 0; + for (String excludeUser : excludeUserList) { + // don't display that excluded #hopper in inventory rollbacks + if (actionList.contains(4) && actionList.contains(11)) { + if (excludeUser.equals("#hopper")) { + continue; + } + } + + if (excludeCount == 0) { + excludeUsers = excludeUsers.append("" + excludeUser + ""); + } + else { + excludeUsers.append(", ").append(excludeUser); + } + + excludeCount++; + } + + if (excludeCount > 0) { + Chat.sendMessage(user, Color.DARK_AQUA + "CoreProtect " + Color.WHITE + "- " + Phrase.build(Phrase.ROLLBACK_EXCLUDED_USERS, excludeUsers.toString(), (excludeCount == 1 ? Selector.FIRST : Selector.SECOND))); + } + } + + StringBuilder modifiedData = new StringBuilder(); + Integer modifyCount = 0; + if (actionList.contains(5)) { + modifiedData = modifiedData.append(Phrase.build(Phrase.AMOUNT_ITEM, NumberFormat.getInstance().format(blockCount), (blockCount == 1 ? Selector.FIRST : Selector.SECOND))); + modifyCount++; + } + else { + if (itemCount > 0 || actionList.contains(4)) { + modifiedData = modifiedData.append(Phrase.build(Phrase.AMOUNT_ITEM, NumberFormat.getInstance().format(itemCount), (itemCount == 1 ? Selector.FIRST : Selector.SECOND))); + modifyCount++; + } + + if (entityCount > 0) { + if (modifyCount > 0) { + modifiedData.append(", "); + } + modifiedData.append(Phrase.build(Phrase.AMOUNT_ENTITY, NumberFormat.getInstance().format(entityCount), (entityCount == 1 ? Selector.FIRST : Selector.SECOND))); + modifyCount++; + } + + if (blockCount > 0 || !actionList.contains(4) || preview > 0) { + if (modifyCount > 0) { + modifiedData.append(", "); + } + modifiedData.append(Phrase.build(Phrase.AMOUNT_BLOCK, NumberFormat.getInstance().format(blockCount), (blockCount == 1 ? Selector.FIRST : Selector.SECOND))); + modifyCount++; + } + } + + StringBuilder modifiedDataVerbose = new StringBuilder(); + if (verbose && preview == 0 && !actionList.contains(11)) { + if (chunkCount > -1 && modifyCount < 3) { + if (modifyCount > 0) { + modifiedData.append(", "); + } + modifiedData.append(Phrase.build(Phrase.AMOUNT_CHUNK, NumberFormat.getInstance().format(chunkCount), (chunkCount == 1 ? Selector.FIRST : Selector.SECOND))); + modifyCount++; + } + else if (chunkCount > 1) { + modifiedDataVerbose.append(Phrase.build(Phrase.AMOUNT_CHUNK, NumberFormat.getInstance().format(chunkCount), (chunkCount == 1 ? Selector.FIRST : Selector.SECOND))); + } + } + + Chat.sendMessage(user, Color.DARK_AQUA + "CoreProtect " + Color.WHITE + "- " + Phrase.build(Phrase.ROLLBACK_MODIFIED, modifiedData.toString(), (preview == 0 ? Selector.FIRST : Selector.SECOND))); + if (modifiedDataVerbose.length() > 0) { + Chat.sendMessage(user, Color.DARK_AQUA + "CoreProtect " + Color.WHITE + "- " + Phrase.build(Phrase.ROLLBACK_MODIFIED, modifiedDataVerbose.toString(), (preview == 0 ? Selector.FIRST : Selector.SECOND))); + } + + if (preview == 0) { + BigDecimal decimalSeconds = new BigDecimal(seconds).setScale(1, RoundingMode.HALF_EVEN); + Chat.sendMessage(user, Color.DARK_AQUA + "CoreProtect " + Color.WHITE + "- " + Phrase.build(Phrase.ROLLBACK_LENGTH, decimalSeconds.stripTrailingZeros().toPlainString(), (decimalSeconds.doubleValue() == 1 ? Selector.FIRST : Selector.SECOND))); + } + + Chat.sendMessage(user, "-----"); + if (preview > 0) { + Chat.sendMessage(user, Color.DARK_AQUA + "CoreProtect " + Color.WHITE + "- " + Phrase.build(Phrase.PLEASE_SELECT, "/co apply", "/co cancel")); + } + } + catch (Exception e) { + e.printStackTrace(); + } + } + +} diff --git a/src/main/java/net/coreprotect/database/rollback/RollbackUtil.java b/src/main/java/net/coreprotect/database/rollback/RollbackUtil.java new file mode 100644 index 0000000..0ee37fb --- /dev/null +++ b/src/main/java/net/coreprotect/database/rollback/RollbackUtil.java @@ -0,0 +1,487 @@ +package net.coreprotect.database.rollback; + +import java.io.ByteArrayInputStream; +import java.util.List; +import java.util.Map; + +import org.bukkit.FireworkEffect; +import org.bukkit.FireworkEffect.Builder; +import org.bukkit.Material; +import org.bukkit.Tag; +import org.bukkit.attribute.Attribute; +import org.bukkit.attribute.AttributeModifier; +import org.bukkit.block.Jukebox; +import org.bukkit.block.ShulkerBox; +import org.bukkit.block.banner.Pattern; +import org.bukkit.entity.ArmorStand; +import org.bukkit.entity.ItemFrame; +import org.bukkit.inventory.EntityEquipment; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.PlayerInventory; +import org.bukkit.inventory.meta.BannerMeta; +import org.bukkit.inventory.meta.BlockStateMeta; +import org.bukkit.inventory.meta.CrossbowMeta; +import org.bukkit.inventory.meta.FireworkEffectMeta; +import org.bukkit.inventory.meta.FireworkMeta; +import org.bukkit.inventory.meta.ItemMeta; +import org.bukkit.inventory.meta.LeatherArmorMeta; +import org.bukkit.inventory.meta.MapMeta; +import org.bukkit.inventory.meta.PotionMeta; +import org.bukkit.inventory.meta.SuspiciousStewMeta; +import org.bukkit.potion.PotionEffect; +import org.bukkit.util.io.BukkitObjectInputStream; + +import net.coreprotect.bukkit.BukkitAdapter; +import net.coreprotect.database.Lookup; +import net.coreprotect.model.BlockGroup; +import net.coreprotect.utility.Util; + +public class RollbackUtil extends Lookup { + + protected static int modifyContainerItems(Material type, Object container, int slot, ItemStack itemstack, int action) { + int modifiedArmor = -1; + try { + ItemStack[] contents = null; + + if (type != null && type.equals(Material.ARMOR_STAND)) { + EntityEquipment equipment = (EntityEquipment) container; + if (equipment != null) { + if (action == 1) { + itemstack.setAmount(1); + } + else { + itemstack.setType(Material.AIR); + itemstack.setAmount(0); + } + + if (slot < 4) { + contents = equipment.getArmorContents(); + if (slot >= 0) { + contents[slot] = itemstack; + } + equipment.setArmorContents(contents); + } + else { + ArmorStand armorStand = (ArmorStand) equipment.getHolder(); + armorStand.setArms(true); + switch (slot) { + case 4: + equipment.setItemInMainHand(itemstack); + break; + case 5: + equipment.setItemInOffHand(itemstack); + break; + } + } + } + } + else if (type != null && type.equals(Material.ITEM_FRAME)) { + ItemFrame frame = (ItemFrame) container; + if (frame != null) { + if (action == 1) { + itemstack.setAmount(1); + } + else { + itemstack.setType(Material.AIR); + itemstack.setAmount(0); + } + + frame.setItem(itemstack); + } + } + else if (type != null && type.equals(Material.JUKEBOX)) { + Jukebox jukebox = (Jukebox) container; + if (jukebox != null) { + if (action == 1 && Tag.ITEMS_MUSIC_DISCS.isTagged(itemstack.getType())) { + itemstack.setAmount(1); + } + else { + itemstack.setType(Material.AIR); + itemstack.setAmount(0); + } + + jukebox.setRecord(itemstack); + jukebox.update(); + } + } + else { + Inventory inventory = (Inventory) container; + if (inventory != null) { + boolean isPlayerInventory = (inventory instanceof PlayerInventory); + if (action == 1) { + int count = 0; + int amount = itemstack.getAmount(); + itemstack.setAmount(1); + + while (count < amount) { + boolean addedItem = false; + if (isPlayerInventory) { + int setArmor = Util.setPlayerArmor((PlayerInventory) inventory, itemstack); + addedItem = (setArmor > -1); + modifiedArmor = addedItem ? setArmor : modifiedArmor; + } + if (!addedItem) { + if (BukkitAdapter.ADAPTER.isChiseledBookshelf(type)) { + ItemStack[] inventoryContents = inventory.getStorageContents(); + int i = 0; + for (ItemStack stack : inventoryContents) { + if (stack == null) { + inventoryContents[i] = itemstack; + addedItem = true; + break; + } + i++; + } + if (addedItem) { + inventory.setStorageContents(inventoryContents); + } + else { + addedItem = (inventory.addItem(itemstack).size() == 0); + } + } + else { + addedItem = (inventory.addItem(itemstack).size() == 0); + } + } + if (!addedItem && isPlayerInventory) { + PlayerInventory playerInventory = (PlayerInventory) inventory; + ItemStack offhand = playerInventory.getItemInOffHand(); + if (offhand == null || offhand.getType() == Material.AIR || (itemstack.isSimilar(offhand) && offhand.getAmount() < offhand.getMaxStackSize())) { + ItemStack setOffhand = itemstack.clone(); + if (itemstack.isSimilar(offhand)) { + setOffhand.setAmount(offhand.getAmount() + 1); + } + + playerInventory.setItemInOffHand(setOffhand); + } + } + count++; + } + } + else { + int removeAmount = itemstack.getAmount(); + ItemStack removeMatch = itemstack.clone(); + removeMatch.setAmount(1); + + ItemStack[] inventoryContents = (isPlayerInventory ? inventory.getContents() : inventory.getStorageContents()).clone(); + for (int i = inventoryContents.length - 1; i >= 0; i--) { + if (inventoryContents[i] != null) { + ItemStack itemStack = inventoryContents[i].clone(); + int maxAmount = itemStack.getAmount(); + int currentAmount = maxAmount; + itemStack.setAmount(1); + + if (itemStack.toString().equals(removeMatch.toString())) { + for (int scan = 0; scan < maxAmount; scan++) { + if (removeAmount > 0) { + currentAmount--; + itemStack.setAmount(currentAmount); + removeAmount--; + } + else { + break; + } + } + } + else { + itemStack.setAmount(maxAmount); + } + + if (itemStack.getAmount() == 0) { + inventoryContents[i] = null; + } + else { + inventoryContents[i] = itemStack; + } + } + + if (removeAmount == 0) { + break; + } + } + + if (isPlayerInventory) { + inventory.setContents(inventoryContents); + } + else { + inventory.setStorageContents(inventoryContents); + } + + int count = 0; + while (count < removeAmount) { + inventory.removeItem(removeMatch); + count++; + } + } + } + } + } + catch (Exception e) { + e.printStackTrace(); + } + + return modifiedArmor; + } + + public static void sortContainerItems(PlayerInventory inventory, List modifiedArmorSlots) { + try { + ItemStack[] armorContents = inventory.getArmorContents(); + ItemStack[] storageContents = inventory.getStorageContents(); + + for (int armor = 0; armor < armorContents.length; armor++) { + ItemStack armorItem = armorContents[armor]; + if (armorItem == null || !modifiedArmorSlots.contains(armor)) { + continue; + } + + for (int storage = 0; storage < storageContents.length; storage++) { + ItemStack storageItem = storageContents[storage]; + if (storageItem == null) { + storageContents[storage] = armorItem; + armorContents[armor] = null; + break; + } + } + } + + inventory.setArmorContents(armorContents); + inventory.setStorageContents(storageContents); + } + catch (Exception e) { + e.printStackTrace(); + } + } + + private static void buildFireworkEffect(Builder effectBuilder, Material rowType, ItemStack itemstack) { + try { + FireworkEffect effect = effectBuilder.build(); + if ((rowType == Material.FIREWORK_ROCKET)) { + FireworkMeta meta = (FireworkMeta) itemstack.getItemMeta(); + meta.addEffect(effect); + itemstack.setItemMeta(meta); + } + else if ((rowType == Material.FIREWORK_STAR)) { + FireworkEffectMeta meta = (FireworkEffectMeta) itemstack.getItemMeta(); + meta.setEffect(effect); + itemstack.setItemMeta(meta); + } + } + catch (Exception e) { + e.printStackTrace(); + } + } + + @SuppressWarnings("unchecked") + public static Object[] populateItemStack(ItemStack itemstack, Object list) { + int slot = 0; + String faceData = ""; + + try { + /* + if (list instanceof Object[]) { + slot = (int) ((Object[]) list)[0]; + ItemMeta itemMeta = (ItemMeta) ((Object[]) list)[1]; + itemstack.setItemMeta(itemMeta); + return new Object[] { slot, itemstack }; + } + */ + + Material rowType = itemstack.getType(); + List metaList = (List) list; + if (metaList.size() > 0 && !(metaList.get(0) instanceof List)) { + if (rowType.name().endsWith("_BANNER")) { + BannerMeta meta = (BannerMeta) itemstack.getItemMeta(); + for (Object value : metaList) { + if (value instanceof Map) { + Pattern pattern = new Pattern((Map) value); + meta.addPattern(pattern); + } + } + itemstack.setItemMeta(meta); + } + else if (BlockGroup.SHULKER_BOXES.contains(rowType)) { + BlockStateMeta meta = (BlockStateMeta) itemstack.getItemMeta(); + ShulkerBox shulkerBox = (ShulkerBox) meta.getBlockState(); + for (Object value : metaList) { + ItemStack item = Util.unserializeItemStackLegacy(value); + if (item != null) { + shulkerBox.getInventory().addItem(item); + } + } + meta.setBlockState(shulkerBox); + itemstack.setItemMeta(meta); + } + + return new Object[] { slot, faceData, itemstack }; + } + + int itemCount = 0; + Builder effectBuilder = FireworkEffect.builder(); + for (List> map : (List>>) list) { + if (map.size() == 0) { + if (itemCount == 3 && (rowType == Material.FIREWORK_ROCKET || rowType == Material.FIREWORK_STAR)) { + buildFireworkEffect(effectBuilder, rowType, itemstack); + itemCount = 0; + } + + itemCount++; + continue; + } + Map mapData = map.get(0); + + if (mapData.get("slot") != null) { + slot = (Integer) mapData.get("slot"); + } + else if (mapData.get("facing") != null) { + faceData = (String) mapData.get("facing"); + } + else if (mapData.get("modifiers") != null) { + ItemMeta itemMeta = itemstack.getItemMeta(); + if (itemMeta.hasAttributeModifiers()) { + for (Map.Entry entry : itemMeta.getAttributeModifiers().entries()) { + itemMeta.removeAttributeModifier(entry.getKey(), entry.getValue()); + } + } + + List modifiers = (List) mapData.get("modifiers"); + + for (Object item : modifiers) { + Map> modifiersMap = (Map>) item; + for (Map.Entry> entry : modifiersMap.entrySet()) { + try { + Attribute attribute = entry.getKey(); + AttributeModifier modifier = AttributeModifier.deserialize(entry.getValue()); + itemMeta.addAttributeModifier(attribute, modifier); + } + catch (IllegalArgumentException e) { + // AttributeModifier already exists + } + } + } + + itemstack.setItemMeta(itemMeta); + } + else if (itemCount == 0) { + ItemMeta meta = Util.deserializeItemMeta(itemstack.getItemMeta().getClass(), map.get(0)); + itemstack.setItemMeta(meta); + + if (map.size() > 1 && (rowType == Material.POTION)) { + PotionMeta subMeta = (PotionMeta) itemstack.getItemMeta(); + org.bukkit.Color color = org.bukkit.Color.deserialize(map.get(1)); + subMeta.setColor(color); + itemstack.setItemMeta(subMeta); + } + } + else { + if ((rowType == Material.LEATHER_HORSE_ARMOR) || (rowType == Material.LEATHER_HELMET) || (rowType == Material.LEATHER_CHESTPLATE) || (rowType == Material.LEATHER_LEGGINGS) || (rowType == Material.LEATHER_BOOTS)) { // leather armor + for (Map colorData : map) { + LeatherArmorMeta meta = (LeatherArmorMeta) itemstack.getItemMeta(); + org.bukkit.Color color = org.bukkit.Color.deserialize(colorData); + meta.setColor(color); + itemstack.setItemMeta(meta); + } + } + else if ((rowType == Material.POTION)) { // potion + for (Map potionData : map) { + PotionMeta meta = (PotionMeta) itemstack.getItemMeta(); + PotionEffect effect = new PotionEffect(potionData); + meta.addCustomEffect(effect, true); + itemstack.setItemMeta(meta); + } + } + else if (rowType.name().endsWith("_BANNER")) { + for (Map patternData : map) { + BannerMeta meta = (BannerMeta) itemstack.getItemMeta(); + Pattern pattern = new Pattern(patternData); + meta.addPattern(pattern); + itemstack.setItemMeta(meta); + } + } + else if ((rowType == Material.CROSSBOW)) { + CrossbowMeta meta = (CrossbowMeta) itemstack.getItemMeta(); + for (Map itemData : map) { + ItemStack crossbowItem = Util.unserializeItemStack(itemData); + if (crossbowItem != null) { + meta.addChargedProjectile(crossbowItem); + } + } + itemstack.setItemMeta(meta); + } + else if (rowType == Material.MAP || rowType == Material.FILLED_MAP) { + for (Map colorData : map) { + MapMeta meta = (MapMeta) itemstack.getItemMeta(); + org.bukkit.Color color = org.bukkit.Color.deserialize(colorData); + meta.setColor(color); + itemstack.setItemMeta(meta); + } + } + else if ((rowType == Material.FIREWORK_ROCKET) || (rowType == Material.FIREWORK_STAR)) { + if (itemCount == 1) { + effectBuilder = FireworkEffect.builder(); + for (Map fireworkData : map) { + org.bukkit.FireworkEffect.Type type = (org.bukkit.FireworkEffect.Type) fireworkData.getOrDefault("type", org.bukkit.FireworkEffect.Type.BALL); + boolean hasFlicker = (Boolean) fireworkData.get("flicker"); + boolean hasTrail = (Boolean) fireworkData.get("trail"); + effectBuilder.with(type); + effectBuilder.flicker(hasFlicker); + effectBuilder.trail(hasTrail); + } + } + else if (itemCount == 2) { + for (Map colorData : map) { + org.bukkit.Color color = org.bukkit.Color.deserialize(colorData); + effectBuilder.withColor(color); + } + } + else if (itemCount == 3) { + for (Map colorData : map) { + org.bukkit.Color color = org.bukkit.Color.deserialize(colorData); + effectBuilder.withFade(color); + } + buildFireworkEffect(effectBuilder, rowType, itemstack); + itemCount = 0; + } + } + else if ((rowType == Material.SUSPICIOUS_STEW)) { + for (Map suspiciousStewData : map) { + SuspiciousStewMeta meta = (SuspiciousStewMeta) itemstack.getItemMeta(); + PotionEffect effect = new PotionEffect(suspiciousStewData); + meta.addCustomEffect(effect, true); + itemstack.setItemMeta(meta); + } + } + else { + BukkitAdapter.ADAPTER.setItemMeta(rowType, itemstack, map); + } + } + + itemCount++; + } + } + catch (Exception e) { + e.printStackTrace(); + } + return new Object[] { slot, faceData, itemstack }; + } + + public static Object[] populateItemStack(ItemStack itemstack, byte[] metadata) { + if (metadata != null) { + try { + ByteArrayInputStream metaByteStream = new ByteArrayInputStream(metadata); + BukkitObjectInputStream metaObjectStream = new BukkitObjectInputStream(metaByteStream); + Object metaList = metaObjectStream.readObject(); + metaObjectStream.close(); + metaByteStream.close(); + + return populateItemStack(itemstack, metaList); + } + catch (Exception e) { + e.printStackTrace(); + } + } + + return new Object[] { 0, "", itemstack }; + } + +} diff --git a/src/main/java/net/coreprotect/utility/Util.java b/src/main/java/net/coreprotect/utility/Util.java index 0a19b86..502b326 100755 --- a/src/main/java/net/coreprotect/utility/Util.java +++ b/src/main/java/net/coreprotect/utility/Util.java @@ -56,7 +56,7 @@ import net.coreprotect.bukkit.BukkitAdapter; import net.coreprotect.config.Config; import net.coreprotect.config.ConfigHandler; import net.coreprotect.consumer.Queue; -import net.coreprotect.database.Rollback; +import net.coreprotect.database.rollback.Rollback; import net.coreprotect.language.Phrase; import net.coreprotect.model.BlockGroup; import net.coreprotect.thread.CacheHandler; diff --git a/src/main/java/net/coreprotect/utility/entity/EntityUtil.java b/src/main/java/net/coreprotect/utility/entity/EntityUtil.java index a8f4b16..ed61965 100644 --- a/src/main/java/net/coreprotect/utility/entity/EntityUtil.java +++ b/src/main/java/net/coreprotect/utility/entity/EntityUtil.java @@ -57,7 +57,7 @@ import org.bukkit.inventory.meta.LeatherArmorMeta; import net.coreprotect.CoreProtect; import net.coreprotect.bukkit.BukkitAdapter; -import net.coreprotect.database.Rollback; +import net.coreprotect.database.rollback.Rollback; import net.coreprotect.thread.CacheHandler; import net.coreprotect.thread.Scheduler; import net.coreprotect.utility.Util;