Improve items for GameModeConfig
Pull Request Build / Build (pull_request) Successful in 1m38s

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
+5
View File
@@ -19,6 +19,7 @@
plugins {
steamwar.kotlin
kotlin("plugin.lombok")
}
kotlin {
@@ -40,4 +41,8 @@ dependencies {
compileOnlyApi(libs.exposedDao)
compileOnlyApi(libs.exposedJdbc)
compileOnlyApi(libs.exposedTime)
testImplementation(kotlin("test"))
}
repositories {
mavenCentral()
}
@@ -688,13 +688,6 @@ public final class GameModeConfig<M, W> {
*/
public final int MaxBlocks;
/**
* Maximal amount of items per dispenser
*
* @implSpec {@code 128} by default
*/
public final int MaxDispenserItems;
/**
* Maximal blast resistance for the blocks
*
@@ -715,6 +708,42 @@ public final class GameModeConfig<M, W> {
*/
public final Map<Set<M>, Integer> Limited;
/**
* Item amount limits per inventory (container) type.<br/>
* Key: inventory material (e.g. DISPENSER, CHEST, ...). Value: item material -&gt; maximal
* amount of that item allowed to be stored in a single inventory of that type.<br/>
* An item is only allowed to be placed in an inventory at all if it appears here for that
* inventory's material and item. Every material returned by
* {@link SQLWrapper#getInventoryMaterials()} is always present as a key - with an empty value
* map if not explicitly configured - so every real container is always scanned by the schematic
* checker for forbidden contents, it just allows no items by default.<br/>
* Configured via the {@code ItemsInInventory} list, entries consisting of {@code Inventories}
* (list of inventory materials or group names - {@code storage} for
* {@link SQLWrapper#getStorageMaterials()}, {@code all} for every material from
* {@link SQLWrapper#getInventoryMaterials()}), {@code Items} (list of item materials, each
* checked independently against {@code Amount} - not summed) and {@code Amount}.
*
* @implSpec No item is allowed in any inventory unless configured here
*/
public final Map<M, Map<M, Integer>> ItemsInInventory;
/**
* Resolves one {@code Inventories} entry to the concrete inventory materials it denotes:
* {@code storage} for {@link SQLWrapper#getStorageMaterials()}, {@code all} for
* {@link SQLWrapper#getInventoryMaterials()}, or the material itself otherwise.
*/
private Set<M> expandInventoryGroup(YMLWrapper<M, ?> loader, String name) {
switch (name.toUpperCase()) {
case "STORAGE":
return (Set<M>) SQLWrapper.impl.getStorageMaterials();
case "ALL":
return (Set<M>) SQLWrapper.impl.getInventoryMaterials();
default:
M material = loader.materialMapper.apply(name.toUpperCase());
return material != null ? Collections.singleton(material) : Collections.emptySet();
}
}
private SchematicConfig(YMLWrapper<M, ?> loader) {
loaded = loader.canLoad();
Size = new SizeConfig(loader.with("Size"));
@@ -731,7 +760,6 @@ public final class GameModeConfig<M, W> {
IgnorePublicOnly = loader.getBoolean("IgnorePublicOnly", false);
UnlimitedPrepare = loader.getBoolean("UnlimitedPrepare", false);
MaxBlocks = loader.getInt("MaxBlocks", 0);
MaxDispenserItems = loader.getInt("MaxDispenserItems", 128);
MaxBlastResistance = loader.getDouble("MaxBlastResistance", Double.MAX_VALUE);
MaxDesignBlastResistance = loader.getDouble("MaxDesignBlastResistance", MaxBlastResistance);
@@ -753,6 +781,30 @@ public final class GameModeConfig<M, W> {
});
this.Limited = Collections.unmodifiableMap(Limited);
Map<M, Map<M, Integer>> itemsInInventory = new HashMap<>();
for (Map<?, ?> entry : loader.getMapList("ItemsInInventory")) {
int amount = (Integer) entry.get("Amount");
List<String> inventories = (List<String>) entry.get("Inventories");
List<String> items = (List<String>) entry.get("Items");
for (String inventoryName : inventories) {
for (M inventoryMaterial : expandInventoryGroup(loader, inventoryName)) {
if (inventoryMaterial == null) continue;
Map<M, Integer> itemCaps = itemsInInventory.computeIfAbsent(inventoryMaterial, m -> new HashMap<>());
for (String itemName : items) {
M itemMaterial = loader.materialMapper.apply(itemName.toUpperCase());
if (itemMaterial == null) continue;
itemCaps.put(itemMaterial, amount);
}
}
}
}
for (M allMaterial : (Set<M>) SQLWrapper.impl.getInventoryMaterials()) {
if (allMaterial == null) continue;
itemsInInventory.computeIfAbsent(allMaterial, m -> new HashMap<>());
}
this.ItemsInInventory = Collections.unmodifiableMap(itemsInInventory.entrySet().stream()
.collect(Collectors.toMap(Map.Entry::getKey, e -> Collections.unmodifiableMap(e.getValue()))));
this.ReplacementsWithoutBlockUpdates = loader.getMap("ReplacementsWithoutBlockUpdates", loader.materialMapper, loader.materialMapper);
this.ReplacementsWithBlockUpdates = loader.getMap("ReplacementsWithBlockUpdates", loader.materialMapper, loader.materialMapper);
}
@@ -24,6 +24,7 @@ import de.steamwar.ImplementationProvider;
import java.io.File;
import java.util.Collections;
import java.util.List;
import java.util.Set;
public interface SQLWrapper<M> {
SQLWrapper<?> impl = ImplementationProvider.getImpl("de.steamwar.sql.SQLWrapperImpl");
@@ -36,5 +37,21 @@ public interface SQLWrapper<M> {
return Collections.emptyList();
}
/**
* Storage-type inventory materials (chests, barrels, shulker boxes of any color) - the
* {@code storage} group usable in {@code GameModeConfig}'s {@code ItemsInInventory}.
*/
default Set<M> getStorageMaterials() {
return Collections.emptySet();
}
/**
* Every inventory material - the {@code all} group usable in {@code GameModeConfig}'s
* {@code ItemsInInventory}. Expected to be a superset of {@link #getStorageMaterials()}.
*/
default Set<M> getInventoryMaterials() {
return Collections.emptySet();
}
void additionalExceptionMetadata(StringBuilder builder);
}
+19 -2
View File
@@ -107,8 +107,6 @@ Schematic:
UnlimitedPrepare: false # defaults to false if missing
# Maximal amount of blocks allowed in the schematic
MaxBlocks: 0 # defaults to 0 (ignored) if missing
# Maximal amount of items per dispenser
MaxDispenserItems: 128 # defaults to 128 if missing
# Maximal blast resistance for the design blocks
MaxDesignBlastResistance: 100000000 # defaults to Double.MAX_VALUE if missing
# List of limited material (combinations)
@@ -116,6 +114,25 @@ Schematic:
Limited:
- Materials: [ ]
Amount: 0
# Item amount limits per inventory (container) type.
# An item is only allowed to be placed in an inventory at all if it appears here for that
# inventory's material (a small set of decorative items, e.g. flowers, is always allowed
# everywhere regardless of this list) - NOTHING is allowed in any inventory unless listed here.
# Each entry contains Inventories (list of inventory materials, or a group name - 'storage' for
# chests/barrels/shulker boxes of any color, 'all' for every scanned inventory material including
# dispensers, droppers, hoppers, furnaces, etc.), Items (list of item materials, each checked
# independently against Amount - not summed) and Amount (max stored amount of that item per
# single inventory of that type).
ItemsInInventory: # defaults to none (nothing allowed in any inventory) if missing
- Inventories: [ DISPENSER ]
Items: [ BUCKET ]
Amount: 1
- Inventories: [ DISPENSER ]
Items: [ ARROW, FIRE_CHARGE ]
Amount: 128
- Inventories: [ storage ]
Items: [ TNT ]
Amount: 1728
# The name of the game mode presented to the players
GameName: WarGear # defaults to WarGear if missing
@@ -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;
}
@@ -28,7 +28,10 @@ import org.bukkit.entity.Player;
import java.io.File;
import java.util.Arrays;
import java.util.Collections;
import java.util.EnumSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
public class SQLWrapperImpl implements SQLWrapper<Material> {
@@ -52,6 +55,45 @@ public class SQLWrapperImpl implements SQLWrapper<Material> {
.collect(Collectors.toList());
}
/**
* Storage-type inventory materials (chests, barrels, shulker boxes of any color).
*/
private static final Set<Material> STORAGE_MATERIALS = Collections.unmodifiableSet(EnumSet.of(
Material.CHEST, Material.TRAPPED_CHEST, Material.BARREL, 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
));
/**
* Every inventory material - {@link #STORAGE_MATERIALS} plus the "functional" containers that
* are not storage (dispenser, dropper, hopper, the furnace family, brewing stand, campfire,
* jukebox). Built on top of {@link #STORAGE_MATERIALS} so anything added there is automatically
* included here.
*/
private static final Set<Material> INVENTORY_MATERIALS;
static {
Set<Material> materials = EnumSet.copyOf(STORAGE_MATERIALS);
materials.addAll(EnumSet.of(
Material.DISPENSER, Material.DROPPER, Material.HOPPER,
Material.FURNACE, Material.BLAST_FURNACE, Material.SMOKER,
Material.BREWING_STAND, Material.CAMPFIRE, Material.JUKEBOX
));
INVENTORY_MATERIALS = Collections.unmodifiableSet(materials);
}
@Override
public Set<Material> getStorageMaterials() {
return STORAGE_MATERIALS;
}
@Override
public Set<Material> getInventoryMaterials() {
return INVENTORY_MATERIALS;
}
private static final String SERVER_VERSION = Bukkit.getServer().getVersion();
@Override
+6
View File
@@ -21,6 +21,12 @@ import org.apache.tools.ant.taskdefs.condition.Os
import java.net.URI
import java.util.*
pluginManagement {
plugins {
kotlin("plugin.lombok") version "2.3.20"
}
}
rootProject.name = "SteamWar"
private val isInCi by lazy { Os.isFamily(Os.FAMILY_UNIX) && ProcessBuilder("hostname").start().inputStream.bufferedReader().readText().startsWith("steamwar.de") }