forked from SteamWar/SteamWar
Merge pull request 'Improve AutoChecker and GameModeConfig again' (#478) from AutoChecker into main
Reviewed-on: SteamWar/SteamWar#478
This commit is contained in:
@@ -703,46 +703,12 @@ public final class GameModeConfig<M, W> {
|
|||||||
public final double MaxDesignBlastResistance;
|
public final double MaxDesignBlastResistance;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* List of limited material (combinations)<br/>
|
* List of limited block materials
|
||||||
* List contains tags Amount (integer) and Materials (List of material names in Spigot 1.12 AND Spigot 1.15 format)
|
|
||||||
*/
|
|
||||||
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 -> 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
|
* @implSpec {@link SQLWrapper#getInventoryMaterials)} are all disallowed by default to have any content but are unlimited in number.
|
||||||
|
* @implSpec Any Block that has more Blast Resistance than {@link #MaxBlastResistance} will be defaulted to 0.
|
||||||
*/
|
*/
|
||||||
public final Map<M, Map<M, Integer>> ItemsInInventory;
|
public final List<BlockRule<M>> Limited;
|
||||||
|
|
||||||
/**
|
|
||||||
* 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) {
|
private SchematicConfig(YMLWrapper<M, ?> loader) {
|
||||||
loaded = loader.canLoad();
|
loaded = loader.canLoad();
|
||||||
@@ -763,52 +729,142 @@ public final class GameModeConfig<M, W> {
|
|||||||
MaxBlastResistance = loader.getDouble("MaxBlastResistance", Double.MAX_VALUE);
|
MaxBlastResistance = loader.getDouble("MaxBlastResistance", Double.MAX_VALUE);
|
||||||
MaxDesignBlastResistance = loader.getDouble("MaxDesignBlastResistance", MaxBlastResistance);
|
MaxDesignBlastResistance = loader.getDouble("MaxDesignBlastResistance", MaxBlastResistance);
|
||||||
|
|
||||||
Map<Set<M>, Integer> Limited = new HashMap<>();
|
List<BlockRule<M>> limited = new ArrayList<>();
|
||||||
for (Map<?, ?> entry : loader.getMapList("Limited")) {
|
Set<M> blocks = new HashSet<>();
|
||||||
int amount = (Integer) entry.get("Amount");
|
for (YMLWrapper<M, ?> limitedLoader : loader.withAsList("Limited")) {
|
||||||
Set<String> materials = new HashSet<>((List<String>) entry.get("Materials"));
|
BlockRule<M> blockRule = new BlockRule<>(limitedLoader);
|
||||||
if (amount == 0) {
|
blocks.addAll(blockRule.Blocks);
|
||||||
materials.forEach(material -> {
|
limited.add(blockRule);
|
||||||
Limited.put(Collections.singleton(loader.materialMapper.apply(material.toUpperCase())), 0);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
Limited.put(Collections.unmodifiableSet(materials.stream().map(String::toUpperCase).map(loader.materialMapper).collect(Collectors.toSet())), amount);
|
|
||||||
}
|
}
|
||||||
|
for (M material : (List<M>) SQLWrapper.impl.getMaterialWithGreaterBlastResistance(MaxBlastResistance)) {
|
||||||
|
if (material == null || !blocks.add(material)) continue;
|
||||||
|
limited.add(new BlockRule<>(material, 0));
|
||||||
}
|
}
|
||||||
SQLWrapper.impl.getMaterialWithGreaterBlastResistance(MaxBlastResistance).forEach(material -> {
|
for (M material : (Set<M>) SQLWrapper.impl.getInventoryMaterials()) {
|
||||||
if (Limited.entrySet().stream().anyMatch(entry -> entry.getKey().contains(material))) return;
|
if (material == null || !blocks.add(material)) continue;
|
||||||
Limited.put(Collections.singleton((M) material), 0);
|
limited.add(new BlockRule<>(material, Integer.MAX_VALUE));
|
||||||
});
|
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
}
|
this.Limited = Collections.unmodifiableList(limited);
|
||||||
}
|
|
||||||
}
|
|
||||||
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.ReplacementsWithoutBlockUpdates = loader.getMap("ReplacementsWithoutBlockUpdates", loader.materialMapper, loader.materialMapper);
|
||||||
this.ReplacementsWithBlockUpdates = loader.getMap("ReplacementsWithBlockUpdates", loader.materialMapper, loader.materialMapper);
|
this.ReplacementsWithBlockUpdates = loader.getMap("ReplacementsWithBlockUpdates", loader.materialMapper, loader.materialMapper);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getMaxCount(M material) {
|
||||||
|
return Limited.stream()
|
||||||
|
.filter(rule -> rule.Blocks.contains(material))
|
||||||
|
.mapToInt(rule -> rule.MaxCount)
|
||||||
|
.max()
|
||||||
|
.orElse(Integer.MAX_VALUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isInventory(M material) {
|
||||||
|
return Limited.stream()
|
||||||
|
.filter(rule -> rule.Blocks.contains(material))
|
||||||
|
.anyMatch(rule -> rule.Content.loaded);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getItemAmount(M material, M item) {
|
||||||
|
return Limited.stream()
|
||||||
|
.filter(rule -> rule.Blocks.contains(material))
|
||||||
|
.filter(rule -> rule.Content.Items.contains(item))
|
||||||
|
.mapToInt(rule -> rule.Content.Amount)
|
||||||
|
.max()
|
||||||
|
.orElse(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ToString
|
||||||
|
public static final class BlockRule<M> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The block materials this rule applies to
|
||||||
|
*/
|
||||||
|
public final Set<M> Blocks;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Maximal amount of Blocks allowed in the schematic
|
||||||
|
*
|
||||||
|
* @implSpec {@code 0} by default
|
||||||
|
*/
|
||||||
|
public final int MaxCount;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The item content filter for Blocks
|
||||||
|
*
|
||||||
|
* @implSpec no Items with {@code Amount 0} (denies any item) by default
|
||||||
|
*/
|
||||||
|
public final Content<M> Content;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resolves one {@code Materials} entry to the concrete 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 "INVENTORY":
|
||||||
|
return (Set<M>) SQLWrapper.impl.getInventoryMaterials();
|
||||||
|
default:
|
||||||
|
M material = loader.materialMapper.apply(name.toUpperCase());
|
||||||
|
return material != null ? Collections.singleton(material) : Collections.emptySet();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private BlockRule(YMLWrapper<M, ?> loader) {
|
||||||
|
List<M> blocks = loader.getStringList("Blocks")
|
||||||
|
.stream()
|
||||||
|
.flatMap(value -> expandInventoryGroup(loader, value).stream())
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
if (blocks.isEmpty()) { // Legacy support
|
||||||
|
blocks = loader.getMaterialList("Materials");
|
||||||
|
}
|
||||||
|
Blocks = Collections.unmodifiableSet(new HashSet<>(blocks));
|
||||||
|
MaxCount = loader.getInt("MaxCount", // Legacy support
|
||||||
|
loader.getInt("Amount", 0)
|
||||||
|
);
|
||||||
|
Content = new Content<>(loader.with("Content"));
|
||||||
|
}
|
||||||
|
|
||||||
|
private BlockRule(M block, int maxCount) {
|
||||||
|
Blocks = Collections.singleton(block);
|
||||||
|
MaxCount = maxCount;
|
||||||
|
Content = new Content<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
@ToString
|
||||||
|
public static final class Content<M> {
|
||||||
|
|
||||||
|
public final boolean loaded;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Items allowed by this rule
|
||||||
|
*/
|
||||||
|
public final Set<M> Items;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Maximal amount of an allowed item per single block instance
|
||||||
|
*
|
||||||
|
* @implSpec {@code 0} by default
|
||||||
|
*/
|
||||||
|
public final int Amount;
|
||||||
|
|
||||||
|
private Content(YMLWrapper<M, ?> loader) {
|
||||||
|
loaded = loader.canLoad();
|
||||||
|
List<M> items = loader.getMaterialList("Items");
|
||||||
|
Items = Collections.unmodifiableSet(new HashSet<>(items));
|
||||||
|
Amount = loader.getInt("Amount", 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Content() {
|
||||||
|
loaded = false;
|
||||||
|
Items = new HashSet<>();
|
||||||
|
Amount = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@ToString
|
@ToString
|
||||||
public static final class SizeConfig {
|
public static final class SizeConfig {
|
||||||
|
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ public interface SQLWrapper<M> {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Storage-type inventory materials (chests, barrels, shulker boxes of any color) - the
|
* Storage-type inventory materials (chests, barrels, shulker boxes of any color) - the
|
||||||
* {@code storage} group usable in {@code GameModeConfig}'s {@code ItemsInInventory}.
|
* {@code storage} group usable in {@code GameModeConfig}'s {@code Limited}.
|
||||||
*/
|
*/
|
||||||
default Set<M> getStorageMaterials() {
|
default Set<M> getStorageMaterials() {
|
||||||
return Collections.emptySet();
|
return Collections.emptySet();
|
||||||
@@ -47,7 +47,7 @@ public interface SQLWrapper<M> {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Every inventory material - the {@code all} group usable in {@code GameModeConfig}'s
|
* Every inventory material - the {@code all} group usable in {@code GameModeConfig}'s
|
||||||
* {@code ItemsInInventory}. Expected to be a superset of {@link #getStorageMaterials()}.
|
* {@code Limited}. Expected to be a superset of {@link #getStorageMaterials()}.
|
||||||
*/
|
*/
|
||||||
default Set<M> getInventoryMaterials() {
|
default Set<M> getInventoryMaterials() {
|
||||||
return Collections.emptySet();
|
return Collections.emptySet();
|
||||||
|
|||||||
@@ -76,6 +76,25 @@ final class YMLWrapper<M, W> {
|
|||||||
return new YMLWrapper<>(false, Collections.emptyMap(), materialMapper, winconditionMapper);
|
return new YMLWrapper<>(false, Collections.emptyMap(), materialMapper, winconditionMapper);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<YMLWrapper<M, W>> withAsList(String path) {
|
||||||
|
if (document.containsKey(path)) {
|
||||||
|
Object value = document.get(path);
|
||||||
|
if (value instanceof List) {
|
||||||
|
List<?> list = (List<?>) value;
|
||||||
|
List<Map> maps = list.stream()
|
||||||
|
.filter(Map.class::isInstance)
|
||||||
|
.map(Map.class::cast)
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
if (maps.size() == list.size()) {
|
||||||
|
return (List) maps.stream()
|
||||||
|
.map(map -> new YMLWrapper(true, map, materialMapper, winconditionMapper))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
public <T> T get(String path, T defaultValue, Function<Object, T> mapper) {
|
public <T> T get(String path, T defaultValue, Function<Object, T> mapper) {
|
||||||
Object value = this.document.get(path);
|
Object value = this.document.get(path);
|
||||||
if (value == null) return defaultValue;
|
if (value == null) return defaultValue;
|
||||||
|
|||||||
@@ -109,28 +109,19 @@ Schematic:
|
|||||||
MaxBlocks: 0 # defaults to 0 (ignored) if missing
|
MaxBlocks: 0 # defaults to 0 (ignored) if missing
|
||||||
# Maximal blast resistance for the design blocks
|
# Maximal blast resistance for the design blocks
|
||||||
MaxDesignBlastResistance: 100000000 # defaults to Double.MAX_VALUE if missing
|
MaxDesignBlastResistance: 100000000 # defaults to Double.MAX_VALUE if missing
|
||||||
# List of limited material (combinations)
|
# List of limited block materials
|
||||||
# List contains tags Amount (integer) and Materials (List of material names in Spigot 1.12 AND Spigot 1.15 format)
|
# InventoryMaterials are all disallowed by default to have any content but are unlimited in number
|
||||||
|
# Any Block that has more Blast Resistance than MaxBlastResistance will be defaulted to 0.
|
||||||
Limited:
|
Limited:
|
||||||
- Materials: [ ]
|
- Blocks: [ DISPENSER ]
|
||||||
Amount: 0
|
MaxCount: 64
|
||||||
# Item amount limits per inventory (container) type.
|
- Blocks: [ DISPENSER ]
|
||||||
# An item is only allowed to be placed in an inventory at all if it appears here for that
|
MaxCount: 16
|
||||||
# inventory's material (a small set of decorative items, e.g. flowers, is always allowed
|
Content:
|
||||||
# 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 ]
|
Items: [ ARROW, FIRE_CHARGE ]
|
||||||
Amount: 128
|
Amount: 128
|
||||||
- Inventories: [ storage ]
|
- Blocks: [ storage ]
|
||||||
|
Content:
|
||||||
Items: [ TNT ]
|
Items: [ TNT ]
|
||||||
Amount: 1728
|
Amount: 1728
|
||||||
|
|
||||||
|
|||||||
@@ -75,7 +75,7 @@ public class AutoChecker {
|
|||||||
|
|
||||||
BlockPos pos = new BlockPos(x, y, z);
|
BlockPos pos = new BlockPos(x, y, z);
|
||||||
|
|
||||||
if (type.Schematic.ItemsInInventory.containsKey(material)) {
|
if (type.Schematic.isInventory(material)) {
|
||||||
checkInventory(result, block, material, pos, type);
|
checkInventory(result, block, material, pos, type);
|
||||||
if (!result.getInventoryItemCounts().getOrDefault(pos, Collections.emptyMap()).isEmpty()) {
|
if (!result.getInventoryItemCounts().getOrDefault(pos, Collections.emptyMap()).isEmpty()) {
|
||||||
result.getBlockCounts().merge(material, 1, Integer::sum);
|
result.getBlockCounts().merge(material, 1, Integer::sum);
|
||||||
@@ -109,7 +109,6 @@ public class AutoChecker {
|
|||||||
List<CompoundTag> items = nbt.getList("Items", CompoundTag.class);
|
List<CompoundTag> items = nbt.getList("Items", CompoundTag.class);
|
||||||
if (items.isEmpty()) return; // Leeres Inventar
|
if (items.isEmpty()) return; // Leeres Inventar
|
||||||
|
|
||||||
Map<Material, Integer> itemCaps = type.Schematic.ItemsInInventory.getOrDefault(material, Collections.emptyMap());
|
|
||||||
Map<Material, Integer> itemCounts = new EnumMap<>(Material.class);
|
Map<Material, Integer> itemCounts = new EnumMap<>(Material.class);
|
||||||
int windChargeCount = 0;
|
int windChargeCount = 0;
|
||||||
for (CompoundTag item : items) {
|
for (CompoundTag item : items) {
|
||||||
@@ -124,7 +123,7 @@ public class AutoChecker {
|
|||||||
|
|
||||||
if (type.Schematic.Type.getName().equals("wargearseason26") && material == Material.DISPENSER && itemType == Material.WIND_CHARGE) {
|
if (type.Schematic.Type.getName().equals("wargearseason26") && material == Material.DISPENSER && itemType == Material.WIND_CHARGE) {
|
||||||
windChargeCount += item.getInt("count");
|
windChargeCount += item.getInt("count");
|
||||||
} else if (!itemCaps.containsKey(itemType)) {
|
} else if (type.Schematic.getItemAmount(material, itemType) == 0) {
|
||||||
result.getForbiddenItems().computeIfAbsent(pos, blockVector3 -> new HashSet<>()).add(itemType);
|
result.getForbiddenItems().computeIfAbsent(pos, blockVector3 -> new HashSet<>()).add(itemType);
|
||||||
} else {
|
} else {
|
||||||
itemCounts.merge(itemType, item.getInt("count"), Integer::sum);
|
itemCounts.merge(itemType, item.getInt("count"), Integer::sum);
|
||||||
|
|||||||
@@ -29,7 +29,6 @@ import org.bukkit.Material;
|
|||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
@@ -75,9 +74,10 @@ public class AutoCheckerResult {
|
|||||||
public boolean isInventoryItemsOK() {
|
public boolean isInventoryItemsOK() {
|
||||||
return blockScanResult.getInventoryItemCounts().entrySet().stream().allMatch(posEntry -> {
|
return blockScanResult.getInventoryItemCounts().entrySet().stream().allMatch(posEntry -> {
|
||||||
Material inventory = blockScanResult.getInventoryBlockType().get(posEntry.getKey());
|
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 -> {
|
||||||
return posEntry.getValue().entrySet().stream()
|
int cap = type.Schematic.getItemAmount(inventory, itemEntry.getKey());
|
||||||
.allMatch(itemEntry -> itemEntry.getValue() <= caps.getOrDefault(itemEntry.getKey(), Integer.MAX_VALUE));
|
return itemEntry.getValue() <= cap;
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -106,13 +106,8 @@ public class AutoCheckerResult {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean isLimitedBlocksOK() {
|
public boolean isLimitedBlocksOK() {
|
||||||
try {
|
return blockScanResult.getBlockCounts().entrySet().stream()
|
||||||
return type.Schematic.Limited.entrySet().stream()
|
.allMatch(entry -> entry.getValue() <= type.Schematic.getMaxCount(entry.getKey()));
|
||||||
.map(setIntegerEntry -> setIntegerEntry.getKey().stream().map(blockScanResult.getBlockCounts()::get).map(i -> i == null || i <= setIntegerEntry.getValue()).reduce(Boolean::logicalAnd).orElse(false))
|
|
||||||
.reduce(Boolean::logicalAnd).orElse(true);
|
|
||||||
} catch (NullPointerException e) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isDesignBlastResistanceOK() {
|
public boolean isDesignBlastResistanceOK() {
|
||||||
@@ -136,14 +131,13 @@ public class AutoCheckerResult {
|
|||||||
SchematicSystem.MESSAGE.sendPrefixless("AUTO_CHECKER_RESULT_BLOCKS", p, blockScanResult.getBlockCounts().values().stream().reduce(Integer::sum).orElse(0), type.Schematic.MaxBlocks);
|
SchematicSystem.MESSAGE.sendPrefixless("AUTO_CHECKER_RESULT_BLOCKS", p, blockScanResult.getBlockCounts().values().stream().reduce(Integer::sum).orElse(0), type.Schematic.MaxBlocks);
|
||||||
}
|
}
|
||||||
if (!isLimitedBlocksOK()) {
|
if (!isLimitedBlocksOK()) {
|
||||||
type.Schematic.Limited.forEach((materials, integer) -> {
|
blockScanResult.getBlockCounts().forEach((mat, count) -> {
|
||||||
for (Material mat : materials) {
|
int maxCount = type.Schematic.getMaxCount(mat);
|
||||||
if (mat != null && blockScanResult.getBlockCounts().getOrDefault(mat, 0) > integer) {
|
if (count > maxCount) {
|
||||||
if (integer == 0) {
|
if (maxCount == 0) {
|
||||||
SchematicSystem.MESSAGE.sendPrefixless("AUTO_CHECKER_RESULT_FORBIDDEN_BLOCK", p, mat.name());
|
SchematicSystem.MESSAGE.sendPrefixless("AUTO_CHECKER_RESULT_FORBIDDEN_BLOCK", p, mat.name());
|
||||||
} else {
|
} else {
|
||||||
SchematicSystem.MESSAGE.sendPrefixless("AUTO_CHECKER_RESULT_TOO_MANY_BLOCK", p, mat.name(), blockScanResult.getBlockCounts().getOrDefault(mat, 0), integer);
|
SchematicSystem.MESSAGE.sendPrefixless("AUTO_CHECKER_RESULT_TOO_MANY_BLOCK", p, mat.name(), count, maxCount);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -163,9 +157,8 @@ public class AutoCheckerResult {
|
|||||||
|
|
||||||
blockScanResult.getInventoryItemCounts().forEach((pos, itemCounts) -> {
|
blockScanResult.getInventoryItemCounts().forEach((pos, itemCounts) -> {
|
||||||
Material inventory = blockScanResult.getInventoryBlockType().get(pos);
|
Material inventory = blockScanResult.getInventoryBlockType().get(pos);
|
||||||
Map<Material, Integer> caps = type.Schematic.ItemsInInventory.getOrDefault(inventory, Collections.emptyMap());
|
|
||||||
itemCounts.forEach((itemType, count) -> {
|
itemCounts.forEach((itemType, count) -> {
|
||||||
int cap = caps.getOrDefault(itemType, Integer.MAX_VALUE);
|
int cap = type.Schematic.getItemAmount(inventory, itemType);
|
||||||
if (count <= cap) return;
|
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),
|
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.getBlockX(),
|
||||||
|
|||||||
+4
-5
@@ -200,11 +200,10 @@ public class SchematicCommand extends SWCommand {
|
|||||||
for (Map.Entry<BlockPos, Map<Material, Integer>> posEntry : result.getBlockScanResult().getInventoryItemCounts().entrySet()) {
|
for (Map.Entry<BlockPos, Map<Material, Integer>> posEntry : result.getBlockScanResult().getInventoryItemCounts().entrySet()) {
|
||||||
BlockPos pos = posEntry.getKey();
|
BlockPos pos = posEntry.getKey();
|
||||||
Material inventory = result.getBlockScanResult().getInventoryBlockType().get(pos);
|
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()) {
|
for (Map.Entry<Material, Integer> itemEntry : posEntry.getValue().entrySet()) {
|
||||||
Material itemType = itemEntry.getKey();
|
Material itemType = itemEntry.getKey();
|
||||||
int cap = caps.getOrDefault(itemType, Integer.MAX_VALUE);
|
Integer cap = type.Schematic.getItemAmount(inventory, itemType);
|
||||||
if (itemEntry.getValue() <= cap) {
|
if (itemEntry.getValue() <= cap) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -243,9 +242,9 @@ public class SchematicCommand extends SWCommand {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!result.isLimitedBlocksOK()) {
|
if (!result.isLimitedBlocksOK()) {
|
||||||
Set<Material> toReplace = type.Schematic.Limited.entrySet().stream()
|
Set<Material> toReplace = type.Schematic.Limited.stream()
|
||||||
.filter(setIntegerEntry -> setIntegerEntry.getValue() == 0)
|
.filter(rule -> rule.MaxCount == 0)
|
||||||
.flatMap(setIntegerEntry -> setIntegerEntry.getKey().stream())
|
.flatMap(rule -> rule.Blocks.stream())
|
||||||
.collect(Collectors.toSet());
|
.collect(Collectors.toSet());
|
||||||
BlockState replaceType = Objects.requireNonNull(toReplace.contains(Material.END_STONE) ? BlockTypes.IRON_BLOCK : BlockTypes.END_STONE).getDefaultState();
|
BlockState replaceType = Objects.requireNonNull(toReplace.contains(Material.END_STONE) ? BlockTypes.IRON_BLOCK : BlockTypes.END_STONE).getDefaultState();
|
||||||
BlockVector3 min = clipboard.getMinimumPoint();
|
BlockVector3 min = clipboard.getMinimumPoint();
|
||||||
|
|||||||
Reference in New Issue
Block a user