new Builder block picking logic

This commit is contained in:
Adrian 2015-05-08 21:10:12 +02:00
parent 9808a7986e
commit 36e63d2baf
4 changed files with 245 additions and 65 deletions

View file

@ -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>();

View 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;
}
}

View file

@ -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;

View 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();
}
}