diff --git a/SchematicSystem/SchematicSystem_21/build.gradle.kts b/SchematicSystem/SchematicSystem_21/build.gradle.kts new file mode 100644 index 00000000..2654c5b7 --- /dev/null +++ b/SchematicSystem/SchematicSystem_21/build.gradle.kts @@ -0,0 +1,37 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2025 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 . + */ + +plugins { + steamwar.java +} + +dependencies { + compileOnly(project(":SpigotCore", "default")) + compileOnly(project(":SchematicSystem:SchematicSystem_Core", "default")) + + compileOnly(libs.paperapi21) { + attributes { + // Very Hacky, but it works + attribute(TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE, 21) + } + } + + compileOnly(libs.nms21) + compileOnly(libs.fawe21) +} diff --git a/SchematicSystem/SchematicSystem_21/src/de/steamwar/schematicsystem/autocheck/AutoChecker21.java b/SchematicSystem/SchematicSystem_21/src/de/steamwar/schematicsystem/autocheck/AutoChecker21.java new file mode 100644 index 00000000..e2b43bce --- /dev/null +++ b/SchematicSystem/SchematicSystem_21/src/de/steamwar/schematicsystem/autocheck/AutoChecker21.java @@ -0,0 +1,137 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2026 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.jnbt.CompoundTag; +import com.sk89q.worldedit.entity.Entity; +import com.sk89q.worldedit.extent.clipboard.Clipboard; +import com.sk89q.worldedit.math.BlockVector3; +import com.sk89q.worldedit.world.block.BaseBlock; +import de.steamwar.core.Core; +import de.steamwar.sql.GameModeConfig; +import org.bukkit.Material; + +import java.util.*; +import java.util.stream.Collectors; + +public class AutoChecker21 implements AutoChecker.IAutoChecker { + + public AutoChecker.BlockScanResult scan(Clipboard clipboard, GameModeConfig 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++) { + final BaseBlock block = clipboard.getFullBlock(BlockVector3.at(x, y, z)); + final Material material = Material.matchMaterial(block.getBlockType().getId()); + if (material == null) { + continue; + } + + result.getBlockCounts().merge(material, 1, Integer::sum); + + if (AutoCheckerItems.impl.getInventoryMaterials().contains(material)) { + checkInventory(result, block, material, new BlockPos(x, y, z), type); + } + + if (x == min.getBlockX() || x == max.getBlockX() || y == max.getBlockY() || z == min.getBlockZ() || z == max.getBlockZ()) { + result.getDesignBlocks().computeIfAbsent(material, m -> new ArrayList<>()).add(new BlockPos(x, y, z)); + } + } + } + } + return result; + } + + private static final Map> itemsInInv = new EnumMap<>(Material.class); + + static { + itemsInInv.put(Material.BUCKET, EnumSet.of(Material.DISPENSER)); + itemsInInv.put(Material.TNT, EnumSet.of(Material.CHEST, Material.BARREL, Material.SHULKER_BOX, Material.BLACK_SHULKER_BOX, Material.BLUE_SHULKER_BOX, + Material.BROWN_SHULKER_BOX, Material.CYAN_SHULKER_BOX, Material.GRAY_SHULKER_BOX, Material.GREEN_SHULKER_BOX, Material.LIGHT_BLUE_SHULKER_BOX, + Material.LIGHT_GRAY_SHULKER_BOX, Material.LIME_SHULKER_BOX, Material.MAGENTA_SHULKER_BOX, Material.ORANGE_SHULKER_BOX, + Material.PINK_SHULKER_BOX, Material.PURPLE_SHULKER_BOX, Material.RED_SHULKER_BOX, Material.WHITE_SHULKER_BOX, Material.YELLOW_SHULKER_BOX)); + itemsInInv.put(Material.FIRE_CHARGE, EnumSet.of(Material.DISPENSER)); + itemsInInv.put(Material.ARROW, EnumSet.of(Material.DISPENSER)); + AutoCheckerItems.impl.getAllowedMaterialsInInventory().forEach(material -> itemsInInv.put(material, AutoCheckerItems.impl.getInventoryMaterials())); + } + + private void checkInventory(AutoChecker.BlockScanResult result, BaseBlock block, Material material, BlockPos pos, GameModeConfig type) { + CompoundTag nbt = block.getNbtData(); + if (nbt == null) { + result.getDefunctNbt().add(pos); + return; + } + + + if (material == Material.JUKEBOX && nbt.getValue().containsKey("RecordItem")) { + result.getRecords().add(pos); + return; + } + + List items = nbt.getList("Items", CompoundTag.class); + if (items.isEmpty()) + return; // Leeres Inventar + + int counter = 0; + int windChargeCount = 0; + for (CompoundTag item : items) { + if (!item.containsKey("id")) { + result.getDefunctNbt().add(pos); + continue; + } + + Material itemType = Material.matchMaterial(item.getString("id")); + if (itemType == null) // Leere Slots + continue; + + if(type.Schematic.Type.equals("wargearseason26") && material == Material.DISPENSER && itemType == Material.WIND_CHARGE) { + windChargeCount += item.getInt("count"); + } + else if (!itemsInInv.getOrDefault(itemType, EnumSet.noneOf(Material.class)).contains(material)) { + result.getForbiddenItems().computeIfAbsent(pos, blockVector3 -> new HashSet<>()).add(itemType); + } else if (material == Material.DISPENSER && (itemType == Material.ARROW || itemType == Material.FIRE_CHARGE)) { + counter += Core.getVersion() >= 21 ? item.getInt("count") : item.getByte("Count"); + } + if (item.containsKey("tag")) { + result.getForbiddenNbt().computeIfAbsent(pos, blockVector3 -> new HashSet<>()).add(itemType); + } + } + result.getDispenserItems().put(pos, counter); + result.getWindChargeCount().put(pos, windChargeCount); + } + + @Override + public AutoCheckerResult check(Clipboard clipboard, GameModeConfig type) { + return AutoCheckerResult.builder().type(type).height(clipboard.getDimensions().getBlockY()).width(clipboard.getDimensions().getBlockX()) + .depth(clipboard.getDimensions().getBlockZ()).blockScanResult(scan(clipboard, type)) + .entities(clipboard.getEntities().stream().map(Entity::getLocation) + .map(blockVector3 -> new BlockPos(blockVector3.getBlockX(), blockVector3.getBlockY(), blockVector3.getBlockZ())) + .collect(Collectors.toList())) + .build(); + } + + @Override + public AutoCheckerResult sizeCheck(Clipboard clipboard, GameModeConfig type) { + return AutoCheckerResult.builder().type(type).height(clipboard.getDimensions().getBlockY()).width(clipboard.getDimensions().getBlockX()) + .depth(clipboard.getDimensions().getBlockZ()).build(); + } +} diff --git a/SchematicSystem/SchematicSystem_21/src/de/steamwar/schematicsystem/autocheck/AutoCheckerItems21.java b/SchematicSystem/SchematicSystem_21/src/de/steamwar/schematicsystem/autocheck/AutoCheckerItems21.java new file mode 100644 index 00000000..af50a3fa --- /dev/null +++ b/SchematicSystem/SchematicSystem_21/src/de/steamwar/schematicsystem/autocheck/AutoCheckerItems21.java @@ -0,0 +1,49 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2025 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 org.bukkit.Material; + +import java.util.EnumSet; +import java.util.Set; + +public class AutoCheckerItems21 implements AutoCheckerItems { + + private static final Set INVENTORY = EnumSet.of(Material.BARREL, Material.BLAST_FURNACE, Material.BREWING_STAND, Material.CAMPFIRE, + Material.CHEST, Material.DISPENSER, Material.DROPPER, Material.FURNACE, Material.HOPPER, Material.JUKEBOX, Material.SHULKER_BOX, + Material.WHITE_SHULKER_BOX, Material.ORANGE_SHULKER_BOX, Material.MAGENTA_SHULKER_BOX, Material.LIGHT_BLUE_SHULKER_BOX, Material.YELLOW_SHULKER_BOX, + Material.LIME_SHULKER_BOX, Material.PINK_SHULKER_BOX, Material.GRAY_SHULKER_BOX, Material.LIGHT_GRAY_SHULKER_BOX, Material.CYAN_SHULKER_BOX, + Material.PURPLE_SHULKER_BOX, Material.BLUE_SHULKER_BOX, Material.BROWN_SHULKER_BOX, Material.GREEN_SHULKER_BOX, Material.RED_SHULKER_BOX, + Material.BLACK_SHULKER_BOX, Material.SMOKER, Material.TRAPPED_CHEST); + + private static final Set FLOWERS = EnumSet.of(Material.CORNFLOWER, Material.POPPY, Material.FERN, Material.DANDELION, Material.BLUE_ORCHID, + Material.ALLIUM, Material.AZURE_BLUET, Material.RED_TULIP, Material.ORANGE_TULIP, Material.WHITE_TULIP, Material.PINK_TULIP, Material.OXEYE_DAISY, + Material.LILY_OF_THE_VALLEY, Material.WITHER_ROSE, Material.SUNFLOWER, Material.DIAMOND_HORSE_ARMOR, Material.IRON_HORSE_ARMOR, + Material.GOLDEN_HORSE_ARMOR, Material.LEATHER_HORSE_ARMOR, Material.HONEY_BOTTLE, Material.LILAC, Material.ROSE_BUSH, Material.PEONY, + Material.TALL_GRASS, Material.LARGE_FERN); + + @Override + public Set getInventoryMaterials() { + return INVENTORY; + } + + @Override + public Set getAllowedMaterialsInInventory() { + return FLOWERS; + } +} diff --git a/SchematicSystem/SchematicSystem_Core/src/SchematicSystem.properties b/SchematicSystem/SchematicSystem_Core/src/SchematicSystem.properties index 0ff05daa..da86e45c 100644 --- a/SchematicSystem/SchematicSystem_Core/src/SchematicSystem.properties +++ b/SchematicSystem/SchematicSystem_Core/src/SchematicSystem.properties @@ -262,6 +262,8 @@ 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_WIND_CHARGES=§7Windcharges: §c{0}§7, Max: §e2048 +AUTO_CHECKER_RESULT_WIND_CHARGES_DISPENSER=§7Dispenser: §c[{0}, {1}, {2}]§7, Windcharges: §c{3}§7 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_DESIGN_BLOCK=§7{0} in Design: [{1}, {2}, {3}] diff --git a/SchematicSystem/SchematicSystem_Core/src/SchematicSystem_de.properties b/SchematicSystem/SchematicSystem_Core/src/SchematicSystem_de.properties index 12030a2f..aa72936e 100644 --- a/SchematicSystem/SchematicSystem_Core/src/SchematicSystem_de.properties +++ b/SchematicSystem/SchematicSystem_Core/src/SchematicSystem_de.properties @@ -242,6 +242,8 @@ 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_WIND_CHARGES=§7Windcharges: §c{0}§7, Max: §e2048 +AUTO_CHECKER_RESULT_WIND_CHARGES_DISPENSER=§7Werfer: §c[{0}, {1}, {2}]§7, Windcharges: §c{3}§7 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_DESIGN_BLOCK=§7{0} im Design: [{1}, {2}, {3}] diff --git a/SchematicSystem/SchematicSystem_Core/src/de/steamwar/schematicsystem/autocheck/AutoChecker.java b/SchematicSystem/SchematicSystem_Core/src/de/steamwar/schematicsystem/autocheck/AutoChecker.java index eb464553..7d17e8f9 100644 --- a/SchematicSystem/SchematicSystem_Core/src/de/steamwar/schematicsystem/autocheck/AutoChecker.java +++ b/SchematicSystem/SchematicSystem_Core/src/de/steamwar/schematicsystem/autocheck/AutoChecker.java @@ -55,6 +55,7 @@ public class AutoChecker { private final List records = new ArrayList<>(); private final Map> designBlocks = new EnumMap<>(Material.class); private final Map dispenserItems = new HashMap<>(); + private final Map windChargeCount = new HashMap<>(); private final Map> forbiddenItems = new HashMap<>(); private final Map> forbiddenNbt = new HashMap<>(); } diff --git a/SchematicSystem/SchematicSystem_Core/src/de/steamwar/schematicsystem/autocheck/AutoCheckerResult.java b/SchematicSystem/SchematicSystem_Core/src/de/steamwar/schematicsystem/autocheck/AutoCheckerResult.java index e6ba4728..d96a9557 100644 --- a/SchematicSystem/SchematicSystem_Core/src/de/steamwar/schematicsystem/autocheck/AutoCheckerResult.java +++ b/SchematicSystem/SchematicSystem_Core/src/de/steamwar/schematicsystem/autocheck/AutoCheckerResult.java @@ -52,6 +52,7 @@ public class AutoCheckerResult { isBlockCountOk() && isLimitedBlocksOK() && isDispenserItemsOK() && + isWindchargeCountOK() && !type.isAfterDeadline() && entities.isEmpty() && isDesignBlastResistanceOK(); @@ -62,8 +63,18 @@ public class AutoCheckerResult { !type.isAfterDeadline(); } + public boolean isWindchargeCountOK() { + if(type.Schematic.Type.equals("wargearseason26")) { + int windChargesCount = blockScanResult.getWindChargeCount().values().stream().reduce(Integer::sum).orElse(0); + return windChargesCount <= 2048; + } + else { + return true; + } + } + public boolean isDispenserItemsOK() { - return blockScanResult.getDispenserItems().values().stream().allMatch(i -> i <= type.Schematic.MaxDispenserItems); + return blockScanResult.getDispenserItems().values().stream().allMatch(i -> i <= type.Schematic.MaxDispenserItems); } public boolean hasWarnings() { @@ -127,6 +138,19 @@ public class AutoCheckerResult { } }); } + + if(!isWindchargeCountOK()) { + int windChargesCount = blockScanResult.getWindChargeCount().values().stream().reduce(Integer::sum).orElse(0); + SchematicSystem.MESSAGE.sendPrefixless("AUTO_CHECKER_RESULT_WIND_CHARGES", p, windChargesCount, 2048); + blockScanResult.getWindChargeCount().entrySet().stream().filter(blockVector3IntegerEntry -> blockVector3IntegerEntry.getValue() > 0).forEach(blockVector3IntegerEntry -> { + SchematicSystem.MESSAGE.sendPrefixless("AUTO_CHECKER_RESULT_WIND_CHARGES_DISPENSER", p, SchematicSystem.MESSAGE.parse("AUTO_CHECKER_RESULT_TELEPORT_HERE", p), tpCommandTo(blockVector3IntegerEntry.getKey()), + blockVector3IntegerEntry.getKey().getBlockX(), + blockVector3IntegerEntry.getKey().getBlockY(), + blockVector3IntegerEntry.getKey().getBlockZ(), + blockVector3IntegerEntry.getValue()); + }); + } + blockScanResult.getDispenserItems().entrySet().stream().filter(blockVector3IntegerEntry -> blockVector3IntegerEntry.getValue() > type.Schematic.MaxDispenserItems).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(), @@ -135,6 +159,7 @@ public class AutoCheckerResult { blockVector3IntegerEntry.getValue(), type.Schematic.MaxDispenserItems); }); + blockScanResult.getRecords().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()); }); diff --git a/SchematicSystem/build.gradle.kts b/SchematicSystem/build.gradle.kts index 65613802..947812e3 100644 --- a/SchematicSystem/build.gradle.kts +++ b/SchematicSystem/build.gradle.kts @@ -32,4 +32,5 @@ dependencies { implementation(project(":SchematicSystem:SchematicSystem_15")) implementation(project(":SchematicSystem:SchematicSystem_19")) implementation(project(":SchematicSystem:SchematicSystem_20")) + implementation(project(":SchematicSystem:SchematicSystem_21")) } diff --git a/settings.gradle.kts b/settings.gradle.kts index 5f364d5b..ea47eac1 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -101,6 +101,7 @@ dependencyResolutionManagement { library("hamcrest", "org.hamcrest:hamcrest:2.2") library("classindex", "org.atteo.classindex:classindex:3.13") + library("spigotapi", "org.spigotmc:spigot-api:1.20-R0.1-SNAPSHOT") library("spigotannotations", "org.spigotmc:plugin-annotations:1.2.3-SNAPSHOT") library("paperapi", "io.papermc.paper:paper-api:1.19.2-R0.1-SNAPSHOT") @@ -222,6 +223,7 @@ include( "SchematicSystem:SchematicSystem_15", "SchematicSystem:SchematicSystem_19", "SchematicSystem:SchematicSystem_20", + "SchematicSystem:SchematicSystem_21", "SchematicSystem:SchematicSystem_Core" )