/* * 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 com.sk89q.jnbt.CompoundTag; import com.sk89q.worldedit.Vector; import com.sk89q.worldedit.blocks.BaseBlock; import com.sk89q.worldedit.entity.Entity; 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.*; import java.util.stream.Collectors; @SuppressWarnings("deprecation") public class AutoChecker8 implements AutoChecker.IAutoChecker { private static final int DISPENSER = Material.DISPENSER.getId(); private static final int JUKEBOX = Material.JUKEBOX.getId(); private static final int CHEST = Material.CHEST.getId(); private static final Set INVENTORY = new HashSet<>(); private static final Set FLOWERS; static{ INVENTORY.add(CHEST); INVENTORY.add(Material.TRAPPED_CHEST.getId()); INVENTORY.add(Material.HOPPER.getId()); INVENTORY.add(Material.FURNACE.getId()); INVENTORY.add(Material.BURNING_FURNACE.getId()); INVENTORY.add(JUKEBOX); //RecordItem INVENTORY.add(DISPENSER); INVENTORY.add(Material.DROPPER.getId()); INVENTORY.add(Material.ANVIL.getId()); INVENTORY.add(Material.BREWING_STAND.getId()); for(int i = 219; i <= 234; i++) { INVENTORY.add(i); // ShulkerBoxes } Set flowers = new HashSet<>(); flowers.add(Material.YELLOW_FLOWER); flowers.add(Material.RED_ROSE); flowers.add(Material.DOUBLE_PLANT); flowers.add(Material.DIAMOND_BARDING); flowers.add(Material.IRON_BARDING); flowers.add(Material.GOLD_BARDING); FLOWERS = flowers; } public void scan(AutoChecker.BlockScanResult result, Clipboard clipboard) { Region region = clipboard.getRegion(); Vector min = region.getMinimumPoint(); Vector max = region.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.getBlock(new Vector(x, y, z)); final int blockId = block.getId(); final Material material = Material.getMaterial(blockId); result.getBlockCounts().merge(material, 1, Integer::sum); if(INVENTORY.contains(blockId)){ checkInventory(result, block, blockId, new BlockPos(x, y, z)); } if(x == 0 || x == max.getBlockX() - 1 || y == max.getBlockY() - 1 || z == 0 || z == max.getBlockZ() - 1) { result.getDesignBlocks().computeIfAbsent(material, m -> new ArrayList<>()).add(new BlockPos(x, y, z)); } } } } } 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)); itemsInInv.put(Material.FIREBALL, EnumSet.of(Material.DISPENSER)); itemsInInv.put(Material.ARROW, EnumSet.of(Material.DISPENSER)); FLOWERS.forEach(material -> itemsInInv.put(material, INVENTORY.stream().map(Material::getMaterial).collect(Collectors.toCollection(() -> EnumSet.noneOf(Material.class))))); } private static void checkInventory(AutoChecker.BlockScanResult result, BaseBlock block, int blockId, BlockPos pos) { CompoundTag nbt = block.getNbtData(); if(nbt == null){ result.getDefunctNbt().add(pos); return; } if(blockId == 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; for(CompoundTag item : items){ if(!item.containsKey("id")){ result.getDefunctNbt().add(pos); continue; } String materialName = item.getString("id"); if(materialName.contains(":")) materialName = materialName.split(":")[1]; materialName = materialName.toUpperCase().replace("SHOVEL", "SPADE"); Material itemType = Material.getMaterial(materialName); if(itemType == null && item.getString("id").equals("minecraft:fire_charge")) itemType = Material.FIREBALL; if(itemType == null) //Leere Slots continue; if(!itemsInInv.getOrDefault(itemType, EnumSet.noneOf(Material.class)).contains(Material.getMaterial(blockId))) { result.getForbiddenItems().computeIfAbsent(pos, blockPos -> new HashSet<>()).add(Material.getMaterial(blockId)); } else if(blockId == DISPENSER && (itemType.equals(Material.FIREBALL) || itemType.equals(Material.ARROW))) { counter += item.getByte("Count"); } if(item.containsKey("tag")) { result.getForbiddenNbt().computeIfAbsent(pos, blockPos -> new HashSet<>()).add(Material.getMaterial(blockId)); } } result.getDispenserItems().put(pos, counter); } @Override public AutoCheckerResult check(Clipboard clipboard, CheckSchemType type) { AutoChecker.BlockScanResult blockScanResult = new AutoChecker.BlockScanResult(); scan(blockScanResult, clipboard); return AutoCheckerResult.builder() .type(type) .height(clipboard.getDimensions().getBlockY()) .width(clipboard.getDimensions().getBlockX()) .depth(clipboard.getDimensions().getBlockZ()) .blockScanResult(blockScanResult) .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, CheckSchemType type) { return AutoCheckerResult.builder() .type(type) .height(clipboard.getDimensions().getBlockY()) .width(clipboard.getDimensions().getBlockX()) .depth(clipboard.getDimensions().getBlockZ()) .build(); } }