diff --git a/SchematicSystem_15/src/de/steamwar/schematicsystem/CheckSchemType15.java b/SchematicSystem_15/src/de/steamwar/schematicsystem/autocheck/AutoChecker15.java similarity index 63% rename from SchematicSystem_15/src/de/steamwar/schematicsystem/CheckSchemType15.java rename to SchematicSystem_15/src/de/steamwar/schematicsystem/autocheck/AutoChecker15.java index e0640c9..d171e8b 100644 --- a/SchematicSystem_15/src/de/steamwar/schematicsystem/CheckSchemType15.java +++ b/SchematicSystem_15/src/de/steamwar/schematicsystem/autocheck/AutoChecker15.java @@ -1,7 +1,7 @@ -/* +/* This file is a part of the SteamWar software. - - Copyright (C) 2020 SteamWar.de-Serverteam + + Copyright (C) 2022 SteamWar.de-Serverteam This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by @@ -17,20 +17,21 @@ along with this program. If not, see . */ -package de.steamwar.schematicsystem; +package de.steamwar.schematicsystem.autocheck; import com.sk89q.jnbt.CompoundTag; import com.sk89q.worldedit.extent.clipboard.Clipboard; import com.sk89q.worldedit.math.BlockVector3; -import com.sk89q.worldedit.regions.Region; import com.sk89q.worldedit.world.block.BaseBlock; +import de.steamwar.schematicsystem.CheckSchemType; import org.bukkit.Material; import java.util.EnumSet; +import java.util.HashSet; import java.util.List; import java.util.Set; -public class CheckSchemType15 implements CheckSchemType.ICheckSchemType { +public class AutoChecker15 implements AutoChecker.IAutoChecker { private static final Set INVENTORY = EnumSet.of( Material.BARREL, Material.BLAST_FURNACE, @@ -75,7 +76,6 @@ public class CheckSchemType15 implements CheckSchemType.ICheckSchemType { Material.WHITE_TULIP, Material.PINK_TULIP, Material.OXEYE_DAISY, - Material.CORNFLOWER, Material.LILY_OF_THE_VALLEY, Material.WITHER_ROSE, Material.SUNFLOWER, @@ -85,48 +85,41 @@ public class CheckSchemType15 implements CheckSchemType.ICheckSchemType { Material.HONEY_BOTTLE); @Override - public void autoCheck(AutoCheckResult result, Clipboard clipboard) { - BlockVector3 dimensions = clipboard.getDimensions(); - result.setLength(dimensions.getBlockX()); - result.setHeight(dimensions.getBlockY()); - result.setWidth(dimensions.getBlockZ()); - - Region region = clipboard.getRegion(); - BlockVector3 min = region.getMinimumPoint(); - BlockVector3 max = region.getMaximumPoint(); - - int blocks = 0; + public AutoChecker.BlockScanResult scan(Clipboard clipboard, CheckSchemType type) { + AutoChecker.BlockScanResult result = new AutoChecker.BlockScanResult(); + BlockVector3 min = clipboard.getMinimumPoint(); + BlockVector3 max = clipboard.getMaximumPoint(); for(int x = min.getBlockX(); x <= max.getBlockX(); x++){ - for(int y = min.getBlockY(); y <= max.getBlockY(); y++){ - for(int z = min.getBlockZ(); z <= max.getBlockZ(); z++){ + for(int y = min.getBlockY(); y <= max.getBlockY(); y++) { + for (int z = min.getBlockZ(); z <= max.getBlockZ(); z++) { + final BlockPos pos = new BlockPos(x, y, z); final BaseBlock block = clipboard.getFullBlock(BlockVector3.at(x, y, z)); - final Material blockMaterial = Material.matchMaterial(block.getBlockType().getId()); - if(blockMaterial == null) + final Material material = Material.matchMaterial(block.getBlockType().getId()); + if(material == null) { continue; + } - result.checkMaterial(blockMaterial.name()); + result.getBlockCounts().merge(material, 1, Integer::sum); - if(blockMaterial != Material.AIR) - blocks++; - - if(INVENTORY.contains(blockMaterial)) - checkInventory(result, block, blockMaterial); + if(INVENTORY.contains(material)) { + checkInventory(result, block, material, pos); + } } } } - - result.setBlocks(blocks); + return result; } - private static void checkInventory(AutoCheckResult result, BaseBlock block, Material blockMaterial) { + private void checkInventory(AutoChecker.BlockScanResult result, BaseBlock block, Material material, BlockPos pos) { CompoundTag nbt = block.getNbtData(); - if(nbt == null){ - result.defunctNbt(blockMaterial.name()); + if(nbt == null) { + result.getDefunctNbt().add(pos); return; } - if(blockMaterial == Material.JUKEBOX && nbt.getValue().containsKey("RecordItem")){ - result.foundRecord(); + + if(material == Material.JUKEBOX && nbt.getValue().containsKey("RecordItem")){ + result.getRecords().add(pos); return; } @@ -137,7 +130,7 @@ public class CheckSchemType15 implements CheckSchemType.ICheckSchemType { int counter = 0; for(CompoundTag item : items){ if(!item.containsKey("id")){ - result.defunctNbt(blockMaterial.name()); + result.getDefunctNbt().add(pos); continue; } @@ -145,14 +138,14 @@ public class CheckSchemType15 implements CheckSchemType.ICheckSchemType { if(itemType == null) //Leere Slots continue; - if(blockMaterial == Material.DISPENSER && (itemType.equals(Material.FIRE_CHARGE) || itemType.equals(Material.ARROW))) + if(material == Material.DISPENSER && (itemType.equals(Material.FIRE_CHARGE) || itemType.equals(Material.ARROW))) { counter += item.getByte("Count"); - else if(!FLOWERS.contains(itemType) && !((blockMaterial == Material.CHEST || blockMaterial == Material.BARREL) && itemType.equals(Material.TNT))) - result.foundForbiddenItem(blockMaterial.name(), itemType.name(), item.getByte("Count")); - else if(item.containsKey("tag")) - result.foundItemWithTag(blockMaterial.name(), itemType.name(), item.getByte("Count")); + } else if(!FLOWERS.contains(itemType) && !((material == Material.CHEST || material == Material.BARREL) && itemType.equals(Material.TNT))) { + result.getForbiddenItems().computeIfAbsent(pos, blockVector3 -> new HashSet<>()).add(itemType); + }else if(item.containsKey("tag")) { + result.getForbiddenNbt().computeIfAbsent(pos, blockVector3 -> new HashSet<>()).add(itemType); + } } - - result.dispenserItems(counter); + result.getDispenserItems().put(pos, counter); } } diff --git a/SchematicSystem_15/src/de/steamwar/schematicsystem/commands/SchematicCommand15.java b/SchematicSystem_15/src/de/steamwar/schematicsystem/commands/SchematicCommand15.java new file mode 100644 index 0000000..64797e0 --- /dev/null +++ b/SchematicSystem_15/src/de/steamwar/schematicsystem/commands/SchematicCommand15.java @@ -0,0 +1,138 @@ +/* + This file is a part of the SteamWar software. + + Copyright (C) 2022 SteamWar.de-Serverteam + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . +*/ + +package de.steamwar.schematicsystem.commands; + +import com.sk89q.jnbt.CompoundTag; +import com.sk89q.jnbt.CompoundTagBuilder; +import com.sk89q.jnbt.ListTag; +import com.sk89q.worldedit.extent.clipboard.Clipboard; +import com.sk89q.worldedit.math.BlockVector3; +import com.sk89q.worldedit.world.block.BaseBlock; +import com.sk89q.worldedit.world.block.BlockState; +import com.sk89q.worldedit.world.block.BlockTypes; +import de.steamwar.schematicsystem.CheckSchemType; +import de.steamwar.schematicsystem.autocheck.AutoCheckerResult; +import de.steamwar.schematicsystem.autocheck.BlockPos; +import org.bukkit.Material; + +import java.util.*; +import java.util.stream.Collectors; + +public class SchematicCommand15 implements SchematicCommand.ISchematicCommand { + @Override + public Clipboard fixClipboard(Clipboard clipboard, AutoCheckerResult result, CheckSchemType type) throws Exception { + for (BlockPos blockPos : result.getRecords()) { + BlockVector3 vector = BlockVector3.at(blockPos.getX(), blockPos.getY(), blockPos.getZ()); + clipboard.setBlock(vector, clipboard.getFullBlock(vector).toBaseBlock(new CompoundTag(Collections.emptyMap()))); + } + + Map> toBeCheckedInvs = new HashMap<>(); + + toBeCheckedInvs.putAll(result.getForbiddenItems()); + toBeCheckedInvs.putAll(result.getForbiddenNbt()); + + for (Map.Entry> entry: toBeCheckedInvs.entrySet()) { + BlockPos pos = entry.getKey(); + Set materials = entry.getValue(); + BlockVector3 vector = BlockVector3.at(pos.getX(), pos.getY(), pos.getZ()); + BaseBlock block = clipboard.getFullBlock(vector); + CompoundTag tag = block.getNbtData(); + CompoundTagBuilder builder = CompoundTagBuilder.create(); + List list = new ArrayList<>(); + for (CompoundTag items : tag.getList("Items", CompoundTag.class)) { + if(materials.contains(Material.matchMaterial(items.getString("id")))) { + continue; + } + + if(items.containsKey("tag")) { + continue; + } + + list.add(items); + } + builder.put("Items", new ListTag(CompoundTag.class, list)); + clipboard.setBlock(vector, block.toBaseBlock(builder.build())); + } + + if(type.getMaxDispenserItems() > 0 ) { + for (Map.Entry entry : result.getDispenserItems().entrySet()) { + if(entry.getValue() <= type.getMaxDispenserItems()) { + continue; + } + + BlockPos pos = entry.getKey(); + BlockVector3 vector = BlockVector3.at(pos.getX(), pos.getY(), pos.getZ()); + BaseBlock block = clipboard.getFullBlock(vector); + CompoundTag tag = block.getNbtData(); + CompoundTagBuilder builder = tag.createBuilder(); + List items = tag.getList("Items", CompoundTag.class); + Collections.reverse(items); // To let the first item be in the Dispenser + List list = new ArrayList<>(); + int diff = entry.getValue() - type.getMaxDispenserItems(); + for (CompoundTag item : items) { + if(item == null) { + continue; + } + + if(diff == 0) { + list.add(item); + continue; + } + + if(diff > item.getByte("Count")) { + diff -= item.getByte("Count"); + continue; + } + + item = item.createBuilder().putByte("Count", (byte) (item.getByte("Count") - diff)).build(); + diff = 0; + list.add(item); + } + + builder.put("Items", new ListTag(CompoundTag.class, list)); + clipboard.setBlock(vector, block.toBaseBlock(builder.build())); + } + } + + if(!result.isLimitedBlocksOK()) { + Set toReplace = type.getLimits().entrySet().stream() + .filter(setIntegerEntry -> setIntegerEntry.getValue() == 0) + .flatMap(setIntegerEntry -> setIntegerEntry.getKey().stream()) + .map(Material::matchMaterial) + .collect(Collectors.toSet()); + BlockState replaceType = Objects.requireNonNull(toReplace.contains(Material.END_STONE) ? BlockTypes.IRON_BLOCK : BlockTypes.END_STONE).getDefaultState(); + BlockVector3 min = clipboard.getMinimumPoint(); + BlockVector3 max = clipboard.getMaximumPoint(); + for (int i = min.getBlockX(); i <= max.getBlockX(); i++) { + for (int j = min.getBlockY(); j <= max.getBlockY(); j++) { + for (int k = min.getBlockZ(); k <= max.getBlockZ(); k++) { + BlockVector3 vector = BlockVector3.at(i, j, k); + BaseBlock block = clipboard.getFullBlock(vector); + if(toReplace.contains(Material.matchMaterial(block.getBlockType().getId()))) { + clipboard.setBlock(vector, replaceType.toBaseBlock()); + } + } + } + } + } + + return clipboard; + } +} diff --git a/SchematicSystem_8/src/de/steamwar/schematicsystem/CheckSchemType8.java b/SchematicSystem_8/src/de/steamwar/schematicsystem/autocheck/AutoChecker8.java similarity index 78% rename from SchematicSystem_8/src/de/steamwar/schematicsystem/CheckSchemType8.java rename to SchematicSystem_8/src/de/steamwar/schematicsystem/autocheck/AutoChecker8.java index c5fa415..af24a28 100644 --- a/SchematicSystem_8/src/de/steamwar/schematicsystem/CheckSchemType8.java +++ b/SchematicSystem_8/src/de/steamwar/schematicsystem/autocheck/AutoChecker8.java @@ -1,7 +1,7 @@ -/* +/* This file is a part of the SteamWar software. - - Copyright (C) 2020 SteamWar.de-Serverteam + + Copyright (C) 2022 SteamWar.de-Serverteam This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by @@ -17,13 +17,14 @@ along with this program. If not, see . */ -package de.steamwar.schematicsystem; +package de.steamwar.schematicsystem.autocheck; import com.sk89q.jnbt.CompoundTag; import com.sk89q.worldedit.Vector; import com.sk89q.worldedit.blocks.BaseBlock; import com.sk89q.worldedit.extent.clipboard.Clipboard; import com.sk89q.worldedit.regions.Region; +import de.steamwar.schematicsystem.CheckSchemType; import org.bukkit.Material; import java.util.HashSet; @@ -31,7 +32,7 @@ import java.util.List; import java.util.Set; @SuppressWarnings("deprecation") -public class CheckSchemType8 implements CheckSchemType.ICheckSchemType { +public class AutoChecker8 implements AutoChecker.IAutoChecker { private static final int TNT = Material.TNT.getId(); private static final int SLIME = Material.SLIME_BLOCK.getId(); private static final int OBSIDIAN = Material.OBSIDIAN.getId(); @@ -68,13 +69,7 @@ public class CheckSchemType8 implements CheckSchemType.ICheckSchemType { FLOWERS = flowers; } - @Override - public void autoCheck(AutoCheckResult result, Clipboard clipboard) { - Vector dimensions = clipboard.getDimensions(); - result.setLength(dimensions.getBlockX()); - result.setHeight(dimensions.getBlockY()); - result.setWidth(dimensions.getBlockZ()); - + public void scan(AutoChecker.BlockScanResult result, Clipboard clipboard) { Region region = clipboard.getRegion(); Vector min = region.getMinimumPoint(); Vector max = region.getMaximumPoint(); @@ -86,30 +81,28 @@ public class CheckSchemType8 implements CheckSchemType.ICheckSchemType { final BaseBlock block = clipboard.getBlock(new Vector(x, y, z)); final int blockId = block.getId(); - result.checkMaterial(Material.getMaterial(blockId).name()); + result.getBlockCounts().merge(Material.getMaterial(blockId), 1, Integer::sum); if (blockId != AIR) blocks++; if(INVENTORY.contains(blockId)){ - checkInventory(result, block, blockId); + checkInventory(result, block, blockId, new BlockPos(x, y, z)); } } } } - - result.setBlocks(blocks); } - private static void checkInventory(AutoCheckResult result, BaseBlock block, int blockId) { + private static void checkInventory(AutoChecker.BlockScanResult result, BaseBlock block, int blockId, BlockPos pos) { CompoundTag nbt = block.getNbtData(); if(nbt == null){ - result.defunctNbt(Material.getMaterial(blockId).name()); + result.getDefunctNbt().add(pos); return; } if(blockId == JUKEBOX && nbt.getValue().containsKey("RecordItem")){ - result.foundRecord(); + result.getRecords().add(pos); return; } @@ -120,7 +113,7 @@ public class CheckSchemType8 implements CheckSchemType.ICheckSchemType { int counter = 0; for(CompoundTag item : items){ if(!item.containsKey("id")){ - result.defunctNbt(Material.getMaterial(blockId).name()); + result.getDefunctNbt().add(pos); continue; } @@ -136,12 +129,19 @@ public class CheckSchemType8 implements CheckSchemType.ICheckSchemType { if(blockId == DISPENSER && (itemType.equals(Material.FIREBALL) || itemType.equals(Material.ARROW))) counter += item.getByte("Count"); - else if(!FLOWERS.contains(itemType) && !(blockId == CHEST && itemType.equals(Material.TNT))) - result.foundForbiddenItem(Material.getMaterial(blockId).name(), itemType.name(), item.getByte("Count")); - else if(item.containsKey("tag")) - result.foundItemWithTag(Material.getMaterial(blockId).name(), itemType.name(), item.getByte("Count")); + else if(!FLOWERS.contains(itemType) && !(blockId == CHEST && itemType.equals(Material.TNT))) { + result.getForbiddenItems().computeIfAbsent(pos, blockPos -> new HashSet<>()).add(Material.getMaterial(blockId)); + } + else if(item.containsKey("tag")) { + result.getForbiddenNbt().computeIfAbsent(pos, blockPos -> new HashSet<>()).add(Material.getMaterial(blockId)); + } } - result.dispenserItems(counter); + result.getDispenserItems().put(pos, counter); + } + + @Override + public AutoChecker.BlockScanResult scan(Clipboard clipboard, CheckSchemType type) { + return null; } } diff --git a/SchematicSystem_Core/src/SchematicSystem.properties b/SchematicSystem_Core/src/SchematicSystem.properties index 5ffaa02..1a372a3 100644 --- a/SchematicSystem_Core/src/SchematicSystem.properties +++ b/SchematicSystem_Core/src/SchematicSystem.properties @@ -82,6 +82,8 @@ UTIL_SUBMIT_DIRECT=§eSubmit directly UTIL_SUBMIT_DIRECT_DONE=§aThe Schematic will be reviewed in a timely manner UTIL_SUBMIT_EXTEND=§eExtend Schematic UTIL_SUBMIT_EXTEND_DONE=§aThe preparation server is starting +UTIL_CHECK_TYPE_NOT_FOUND=§cThe type {0} was not found +UTIL_CHECK_SUCCESS=§aThe schematic was checked successfully COMMAND_INVALID_NODE=§cInvalid Schematic COMMAND_NOT_OWN=§cYou can only use this command on your own Schematic @@ -130,6 +132,14 @@ COMMAND_DELETE_MEMBER=§aYou have removed yourself from the Schematic COMMAND_DELETE_DIR=§aThe folder §e{0}§a is deleted... COMMAND_DELETE_DIR_FULL=§cThe folder must be empty to delete it COMMAND_DELETE_SCHEM=§aThe Schematic §e{0}§a is deleted... +COMMAND_CHECK_SELECTION_INCOMPLETE=§cThe selection is incomplete +COMMAND_CHECK_CLIPBOARD_EMPTY=§cThe clipboard is empty +COMMAND_FIX_OK=§aThe schematic is already fixed +COMMAND_FIX_DONE=§aThe schematic has been fixed +COMMAND_FIX_COULD_NOT_FIX=§cCould not fix this in the schematic +COMMAND_FIX_MANUAL=manually fix +COMMAND_FIX_ERROR=§cError while fixing the schematic, please contact a developer +COMMAND_FIX_WRONG_VERSION=§cThis feature is only available for version 1.15 and greater HELP_HEADER=§e§lSchematicSystem §8§lHelp HELP_VIEW=Find & Load @@ -141,6 +151,7 @@ HELP_VIEW_4=§8/§7schem §esearch §8[§7keyword§8] - §7Searches for matching HELP_VIEW_5=§8/§7schem §eload §8[§7schematic§8] - §7Loads a schematic HELP_VIEW_6=§8/§7schem §edownload §8[§7schematic§8] - §7Gives you a download link (valid for 1 min) HELP_VIEW_7=§8/§7download §8- §7Gives you a download link for your current clipboard (valid for 1 min) +HELP_VIEW_8=§8/§7schem §echeck §8[§7schematic§8|§7selection§8|§7clipboard§8] [§7schematictype§8] - §7Checks the schematic for errors HELP_EDIT=Save & Edit HELP_EDIT_HOVER=Modification of schematics and folders HELP_EDIT_1=§8/§7schem §esave §8[§7schematic§8] - §7Saves your clipboard as a schematic @@ -151,6 +162,7 @@ HELP_EDIT_5=§8/§7schem §echangetype §8[§7schematic§8] - §7Changes the typ HELP_EDIT_6=§8/§7schem §elockreplay §8[§7schematic§8] - §7Locks replays of the schematic HELP_EDIT_7=§8/§7schem §ereplacecolor §8[§7schematic§8] - §7Changes color substitution in the arena HELP_EDIT_8=§8/§7schem §edelete §8[§7schematic§8] - §7Deletes a schematic +HELP_EDIT_9=§8/§7schem §efix §8[§7schematictype§8] - §7Tries to fix the schematic in your clipboard HELP_SHARE=Ownership HELP_SHARE_HOVER=Share Schematics with others HELP_SHARE_1=§8/§7schem §eaddmember §8[§7schematic§8] §8[§7Spieler§8] - §7Adds a player to a schematic @@ -209,3 +221,19 @@ SAFE_NODE_INVALID_NAME=§cThis name is illegal SAFE_NODE_NOT_OWNER=§cYou are not the owner of this schematic DOWNLOAD_ERROR=§cAn error occurred while uploading the schematic + +AUTO_CHECKER_RESULT_HEADER=§7---=== (§eAuto-Check: {0}§7) ===--- +AUTO_CHECKER_RESULT_WIDTH =§7Width: §c{0}§7, Max: §e{1} +AUTO_CHECKER_RESULT_LENGTH=§7Length: §c{0}§7, Max: §e{1} +AUTO_CHECKER_RESULT_HEIGHT=§7Height: §c{0}§7, Max: §e{1} +AUTO_CHECKER_RESULT_BLOCKS=§7Blocks: §c{0}§7, Max: §e{1} +AUTO_CHECKER_RESULT_UNKNOWN_MATERIAL=§7Unknown block: §c{0} +AUTO_CHECKER_RESULT_TOO_MANY_BLOCK=§7{0}: §c{1}§7, Max: §e{2} +AUTO_CHECKER_RESULT_FORBIDDEN_BLOCK=§7Forbidden block: §c{0} +AUTO_CHECKER_RESULT_FORBIDDEN_ITEM=§7Forbidden Item: [{0}, {1}, {2}] -> §c{3} +AUTO_CHECKER_RESULT_DEFUNCT_NBT=§7Defunct NBT: §7[{0}, {1}, {2}] +AUTO_CHECKER_RESULT_RECORD=§7Record: §c[{0}, {1}, {2}] +AUTO_CHECKER_RESULT_TOO_MANY_DISPENSER_ITEMS=§7Dispenser: §c[{0}, {1}, {2}]§7, §c{3} §7items, Max: §e{4} +AUTO_CHECKER_RESULT_FORBIDDEN_ITEM_NBT=§7Forbidden Item NBT: [{0}, {1}, {2}] -> §c{3} +AUTO_CHECKER_RESULT_TELEPORT_HERE=§7Teleport to block +AUTO_CHECKER_RESULT_AFTER_DEADLINE=§cThe deadline has expired: {0} \ No newline at end of file diff --git a/SchematicSystem_Core/src/SchematicSystem_de.properties b/SchematicSystem_Core/src/SchematicSystem_de.properties index b45a613..66a1cae 100644 --- a/SchematicSystem_Core/src/SchematicSystem_de.properties +++ b/SchematicSystem_Core/src/SchematicSystem_de.properties @@ -117,6 +117,14 @@ COMMAND_DELETE_MEMBER=§aDu hast dich von der Schematic entfernt COMMAND_DELETE_DIR=§aDer Ordner §e{0}§a wird gelöscht... COMMAND_DELETE_DIR_FULL=§cDer Ordner muss leer sein, um ihn zu löschen COMMAND_DELETE_SCHEM=§aDie Schematic §e{0}§a wird gelöscht... +COMMAND_CHECK_SELECTION_INCOMPLETE=§cDeine Auswahl ist unvollständig +COMMAND_CHECK_CLIPBOARD_EMPTY=§cDein Clipboard ist leer +COMMAND_FIX_OK=§aDie Schematic ist bereits gefixt +COMMAND_FIX_DONE=§aDie Schematic wurde repariert +COMMAND_FIX_COULD_NOT_FIX=§cKonnte diese nicht sachen in der Schematic reparieren +COMMAND_FIX_MANUAL=Manuel Fixen +COMMAND_FIX_ERROR=§cFehler beim Fixen der Schematic, bitte kontaktiere einen Developer +COMMAND_FIX_WRONG_VERSION=§cDiese Funktion ist nur für Version 1.15 und höher verfügbar HELP_HEADER=§e§lSchematicSystem §8§lHilfe HELP_VIEW=Finden & Laden @@ -128,6 +136,7 @@ HELP_VIEW_4=§8/§7schem §esearch §8[§7Stichwort§8] - §7Sucht nach passende HELP_VIEW_5=§8/§7schem §eload §8[§7Schematic§8] - §7Lädt eine Schematic HELP_VIEW_6=§8/§7schem §edownload §8[§7Schematic§8] - §7Gibt dir einen Downloadlink (1 min gültig) HELP_VIEW_7=§8/§7download §8- §7Gibt dir einen Downloadlink von deinem Clipboard (1 min gültig) +HELP_VIEW_8=§8/§7schem §echeck §8[§7Schematic§8|§7selection§8|§7clipboard§8] [§7SchematicTyp§8] - §7Überprüft deine Schematic HELP_EDIT=Speichern & Bearbeiten HELP_EDIT_HOVER=Modifizierung von Schematics und Ordnern HELP_EDIT_1=§8/§7schem §esave §8[§7Schematic§8] - §7Speichert dein Clipboard als Schematic @@ -138,6 +147,7 @@ HELP_EDIT_5=§8/§7schem §echangetype §8[§7Schematic§8] - §7Ändert die Art HELP_EDIT_6=§8/§7schem §elockreplay §8[§7Schematic§8] - §7Sperrt Replays mit der Schematic HELP_EDIT_7=§8/§7schem §ereplacecolor §8[§7Schematic§8] - §7Ändert Farbersetzung in der Arena HELP_EDIT_8=§8/§7schem §edelete §8[§7Schematic§8] - §7Löscht eine Schematic +HELP_EDIT_9=§8/§7schem §efix §8[§7SchematicTyp§8] - §7Versucht die Schematic in deinem Clipboard konform zu machen HELP_SHARE=Besitzrechte HELP_SHARE_HOVER=Schematics mit anderen teilen HELP_SHARE_1=§8/§7schem §eaddmember §8[§7Schematic§8] §8[§7Spieler§8] - §7Fügt einen Spieler zu einer Schematic hinzu @@ -192,3 +202,19 @@ SAFE_NODE_INVALID_NAME=§cDieser Name ist unzulässig SAFE_NODE_NOT_OWNER=§cDu bist nicht der Besitzer dieser Schematic DOWNLOAD_ERROR=§cFehler beim Hochladen deines Clipboards + +AUTO_CHECKER_RESULT_HEADER=§7---=== (§eAutoPrüfer: {0}§7) ===--- +AUTO_CHECKER_RESULT_WIDTH=§7Breite: §c{0}§7, Max: §e{1} +AUTO_CHECKER_RESULT_LENGTH=§7Länge: §c{0}§7, Max: §e{1} +AUTO_CHECKER_RESULT_HEIGHT=§7Höhe: §c{0}§7, Max: §e{1} +AUTO_CHECKER_RESULT_BLOCKS=§7Blöcke: §c{0}§7, Max: §e{1} +AUTO_CHECKER_RESULT_UNKNOWN_MATERIAL=§7Unbekannter Block: §c{0} +AUTO_CHECKER_RESULT_TOO_MANY_BLOCK=§7{0}: §c{1}§7, Max: §e{2} +AUTO_CHECKER_RESULT_FORBIDDEN_BLOCK=§7Verbotener Block: §c{0} +AUTO_CHECKER_RESULT_FORBIDDEN_ITEM=§7Verbotener gegenstand: [{0}, {1}, {2}] -> §c{3} +AUTO_CHECKER_RESULT_DEFUNCT_NBT=§7Keine NBT-Daten: §c[{0}, {1}, {2}] +AUTO_CHECKER_RESULT_RECORD=§7Schallplatte: §c[{0}, {1}, {2}] +AUTO_CHECKER_RESULT_TOO_MANY_DISPENSER_ITEMS=§7Dispenser: §c[{0}, {1}, {2}]§7, §c{3} §7gegenstände, Max: §e{4} +AUTO_CHECKER_RESULT_FORBIDDEN_ITEM_NBT=§7Verbotene NBT-Daten: [{0}, {1}, {2}] -> §c{3} +AUTO_CHECKER_RESULT_TELEPORT_HERE=§7Zum block teleportieren +AUTO_CHECKER_RESULT_AFTER_DEADLINE=§cDer einsendeschluss ist bereits vorbei: {0} \ No newline at end of file diff --git a/SchematicSystem_Core/src/de/steamwar/schematicsystem/AutoCheckResult.java b/SchematicSystem_Core/src/de/steamwar/schematicsystem/AutoCheckResult.java deleted file mode 100644 index 994324e..0000000 --- a/SchematicSystem_Core/src/de/steamwar/schematicsystem/AutoCheckResult.java +++ /dev/null @@ -1,168 +0,0 @@ -/* - This file is a part of the SteamWar software. - - Copyright (C) 2020 SteamWar.de-Serverteam - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . -*/ - -package de.steamwar.schematicsystem; - -import java.util.*; - -public class AutoCheckResult { - - private final CheckSchemType type; - - private boolean errorLoadingSchematic = false; - - private int width = 0; - private int height = 0; - private int length = 0; - - private int blocks = 0; - - private final Map, Integer> limitedMaterials; - - private final Map defunctNbt = new HashMap<>(); // Amount of defect NBT-Blocks with material name - - private int records = 0; // Amount of found records - private final Map> forbiddenItems = new HashMap<>(); // Amount forbidden items per inventory block - private final Map> itemsWithTag = new HashMap<>(); // Amount of items with forbidden nbt tags - private int tooManyDispenserItems = 0; // Amount of dispensers with too many items - - public AutoCheckResult(CheckSchemType type) { - this.type = type; - this.limitedMaterials = type.getLimits(); - } - - public Map errors() { - Map errors = new HashMap<>(); - - if(errorLoadingSchematic) { - errors.put("AUTO_CHECK_RESULT_NOT_LOAD", new Object[0]); - } - - assert type != null; - // SW Quality Code, Check the Comments! - if(width > type.getDepth()) - // Width - errors.put("AUTO_CHECK_RESULT_TOO_WIDE", new Object[]{width, type.getDepth()}); - if(length > type.getWidth()) - // Length - errors.put("AUTO_CHECK_RESULT_TOO_LONG", new Object[]{width, type.getWidth()}); - if(height > type.getHeight()) - errors.put("AUTO_CHECK_RESULT_TOO_HIGH", new Object[]{height, type.getHeight()}); - - for(Map.Entry, Integer> entry : limitedMaterials.entrySet()) { - if(entry.getValue() < 0) { - errors.put((entry.getKey().size() == 1 ? "AUTO_CHECK_RESULT_TOO_MANY_BLOCK" : "AUTO_CHECK_RESULT_TOO_MANY_BLOCKS"), new Object[]{String.join(" ", entry.getKey()), -entry.getValue()}); - } - } - - if(type.getMaxBlocks() != 0 && blocks > type.getMaxBlocks()) { - errors.put("AUTO_CHECK_RESULT_TOO_MANY_ALL_BLOCKS", new Object[]{blocks, type.getMaxBlocks()}); - } - - if(records > 0) { - errors.put("AUTO_CHECK_RESULT_TOO_MANY_RECORDS", new Object[]{records}); - } - - for(Map.Entry> block : forbiddenItems.entrySet()) { - for (Map.Entry item : block.getValue().entrySet()) { - errors.put("AUTO_CHECK_RESULT_FORBIDDEN_ITEM", new Object[]{block.getKey(), item.getKey(), item.getValue()}); - } - } - for(Map.Entry> block : itemsWithTag.entrySet()) { - for (Map.Entry item : block.getValue().entrySet()) { - errors.put("AUTO_CHECK_RESULT_FORBIDDEN_ITEM_NBT", new Object[]{block.getKey(), item.getKey(), item.getValue()}); - } - } - if(tooManyDispenserItems == 1) { - errors.put("AUTO_CHECK_RESULT_TOO_MANY_DISPENSER_ITEMS", new Object[]{type.getMaxDispenserItems()}); - } - else if(tooManyDispenserItems > 1) { - errors.put("AUTO_CHECK_RESULT_TOO_MANY_DISPENSERS_ITEMS", new Object[]{tooManyDispenserItems, type.getMaxDispenserItems()}); - } - - return errors; - } - - public Map warnings(){ - Map warnings = new HashMap<>(); - - for(Map.Entry nbtBlock : defunctNbt.entrySet()){ - if(nbtBlock.getValue() > 1) { - warnings.put("AUTO_CHECK_RESULT_NBTS_WARNING", new Object[]{nbtBlock.getValue(), nbtBlock.getKey()}); - } else { - warnings.put("AUTO_CHECK_RESULT_NBT_WARNING", new Object[]{nbtBlock.getKey()}); - } - } - - return warnings; - } - - void setErrorLoadingSchematic(){ - errorLoadingSchematic = true; - } - - void setWidth(int width){ - this.width = width; - } - void setLength(int length){ - this.length = length; - } - void setHeight(int height){ - this.height = height; - } - - void setBlocks(int blocks) { - this.blocks = blocks; - } - - void checkMaterial(String name){ - for(Map.Entry, Integer> entry : limitedMaterials.entrySet()) { - if(entry.getKey().contains(name)) - entry.setValue(entry.getValue() - 1); - } - } - - void defunctNbt(String name){ - defunctNbt.compute(name, (k, v) -> v == null ? 1 : v+1); - } - void foundRecord(){ - records++; - } - void foundForbiddenItem(String material, String item, int count){ - forbiddenItems.compute(material, (k1, v) -> { - if(v == null) - v = new HashMap<>(); - v.compute(item, (k2, v2) -> v2 == null ? count : v2 + count); - return v; - }); - } - void foundItemWithTag(String material, String item, int count){ - itemsWithTag.compute(material, (k1, v) -> { - if(v == null) - v = new HashMap<>(); - v.compute(item, (k2, v2) -> v2 == null ? count : v2 + count); - return v; - }); - } - void dispenserItems(int counter){ - assert type != null; - if(counter > type.getMaxDispenserItems()) - tooManyDispenserItems++; - } -} diff --git a/SchematicSystem_Core/src/de/steamwar/schematicsystem/CheckSchemType.java b/SchematicSystem_Core/src/de/steamwar/schematicsystem/CheckSchemType.java index f57c958..769b692 100644 --- a/SchematicSystem_Core/src/de/steamwar/schematicsystem/CheckSchemType.java +++ b/SchematicSystem_Core/src/de/steamwar/schematicsystem/CheckSchemType.java @@ -19,24 +19,16 @@ package de.steamwar.schematicsystem; -import com.sk89q.worldedit.extent.clipboard.Clipboard; -import de.steamwar.core.VersionDependent; -import de.steamwar.sql.NoClipboardException; -import de.steamwar.sql.SchematicData; -import de.steamwar.sql.SchematicNode; import de.steamwar.sql.SchematicType; -import org.bukkit.Bukkit; import org.bukkit.configuration.ConfigurationSection; import org.bukkit.configuration.file.YamlConfiguration; import java.io.File; -import java.io.IOException; import java.text.DateFormat; import java.text.ParseException; import java.text.SimpleDateFormat; import java.time.Instant; import java.util.*; -import java.util.logging.Level; public class CheckSchemType { @@ -106,21 +98,6 @@ public class CheckSchemType { return types.get(type); } - public AutoCheckResult autoCheck(SchematicNode schematic) { - AutoCheckResult result = new AutoCheckResult(this); - Clipboard clipboard; - try { - clipboard = new SchematicData(schematic).load(); - } catch (IOException | NoClipboardException e) { - Bukkit.getLogger().log(Level.SEVERE, "Schematic could not be loaded", e); - result.setErrorLoadingSchematic(); - return result; - } - - impl.autoCheck(result, clipboard); - return result; - } - public int getWidth() { return width; } @@ -149,14 +126,7 @@ public class CheckSchemType { return deadline != null && deadline.before(Date.from(Instant.now())); } - public String getDeadline() { - return DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.SHORT, Locale.GERMAN).format(deadline); - } - - - public static final ICheckSchemType impl = VersionDependent.getVersionImpl(SchematicSystem.getInstance()); - - public interface ICheckSchemType { - void autoCheck(AutoCheckResult result, Clipboard clipboard); + public Date getDeadline() { + return deadline; } } diff --git a/SchematicSystem_Core/src/de/steamwar/schematicsystem/autocheck/AutoChecker.java b/SchematicSystem_Core/src/de/steamwar/schematicsystem/autocheck/AutoChecker.java new file mode 100644 index 0000000..4170828 --- /dev/null +++ b/SchematicSystem_Core/src/de/steamwar/schematicsystem/autocheck/AutoChecker.java @@ -0,0 +1,75 @@ +/* + This file is a part of the SteamWar software. + + Copyright (C) 2022 SteamWar.de-Serverteam + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . +*/ + +package de.steamwar.schematicsystem.autocheck; + +import com.sk89q.worldedit.extent.clipboard.Clipboard; +import de.steamwar.core.VersionDependent; +import de.steamwar.schematicsystem.CheckSchemType; +import de.steamwar.schematicsystem.SchematicSystem; +import lombok.Getter; +import lombok.ToString; +import org.bukkit.Material; + +import java.util.*; + +public class AutoChecker { + + public static AutoCheckerResult check(Clipboard clipboard, CheckSchemType type) { + BlockScanResult blockScanResult = impl.scan(clipboard, type); + return AutoCheckerResult.builder() + .type(type) + .height(clipboard.getDimensions().getBlockY()) + .width(clipboard.getDimensions().getBlockX()) + .depth(clipboard.getDimensions().getBlockZ()) + .blockCounts(blockScanResult.getBlockCounts()) + .defunctNbt(blockScanResult.getDefunctNbt()) + .dispenserItems(blockScanResult.getDispenserItems()) + .records(blockScanResult.getRecords()) + .forbiddenItems(blockScanResult.getForbiddenItems()) + .forbiddenNbt(blockScanResult.getForbiddenNbt()) + .build(); + } + + public static AutoCheckerResult sizeCheck(Clipboard clipboard, CheckSchemType type) { + return AutoCheckerResult.builder() + .type(type) + .height(clipboard.getDimensions().getBlockY()) + .width(clipboard.getDimensions().getBlockX()) + .depth(clipboard.getDimensions().getBlockZ()) + .build(); + } + + private static final IAutoChecker impl = VersionDependent.getVersionImpl(SchematicSystem.getInstance()); + + public interface IAutoChecker { + BlockScanResult scan(Clipboard clipboard, CheckSchemType type); + } + + @Getter + @ToString + public static class BlockScanResult { + private final Map blockCounts = new EnumMap<>(Material.class); + private final List defunctNbt = new ArrayList<>(); + private final List records = new ArrayList<>(); + private final Map dispenserItems = new HashMap<>(); + private final Map> forbiddenItems = new HashMap<>(); + private final Map> forbiddenNbt = new HashMap<>(); + } +} diff --git a/SchematicSystem_Core/src/de/steamwar/schematicsystem/autocheck/AutoCheckerResult.java b/SchematicSystem_Core/src/de/steamwar/schematicsystem/autocheck/AutoCheckerResult.java new file mode 100644 index 0000000..72054e1 --- /dev/null +++ b/SchematicSystem_Core/src/de/steamwar/schematicsystem/autocheck/AutoCheckerResult.java @@ -0,0 +1,159 @@ +/* + This file is a part of the SteamWar software. + + Copyright (C) 2022 SteamWar.de-Serverteam + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . +*/ + +package de.steamwar.schematicsystem.autocheck; + +import de.steamwar.schematicsystem.CheckSchemType; +import de.steamwar.schematicsystem.SchematicSystem; +import lombok.Builder; +import lombok.Getter; +import lombok.ToString; +import net.md_5.bungee.api.chat.ClickEvent; +import org.bukkit.Material; +import org.bukkit.entity.Player; + +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.Set; + +@Builder +@Getter +@ToString +public class AutoCheckerResult { + private final CheckSchemType type; + private final int width; + private final int height; + private final int depth; + private final Map blockCounts; + private final List defunctNbt; + private final Map dispenserItems; + private final List records; + private final Map> forbiddenItems; + private final Map> forbiddenNbt; + + public boolean isOk() { + return records.isEmpty() && + forbiddenItems.isEmpty() && + forbiddenNbt.isEmpty() && + isSizeOk() && + isBlockCountOk() && + isLimitedBlocksOK() && + isDispenserItemsOK() && + !type.isAfterDeadline(); + } + + public boolean fastOk() { + return isSizeOk() && + !type.isAfterDeadline(); + } + + public boolean isDispenserItemsOK() { + return dispenserItems.values().stream().allMatch(i -> i <= type.getMaxDispenserItems()); + } + + public boolean hasWarnings() { + return defunctNbt.isEmpty(); + } + + public boolean isSizeOk() { + return !isTooWide() && !isTooHigh() && !isTooDeep(); + } + + public boolean isTooWide() { + return width > type.getWidth(); + } + + public boolean isTooHigh() { + return height > type.getHeight(); + } + + public boolean isTooDeep() { + return depth > type.getDepth(); + } + + public boolean isBlockCountOk() { + return type.getMaxBlocks() == 0 || blockCounts.values().stream().reduce(Integer::sum).map(i -> i <= type.getMaxBlocks()).orElse(false); + } + + public boolean isLimitedBlocksOK() { + try { + return type.getLimits().entrySet().stream() + .map(setIntegerEntry -> setIntegerEntry.getKey().stream().map(Material::getMaterial).map(blockCounts::get).map(i -> i == null || i <= setIntegerEntry.getValue()).reduce(Boolean::logicalAnd).orElse(false)) + .reduce(Boolean::logicalAnd).orElse(true); + } catch (NullPointerException e) { + return false; + } + } + + public void sendErrorMessage(Player p, String schemName) { + SchematicSystem.MESSAGE.sendPrefixless("AUTO_CHECKER_RESULT_HEADER", p, schemName); + if(isTooWide()) SchematicSystem.MESSAGE.sendPrefixless("AUTO_CHECKER_RESULT_WIDTH", p, width, type.getWidth()); + if(isTooHigh()) SchematicSystem.MESSAGE.sendPrefixless("AUTO_CHECKER_RESULT_HEIGHT", p, height, type.getHeight()); + if(isTooDeep()) SchematicSystem.MESSAGE.sendPrefixless("AUTO_CHECKER_RESULT_LENGTH", p, depth, type.getDepth()); + if(type.getMaxBlocks() != 0 && !isBlockCountOk()) { + SchematicSystem.MESSAGE.sendPrefixless("AUTO_CHECKER_RESULT_BLOCKS", p, blockCounts.values().stream().reduce(Integer::sum).orElse(0), type.getMaxBlocks()); + } + if(!isLimitedBlocksOK()) { + type.getLimits().forEach((strings, integer) -> { + for (String string : strings) { + Material mat = Material.matchMaterial(string); + if(mat != null && blockCounts.getOrDefault(mat, 0) > integer) { + if(integer == 0) { + SchematicSystem.MESSAGE.sendPrefixless("AUTO_CHECKER_RESULT_FORBIDDEN_BLOCK", p, mat.name()); + } else { + SchematicSystem.MESSAGE.sendPrefixless("AUTO_CHECKER_RESULT_TOO_MANY_BLOCK", p, mat.name(), blockCounts.getOrDefault(mat, 0), integer); + } + } + } + }); + } + dispenserItems.entrySet().stream().filter(blockVector3IntegerEntry -> blockVector3IntegerEntry.getValue() > type.getMaxDispenserItems()).forEach(blockVector3IntegerEntry -> { + SchematicSystem.MESSAGE.sendPrefixless("AUTO_CHECKER_RESULT_TOO_MANY_DISPENSER_ITEMS", p, SchematicSystem.MESSAGE.parse("AUTO_CHECKER_RESULT_TELEPORT_HERE", p), tpCommandTo(blockVector3IntegerEntry.getKey()), + blockVector3IntegerEntry.getKey().getBlockX(), + blockVector3IntegerEntry.getKey().getBlockY(), + blockVector3IntegerEntry.getKey().getBlockZ(), + blockVector3IntegerEntry.getValue(), + type.getMaxDispenserItems()); + }); + records.forEach(blockVector3 -> { + SchematicSystem.MESSAGE.sendPrefixless("AUTO_CHECKER_RESULT_RECORD", p, SchematicSystem.MESSAGE.parse("AUTO_CHECKER_RESULT_TELEPORT_HERE", p), tpCommandTo(blockVector3), blockVector3.getBlockX(), blockVector3.getBlockY(), blockVector3.getBlockZ()); + }); + forbiddenItems.forEach((blockVector3, materials) -> { + SchematicSystem.MESSAGE.sendPrefixless("AUTO_CHECKER_RESULT_FORBIDDEN_ITEM", p, SchematicSystem.MESSAGE.parse("AUTO_CHECKER_RESULT_TELEPORT_HERE", p), tpCommandTo(blockVector3), blockVector3.getX(), blockVector3.getY(), blockVector3.getZ(), setToString(materials)); + }); + forbiddenNbt.forEach((blockVector3, materials) -> { + SchematicSystem.MESSAGE.sendPrefixless("AUTO_CHECKER_RESULT_FORBIDDEN_ITEM_NBT", p, SchematicSystem.MESSAGE.parse("AUTO_CHECKER_RESULT_TELEPORT_HERE", p), tpCommandTo(blockVector3), blockVector3.getX(), blockVector3.getY(), blockVector3.getZ(), setToString(materials)); + }); + defunctNbt.forEach(blockVector3 -> { + SchematicSystem.MESSAGE.sendPrefixless("AUTO_CHECKER_RESULT_DEFUNCT_NBT", p, SchematicSystem.MESSAGE.parse("AUTO_CHECKER_RESULT_TELEPORT_HERE", p), tpCommandTo(blockVector3), blockVector3.getX(), blockVector3.getY(), blockVector3.getZ()); + }); + if(type.isAfterDeadline()) { + SchematicSystem.MESSAGE.sendPrefixless("AUTO_CHECKER_RESULT_AFTER_DEADLINE", p, type.getDeadline()); + } + } + + private static ClickEvent tpCommandTo(BlockPos pos) { + return new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/tp " + pos.getBlockX() + " " + pos.getBlockY() + " " + pos.getBlockZ()); + } + + private static String setToString(Collection set) { + return set.stream().map(material -> material.getKey().getKey()).reduce((s, s2) -> s + "§7, §c" + s2).orElse(""); + } +} diff --git a/SchematicSystem_Core/src/de/steamwar/schematicsystem/autocheck/BlockPos.java b/SchematicSystem_Core/src/de/steamwar/schematicsystem/autocheck/BlockPos.java new file mode 100644 index 0000000..7dff0db --- /dev/null +++ b/SchematicSystem_Core/src/de/steamwar/schematicsystem/autocheck/BlockPos.java @@ -0,0 +1,50 @@ +/* + This file is a part of the SteamWar software. + + Copyright (C) 2022 SteamWar.de-Serverteam + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . +*/ + +package de.steamwar.schematicsystem.autocheck; + +import lombok.AllArgsConstructor; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.ToString; + +/* + * Can be removed with 1.12 support removal + */ +@Getter +@AllArgsConstructor +@ToString +@EqualsAndHashCode +public class BlockPos { + private int x; + private int y; + private int z; + + public int getBlockX() { + return x; + } + + public int getBlockY() { + return y; + } + + public int getBlockZ() { + return z; + } +} diff --git a/SchematicSystem_Core/src/de/steamwar/schematicsystem/commands/GUI.java b/SchematicSystem_Core/src/de/steamwar/schematicsystem/commands/GUI.java index 2262dd1..0dbfc95 100644 --- a/SchematicSystem_Core/src/de/steamwar/schematicsystem/commands/GUI.java +++ b/SchematicSystem_Core/src/de/steamwar/schematicsystem/commands/GUI.java @@ -19,18 +19,23 @@ package de.steamwar.schematicsystem.commands; +import com.sk89q.worldedit.extent.clipboard.Clipboard; import de.steamwar.core.Core; import de.steamwar.inventory.*; +import de.steamwar.schematicsystem.CheckSchemType; import de.steamwar.schematicsystem.SafeSchematicNode; import de.steamwar.schematicsystem.SchematicSystem; +import de.steamwar.schematicsystem.autocheck.AutoChecker; import de.steamwar.sql.*; import org.bukkit.Bukkit; import org.bukkit.Material; import org.bukkit.entity.Player; import org.bukkit.event.inventory.ClickType; +import java.io.IOException; import java.util.*; import java.util.concurrent.atomic.AtomicBoolean; +import java.util.stream.Collectors; import static de.steamwar.schematicsystem.commands.SchematicCommandUtils.*; @@ -199,17 +204,17 @@ public class GUI { } static void changeType(Player p, SchematicNode schem){ - List> types = new LinkedList<>(); - for(SchematicType type : SchematicType.values()){ - if(!type.isAssignable()) - continue; + Clipboard clipboard = null; + try { + clipboard = new SchematicData(schem).load(); + } catch (IOException ignored) { } - SWItem item = new SWItem(SWItem.getMaterial(type.getMaterial()), type.name()); - if(type.fightType()) - item.setEnchanted(true); - - types.add(new SWListInv.SWListEntry<>(item, type)); - } + Clipboard finalClipboard = clipboard; + List> types = SchematicType.values().parallelStream() + .filter(SchematicType::isAssignable) + .filter(type -> finalClipboard == null || CheckSchemType.get(type) == null || AutoChecker.sizeCheck(finalClipboard, CheckSchemType.get(type)).fastOk()) + .map(type -> new SWListInv.SWListEntry<>(new SWItem(SWItem.getMaterial(type.getMaterial()), type.name(), Collections.emptyList(), type.fightType(), null), type)) + .collect(Collectors.toList()); SWListInv inv = new SWListInv<>(p, SchematicSystem.MESSAGE.parse("GUI_CHANGE_TYPE", p), types, (clickType, schematicType) -> { p.closeInventory(); diff --git a/SchematicSystem_Core/src/de/steamwar/schematicsystem/commands/SchematicCommand.java b/SchematicSystem_Core/src/de/steamwar/schematicsystem/commands/SchematicCommand.java index 15d3aed..d347a21 100644 --- a/SchematicSystem_Core/src/de/steamwar/schematicsystem/commands/SchematicCommand.java +++ b/SchematicSystem_Core/src/de/steamwar/schematicsystem/commands/SchematicCommand.java @@ -19,12 +19,25 @@ package de.steamwar.schematicsystem.commands; +import com.sk89q.worldedit.*; +import com.sk89q.worldedit.bukkit.BukkitPlayer; +import com.sk89q.worldedit.bukkit.BukkitWorld; +import com.sk89q.worldedit.extent.clipboard.BlockArrayClipboard; +import com.sk89q.worldedit.extent.clipboard.Clipboard; +import com.sk89q.worldedit.function.operation.ForwardExtentCopy; +import com.sk89q.worldedit.function.operation.Operations; +import com.sk89q.worldedit.session.ClipboardHolder; import de.steamwar.command.*; +import de.steamwar.core.Core; +import de.steamwar.core.VersionDependent; import de.steamwar.inventory.SWAnvilInv; import de.steamwar.inventory.SchematicSelector; import de.steamwar.providers.BauServerInfo; +import de.steamwar.schematicsystem.CheckSchemType; import de.steamwar.schematicsystem.SafeSchematicNode; import de.steamwar.schematicsystem.SchematicSystem; +import de.steamwar.schematicsystem.autocheck.AutoChecker; +import de.steamwar.schematicsystem.autocheck.AutoCheckerResult; import de.steamwar.sql.*; import net.md_5.bungee.api.ChatColor; import net.md_5.bungee.api.chat.ClickEvent; @@ -35,6 +48,7 @@ import org.bukkit.Material; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; +import java.io.IOException; import java.time.Instant; import java.util.*; import java.util.function.Function; @@ -378,14 +392,24 @@ public class SchematicCommand extends SWCommand { SteamwarUser user = getUser(player); TextComponent base = new TextComponent(); - SchematicType.values().forEach(type -> { - if (!type.isAssignable()) return; + Clipboard clipboard = null; + try { + clipboard = new SchematicData(node).load(); + } catch (IOException ignored) { } + Clipboard finalClipboard = clipboard; + + String breadcrumb = node.generateBreadcrumbs(user); + + SchematicType.values().parallelStream() + .filter(SchematicType::isAssignable) + .filter(type -> finalClipboard == null || CheckSchemType.get(type) == null || AutoChecker.sizeCheck(finalClipboard, CheckSchemType.get(type)).fastOk()) + .forEachOrdered(type -> { TextComponent component = new TextComponent(type.name() + " "); component.setColor(ChatColor.GRAY); component.setBold(true); component.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, TextComponent.fromLegacyText(SchematicSystem.MESSAGE.parse("COMMAND_CHANGE_TYPE_SELECT", player)))); - component.setClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/schem changetype " + node.generateBreadcrumbs(user) + " " + type.name())); + component.setClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/schem changetype " + breadcrumb + " " + type.name())); base.addExtra(component); }); @@ -547,6 +571,74 @@ public class SchematicCommand extends SWCommand { } } + @Register("check") + public void checkCommand(Player player, @Validator("isOwnerSchematicValidator") SchematicNode node, CheckSchemType type) { + try { + check(player, new SchematicData(node).load(), type, node.getName(), false); + } catch (IOException e) { + SchematicSystem.MESSAGE.send("UTIL_LOAD_ERROR", player); + } + } + + @Register(value = {"check", "clipboard"}) + public void checkClipboardCommand(Player player, @ErrorMessage("UTIL_CHECK_TYPE_NOT_FOUND") CheckSchemType type) { + try { + check(player, WorldEdit.getInstance().getSessionManager().get(new BukkitPlayer(player)).getClipboard().getClipboard(), type, "clipboard", false); + } catch (EmptyClipboardException e) { + SchematicSystem.MESSAGE.send("COMMAND_CHECK_CLIPBOARD_EMPTY", player); + } + } + + @Register(value = {"check", "selection"}) + public void checkSelectionCommand(Player player, @ErrorMessage("UTIL_CHECK_TYPE_NOT_FOUND") CheckSchemType type) { + try { + Clipboard clipboard = new BlockArrayClipboard(WorldEdit.getInstance().getSessionManager().get(new BukkitPlayer(player)).getSelection(new BukkitWorld(player.getWorld()))); + EditSession editSession = WorldEdit.getInstance().getEditSessionFactory().getEditSession(new BukkitWorld(player.getWorld()), -1); + + Operations.complete(new ForwardExtentCopy(editSession, clipboard.getRegion(), clipboard, clipboard.getMinimumPoint())); + + check(player, clipboard, type, "selection", false); + } catch (IncompleteRegionException e) { + SchematicSystem.MESSAGE.send("COMMAND_CHECK_SELECTION_INCOMPLETE", player); + } catch (WorldEditException e) { + SchematicSystem.MESSAGE.send("COMMAND_SAVE_ERROR", player); + } + } + + @Register("fix") + public void fixSchematicCommand(Player player, @ErrorMessage("UTIL_CHECK_TYPE_NOT_FOUND") CheckSchemType type) { + if(Core.getVersion() < 15) { + SchematicSystem.MESSAGE.send("COMMAND_FIX_WRONG_VERSION", player); + return; + } + Clipboard clipboard; + try { + clipboard = WorldEdit.getInstance().getSessionManager().get(new BukkitPlayer(player)).getClipboard().getClipboard(); + } catch (EmptyClipboardException e) { + SchematicSystem.MESSAGE.send("COMMAND_CHECK_CLIPBOARD_EMPTY", player); + return; + } + AutoCheckerResult result = AutoChecker.check(clipboard, type); + if(result.isOk()) { + SchematicSystem.MESSAGE.send("COMMAND_FIX_OK", player); + return; + } + try { + clipboard = impl.fixClipboard(clipboard, result, type); + WorldEdit.getInstance().getSessionManager().get(new BukkitPlayer(player)).setClipboard(new ClipboardHolder(clipboard)); + AutoCheckerResult after = AutoChecker.check(clipboard, type); + if(after.isOk()) { + SchematicSystem.MESSAGE.send("COMMAND_FIX_DONE", player); + } else { + after.sendErrorMessage(player, SchematicSystem.MESSAGE.parse("COMMAND_FIX_MANUAL", player)); + SchematicSystem.MESSAGE.send("COMMAND_FIX_COULD_NOT_FIX", player); + } + } catch (Exception e) { + SchematicSystem.MESSAGE.send("COMMAND_FIX_ERROR", player); + SchematicSystem.getInstance().getLogger().log(Level.SEVERE, e.getMessage(), e); + } + } + @Register(value = "page", noTabComplete = true) public void pageCommand(Player player, int page) { cachedSchemList(player, page); @@ -673,6 +765,21 @@ public class SchematicCommand extends SWCommand { }; } + @ClassMapper(value = CheckSchemType.class, local = true) + public TypeMapper checkSchemTypeTypeMapper() { + return new TypeMapper() { + @Override + public Collection tabCompletes(CommandSender commandSender, String[] strings, String s) { + return SchematicType.values().stream().filter(type -> CheckSchemType.get(type) != null).map(SchematicType::name).collect(Collectors.toList()); + } + + @Override + public CheckSchemType map(CommandSender commandSender, String[] previousArguments, String s) { + return SchematicType.values().stream().filter(type -> type.name().equalsIgnoreCase(s)).map(CheckSchemType::get).findAny().orElse(null); + } + }; + } + @Mapper(value = "searchMapper", local = true) public TypeMapper searchTypeMapper() { return new TypeMapper() { @@ -783,4 +890,10 @@ public class SchematicCommand extends SWCommand { AUSFAHREN, NORMAL } + + private static final ISchematicCommand impl = VersionDependent.getVersionImpl(SchematicSystem.getInstance()); + + public static interface ISchematicCommand { + Clipboard fixClipboard(Clipboard clipboard, AutoCheckerResult result, CheckSchemType type) throws Exception; + } } diff --git a/SchematicSystem_Core/src/de/steamwar/schematicsystem/commands/SchematicCommandHelp.java b/SchematicSystem_Core/src/de/steamwar/schematicsystem/commands/SchematicCommandHelp.java index f843dfc..0490e01 100644 --- a/SchematicSystem_Core/src/de/steamwar/schematicsystem/commands/SchematicCommandHelp.java +++ b/SchematicSystem_Core/src/de/steamwar/schematicsystem/commands/SchematicCommandHelp.java @@ -56,7 +56,8 @@ public class SchematicCommandHelp { "HELP_VIEW_4", "HELP_VIEW_5", "HELP_VIEW_6", - "HELP_VIEW_7" + "HELP_VIEW_7", + "HELP_VIEW_8" }), BEARBEITUNG("HELP_EDIT", "HELP_EDIT_HOVER", new String[]{ "HELP_EDIT_1", @@ -66,7 +67,8 @@ public class SchematicCommandHelp { "HELP_EDIT_5", "HELP_EDIT_6", "HELP_EDIT_7", - "HELP_EDIT_8" + "HELP_EDIT_8", + "HELP_EDIT_9" }), MEMBER("HELP_SHARE", "HELP_SHARE_HOVER", new String[]{ "HELP_SHARE_1", diff --git a/SchematicSystem_Core/src/de/steamwar/schematicsystem/commands/SchematicCommandUtils.java b/SchematicSystem_Core/src/de/steamwar/schematicsystem/commands/SchematicCommandUtils.java index 297835e..de38e56 100644 --- a/SchematicSystem_Core/src/de/steamwar/schematicsystem/commands/SchematicCommandUtils.java +++ b/SchematicSystem_Core/src/de/steamwar/schematicsystem/commands/SchematicCommandUtils.java @@ -19,14 +19,16 @@ package de.steamwar.schematicsystem.commands; +import com.sk89q.worldedit.extent.clipboard.Clipboard; import de.steamwar.inventory.SWInventory; import de.steamwar.inventory.SWItem; import de.steamwar.network.NetworkSender; import de.steamwar.network.packets.client.PrepareSchemPacket; import de.steamwar.providers.BauServerInfo; -import de.steamwar.schematicsystem.AutoCheckResult; import de.steamwar.schematicsystem.CheckSchemType; import de.steamwar.schematicsystem.SchematicSystem; +import de.steamwar.schematicsystem.autocheck.AutoChecker; +import de.steamwar.schematicsystem.autocheck.AutoCheckerResult; import de.steamwar.sql.*; import lombok.AllArgsConstructor; import lombok.Builder; @@ -40,6 +42,7 @@ import net.md_5.bungee.api.chat.TextComponent; import org.bukkit.Bukkit; import org.bukkit.entity.Player; +import java.io.IOException; import java.util.*; import java.util.function.IntFunction; import java.util.function.UnaryOperator; @@ -302,6 +305,15 @@ public class SchematicCommandUtils { } } + public static void check(Player player, Clipboard clipboard, CheckSchemType type, String schemName, boolean gui) { + AutoCheckerResult result = AutoChecker.check(clipboard, type); + if(!result.isOk()) { + result.sendErrorMessage(player, schemName); + } else { + SchematicSystem.MESSAGE.send("UTIL_CHECK_SUCCESS", player, schemName); + } + } + public static SchematicNode mkdirs(String[] layers, SteamwarUser user, int minus) { SchematicNode currentNode = null; for (int i = 0; i < layers.length - minus; i++) { @@ -430,16 +442,17 @@ public class SchematicCommandUtils { return; } - AutoCheckResult result = checkSchemType.autoCheck(node); - Map errors = result.errors(); - for (Map.Entry warning : result.warnings().entrySet()) { - SchematicSystem.MESSAGE.sendPrefixless(warning.getKey(), player, warning.getValue()); + AutoCheckerResult result = null; + try { + result = AutoChecker.check(new SchematicData(node).load(), checkSchemType); + } catch (IOException e) { + SchematicSystem.MESSAGE.send("UTIL_LOAD_ERROR", player); + SchematicSystem.getInstance().getLogger().throwing(SchematicCommandUtils.class.getName(), "changeType", e); + return; } - for (Map.Entry error : errors.entrySet()) { - SchematicSystem.MESSAGE.sendPrefixless(error.getKey(), player, error.getValue()); - } - if (!errors.isEmpty()) { + if (!result.isOk()) { SchematicSystem.MESSAGE.send("UTIL_TYPE_ERROR", player); + result.sendErrorMessage(player, node.getName()); return; } diff --git a/build.gradle b/build.gradle index b8b1983..2acfd58 100644 --- a/build.gradle +++ b/build.gradle @@ -82,7 +82,6 @@ mainClassName = '' allprojects { repositories { mavenCentral() - jcenter() maven { url = uri("https://repo.codemc.io/repository/maven-snapshots/")