Unloader optimizations from buthed

This commit is contained in:
Anuken
2024-05-08 10:24:38 -04:00
parent db314c1134
commit 6cf371b949
@@ -24,6 +24,9 @@ public class Unloader extends Block{
public float speed = 1f; public float speed = 1f;
/** Cached result of content.items() */
static Item[] allItems;
public Unloader(String name){ public Unloader(String name){
super(name); super(name);
update = true; update = true;
@@ -41,6 +44,13 @@ public class Unloader extends Block{
configClear((UnloaderBuild tile) -> tile.sortItem = null); configClear((UnloaderBuild tile) -> tile.sortItem = null);
} }
@Override
public void init(){
super.init();
allItems = content.items().toArray(Item.class);
}
@Override @Override
public void setStats(){ public void setStats(){
super.setStats(); super.setStats();
@@ -63,27 +73,17 @@ public class Unloader extends Block{
float loadFactor; float loadFactor;
boolean canLoad; boolean canLoad;
boolean canUnload; boolean canUnload;
/** Cached !(building instanceof StorageBuild) */
boolean notStorage;
int lastUsed; int lastUsed;
@Override
public String toString(){
return "ContainerStat{" +
"building=" + building.block + "#" + building.id +
", loadFactor=" + loadFactor +
", canLoad=" + canLoad +
", canUnload=" + canUnload +
", lastUsed=" + lastUsed +
'}';
}
} }
public class UnloaderBuild extends Building{ public class UnloaderBuild extends Building{
public float unloadTimer = 0f; public float unloadTimer = 0f;
public int rotations = 0; public int rotations = 0;
private final int itemsLength = content.items().size;
public Item sortItem = null; public Item sortItem = null;
public ContainerStat dumpingFrom, dumpingTo; public ContainerStat dumpingFrom, dumpingTo;
public final Seq<ContainerStat> possibleBlocks = new Seq<>(); public final Seq<ContainerStat> possibleBlocks = new Seq<>(ContainerStat.class);
protected final Comparator<ContainerStat> comparator = (x, y) -> { protected final Comparator<ContainerStat> comparator = (x, y) -> {
//sort so it gives priority for blocks that can only either receive or give (not both), and then by load, and then by last use //sort so it gives priority for blocks that can only either receive or give (not both), and then by load, and then by last use
@@ -99,19 +99,20 @@ public class Unloader extends Block{
private boolean isPossibleItem(Item item){ private boolean isPossibleItem(Item item){
boolean hasProvider = false, boolean hasProvider = false,
hasReceiver = false, hasReceiver = false,
isDistinct = false; isDistinct = false;
for(int i = 0; i < possibleBlocks.size; i++){ var pbi = possibleBlocks.items;
var pb = possibleBlocks.get(i); for(int i = 0, l = possibleBlocks.size; i < l; i++){
var pb = pbi[i];
var other = pb.building; var other = pb.building;
//set the stats of buildings in possibleBlocks while we are at it //set the stats of buildings in possibleBlocks while we are at it
pb.canLoad = !(other.block instanceof StorageBlock) && other.acceptItem(this, item); pb.canLoad = pb.notStorage && other.acceptItem(this, item);
pb.canUnload = other.canUnload() && other.items != null && other.items.has(item); pb.canUnload = other.canUnload() && other.items != null && other.items.has(item);
//thats also handling framerate issues and slow conveyor belts, to avoid skipping items if nulloader //thats also handling framerate issues and slow conveyor belts, to avoid skipping items if nulloader
if((hasProvider && pb.canLoad) || (hasReceiver && pb.canUnload)) isDistinct = true; isDistinct |= (hasProvider && pb.canLoad) || (hasReceiver && pb.canUnload);
hasProvider |= pb.canUnload; hasProvider |= pb.canUnload;
hasReceiver |= pb.canLoad; hasReceiver |= pb.canLoad;
} }
@@ -129,14 +130,15 @@ public class Unloader extends Block{
for(int i = 0; i < proximity.size; i++){ for(int i = 0; i < proximity.size; i++){
var other = proximity.get(i); var other = proximity.get(i);
if(!other.interactable(team)) continue; //avoid blocks of the wrong team if(!other.interactable(team)) continue; //avoid blocks of the wrong team
ContainerStat pb = Pools.obtain(ContainerStat.class, ContainerStat::new);
//partial check //partial check
boolean canLoad = !(other.block instanceof StorageBlock); boolean canLoad = !(other.block instanceof StorageBlock);
boolean canUnload = other.canUnload() && other.items != null; boolean canUnload = other.canUnload() && other.items != null;
if(canLoad || canUnload){ //avoid blocks that can neither give nor receive items if(canLoad || canUnload){ //avoid blocks that can neither give nor receive items
var pb = Pools.obtain(ContainerStat.class, ContainerStat::new);
pb.building = other; pb.building = other;
pb.notStorage = canLoad;
//TODO store the partial canLoad/canUnload? //TODO store the partial canLoad/canUnload?
possibleBlocks.add(pb); possibleBlocks.add(pb);
} }
@@ -154,9 +156,9 @@ public class Unloader extends Block{
}else{ }else{
//selects the next item for nulloaders //selects the next item for nulloaders
//inspired of nextIndex() but for all "proximity" (possibleBlocks) at once, and also way more powerful //inspired of nextIndex() but for all "proximity" (possibleBlocks) at once, and also way more powerful
for(int i = 0; i < itemsLength; i++){ for(int i = 0, l = allItems.length; i < l; i++){
int total = (rotations + i + 1) % itemsLength; int id = (rotations + i + 1) % l;
Item possibleItem = content.item(total); var possibleItem = allItems[id];
if(isPossibleItem(possibleItem)){ if(isPossibleItem(possibleItem)){
item = possibleItem; item = possibleItem;
@@ -167,11 +169,14 @@ public class Unloader extends Block{
if(item != null){ if(item != null){
rotations = item.id; //next rotation for nulloaders //TODO maybe if(sortItem == null) rotations = item.id; //next rotation for nulloaders //TODO maybe if(sortItem == null)
var pbi = possibleBlocks.items;
int pbs = possibleBlocks.size;
for(int i = 0; i < possibleBlocks.size; i++){ for(int i = 0; i < pbs; i++){
var pb = possibleBlocks.get(i); var pb = pbi[i];
var other = pb.building; var other = pb.building;
pb.loadFactor = (other.getMaximumAccepted(item) == 0) || (other.items == null) ? 0 : other.items.get(item) / (float)other.getMaximumAccepted(item); int maxAccepted = other.getMaximumAccepted(item);
pb.loadFactor = maxAccepted == 0 || other.items == null ? 0 : other.items.get(item) / (float)maxAccepted;
pb.lastUsed = (pb.lastUsed + 1) % Integer.MAX_VALUE; //increment the priority if not used pb.lastUsed = (pb.lastUsed + 1) % Integer.MAX_VALUE; //increment the priority if not used
} }
@@ -181,17 +186,17 @@ public class Unloader extends Block{
dumpingFrom = null; dumpingFrom = null;
//choose the building to accept the item //choose the building to accept the item
for(int i = 0; i < possibleBlocks.size; i++){ for(int i = 0; i < pbs; i++){
if(possibleBlocks.get(i).canLoad){ if(pbi[i].canLoad){
dumpingTo = possibleBlocks.get(i); dumpingTo = pbi[i];
break; break;
} }
} }
//choose the building to take the item from //choose the building to take the item from
for(int i = possibleBlocks.size - 1; i >= 0; i--){ for(int i = pbs - 1; i >= 0; i--){
if(possibleBlocks.get(i).canUnload){ if(pbi[i].canUnload){
dumpingFrom = possibleBlocks.get(i); dumpingFrom = pbi[i];
break; break;
} }
} }