From fd66be9b370ffad5c3a92624af3a9134afac30b5 Mon Sep 17 00:00:00 2001 From: Chaoscaot Date: Sun, 20 Nov 2022 23:56:43 +0100 Subject: [PATCH] Early AutoChecker Version --- .../AutoChecker15.java} | 91 ++++------ .../AutoChecker8.java} | 63 +++---- .../src/SchematicSystem.properties | 15 ++ .../src/SchematicSystem_de.properties | 15 ++ .../schematicsystem/AutoCheckResult.java | 168 ------------------ .../schematicsystem/CheckSchemType.java | 31 +--- .../autocheck/AutoChecker.java | 54 ++++++ .../autocheck/AutoCheckerResult.java | 138 ++++++++++++++ .../schematicsystem/autocheck/BlockPos.java | 27 +++ .../schematicsystem/commands/GUI.java | 25 +-- .../commands/SchematicCommand.java | 20 ++- .../commands/SchematicCommandUtils.java | 21 ++- build.gradle | 1 - 13 files changed, 350 insertions(+), 319 deletions(-) rename SchematicSystem_15/src/de/steamwar/schematicsystem/{CheckSchemType15.java => autocheck/AutoChecker15.java} (51%) rename SchematicSystem_8/src/de/steamwar/schematicsystem/{CheckSchemType8.java => autocheck/AutoChecker8.java} (66%) delete mode 100644 SchematicSystem_Core/src/de/steamwar/schematicsystem/AutoCheckResult.java create mode 100644 SchematicSystem_Core/src/de/steamwar/schematicsystem/autocheck/AutoChecker.java create mode 100644 SchematicSystem_Core/src/de/steamwar/schematicsystem/autocheck/AutoCheckerResult.java create mode 100644 SchematicSystem_Core/src/de/steamwar/schematicsystem/autocheck/BlockPos.java diff --git a/SchematicSystem_15/src/de/steamwar/schematicsystem/CheckSchemType15.java b/SchematicSystem_15/src/de/steamwar/schematicsystem/autocheck/AutoChecker15.java similarity index 51% rename from SchematicSystem_15/src/de/steamwar/schematicsystem/CheckSchemType15.java rename to SchematicSystem_15/src/de/steamwar/schematicsystem/autocheck/AutoChecker15.java index e0640c9..dc65441 100644 --- a/SchematicSystem_15/src/de/steamwar/schematicsystem/CheckSchemType15.java +++ b/SchematicSystem_15/src/de/steamwar/schematicsystem/autocheck/AutoChecker15.java @@ -1,36 +1,18 @@ -/* - 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; +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, @@ -85,48 +67,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 +112,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 +120,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_8/src/de/steamwar/schematicsystem/CheckSchemType8.java b/SchematicSystem_8/src/de/steamwar/schematicsystem/autocheck/AutoChecker8.java similarity index 66% rename from SchematicSystem_8/src/de/steamwar/schematicsystem/CheckSchemType8.java rename to SchematicSystem_8/src/de/steamwar/schematicsystem/autocheck/AutoChecker8.java index c5fa415..2f0bc8a 100644 --- a/SchematicSystem_8/src/de/steamwar/schematicsystem/CheckSchemType8.java +++ b/SchematicSystem_8/src/de/steamwar/schematicsystem/autocheck/AutoChecker8.java @@ -1,29 +1,11 @@ -/* - 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; +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 +13,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 +50,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 +62,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 +94,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 +110,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..2cdb525 100644 --- a/SchematicSystem_Core/src/SchematicSystem.properties +++ b/SchematicSystem_Core/src/SchematicSystem.properties @@ -209,3 +209,18 @@ 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}: {1}{2}§7, Max: §e{3} +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..0ebf891 100644 --- a/SchematicSystem_Core/src/SchematicSystem_de.properties +++ b/SchematicSystem_Core/src/SchematicSystem_de.properties @@ -192,3 +192,18 @@ 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_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 257c466..961f122 100644 --- a/SchematicSystem_Core/src/de/steamwar/schematicsystem/CheckSchemType.java +++ b/SchematicSystem_Core/src/de/steamwar/schematicsystem/CheckSchemType.java @@ -21,21 +21,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.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 { @@ -105,21 +100,6 @@ public class CheckSchemType { return types.get(type); } - public AutoCheckResult autoCheck(SchematicNode schematic) { - AutoCheckResult result = new AutoCheckResult(this); - Clipboard clipboard; - try { - clipboard = 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; } @@ -148,14 +128,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..a65ee8c --- /dev/null +++ b/SchematicSystem_Core/src/de/steamwar/schematicsystem/autocheck/AutoChecker.java @@ -0,0 +1,54 @@ +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 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 + 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..78070f2 --- /dev/null +++ b/SchematicSystem_Core/src/de/steamwar/schematicsystem/autocheck/AutoCheckerResult.java @@ -0,0 +1,138 @@ +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.getMaterial(string); + if(mat == null) { + SchematicSystem.MESSAGE.sendPrefixless("AUTO_CHECKER_RESULT_UNKNOWN_MATERIAL", p, string); + } else if(blockCounts.getOrDefault(mat, 0) > integer) { + SchematicSystem.MESSAGE.sendPrefixless("AUTO_CHECKER_RESULT_TOO_MANY_BLOCK", p, mat.name()); + } + } + }); + } + dispenserItems.entrySet().stream().filter(blockVector3IntegerEntry -> blockVector3IntegerEntry.getValue() > type.getMaxBlocks()).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..3880549 --- /dev/null +++ b/SchematicSystem_Core/src/de/steamwar/schematicsystem/autocheck/BlockPos.java @@ -0,0 +1,27 @@ +package de.steamwar.schematicsystem.autocheck; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +/* + * Can be removed with 1.12 support removal + */ +@Getter +@AllArgsConstructor +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 35c771c..21ae020 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(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(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 e21ee72..eea2a6c 100644 --- a/SchematicSystem_Core/src/de/steamwar/schematicsystem/commands/SchematicCommand.java +++ b/SchematicSystem_Core/src/de/steamwar/schematicsystem/commands/SchematicCommand.java @@ -19,12 +19,15 @@ package de.steamwar.schematicsystem.commands; +import com.sk89q.worldedit.extent.clipboard.Clipboard; import de.steamwar.command.*; 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.sql.*; import net.md_5.bungee.api.ChatColor; import net.md_5.bungee.api.chat.ClickEvent; @@ -35,6 +38,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 +382,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); }); diff --git a/SchematicSystem_Core/src/de/steamwar/schematicsystem/commands/SchematicCommandUtils.java b/SchematicSystem_Core/src/de/steamwar/schematicsystem/commands/SchematicCommandUtils.java index 4bfbe9c..2019f32 100644 --- a/SchematicSystem_Core/src/de/steamwar/schematicsystem/commands/SchematicCommandUtils.java +++ b/SchematicSystem_Core/src/de/steamwar/schematicsystem/commands/SchematicCommandUtils.java @@ -24,9 +24,10 @@ 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 +41,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; @@ -430,16 +432,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/")