Merge remote-tracking branch 'origin/master'
This commit is contained in:
@@ -128,3 +128,4 @@ SAMBUYYA
|
|||||||
genNAowl
|
genNAowl
|
||||||
TranquillyUnpleasant
|
TranquillyUnpleasant
|
||||||
Darkness6030
|
Darkness6030
|
||||||
|
hortiSquash
|
||||||
@@ -3,6 +3,7 @@ package mindustry.world.blocks.storage;
|
|||||||
import arc.graphics.*;
|
import arc.graphics.*;
|
||||||
import arc.graphics.g2d.*;
|
import arc.graphics.g2d.*;
|
||||||
import arc.scene.ui.layout.*;
|
import arc.scene.ui.layout.*;
|
||||||
|
import arc.struct.*;
|
||||||
import arc.util.*;
|
import arc.util.*;
|
||||||
import arc.util.io.*;
|
import arc.util.io.*;
|
||||||
import mindustry.entities.units.*;
|
import mindustry.entities.units.*;
|
||||||
@@ -54,56 +55,133 @@ public class Unloader extends Block{
|
|||||||
public class UnloaderBuild extends Building{
|
public class UnloaderBuild extends Building{
|
||||||
public float unloadTimer = 0f;
|
public float unloadTimer = 0f;
|
||||||
public Item sortItem = null;
|
public Item sortItem = null;
|
||||||
public Building dumpingTo;
|
|
||||||
public int offset = 0;
|
public int offset = 0;
|
||||||
public int[] rotations;
|
public int rotations = 0;
|
||||||
|
public Seq<ContainerStat> possibleBlocks = new Seq<>();
|
||||||
|
|
||||||
|
public class ContainerStat{
|
||||||
|
Building building;
|
||||||
|
float loadFactor;
|
||||||
|
boolean canLoad;
|
||||||
|
boolean canUnload;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void updateTile(){
|
public void updateTile(){
|
||||||
if((unloadTimer += delta()) >= speed){
|
if(((unloadTimer += delta()) < speed) || (proximity.size < 2)) return;
|
||||||
boolean any = false;
|
Item item = null;
|
||||||
if(rotations == null || rotations.length != proximity.size){
|
boolean any = false;
|
||||||
rotations = new int[proximity.size];
|
int itemslength = content.items().size;
|
||||||
|
|
||||||
|
//initialize possibleBlocks only if the new size is bigger than the previous, to avoid unnecessary allocations
|
||||||
|
if(possibleBlocks.size != proximity.size){
|
||||||
|
int tmp = possibleBlocks.size;
|
||||||
|
possibleBlocks.setSize(proximity.size);
|
||||||
|
for(int i = tmp; i < proximity.size; i++){
|
||||||
|
possibleBlocks.set(i, new ContainerStat());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(sortItem != null){
|
||||||
|
item = sortItem;
|
||||||
|
|
||||||
|
for(int pos = 0; pos < proximity.size; pos++){
|
||||||
|
var other = proximity.get(pos);
|
||||||
|
boolean interactable = other.interactable(team);
|
||||||
|
|
||||||
|
//set the stats of all buildings in possibleBlocks
|
||||||
|
ContainerStat pb = possibleBlocks.get(pos);
|
||||||
|
pb.building = other;
|
||||||
|
pb.canUnload = interactable && other.canUnload() && other.items != null && other.items.has(sortItem);
|
||||||
|
pb.canLoad = interactable && !(other.block instanceof StorageBlock) && other.acceptItem(this, sortItem);
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
//select the next item for nulloaders
|
||||||
|
//inspired of nextIndex() but for all proximity at once, and also way more powerful
|
||||||
|
for(int i = 0; i < itemslength; i++){
|
||||||
|
int total = (rotations + i + 1) % itemslength;
|
||||||
|
boolean hasProvider = false;
|
||||||
|
boolean hasReceiver = false;
|
||||||
|
boolean isDistinct = false;
|
||||||
|
Item possibleItem = content.item(total);
|
||||||
|
|
||||||
|
for(int pos = 0; pos < proximity.size; pos++){
|
||||||
|
var other = proximity.get(pos);
|
||||||
|
boolean interactable = other.interactable(team);
|
||||||
|
|
||||||
|
//set the stats of all buildings in possibleBlocks while we are at it
|
||||||
|
ContainerStat pb = possibleBlocks.get(pos);
|
||||||
|
pb.building = other;
|
||||||
|
pb.canUnload = interactable && other.canUnload() && other.items != null && other.items.has(possibleItem);
|
||||||
|
pb.canLoad = interactable && !(other.block instanceof StorageBlock) && other.acceptItem(this, possibleItem);
|
||||||
|
|
||||||
|
//the part handling framerate issues and slow conveyor belts, to avoid skipping items
|
||||||
|
if(hasProvider && pb.canLoad) isDistinct = true;
|
||||||
|
if(hasReceiver && pb.canUnload) isDistinct = true;
|
||||||
|
hasProvider = hasProvider || pb.canUnload;
|
||||||
|
hasReceiver = hasReceiver || pb.canLoad;
|
||||||
|
}
|
||||||
|
if(isDistinct){
|
||||||
|
item = possibleItem;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(item != null){
|
||||||
|
//only compute the load factor if a transfer is possible
|
||||||
|
for(int pos = 0; pos < proximity.size; pos++){
|
||||||
|
ContainerStat pb = possibleBlocks.get(pos);
|
||||||
|
var other = pb.building;
|
||||||
|
pb.loadFactor = (other.getMaximumAccepted(item) == 0) || (other.items == null) ? 0 : other.items.get(item) / (float)other.getMaximumAccepted(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
for(int i = 0; i < proximity.size; i++){
|
//sort so it gives full priority to blocks that can give but not receive (mainly plast and storage), and then by load
|
||||||
int pos = (offset + i) % proximity.size;
|
possibleBlocks.sort((e1, e2) -> {
|
||||||
var other = proximity.get(pos);
|
// TODO: instead of canLoad it should be ((instance of Storage) || (is it a plast belt i can unload from))
|
||||||
|
// otherwise a 100% full factory will get full priority over the storage/plast, barely an issue but still wasting trades and thus speed
|
||||||
|
int canLoad = Boolean.compare(e2.canLoad, e1.canLoad);
|
||||||
|
return (canLoad != 0) ? canLoad : Float.compare(e1.loadFactor, e2.loadFactor);
|
||||||
|
});
|
||||||
|
|
||||||
if(other.interactable(team) && other.block.unloadable && other.canUnload() && other.block.hasItems
|
ContainerStat dumpingFrom = null;
|
||||||
&& ((sortItem == null && other.items.total() > 0) || (sortItem != null && other.items.has(sortItem)))){
|
ContainerStat dumpingTo = null;
|
||||||
//make sure the item can't be dumped back into this block
|
|
||||||
dumpingTo = other;
|
|
||||||
|
|
||||||
//get item to be taken
|
//choose the building to accept the item
|
||||||
Item item = sortItem == null ? other.items.takeIndex(rotations[pos]) : sortItem;
|
for(int i = 0; i < possibleBlocks.size; i++){
|
||||||
|
if(possibleBlocks.get(i).canLoad){
|
||||||
//remove item if it's dumped correctly
|
dumpingTo = possibleBlocks.get(i);
|
||||||
if(put(item)){
|
break;
|
||||||
other.items.remove(item, 1);
|
|
||||||
any = true;
|
|
||||||
|
|
||||||
if(sortItem == null){
|
|
||||||
rotations[pos] = item.id + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
other.itemTaken(item);
|
|
||||||
}else if(sortItem == null){
|
|
||||||
rotations[pos] = other.items.nextIndex(rotations[pos]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(any){
|
//choose the building to give the item
|
||||||
unloadTimer %= speed;
|
for(int i = possibleBlocks.size - 1; i >= 0; i--){
|
||||||
}else{
|
if(possibleBlocks.get(i).canUnload){
|
||||||
unloadTimer = Math.min(unloadTimer, speed);
|
dumpingFrom = possibleBlocks.get(i);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(proximity.size > 0){
|
//trade the items
|
||||||
offset ++;
|
if(dumpingFrom != null && dumpingTo != null && dumpingFrom.loadFactor != dumpingTo.loadFactor){
|
||||||
offset %= proximity.size;
|
dumpingTo.building.handleItem(this, item);
|
||||||
|
dumpingFrom.building.removeStack(item, 1);
|
||||||
|
any = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(sortItem == null) rotations = item.id;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(any){
|
||||||
|
unloadTimer %= speed;
|
||||||
|
}else{
|
||||||
|
unloadTimer = Math.min(unloadTimer, speed);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(proximity.size > 0){
|
||||||
|
offset++;
|
||||||
|
offset %= proximity.size;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -132,11 +210,6 @@ public class Unloader extends Block{
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean canDump(Building to, Item item){
|
|
||||||
return !(to.block instanceof StorageBlock) && to != dumpingTo;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Item config(){
|
public Item config(){
|
||||||
return sortItem;
|
return sortItem;
|
||||||
|
|||||||
Reference in New Issue
Block a user