mirror of
https://github.com/GTNewHorizons/StructureLib.git
synced 2026-11-09 15:04:56 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a168702151 | ||
|
|
73f113ed9b | ||
|
|
c19ac860d4 | ||
|
|
d33cdd79c4 | ||
|
|
ed24f15033 | ||
|
|
15c34061bc | ||
|
|
728f25114b | ||
|
|
4a8c154855 | ||
|
|
f65010a547 |
No files matched your search
@@ -30,4 +30,5 @@ The project is developed using IDEA. Please manually configure the build to not
|
||||
|
||||
## Current license
|
||||
Due to me adding in ItemStackMap, which was derived from code from CodeChicken's LGPL mod NEI. This mod is effectively considered
|
||||
licensed under LGPL in its entirety since commit ebef584b8c518f8202cfe0984fb28a6d23e52b3d.
|
||||
licensed under LGPL in its entirety since commit ebef584b8c518f8202cfe0984fb28a6d23e52b3d or any squash commit containing it, e.g.
|
||||
609e50428ee4e293f65f67f554a70b9fcfae97c4.
|
||||
+2
-2
@@ -1,4 +1,4 @@
|
||||
//version: 1659365110
|
||||
//version: 1659977784
|
||||
/*
|
||||
DO NOT CHANGE THIS FILE!
|
||||
Also, you may replace this file at any time if there is an update available.
|
||||
@@ -651,7 +651,7 @@ task updateBuildScript {
|
||||
}
|
||||
}
|
||||
|
||||
if (isNewBuildScriptVersionAvailable(projectDir.toString())) {
|
||||
if (!project.getGradle().startParameter.isOffline() && isNewBuildScriptVersionAvailable(projectDir.toString())) {
|
||||
if (autoUpdateBuildScript.toBoolean()) {
|
||||
performBuildScriptUpdate(projectDir.toString())
|
||||
} else {
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
// Add your dependencies here
|
||||
|
||||
dependencies {
|
||||
|
||||
compile("com.github.GTNewHorizons:GTNHLib:0.0.1:dev")
|
||||
}
|
||||
+4
-1
@@ -1,5 +1,8 @@
|
||||
// Add any additional repositiroes for your dependencies here
|
||||
|
||||
repositories {
|
||||
|
||||
maven {
|
||||
name = "GTNH"
|
||||
url = "http://jenkins.usrv.eu:8081/nexus/content/groups/public/"
|
||||
}
|
||||
}
|
||||
+3
-5
@@ -76,11 +76,9 @@ public class ConstructableUtility {
|
||||
} else if (constructable instanceof ISurvivalConstructable) {
|
||||
int built = ((ISurvivalConstructable) constructable)
|
||||
.survivalConstruct(aStack, BUDGET, IItemSource.fromPlayer(playerMP), playerMP);
|
||||
if (built > 0)
|
||||
// TODO somehow notify extensions that their inventory might have been modified and need to be
|
||||
// synced to client or saved
|
||||
playerMP.inventory.markDirty();
|
||||
else if (built == -1) {
|
||||
if (built > 0) {
|
||||
playerMP.addChatMessage(new ChatComponentTranslation("structurelib.autoplace.built_stat", built));
|
||||
} else if (built == -1) {
|
||||
playerMP.addChatMessage(new ChatComponentTranslation("structurelib.autoplace.complete"));
|
||||
}
|
||||
setLastUseTickToStackTag(aStack);
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
package com.gtnewhorizon.structurelib.structure;
|
||||
|
||||
import static com.gtnewhorizon.structurelib.StructureLib.DEBUG_MODE;
|
||||
import static com.gtnewhorizon.structurelib.structure.IStructureWalker.ignoreBlockUnloaded;
|
||||
import static com.gtnewhorizon.structurelib.structure.IStructureWalker.skipBlockUnloaded;
|
||||
|
||||
import com.gtnewhorizon.structurelib.StructureLib;
|
||||
import com.gtnewhorizon.structurelib.alignment.enumerable.ExtendedFacing;
|
||||
import java.util.Arrays;
|
||||
import net.minecraft.entity.player.EntityPlayerMP;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.world.World;
|
||||
@@ -196,135 +197,67 @@ public interface IStructureDefinition<T> {
|
||||
return false;
|
||||
}
|
||||
|
||||
// change base position to base offset
|
||||
basePositionA = -basePositionA;
|
||||
basePositionB = -basePositionB;
|
||||
basePositionC = -basePositionC;
|
||||
|
||||
int[] abc = new int[] {basePositionA, basePositionB, basePositionC};
|
||||
int[] xyz = new int[3];
|
||||
|
||||
if (checkBlocksIfNotNullForceCheckAllIfTrue != null) {
|
||||
boolean success;
|
||||
if (checkBlocksIfNotNullForceCheckAllIfTrue) {
|
||||
for (IStructureElement<T> element : elements) {
|
||||
if (element.isNavigating()) {
|
||||
abc[0] = (element.resetA() ? basePositionA : abc[0]) + element.getStepA();
|
||||
abc[1] = (element.resetB() ? basePositionB : abc[1]) + element.getStepB();
|
||||
abc[2] = (element.resetC() ? basePositionC : abc[2]) + element.getStepC();
|
||||
} else {
|
||||
extendedFacing.getWorldOffset(abc, xyz);
|
||||
xyz[0] += basePositionX;
|
||||
xyz[1] += basePositionY;
|
||||
xyz[2] += basePositionZ;
|
||||
|
||||
StructureLib.LOGGER.info(
|
||||
"Multi [{}, {}, {}] step @ {} {}",
|
||||
basePositionX,
|
||||
basePositionY,
|
||||
basePositionZ,
|
||||
Arrays.toString(xyz),
|
||||
Arrays.toString(abc));
|
||||
|
||||
if (world.blockExists(xyz[0], xyz[1], xyz[2])) {
|
||||
if (!element.check(object, world, xyz[0], xyz[1], xyz[2])) {
|
||||
if (DEBUG_MODE) {
|
||||
StructureLib.LOGGER.info("Multi [" + basePositionX + ", " + basePositionY + ", "
|
||||
+ basePositionZ + "] failed @ " + Arrays.toString(xyz) + " "
|
||||
+ Arrays.toString(abc));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if (DEBUG_MODE) {
|
||||
StructureLib.LOGGER.info("Multi [" + basePositionX + ", " + basePositionY + ", "
|
||||
+ basePositionZ + "] !blockExists @ " + Arrays.toString(xyz) + " "
|
||||
+ Arrays.toString(abc));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
abc[0] += 1;
|
||||
}
|
||||
}
|
||||
success = StructureUtility.iterateV2(
|
||||
elements,
|
||||
world,
|
||||
extendedFacing,
|
||||
basePositionX,
|
||||
basePositionY,
|
||||
basePositionZ,
|
||||
basePositionA,
|
||||
basePositionB,
|
||||
basePositionC,
|
||||
(e, w, x, y, z) -> e.check(object, w, x, y, z),
|
||||
"check");
|
||||
} else {
|
||||
for (IStructureElement<T> element : elements) {
|
||||
if (element.isNavigating()) {
|
||||
abc[0] = (element.resetA() ? basePositionA : abc[0]) + element.getStepA();
|
||||
abc[1] = (element.resetB() ? basePositionB : abc[1]) + element.getStepB();
|
||||
abc[2] = (element.resetC() ? basePositionC : abc[2]) + element.getStepC();
|
||||
} else {
|
||||
extendedFacing.getWorldOffset(abc, xyz);
|
||||
xyz[0] += basePositionX;
|
||||
xyz[1] += basePositionY;
|
||||
xyz[2] += basePositionZ;
|
||||
|
||||
StructureLib.LOGGER.info(
|
||||
"Multi [{}, {}, {}] step @ {} {}",
|
||||
basePositionX,
|
||||
basePositionY,
|
||||
basePositionZ,
|
||||
Arrays.toString(xyz),
|
||||
Arrays.toString(abc));
|
||||
|
||||
if (world.blockExists(xyz[0], xyz[1], xyz[2])) {
|
||||
if (!element.check(object, world, xyz[0], xyz[1], xyz[2])) {
|
||||
if (DEBUG_MODE) {
|
||||
StructureLib.LOGGER.info("Multi [" + basePositionX + ", " + basePositionY + ", "
|
||||
+ basePositionZ + "] failed @ " + Arrays.toString(xyz) + " "
|
||||
+ Arrays.toString(abc));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if (DEBUG_MODE) {
|
||||
StructureLib.LOGGER.info("Multi [" + basePositionX + ", " + basePositionY + ", "
|
||||
+ basePositionZ + "] !blockExists @ " + Arrays.toString(xyz) + " "
|
||||
+ Arrays.toString(abc));
|
||||
}
|
||||
}
|
||||
abc[0] += 1;
|
||||
}
|
||||
}
|
||||
success = StructureUtility.iterateV2(
|
||||
elements,
|
||||
world,
|
||||
extendedFacing,
|
||||
basePositionX,
|
||||
basePositionY,
|
||||
basePositionZ,
|
||||
basePositionA,
|
||||
basePositionB,
|
||||
basePositionC,
|
||||
skipBlockUnloaded((e, w, x, y, z) -> e.check(object, w, x, y, z)),
|
||||
"check force");
|
||||
}
|
||||
if (DEBUG_MODE) {
|
||||
if (DEBUG_MODE && success) {
|
||||
StructureLib.LOGGER.info(
|
||||
"Multi [" + basePositionX + ", " + basePositionY + ", " + basePositionZ + "] pass");
|
||||
}
|
||||
return success;
|
||||
} else {
|
||||
if (hintsOnly) {
|
||||
for (IStructureElement<T> element : elements) {
|
||||
if (element.isNavigating()) {
|
||||
abc[0] = (element.resetA() ? basePositionA : abc[0]) + element.getStepA();
|
||||
abc[1] = (element.resetB() ? basePositionB : abc[1]) + element.getStepB();
|
||||
abc[2] = (element.resetC() ? basePositionC : abc[2]) + element.getStepC();
|
||||
} else {
|
||||
extendedFacing.getWorldOffset(abc, xyz);
|
||||
xyz[0] += basePositionX;
|
||||
xyz[1] += basePositionY;
|
||||
xyz[2] += basePositionZ;
|
||||
|
||||
element.spawnHint(object, world, xyz[0], xyz[1], xyz[2], trigger);
|
||||
|
||||
abc[0] += 1;
|
||||
}
|
||||
}
|
||||
StructureUtility.iterateV2(
|
||||
elements,
|
||||
world,
|
||||
extendedFacing,
|
||||
basePositionX,
|
||||
basePositionY,
|
||||
basePositionZ,
|
||||
basePositionA,
|
||||
basePositionB,
|
||||
basePositionC,
|
||||
ignoreBlockUnloaded((e, w, x, y, z) -> e.spawnHint(object, world, x, y, z, trigger)),
|
||||
"spawnHint");
|
||||
} else {
|
||||
for (IStructureElement<T> element : elements) {
|
||||
if (element.isNavigating()) {
|
||||
abc[0] = (element.resetA() ? basePositionA : abc[0]) + element.getStepA();
|
||||
abc[1] = (element.resetB() ? basePositionB : abc[1]) + element.getStepB();
|
||||
abc[2] = (element.resetC() ? basePositionC : abc[2]) + element.getStepC();
|
||||
} else {
|
||||
extendedFacing.getWorldOffset(abc, xyz);
|
||||
xyz[0] += basePositionX;
|
||||
xyz[1] += basePositionY;
|
||||
xyz[2] += basePositionZ;
|
||||
|
||||
if (world.blockExists(xyz[0], xyz[1], xyz[2])) {
|
||||
element.placeBlock(object, world, xyz[0], xyz[1], xyz[2], trigger);
|
||||
}
|
||||
abc[0] += 1;
|
||||
}
|
||||
}
|
||||
StructureUtility.iterateV2(
|
||||
elements,
|
||||
world,
|
||||
extendedFacing,
|
||||
basePositionX,
|
||||
basePositionY,
|
||||
basePositionZ,
|
||||
basePositionA,
|
||||
basePositionB,
|
||||
basePositionC,
|
||||
ignoreBlockUnloaded((e, w, x, y, z) -> e.placeBlock(object, world, x, y, z, trigger)),
|
||||
"placeBlock");
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
||||
@@ -4,4 +4,36 @@ import net.minecraft.world.World;
|
||||
|
||||
public interface IStructureWalker<T> {
|
||||
boolean visit(IStructureElement<T> element, World world, int x, int y, int z);
|
||||
|
||||
default boolean blockNotLoaded(IStructureElement<T> element, World world, int x, int y, int z) {
|
||||
return false;
|
||||
}
|
||||
|
||||
static <T> IStructureWalker<T> ignoreBlockUnloaded(IStructureWalker<T> walker) {
|
||||
return new IStructureWalker<T>() {
|
||||
@Override
|
||||
public boolean visit(IStructureElement<T> element, World world, int x, int y, int z) {
|
||||
return walker.visit(element, world, x, y, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean blockNotLoaded(IStructureElement<T> element, World world, int x, int y, int z) {
|
||||
return walker.visit(element, world, x, y, z);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
static <T> IStructureWalker<T> skipBlockUnloaded(IStructureWalker<T> walker) {
|
||||
return new IStructureWalker<T>() {
|
||||
@Override
|
||||
public boolean visit(IStructureElement<T> element, World world, int x, int y, int z) {
|
||||
return walker.visit(element, world, x, y, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean blockNotLoaded(IStructureElement<T> element, World world, int x, int y, int z) {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -427,9 +427,16 @@ public class StructureUtility {
|
||||
IItemSource s,
|
||||
EntityPlayerMP actor,
|
||||
Consumer<IChatComponent> chatter) {
|
||||
if (check(t, world, x, y, z)) return PlaceResult.SKIP;
|
||||
Pair<Block, Integer> hint = getHint(trigger);
|
||||
if (hint == null) return PlaceResult.REJECT; // TODO or SKIP?
|
||||
Block block = world.getBlock(x, y, z);
|
||||
int meta = world.getBlockMetadata(x, y, z);
|
||||
TIER tier = tierExtractor.convert(block, meta);
|
||||
if (!Objects.equals(tier, notSet)) {
|
||||
return Objects.equals(tier, tierExtractor.convert(hint.getKey(), hint.getValue()))
|
||||
? PlaceResult.SKIP
|
||||
: PlaceResult.REJECT;
|
||||
}
|
||||
return StructureUtility.survivalPlaceBlock(
|
||||
hint.getKey(), hint.getValue(), world, x, y, z, s, actor, chatter);
|
||||
}
|
||||
@@ -2209,14 +2216,15 @@ public class StructureUtility {
|
||||
xyz[1] += basePositionY;
|
||||
xyz[2] += basePositionZ;
|
||||
|
||||
StructureLib.LOGGER.info(
|
||||
"Multi [{}, {}, {}] {} step @ {} {}",
|
||||
basePositionX,
|
||||
basePositionY,
|
||||
basePositionZ,
|
||||
iterateType,
|
||||
Arrays.toString(xyz),
|
||||
Arrays.toString(abc));
|
||||
if (DEBUG_MODE)
|
||||
StructureLib.LOGGER.info(
|
||||
"Multi [{}, {}, {}] {} step @ {} {}",
|
||||
basePositionX,
|
||||
basePositionY,
|
||||
basePositionZ,
|
||||
iterateType,
|
||||
Arrays.toString(xyz),
|
||||
Arrays.toString(abc));
|
||||
|
||||
if (world.blockExists(xyz[0], xyz[1], xyz[2])) {
|
||||
if (!predicate.visit(element, world, xyz[0], xyz[1], xyz[2])) {
|
||||
@@ -2243,7 +2251,7 @@ public class StructureUtility {
|
||||
Arrays.toString(xyz),
|
||||
Arrays.toString(abc));
|
||||
}
|
||||
return false;
|
||||
if (!predicate.blockNotLoaded(element, world, xyz[0], xyz[1], xyz[2])) return false;
|
||||
}
|
||||
abc[0] += 1;
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
*/
|
||||
package com.gtnewhorizon.structurelib.util;
|
||||
|
||||
import com.gtnewhorizon.gtnhlib.util.map.ItemStackMap;
|
||||
import com.gtnewhorizon.structurelib.util.InventoryUtility.ItemStackExtractor.APIType;
|
||||
import com.gtnewhorizon.structurelib.util.ItemStackPredicate.NBTMode;
|
||||
import java.util.*;
|
||||
|
||||
@@ -1,464 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2021, glee8e, Code Chicken.
|
||||
*
|
||||
* This file is originally part of NotEnoughtItem by Code Chicken.
|
||||
* It is adapted to implement the standard Map interface by glease
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 2.1 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.gtnewhorizon.structurelib.util;
|
||||
|
||||
import static net.minecraftforge.oredict.OreDictionary.WILDCARD_VALUE;
|
||||
|
||||
import com.google.common.base.Objects;
|
||||
import com.google.common.collect.Iterators;
|
||||
import java.util.AbstractMap;
|
||||
import java.util.AbstractSet;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.NoSuchElementException;
|
||||
import java.util.Set;
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
import net.minecraft.init.Items;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
|
||||
/**
|
||||
* A map class for ItemStack keys with wildcard damage/NBT. Optimised for lookup.
|
||||
* <p>
|
||||
* This map does NOT support null values or null keys! null will be silently ignored!
|
||||
* <p>
|
||||
* Originally created by CodeChicken for NotEnoughItems. Adapted to {@code Map<ItemStack, T>} interface by glee8e
|
||||
* @author CodeChiken
|
||||
* @author glee8e
|
||||
*/
|
||||
public final class ItemStackMap<T> extends AbstractMap<ItemStack, T> {
|
||||
public static final NBTTagCompound WILDCARD_TAG;
|
||||
|
||||
static {
|
||||
WILDCARD_TAG = new NBTTagCompound();
|
||||
WILDCARD_TAG.setBoolean("*", true);
|
||||
}
|
||||
|
||||
private final HashMap<Item, DetailMap> itemMap = new HashMap<>();
|
||||
private int size;
|
||||
|
||||
static ItemStack newItemStack(Item item, int size, int damage, NBTTagCompound tag) {
|
||||
ItemStack stack = new ItemStack(item, size, damage);
|
||||
stack.stackTagCompound = tag;
|
||||
return stack;
|
||||
}
|
||||
|
||||
static int actualDamage(ItemStack stack) {
|
||||
return Items.diamond.getDamage(stack);
|
||||
}
|
||||
|
||||
static int getKeyType(int damage, NBTTagCompound tag) {
|
||||
int i = 0;
|
||||
if (isWildcard(damage)) i = 1;
|
||||
if (isWildcard(tag)) i |= 2;
|
||||
return i;
|
||||
}
|
||||
|
||||
static ItemStack wildcard(Item item) {
|
||||
return newItemStack(item, 1, WILDCARD_VALUE, WILDCARD_TAG);
|
||||
}
|
||||
|
||||
static boolean isWildcard(int damage) {
|
||||
return damage == WILDCARD_VALUE;
|
||||
}
|
||||
|
||||
static boolean isWildcard(NBTTagCompound tag) {
|
||||
return tag != null && tag.getBoolean("*");
|
||||
}
|
||||
|
||||
@Override
|
||||
public T get(Object key) {
|
||||
if (!(key instanceof ItemStack)) return null;
|
||||
ItemStack stack = ((ItemStack) key);
|
||||
if (stack.getItem() == null) return null;
|
||||
DetailMap map = itemMap.get(stack.getItem());
|
||||
return map == null ? null : map.get(stack);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T put(ItemStack key, T value) {
|
||||
if (key == null || key.getItem() == null || value == null) return null;
|
||||
return itemMap.computeIfAbsent(key.getItem(), k -> new DetailMap()).put(key, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T remove(Object key) {
|
||||
if (!(key instanceof ItemStack)) return null;
|
||||
ItemStack stack = ((ItemStack) key);
|
||||
if (stack.getItem() == null) return null;
|
||||
DetailMap map = itemMap.get(stack.getItem());
|
||||
return map == null ? null : map.remove(stack);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean containsKey(Object key) {
|
||||
if (!(key instanceof ItemStack)) return false;
|
||||
ItemStack stack = ((ItemStack) key);
|
||||
if (stack.getItem() == null) return false;
|
||||
DetailMap map = itemMap.get(stack.getItem());
|
||||
return map != null && map.get(stack) != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
itemMap.clear();
|
||||
size = 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<Map.Entry<ItemStack, T>> entrySet() {
|
||||
return new SetView();
|
||||
}
|
||||
|
||||
private static class StackMetaKey {
|
||||
public final int damage;
|
||||
public final NBTTagCompound tag;
|
||||
|
||||
public StackMetaKey(int damage, NBTTagCompound tag) {
|
||||
this.damage = damage;
|
||||
this.tag = tag;
|
||||
}
|
||||
|
||||
public StackMetaKey(ItemStack key) {
|
||||
this(actualDamage(key), key.stackTagCompound);
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return Objects.hashCode(damage, tag);
|
||||
}
|
||||
|
||||
public boolean equals(Object o) {
|
||||
if (!(o instanceof StackMetaKey)) return false;
|
||||
StackMetaKey t = (StackMetaKey) o;
|
||||
return damage == t.damage && Objects.equal(tag, t.tag);
|
||||
}
|
||||
}
|
||||
|
||||
private static class DetailIter<T> implements Iterator<Map.Entry<ItemStack, T>> {
|
||||
private final Item owner;
|
||||
private final ItemStackMap<T>.DetailMap backing;
|
||||
|
||||
@Nullable
|
||||
private final Iterator<Map.Entry<Integer, T>> damageIter;
|
||||
|
||||
@Nullable
|
||||
private final Iterator<Map.Entry<NBTTagCompound, T>> tagIter;
|
||||
|
||||
@Nullable
|
||||
private final Iterator<Map.Entry<StackMetaKey, T>> metaIter;
|
||||
|
||||
private DetailIterState state = DetailIterState.NOT_STARTED;
|
||||
private boolean removed = false;
|
||||
|
||||
private DetailIter(Map.Entry<Item, ItemStackMap<T>.DetailMap> input) {
|
||||
this.owner = input.getKey();
|
||||
this.backing = input.getValue();
|
||||
damageIter =
|
||||
backing.damageMap != null ? backing.damageMap.entrySet().iterator() : null;
|
||||
tagIter = backing.tagMap != null ? backing.tagMap.entrySet().iterator() : null;
|
||||
metaIter = backing.metaMap != null ? backing.metaMap.entrySet().iterator() : null;
|
||||
}
|
||||
|
||||
private DetailIterState nextState() {
|
||||
switch (state) {
|
||||
case NOT_STARTED:
|
||||
if (backing.hasWildcard) return DetailIterState.WILDCARD;
|
||||
case WILDCARD:
|
||||
case DAMAGE:
|
||||
if (damageIter != null && damageIter.hasNext()) return DetailIterState.DAMAGE;
|
||||
case TAG:
|
||||
if (tagIter != null && tagIter.hasNext()) return DetailIterState.TAG;
|
||||
case META:
|
||||
if (metaIter != null && metaIter.hasNext()) return DetailIterState.META;
|
||||
case DONE:
|
||||
return DetailIterState.DONE;
|
||||
default:
|
||||
throw new IllegalStateException("Unexpected value: " + state);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove() {
|
||||
if (removed) throw new IllegalStateException("remove() called twice");
|
||||
state.remove(this);
|
||||
removed = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return nextState() != DetailIterState.DONE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map.Entry<ItemStack, T> next() {
|
||||
DetailIterState nextState = nextState();
|
||||
if (nextState == DetailIterState.DONE) throw new NoSuchElementException();
|
||||
state = nextState;
|
||||
removed = false;
|
||||
return nextState.get(this);
|
||||
}
|
||||
|
||||
private enum DetailIterState {
|
||||
NOT_STARTED {
|
||||
@Override
|
||||
<T> Map.Entry<ItemStack, T> get(DetailIter<T> iter) {
|
||||
throw new AssertionError("Should not call get on NOT_STARTED");
|
||||
}
|
||||
|
||||
@Override
|
||||
<T> void remove(DetailIter<T> iter) {
|
||||
throw new IllegalStateException("next() never called");
|
||||
}
|
||||
},
|
||||
WILDCARD {
|
||||
@Override
|
||||
<T> Map.Entry<ItemStack, T> get(DetailIter<T> iter) {
|
||||
return new Map.Entry<ItemStack, T>() {
|
||||
private final ItemStack key = wildcard(iter.owner);
|
||||
|
||||
@Override
|
||||
public ItemStack getKey() {
|
||||
return key;
|
||||
}
|
||||
|
||||
@Override
|
||||
public T getValue() {
|
||||
return iter.backing.wildcard;
|
||||
}
|
||||
|
||||
@Override
|
||||
public T setValue(T value) {
|
||||
return iter.backing.wildcard = value;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
<T> void remove(DetailIter<T> iter) {
|
||||
assert iter.backing.hasWildcard;
|
||||
iter.backing.wildcard = null;
|
||||
iter.backing.hasWildcard = false;
|
||||
}
|
||||
},
|
||||
DAMAGE {
|
||||
@Override
|
||||
<T> Map.Entry<ItemStack, T> get(DetailIter<T> iter) {
|
||||
assert iter.damageIter != null;
|
||||
Map.Entry<Integer, T> entry = iter.damageIter.next();
|
||||
return new ItemStackEntry<>(newItemStack(iter.owner, 1, entry.getKey(), WILDCARD_TAG), entry);
|
||||
}
|
||||
|
||||
@Override
|
||||
<T> void remove(DetailIter<T> iter) {
|
||||
assert iter.damageIter != null;
|
||||
iter.damageIter.remove();
|
||||
}
|
||||
},
|
||||
TAG {
|
||||
@Override
|
||||
<T> Map.Entry<ItemStack, T> get(DetailIter<T> iter) {
|
||||
assert iter.tagIter != null;
|
||||
Map.Entry<NBTTagCompound, T> entry = iter.tagIter.next();
|
||||
return new ItemStackEntry<>(newItemStack(iter.owner, 1, WILDCARD_VALUE, entry.getKey()), entry);
|
||||
}
|
||||
|
||||
@Override
|
||||
<T> void remove(DetailIter<T> iter) {
|
||||
assert iter.tagIter != null;
|
||||
iter.tagIter.remove();
|
||||
}
|
||||
},
|
||||
META {
|
||||
@Override
|
||||
<T> Map.Entry<ItemStack, T> get(DetailIter<T> iter) {
|
||||
assert iter.metaIter != null;
|
||||
Map.Entry<StackMetaKey, T> entry = iter.metaIter.next();
|
||||
return new ItemStackEntry<>(
|
||||
newItemStack(iter.owner, 1, entry.getKey().damage, entry.getKey().tag), entry);
|
||||
}
|
||||
|
||||
@Override
|
||||
<T> void remove(DetailIter<T> iter) {
|
||||
assert iter.metaIter != null;
|
||||
iter.metaIter.remove();
|
||||
}
|
||||
},
|
||||
DONE {
|
||||
@Override
|
||||
<T> Map.Entry<ItemStack, T> get(DetailIter<T> iter) {
|
||||
throw new AssertionError("Should not call get on DONE");
|
||||
}
|
||||
|
||||
@Override
|
||||
<T> void remove(DetailIter<T> iter) {
|
||||
throw new AssertionError("Should not call remove on DONE");
|
||||
}
|
||||
};
|
||||
|
||||
abstract <T> Map.Entry<ItemStack, T> get(DetailIter<T> iter);
|
||||
|
||||
abstract <T> void remove(DetailIter<T> iter);
|
||||
|
||||
private static class ItemStackEntry<T> implements Map.Entry<ItemStack, T> {
|
||||
private final ItemStack key;
|
||||
private final Map.Entry<?, T> entry;
|
||||
|
||||
public ItemStackEntry(ItemStack key, Map.Entry<?, T> entry) {
|
||||
this.key = key;
|
||||
this.entry = entry;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack getKey() {
|
||||
return key;
|
||||
}
|
||||
|
||||
@Override
|
||||
public T getValue() {
|
||||
return entry.getValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public T setValue(T value) {
|
||||
return entry.setValue(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class DetailMap {
|
||||
private boolean hasWildcard;
|
||||
private T wildcard;
|
||||
private HashMap<Integer, T> damageMap;
|
||||
private HashMap<NBTTagCompound, T> tagMap;
|
||||
private HashMap<StackMetaKey, T> metaMap;
|
||||
private int size;
|
||||
|
||||
public T get(ItemStack key) {
|
||||
if (wildcard != null) return wildcard;
|
||||
|
||||
if (damageMap != null) {
|
||||
final T ret = damageMap.get(actualDamage(key));
|
||||
if (ret != null) return ret;
|
||||
}
|
||||
if (tagMap != null) {
|
||||
final T ret = tagMap.get(key.stackTagCompound);
|
||||
if (ret != null) return ret;
|
||||
}
|
||||
if (metaMap != null) return metaMap.get(new StackMetaKey(key));
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public T put(ItemStack key, T value) {
|
||||
try {
|
||||
switch (getKeyType(actualDamage(key), key.stackTagCompound)) {
|
||||
case 0:
|
||||
if (metaMap == null) metaMap = new HashMap<>();
|
||||
return metaMap.put(new StackMetaKey(key), value);
|
||||
case 1:
|
||||
if (tagMap == null) tagMap = new HashMap<>();
|
||||
return tagMap.put(key.stackTagCompound, value);
|
||||
case 2:
|
||||
if (damageMap == null) damageMap = new HashMap<>();
|
||||
return damageMap.put(actualDamage(key), value);
|
||||
case 3:
|
||||
T ret = wildcard;
|
||||
wildcard = value;
|
||||
hasWildcard = true;
|
||||
return ret;
|
||||
}
|
||||
} finally {
|
||||
updateSize();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public T remove(ItemStack key) {
|
||||
try {
|
||||
switch (getKeyType(actualDamage(key), key.stackTagCompound)) {
|
||||
case 0:
|
||||
return metaMap != null ? metaMap.remove(new StackMetaKey(key)) : null;
|
||||
case 1:
|
||||
return tagMap != null ? tagMap.remove(key.stackTagCompound) : null;
|
||||
case 2:
|
||||
return damageMap != null ? damageMap.remove(actualDamage(key)) : null;
|
||||
case 3:
|
||||
T ret = wildcard;
|
||||
wildcard = null;
|
||||
hasWildcard = false;
|
||||
return ret;
|
||||
}
|
||||
} finally {
|
||||
updateSize();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private void updateSize() {
|
||||
int newSize = (hasWildcard ? 1 : 0)
|
||||
+ (metaMap != null ? metaMap.size() : 0)
|
||||
+ (tagMap != null ? tagMap.size() : 0)
|
||||
+ (damageMap != null ? damageMap.size() : 0);
|
||||
|
||||
if (newSize != size) {
|
||||
ItemStackMap.this.size += newSize - size;
|
||||
size = newSize;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class SetView extends AbstractSet<Map.Entry<ItemStack, T>> {
|
||||
@Override
|
||||
public boolean contains(Object o) {
|
||||
if (!(o instanceof Map.Entry)) return false;
|
||||
Map.Entry<?, ?> entry = (Map.Entry<?, ?>) o;
|
||||
return java.util.Objects.equals(get(entry.getKey()), entry.getValue());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean add(Map.Entry<ItemStack, T> itemStackTEntry) {
|
||||
return itemStackTEntry.getKey() != null
|
||||
&& itemStackTEntry.getValue() != null
|
||||
&& put(itemStackTEntry.getKey(), itemStackTEntry.getValue()) == null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean remove(Object o) {
|
||||
if (!(o instanceof Map.Entry)) return false;
|
||||
Map.Entry<?, ?> entry = (Map.Entry<?, ?>) o;
|
||||
return ItemStackMap.this.remove(entry.getKey(), entry.getValue());
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public Iterator<Map.Entry<ItemStack, T>> iterator() {
|
||||
return Iterators.concat(Iterators.transform(itemMap.entrySet().iterator(), DetailIter::new));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return size;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -28,6 +28,7 @@ item.structurelib.constructableTrigger.desc.3=(Sneak use on controller to build)
|
||||
item.structurelib.constructableTrigger.desc.4=Quantity of schematics in item stack affects tier/mode/type
|
||||
item.structurelib.constructableTrigger.too_fast=Please wait %d ticks before another autoplace...
|
||||
|
||||
structurelib.autoplace.built_stat=Built %s blocks
|
||||
structurelib.autoplace.complete=§aThis multiblock has completed!
|
||||
structurelib.autoplace.error.not_enabled=§cThis multiblock does not support autoplace in survival!
|
||||
structurelib.autoplace.error.no_simple_block=§cSuggested to place §r%s§c but none was found
|
||||
|
||||
@@ -24,9 +24,14 @@ item.structurelib.constructableTrigger.name=多方块结构全息投影仪
|
||||
item.structurelib.constructableTrigger.desc.0=可以显示多方块机器的结构
|
||||
item.structurelib.constructableTrigger.desc.1=只能在多方块主机上使用,将会显示机器
|
||||
item.structurelib.constructableTrigger.desc.2=结构的示意图。 (译者注:请搭高使用)
|
||||
item.structurelib.constructableTrigger.desc.3= (创造模式下潜行右键可以直接完成搭建)
|
||||
item.structurelib.constructableTrigger.desc.3= (潜行右键可以直接完成搭建)
|
||||
item.structurelib.constructableTrigger.desc.4=此物品堆叠数量会影响显示的机器等级/模式/类型
|
||||
item.structurelib.constructableTrigger.too_fast=Please wait %d ticks before another autoplace...
|
||||
item.structurelib.constructableTrigger.too_fast=请在下一次自动搭建前等待%dtick...
|
||||
|
||||
structurelib.autoplace.complete=§a这个多方块结构已经完成自动搭建!
|
||||
structurelib.autoplace.error.not_enabled=§c这个多方块结构不支持在生存模式下自动搭建!
|
||||
structurelib.autoplace.error.no_simple_block=§c建议放置§r%s§c,但没有找到它
|
||||
structurelib.autoplace.error.no_item_stack=§c建议使用§r%s§c放置方块,但没有找到它
|
||||
|
||||
structurelib.blockhint.desc.0=帮助你搭建机器
|
||||
structurelib.blockhint.0.name=提示方块:1号
|
||||
|
||||
Reference in new issue
Block a user