Improve items for GameModeConfig

This commit is contained in:
2026-08-24 20:05:58 +02:00
parent 72b70a62e1
commit 5a52771ec1
12 changed files with 200 additions and 101 deletions
@@ -269,7 +269,7 @@ AUTO_CHECKER_RESULT_DEFUNCT_NBT = §7Defunct NBT: §7[{0}, {1}, {2}]
AUTO_CHECKER_RESULT_DESIGN_BLOCK = §7{0} in Design: [{1}, {2}, {3}]
AUTO_CHECKER_RESULT_ENTITY = §7Entity: §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_TOO_MANY_INVENTORY_ITEMS = §7{6}: §c[{0}, {1}, {2}]§7, §c{3}x {5}§7, 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}
@@ -248,7 +248,7 @@ AUTO_CHECKER_RESULT_FORBIDDEN_ITEM = §7Verbotener gegenstand: [{0}, {1}, {2}] -
AUTO_CHECKER_RESULT_DEFUNCT_NBT = §7Keine NBT-Daten: §c[{0}, {1}, {2}]
AUTO_CHECKER_RESULT_DESIGN_BLOCK = §7{0} im Design: [{1}, {2}, {3}]
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_TOO_MANY_INVENTORY_ITEMS = §7{6}: §c[{0}, {1}, {2}]§7, §c{3}x {5}§7, 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}
@@ -75,9 +75,9 @@ public class AutoChecker {
BlockPos pos = new BlockPos(x, y, z);
if (AutoCheckerItems.impl.getInventoryMaterials().contains(material)) {
if (type.Schematic.ItemsInInventory.containsKey(material)) {
checkInventory(result, block, material, pos, type);
if (result.getDispenserItems().getOrDefault(pos, 0) > 0) {
if (!result.getInventoryItemCounts().getOrDefault(pos, Collections.emptyMap()).isEmpty()) {
result.getBlockCounts().merge(material, 1, Integer::sum);
}
} else {
@@ -93,19 +93,6 @@ public class AutoChecker {
return result;
}
private static final Map<Material, Set<Material>> 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<Material, String> type) {
CompoundTag nbt = block.getNbtData();
if (nbt == null) {
@@ -122,7 +109,8 @@ public class AutoChecker {
List<CompoundTag> items = nbt.getList("Items", CompoundTag.class);
if (items.isEmpty()) return; // Leeres Inventar
int counter = 0;
Map<Material, Integer> itemCaps = type.Schematic.ItemsInInventory.getOrDefault(material, Collections.emptyMap());
Map<Material, Integer> itemCounts = new EnumMap<>(Material.class);
int windChargeCount = 0;
for (CompoundTag item : items) {
if (!item.containsKey("id")) {
@@ -136,16 +124,19 @@ public class AutoChecker {
if (type.Schematic.Type.getName().equals("wargearseason26") && material == Material.DISPENSER && itemType == Material.WIND_CHARGE) {
windChargeCount += item.getInt("count");
} else if (!itemsInInv.getOrDefault(itemType, EnumSet.noneOf(Material.class)).contains(material)) {
} else if (!itemCaps.containsKey(itemType)) {
result.getForbiddenItems().computeIfAbsent(pos, blockVector3 -> new HashSet<>()).add(itemType);
} else if (material == Material.DISPENSER && (itemType == Material.ARROW || itemType == Material.FIRE_CHARGE)) {
counter += item.getInt("count");
} else {
itemCounts.merge(itemType, item.getInt("count"), Integer::sum);
}
if (item.containsKey("tag")) {
result.getForbiddenNbt().computeIfAbsent(pos, blockVector3 -> new HashSet<>()).add(itemType);
}
}
result.getDispenserItems().put(pos, counter);
if (!itemCounts.isEmpty()) {
result.getInventoryItemCounts().put(pos, itemCounts);
result.getInventoryBlockType().put(pos, material);
}
result.getWindChargeCount().put(pos, windChargeCount);
}
@@ -156,7 +147,8 @@ public class AutoChecker {
private final List<BlockPos> defunctNbt = new ArrayList<>();
private final List<BlockPos> records = new ArrayList<>();
private final Map<Material, List<BlockPos>> designBlocks = new EnumMap<>(Material.class);
private final Map<BlockPos, Integer> dispenserItems = new HashMap<>();
private final Map<BlockPos, Map<Material, Integer>> inventoryItemCounts = new HashMap<>();
private final Map<BlockPos, Material> inventoryBlockType = new HashMap<>();
private final Map<BlockPos, Integer> windChargeCount = new HashMap<>();
private final Map<BlockPos, Set<Material>> forbiddenItems = new HashMap<>();
private final Map<BlockPos, Set<Material>> forbiddenNbt = new HashMap<>();
@@ -1,51 +0,0 @@
/*
* 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 <https://www.gnu.org/licenses/>.
*/
package de.steamwar.schematicsystem.autocheck;
import org.bukkit.Material;
import java.util.EnumSet;
import java.util.Set;
public class AutoCheckerItems {
public static final AutoCheckerItems impl = new AutoCheckerItems();
private static final Set<Material> 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<Material> 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);
public Set<Material> getInventoryMaterials() {
return INVENTORY;
}
public Set<Material> getAllowedMaterialsInInventory() {
return FLOWERS;
}
}
@@ -29,6 +29,7 @@ import org.bukkit.Material;
import org.bukkit.entity.Player;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
@@ -50,7 +51,7 @@ public class AutoCheckerResult {
isSizeOk() &&
isBlockCountOk() &&
isLimitedBlocksOK() &&
isDispenserItemsOK() &&
isInventoryItemsOK() &&
isWindchargeCountOK() &&
!type.isAfterDeadline() &&
entities.isEmpty() &&
@@ -71,8 +72,13 @@ public class AutoCheckerResult {
}
}
public boolean isDispenserItemsOK() {
return blockScanResult.getDispenserItems().values().stream().allMatch(i -> i <= type.Schematic.MaxDispenserItems);
public boolean isInventoryItemsOK() {
return blockScanResult.getInventoryItemCounts().entrySet().stream().allMatch(posEntry -> {
Material inventory = blockScanResult.getInventoryBlockType().get(posEntry.getKey());
Map<Material, Integer> caps = type.Schematic.ItemsInInventory.getOrDefault(inventory, Collections.emptyMap());
return posEntry.getValue().entrySet().stream()
.allMatch(itemEntry -> itemEntry.getValue() <= caps.getOrDefault(itemEntry.getKey(), Integer.MAX_VALUE));
});
}
public boolean hasWarnings() {
@@ -155,13 +161,21 @@ public class AutoCheckerResult {
});
}
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(),
blockVector3IntegerEntry.getKey().getBlockY(),
blockVector3IntegerEntry.getKey().getBlockZ(),
blockVector3IntegerEntry.getValue(),
type.Schematic.MaxDispenserItems);
blockScanResult.getInventoryItemCounts().forEach((pos, itemCounts) -> {
Material inventory = blockScanResult.getInventoryBlockType().get(pos);
Map<Material, Integer> caps = type.Schematic.ItemsInInventory.getOrDefault(inventory, Collections.emptyMap());
itemCounts.forEach((itemType, count) -> {
int cap = caps.getOrDefault(itemType, Integer.MAX_VALUE);
if (count <= cap) return;
SchematicSystem.MESSAGE.sendPrefixless("AUTO_CHECKER_RESULT_TOO_MANY_INVENTORY_ITEMS", p, SchematicSystem.MESSAGE.parse("AUTO_CHECKER_RESULT_TELEPORT_HERE", p), tpCommandTo(pos),
pos.getBlockX(),
pos.getBlockY(),
pos.getBlockZ(),
count,
cap,
itemType.name(),
inventory.name());
});
});
blockScanResult.getRecords().forEach(blockVector3 -> {
@@ -197,27 +197,32 @@ public class SchematicCommand extends SWCommand {
clipboard.setBlock(vector, block.toBaseBlock(builder.build()));
}
if (type.Schematic.MaxDispenserItems > 0) {
for (Map.Entry<BlockPos, Integer> entry : result.getBlockScanResult().getDispenserItems().entrySet()) {
if (entry.getValue() <= type.Schematic.MaxDispenserItems) {
for (Map.Entry<BlockPos, Map<Material, Integer>> posEntry : result.getBlockScanResult().getInventoryItemCounts().entrySet()) {
BlockPos pos = posEntry.getKey();
Material inventory = result.getBlockScanResult().getInventoryBlockType().get(pos);
Map<Material, Integer> caps = type.Schematic.ItemsInInventory.getOrDefault(inventory, Collections.emptyMap());
for (Map.Entry<Material, Integer> itemEntry : posEntry.getValue().entrySet()) {
Material itemType = itemEntry.getKey();
int cap = caps.getOrDefault(itemType, Integer.MAX_VALUE);
if (itemEntry.getValue() <= cap) {
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<CompoundTag> items = new ArrayList<>(tag.getList("Items", CompoundTag.class));
Collections.reverse(items); // To let the first item be in the Dispenser
Collections.reverse(items); // To let the first item be in the inventory
List<CompoundTag> list = new ArrayList<>();
int diff = entry.getValue() - type.Schematic.MaxDispenserItems;
int diff = itemEntry.getValue() - cap;
for (CompoundTag item : items) {
if (item == null) {
continue;
}
if (diff == 0) {
if (diff == 0 || Material.matchMaterial(item.getString("id")) != itemType) {
list.add(item);
continue;
}