new Builder block picking logic
This commit is contained in:
parent
9808a7986e
commit
36e63d2baf
4 changed files with 245 additions and 65 deletions
|
@ -15,9 +15,13 @@ import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
import java.util.ListIterator;
|
import java.util.ListIterator;
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
|
|
||||||
|
import com.google.common.collect.HashMultiset;
|
||||||
|
import com.google.common.collect.Multiset;
|
||||||
|
|
||||||
import net.minecraft.init.Blocks;
|
import net.minecraft.init.Blocks;
|
||||||
import net.minecraft.inventory.IInventory;
|
import net.minecraft.inventory.IInventory;
|
||||||
import net.minecraft.item.Item;
|
import net.minecraft.item.Item;
|
||||||
|
@ -40,11 +44,12 @@ import buildcraft.api.core.BCLog;
|
||||||
import buildcraft.api.core.BuildCraftAPI;
|
import buildcraft.api.core.BuildCraftAPI;
|
||||||
import buildcraft.api.core.IInvSlot;
|
import buildcraft.api.core.IInvSlot;
|
||||||
import buildcraft.api.core.StackKey;
|
import buildcraft.api.core.StackKey;
|
||||||
|
import buildcraft.core.builders.BuilderItemMetaPair;
|
||||||
import buildcraft.core.builders.BuildingSlot;
|
import buildcraft.core.builders.BuildingSlot;
|
||||||
import buildcraft.core.builders.BuildingSlotBlock;
|
import buildcraft.core.builders.BuildingSlotBlock;
|
||||||
import buildcraft.core.builders.BuildingSlotBlock.Mode;
|
import buildcraft.core.builders.BuildingSlotBlock.Mode;
|
||||||
import buildcraft.core.builders.BuildingSlotEntity;
|
import buildcraft.core.builders.BuildingSlotEntity;
|
||||||
import buildcraft.core.builders.BuildingSlotIterator;
|
import buildcraft.core.builders.BuildingSlotMapIterator;
|
||||||
import buildcraft.core.builders.IBuildingItemsProvider;
|
import buildcraft.core.builders.IBuildingItemsProvider;
|
||||||
import buildcraft.core.builders.TileAbstractBuilder;
|
import buildcraft.core.builders.TileAbstractBuilder;
|
||||||
import buildcraft.core.lib.inventory.InventoryCopy;
|
import buildcraft.core.lib.inventory.InventoryCopy;
|
||||||
|
@ -58,10 +63,11 @@ public class BptBuilderBlueprint extends BptBuilderBase {
|
||||||
|
|
||||||
protected HashSet<Integer> builtEntities = new HashSet<Integer>();
|
protected HashSet<Integer> builtEntities = new HashSet<Integer>();
|
||||||
|
|
||||||
private LinkedList<BuildingSlotBlock> buildList = new LinkedList<BuildingSlotBlock>();
|
private HashMap<BuilderItemMetaPair, List<BuildingSlotBlock>> buildList = new HashMap<BuilderItemMetaPair, List<BuildingSlotBlock>>();
|
||||||
|
private Multiset<Integer> buildStageOccurences = HashMultiset.create();
|
||||||
private LinkedList<BuildingSlotEntity> entityList = new LinkedList<BuildingSlotEntity>();
|
private LinkedList<BuildingSlotEntity> entityList = new LinkedList<BuildingSlotEntity>();
|
||||||
private LinkedList<BuildingSlot> postProcessing = new LinkedList<BuildingSlot>();
|
private LinkedList<BuildingSlot> postProcessing = new LinkedList<BuildingSlot>();
|
||||||
private BuildingSlotIterator iterator;
|
private BuildingSlotMapIterator iterator;
|
||||||
|
|
||||||
public BptBuilderBlueprint(Blueprint bluePrint, World world, int x, int y, int z) {
|
public BptBuilderBlueprint(Blueprint bluePrint, World world, int x, int y, int z) {
|
||||||
super(bluePrint, world, x, y, z);
|
super(bluePrint, world, x, y, z);
|
||||||
|
@ -105,9 +111,8 @@ public class BptBuilderBlueprint extends BptBuilderBase {
|
||||||
b.mode = Mode.ClearIfInvalid;
|
b.mode = Mode.ClearIfInvalid;
|
||||||
b.buildStage = 0;
|
b.buildStage = 0;
|
||||||
|
|
||||||
buildList.add(b);
|
addToBuildList(b);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -163,11 +168,15 @@ public class BptBuilderBlueprint extends BptBuilderBase {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
buildList.addAll(tmpStandalone);
|
for (BuildingSlotBlock b : tmpStandalone) {
|
||||||
buildList.addAll(tmpSupported);
|
addToBuildList(b);
|
||||||
buildList.addAll(tmpExpanding);
|
}
|
||||||
|
for (BuildingSlotBlock b : tmpSupported) {
|
||||||
iterator = new BuildingSlotIterator(buildList);
|
addToBuildList(b);
|
||||||
|
}
|
||||||
|
for (BuildingSlotBlock b : tmpExpanding) {
|
||||||
|
addToBuildList(b);
|
||||||
|
}
|
||||||
|
|
||||||
int seqId = 0;
|
int seqId = 0;
|
||||||
|
|
||||||
|
@ -192,7 +201,8 @@ public class BptBuilderBlueprint extends BptBuilderBase {
|
||||||
public void deploy () {
|
public void deploy () {
|
||||||
initialize();
|
initialize();
|
||||||
|
|
||||||
for (BuildingSlotBlock b : buildList) {
|
for (List<BuildingSlotBlock> lb : buildList.values()) {
|
||||||
|
for (BuildingSlotBlock b : lb) {
|
||||||
if (b.mode == Mode.ClearIfInvalid) {
|
if (b.mode == Mode.ClearIfInvalid) {
|
||||||
context.world.setBlockToAir(b.x, b.y, b.z);
|
context.world.setBlockToAir(b.x, b.y, b.z);
|
||||||
} else if (!b.schematic.doNotBuild()) {
|
} else if (!b.schematic.doNotBuild()) {
|
||||||
|
@ -213,6 +223,7 @@ public class BptBuilderBlueprint extends BptBuilderBase {
|
||||||
b.writeToWorld(context);
|
b.writeToWorld(context);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (BuildingSlotEntity e : entityList) {
|
for (BuildingSlotEntity e : entityList) {
|
||||||
e.stackConsumed = new LinkedList<ItemStack>();
|
e.stackConsumed = new LinkedList<ItemStack>();
|
||||||
|
@ -232,11 +243,13 @@ public class BptBuilderBlueprint extends BptBuilderBase {
|
||||||
e.writeToWorld(context);
|
e.writeToWorld(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (BuildingSlotBlock b : buildList) {
|
for (List<BuildingSlotBlock> lb : buildList.values()) {
|
||||||
|
for (BuildingSlotBlock b : lb) {
|
||||||
if (b.mode != Mode.ClearIfInvalid) {
|
if (b.mode != Mode.ClearIfInvalid) {
|
||||||
b.postProcessing(context);
|
b.postProcessing(context);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (BuildingSlotEntity e : entityList) {
|
for (BuildingSlotEntity e : entityList) {
|
||||||
e.postProcessing(context);
|
e.postProcessing(context);
|
||||||
|
@ -246,16 +259,24 @@ public class BptBuilderBlueprint extends BptBuilderBase {
|
||||||
private void checkDone() {
|
private void checkDone() {
|
||||||
recomputeNeededItems();
|
recomputeNeededItems();
|
||||||
|
|
||||||
if (buildList.size() == 0 && entityList.size() == 0) {
|
if (getBuildListCount() == 0 && entityList.size() == 0) {
|
||||||
done = true;
|
done = true;
|
||||||
} else {
|
} else {
|
||||||
done = false;
|
done = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private int getBuildListCount() {
|
||||||
|
int out = 0;
|
||||||
|
for (int i = 0; i < 4; i++) {
|
||||||
|
out += buildStageOccurences.count(i);
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BuildingSlot reserveNextBlock(World world) {
|
public BuildingSlot reserveNextBlock(World world) {
|
||||||
if (buildList.size() != 0) {
|
if (getBuildListCount() != 0) {
|
||||||
BuildingSlot slot = internalGetNextBlock(world, null);
|
BuildingSlot slot = internalGetNextBlock(world, null);
|
||||||
checkDone();
|
checkDone();
|
||||||
|
|
||||||
|
@ -269,9 +290,20 @@ public class BptBuilderBlueprint extends BptBuilderBase {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void addToBuildList(BuildingSlotBlock b) {
|
||||||
|
if (b != null) {
|
||||||
|
BuilderItemMetaPair imp = new BuilderItemMetaPair(context, b);
|
||||||
|
if (!buildList.containsKey(imp)) {
|
||||||
|
buildList.put(imp, new ArrayList<BuildingSlotBlock>());
|
||||||
|
}
|
||||||
|
buildList.get(imp).add(b);
|
||||||
|
buildStageOccurences.add(b.buildStage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BuildingSlot getNextBlock(World world, TileAbstractBuilder inv) {
|
public BuildingSlot getNextBlock(World world, TileAbstractBuilder inv) {
|
||||||
if (buildList.size() != 0) {
|
if (getBuildListCount() != 0) {
|
||||||
BuildingSlot slot = internalGetNextBlock(world, inv);
|
BuildingSlot slot = internalGetNextBlock(world, inv);
|
||||||
checkDone();
|
checkDone();
|
||||||
return slot;
|
return slot;
|
||||||
|
@ -294,27 +326,29 @@ public class BptBuilderBlueprint extends BptBuilderBase {
|
||||||
*/
|
*/
|
||||||
private BuildingSlot internalGetNextBlock(World world, TileAbstractBuilder builder) {
|
private BuildingSlot internalGetNextBlock(World world, TileAbstractBuilder builder) {
|
||||||
if (builder != null && builder.energyAvailable() < BuilderAPI.BREAK_ENERGY) {
|
if (builder != null && builder.energyAvailable() < BuilderAPI.BREAK_ENERGY) {
|
||||||
// If there's no more energy available, then set reset the list and
|
|
||||||
// quit. This will avoid situations where energy is given at a
|
|
||||||
// random point in time, and therefore builder doesn't start from
|
|
||||||
// the expected point.
|
|
||||||
|
|
||||||
iterator.reset();
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
iterator.startIteration();
|
iterator = new BuildingSlotMapIterator(buildList, builder, buildStageOccurences);
|
||||||
|
BuildingSlotBlock slot;
|
||||||
while (iterator.hasNext()) {
|
|
||||||
BuildingSlotBlock slot = iterator.next();
|
|
||||||
|
|
||||||
|
while ((slot = iterator.next()) != null) {
|
||||||
if (!world.blockExists(slot.x, slot.y, slot.z)) {
|
if (!world.blockExists(slot.x, slot.y, slot.z)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (slot.buildStage > buildList.getFirst().buildStage) {
|
boolean skipped = false;
|
||||||
iterator.reset();
|
|
||||||
return null;
|
for (int i = 0; i < slot.buildStage; i++) {
|
||||||
|
if (buildStageOccurences.count(i) > 0) {
|
||||||
|
iterator.skipList();
|
||||||
|
skipped = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (skipped) {
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (slot.built) {
|
if (slot.built) {
|
||||||
|
@ -599,7 +633,12 @@ public class BptBuilderBlueprint extends BptBuilderBase {
|
||||||
|
|
||||||
HashMap<StackKey, Integer> computeStacks = new HashMap<StackKey, Integer>();
|
HashMap<StackKey, Integer> computeStacks = new HashMap<StackKey, Integer>();
|
||||||
|
|
||||||
for (BuildingSlot slot : buildList) {
|
for (List<BuildingSlotBlock> lb : buildList.values()) {
|
||||||
|
for (BuildingSlotBlock slot : lb) {
|
||||||
|
if (slot == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
LinkedList<ItemStack> stacks = new LinkedList<ItemStack>();
|
LinkedList<ItemStack> stacks = new LinkedList<ItemStack>();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
@ -627,6 +666,7 @@ public class BptBuilderBlueprint extends BptBuilderBase {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (BuildingSlotEntity slot : entityList) {
|
for (BuildingSlotEntity slot : entityList) {
|
||||||
LinkedList<ItemStack> stacks = new LinkedList<ItemStack>();
|
LinkedList<ItemStack> stacks = new LinkedList<ItemStack>();
|
||||||
|
|
48
common/buildcraft/core/builders/BuilderItemMetaPair.java
Normal file
48
common/buildcraft/core/builders/BuilderItemMetaPair.java
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
package buildcraft.core.builders;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import net.minecraft.init.Blocks;
|
||||||
|
import net.minecraft.item.Item;
|
||||||
|
import net.minecraft.item.ItemStack;
|
||||||
|
|
||||||
|
import buildcraft.api.blueprints.IBuilderContext;
|
||||||
|
|
||||||
|
public class BuilderItemMetaPair {
|
||||||
|
public Item item;
|
||||||
|
public int meta;
|
||||||
|
|
||||||
|
public BuilderItemMetaPair(ItemStack stack) {
|
||||||
|
if (stack != null) {
|
||||||
|
this.item = stack.getItem();
|
||||||
|
this.meta = stack.getItemDamage();
|
||||||
|
} else {
|
||||||
|
this.item = Item.getItemFromBlock(Blocks.air);
|
||||||
|
this.meta = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public BuilderItemMetaPair(IBuilderContext context, BuildingSlotBlock block) {
|
||||||
|
this(findStack(context, block));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ItemStack findStack(IBuilderContext context, BuildingSlotBlock block) {
|
||||||
|
List<ItemStack> s = block.getRequirements(context);
|
||||||
|
return s.size() > 0 ? s.get(0) : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (o instanceof BuilderItemMetaPair) {
|
||||||
|
BuilderItemMetaPair imp = (BuilderItemMetaPair) o;
|
||||||
|
return imp.item == item && imp.meta == meta;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Item.getIdFromItem(item) * 17 + meta;
|
||||||
|
}
|
||||||
|
}
|
|
@ -14,7 +14,7 @@ import java.util.LinkedList;
|
||||||
public class BuildingSlotIterator {
|
public class BuildingSlotIterator {
|
||||||
private static int ITERATIONS_MAX = 500;
|
private static int ITERATIONS_MAX = 500;
|
||||||
|
|
||||||
private LinkedList<BuildingSlotBlock> buildList;
|
private final LinkedList<BuildingSlotBlock> buildList;
|
||||||
private Iterator<BuildingSlotBlock> current;
|
private Iterator<BuildingSlotBlock> current;
|
||||||
private int nbIterations;
|
private int nbIterations;
|
||||||
|
|
||||||
|
|
92
common/buildcraft/core/builders/BuildingSlotMapIterator.java
Executable file
92
common/buildcraft/core/builders/BuildingSlotMapIterator.java
Executable file
|
@ -0,0 +1,92 @@
|
||||||
|
/**
|
||||||
|
* Copyright (c) 2011-2015, SpaceToad and the BuildCraft Team
|
||||||
|
* http://www.mod-buildcraft.com
|
||||||
|
*
|
||||||
|
* BuildCraft is distributed under the terms of the Minecraft Mod Public
|
||||||
|
* License 1.0, or MMPL. Please check the contents of the license located in
|
||||||
|
* http://www.mod-buildcraft.com/MMPL-1.0.txt
|
||||||
|
*/
|
||||||
|
package buildcraft.core.builders;
|
||||||
|
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import com.google.common.collect.Multiset;
|
||||||
|
|
||||||
|
import net.minecraft.world.WorldSettings;
|
||||||
|
|
||||||
|
public class BuildingSlotMapIterator {
|
||||||
|
private static final int MAX_PER_ITEM = 80;
|
||||||
|
private final Map<BuilderItemMetaPair, List<BuildingSlotBlock>> slots;
|
||||||
|
private final Set<BuilderItemMetaPair> availablePairs = new HashSet<BuilderItemMetaPair>();
|
||||||
|
private final Multiset<Integer> buildStageOccurences;
|
||||||
|
private final boolean isCreative;
|
||||||
|
private Iterator<BuilderItemMetaPair> impIterator;
|
||||||
|
private BuilderItemMetaPair pair;
|
||||||
|
private List<BuildingSlotBlock> current;
|
||||||
|
private int position, returnsThisCurrent;
|
||||||
|
|
||||||
|
public BuildingSlotMapIterator(Map<BuilderItemMetaPair, List<BuildingSlotBlock>> slots, TileAbstractBuilder builder,
|
||||||
|
Multiset<Integer> buildStageOccurences) {
|
||||||
|
this.slots = slots;
|
||||||
|
this.impIterator = slots.keySet().iterator();
|
||||||
|
this.buildStageOccurences = buildStageOccurences;
|
||||||
|
this.isCreative = builder.getWorldObj().getWorldInfo().getGameType() == WorldSettings.GameType.CREATIVE;
|
||||||
|
|
||||||
|
// Generate available pairs
|
||||||
|
availablePairs.add(new BuilderItemMetaPair(null));
|
||||||
|
for (int i = 0; i < builder.getSizeInventory(); i++) {
|
||||||
|
availablePairs.add(new BuilderItemMetaPair(builder.getStackInSlot(i)));
|
||||||
|
}
|
||||||
|
|
||||||
|
findNewCurrent();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void skipList() {
|
||||||
|
findNewCurrent();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void findNewCurrent() {
|
||||||
|
position = -1;
|
||||||
|
returnsThisCurrent = 0;
|
||||||
|
while (impIterator.hasNext()) {
|
||||||
|
pair = impIterator.next();
|
||||||
|
if (isCreative || availablePairs.contains(pair)) {
|
||||||
|
current = slots.get(pair);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
current = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BuildingSlotBlock next() {
|
||||||
|
while (current != null) {
|
||||||
|
position++;
|
||||||
|
while (returnsThisCurrent < MAX_PER_ITEM && position < current.size()) {
|
||||||
|
BuildingSlotBlock b = current.get(position);
|
||||||
|
if (b != null) {
|
||||||
|
returnsThisCurrent++;
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
position++;
|
||||||
|
}
|
||||||
|
findNewCurrent();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void remove() {
|
||||||
|
buildStageOccurences.remove(current.get(position).buildStage);
|
||||||
|
current.set(position, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void reset() {
|
||||||
|
this.impIterator = slots.keySet().iterator();
|
||||||
|
this.pair = null;
|
||||||
|
this.current = null;
|
||||||
|
findNewCurrent();
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue