Buffers for everything

This commit is contained in:
Anuken
2019-05-16 11:43:02 -04:00
parent aeb3662414
commit cac953e812
5 changed files with 189 additions and 83 deletions

View File

@ -73,8 +73,6 @@ public class Block extends BlockStorage{
public Layer layer2 = null; public Layer layer2 = null;
/** whether this block can be replaced in all cases */ /** whether this block can be replaced in all cases */
public boolean alwaysReplace = false; public boolean alwaysReplace = false;
/** whether this block has instant transfer checking. used for calculations to prevent infinite loops. */
public boolean instantTransfer = false;
/** The block group. Unless {@link #canReplace} is overriden, blocks in the same group can replace each other. */ /** The block group. Unless {@link #canReplace} is overriden, blocks in the same group can replace each other. */
public BlockGroup group = BlockGroup.none; public BlockGroup group = BlockGroup.none;
/** List of block flags. Used for AI indexing. */ /** List of block flags. Used for AI indexing. */

View File

@ -0,0 +1,77 @@
package io.anuke.mindustry.world;
import io.anuke.annotations.Annotations.Struct;
import io.anuke.arc.util.Time;
import io.anuke.mindustry.gen.BufferItem;
import io.anuke.mindustry.type.Item;
import java.io.*;
import static io.anuke.mindustry.Vars.content;
public class DirectionalItemBuffer{
public final long[][] buffers;
public final int[] indexes;
private final float speed;
public DirectionalItemBuffer(int capacity, float speed){
this.buffers = new long[4][capacity];
this.indexes = new int[5];
this.speed = speed;
}
public boolean accepts(int buffer){
return indexes[buffer] < buffers[buffer].length;
}
public void accept(int buffer, Item item){
if(!accepts(buffer)) return;
buffers[buffer][indexes[buffer]++] = BufferItem.get((byte)item.id, Time.time());
}
public Item poll(int buffer){
if(indexes[buffer] > 0){
long l = buffers[buffer][0];
float time = BufferItem.time(l);
if(Time.time() >= time + speed || Time.time() < time){
return content.item(BufferItem.item(l));
}
}
return null;
}
public void remove(int buffer){
System.arraycopy(buffers[buffer], 1, buffers[buffer], 0, indexes[buffer] - 1);
indexes[buffer] --;
}
public void write(DataOutput stream) throws IOException{
for(int i = 0; i < 4; i++){
stream.writeByte(indexes[i]);
stream.writeByte(buffers[i].length);
for(long l : buffers[i]){
stream.writeLong(l);
}
}
}
public void read(DataInput stream) throws IOException{
for(int i = 0; i < 4; i++){
indexes[i] = stream.readByte();
byte length = stream.readByte();
for(int j = 0; j < length; j++){
long value = stream.readLong();
if(j < buffers[i].length){
buffers[i][j] = value;
}
}
}
}
@Struct
class BufferItemStruct{
byte item;
float time;
}
}

View File

@ -1,10 +1,11 @@
package io.anuke.mindustry.world.blocks.distribution; package io.anuke.mindustry.world.blocks.distribution;
import io.anuke.arc.util.*; import io.anuke.arc.util.Pack;
import io.anuke.arc.util.Time;
import io.anuke.mindustry.entities.type.TileEntity; import io.anuke.mindustry.entities.type.TileEntity;
import io.anuke.mindustry.gen.BufferItem;
import io.anuke.mindustry.type.Item; import io.anuke.mindustry.type.Item;
import io.anuke.mindustry.world.Block; import io.anuke.mindustry.world.*;
import io.anuke.mindustry.world.Tile;
import io.anuke.mindustry.world.meta.BlockGroup; import io.anuke.mindustry.world.meta.BlockGroup;
import java.io.*; import java.io.*;
@ -19,7 +20,6 @@ public class Junction extends Block{
super(name); super(name);
update = true; update = true;
solid = true; solid = true;
instantTransfer = true;
group = BlockGroup.transportation; group = BlockGroup.transportation;
} }
@ -31,14 +31,13 @@ public class Junction extends Block{
@Override @Override
public void update(Tile tile){ public void update(Tile tile){
JunctionEntity entity = tile.entity(); JunctionEntity entity = tile.entity();
DirectionalItemBuffer buffer = entity.buffer;
for(int i = 0; i < 4; i++){ for(int i = 0; i < 4; i++){
Buffer buffer = entity.buffers[i]; if(buffer.indexes[i] > 0){
if(buffer.indexes[i] > capacity) buffer.indexes[i] = capacity;
if(buffer.index > 0){ long l = buffer.buffers[i][0];
if(buffer.index > buffer.items.length) buffer.index = buffer.items.length; float time = BufferItem.time(l);
long l = buffer.items[0];
float time = Float.intBitsToFloat(Pack.leftInt(l));
if(Time.time() >= time + speed || Time.time() < time){ if(Time.time() >= time + speed || Time.time() < time){
@ -51,8 +50,8 @@ public class Junction extends Block{
} }
dest.block().handleItem(item, dest, tile); dest.block().handleItem(item, dest, tile);
System.arraycopy(buffer.items, 1, buffer.items, 0, buffer.index - 1); System.arraycopy(buffer.buffers[i], 1, buffer.buffers[i], 0, buffer.indexes[i] - 1);
buffer.index--; buffer.indexes[i] --;
} }
} }
} }
@ -61,9 +60,8 @@ public class Junction extends Block{
@Override @Override
public void handleItem(Item item, Tile tile, Tile source){ public void handleItem(Item item, Tile tile, Tile source){
JunctionEntity entity = tile.entity(); JunctionEntity entity = tile.entity();
long value = Pack.longInt(Float.floatToIntBits(Time.time()), item.id);
int relative = source.relativeTo(tile.x, tile.y); int relative = source.relativeTo(tile.x, tile.y);
entity.buffers[relative].add(value); entity.buffer.accept(relative, item);
} }
@Override @Override
@ -71,7 +69,7 @@ public class Junction extends Block{
JunctionEntity entity = tile.entity(); JunctionEntity entity = tile.entity();
int relative = source.relativeTo(tile.x, tile.y); int relative = source.relativeTo(tile.x, tile.y);
if(entity == null || relative == -1 || entity.buffers[relative].full()) if(entity == null || relative == -1 || !entity.buffer.accepts(relative))
return false; return false;
Tile to = tile.getNearby(relative); Tile to = tile.getNearby(relative);
return to != null && to.link().entity != null; return to != null && to.link().entity != null;
@ -83,55 +81,18 @@ public class Junction extends Block{
} }
class JunctionEntity extends TileEntity{ class JunctionEntity extends TileEntity{
Buffer[] buffers = {new Buffer(), new Buffer(), new Buffer(), new Buffer()}; DirectionalItemBuffer buffer = new DirectionalItemBuffer(capacity, speed);
@Override @Override
public void write(DataOutput stream) throws IOException{ public void write(DataOutput stream) throws IOException{
super.write(stream); super.write(stream);
for(Buffer b : buffers){ buffer.write(stream);
b.write(stream);
}
} }
@Override @Override
public void read(DataInput stream, byte revision) throws IOException{ public void read(DataInput stream, byte revision) throws IOException{
super.read(stream, revision); super.read(stream, revision);
for(Buffer b : buffers){ buffer.read(stream);
b.read(stream);
}
}
}
class Buffer{
long[] items = new long[capacity];
int index;
void add(long id){
if(full()) return;
items[index++] = id;
}
boolean full(){
return index >= items.length - 1;
}
void write(DataOutput stream) throws IOException{
stream.writeByte((byte)index);
stream.writeByte((byte)items.length);
for(long l : items){
stream.writeLong(l);
}
}
void read(DataInput stream) throws IOException{
index = stream.readByte();
byte length = stream.readByte();
for(int i = 0; i < length; i++){
long l = stream.readLong();
if(i < items.length){
items[i] = l;
}
}
} }
} }
} }

View File

@ -10,8 +10,7 @@ import io.anuke.mindustry.entities.type.Player;
import io.anuke.mindustry.entities.type.TileEntity; import io.anuke.mindustry.entities.type.TileEntity;
import io.anuke.mindustry.gen.Call; import io.anuke.mindustry.gen.Call;
import io.anuke.mindustry.type.Item; import io.anuke.mindustry.type.Item;
import io.anuke.mindustry.world.Block; import io.anuke.mindustry.world.*;
import io.anuke.mindustry.world.Tile;
import io.anuke.mindustry.world.blocks.ItemSelection; import io.anuke.mindustry.world.blocks.ItemSelection;
import io.anuke.mindustry.world.meta.BlockGroup; import io.anuke.mindustry.world.meta.BlockGroup;
@ -22,11 +21,13 @@ import static io.anuke.mindustry.Vars.content;
public class Sorter extends Block{ public class Sorter extends Block{
private static Item lastItem; private static Item lastItem;
protected int bufferCapacity = 20;
protected float speed = 20f;
public Sorter(String name){ public Sorter(String name){
super(name); super(name);
update = true; update = true;
solid = true; solid = true;
instantTransfer = true;
group = BlockGroup.transportation; group = BlockGroup.transportation;
configurable = true; configurable = true;
} }
@ -62,17 +63,34 @@ public class Sorter extends Block{
} }
@Override @Override
public boolean acceptItem(Item item, Tile tile, Tile source){ public void update(Tile tile){
Tile to = getTileTarget(item, tile, source, false); SorterEntity entity = tile.entity();
return to != null && to.block().acceptItem(item, to, tile); for(int i = 0; i < 4; i++){
Item item = entity.buffer.poll(i);
if(item != null){
Tile other = getTileTarget(item, tile, tile.getNearby(i), true);
if(other.block().acceptItem(item, other, tile)){
other.block().handleItem(item, other, tile);
entity.buffer.remove(i);
}
}
}
}
@Override
public boolean acceptItem(Item item, Tile tile, Tile source){
SorterEntity entity = tile.entity();
return entity.buffer.accepts(tile.relativeTo(source.x, source.y));
} }
@Override @Override
public void handleItem(Item item, Tile tile, Tile source){ public void handleItem(Item item, Tile tile, Tile source){
Tile to = getTileTarget(item, tile, source, true); SorterEntity entity = tile.entity();
int buffer = tile.relativeTo(source.x, source.y);
to.block().handleItem(item, to, tile); if(entity.buffer.accepts(buffer)){
entity.buffer.accept(buffer, item);
}
} }
Tile getTileTarget(Item item, Tile dest, Tile source, boolean flip){ Tile getTileTarget(Item item, Tile dest, Tile source, boolean flip){
@ -87,10 +105,8 @@ public class Sorter extends Block{
}else{ }else{
Tile a = dest.getNearby(Mathf.mod(dir - 1, 4)); Tile a = dest.getNearby(Mathf.mod(dir - 1, 4));
Tile b = dest.getNearby(Mathf.mod(dir + 1, 4)); Tile b = dest.getNearby(Mathf.mod(dir + 1, 4));
boolean ac = a != null && !(a.block().instantTransfer && source.block().instantTransfer) && boolean ac = a != null && a.block().acceptItem(item, a, dest);
a.block().acceptItem(item, a, dest); boolean bc = b != null && b.block().acceptItem(item, b, dest);
boolean bc = b != null && !(b.block().instantTransfer && source.block().instantTransfer) &&
b.block().acceptItem(item, b, dest);
if(ac && !bc){ if(ac && !bc){
to = a; to = a;
@ -101,12 +117,10 @@ public class Sorter extends Block{
}else{ }else{
if(dest.rotation() == 0){ if(dest.rotation() == 0){
to = a; to = a;
if(flip) if(flip) dest.rotation((byte)1);
dest.rotation((byte)1);
}else{ }else{
to = b; to = b;
if(flip) if(flip) dest.rotation((byte)0);
dest.rotation((byte)0);
} }
} }
} }
@ -128,19 +142,22 @@ public class Sorter extends Block{
return new SorterEntity(); return new SorterEntity();
} }
public static class SorterEntity extends TileEntity{ public class SorterEntity extends TileEntity{
public Item sortItem; DirectionalItemBuffer buffer = new DirectionalItemBuffer(bufferCapacity, speed);
Item sortItem;
@Override @Override
public void write(DataOutput stream) throws IOException{ public void write(DataOutput stream) throws IOException{
super.write(stream); super.write(stream);
stream.writeShort(sortItem == null ? -1 : sortItem.id); stream.writeShort(sortItem == null ? -1 : sortItem.id);
buffer.write(stream);
} }
@Override @Override
public void read(DataInput stream, byte revision) throws IOException{ public void read(DataInput stream, byte revision) throws IOException{
super.read(stream, revision); super.read(stream, revision);
sortItem = content.item(stream.readShort()); sortItem = content.item(stream.readShort());
buffer.read(stream);
} }
} }
} }

View File

@ -1,16 +1,39 @@
package io.anuke.mindustry.world.blocks.sandbox; package io.anuke.mindustry.world.blocks.sandbox;
import io.anuke.annotations.Annotations.Loc;
import io.anuke.annotations.Annotations.Remote;
import io.anuke.arc.scene.ui.layout.Table;
import io.anuke.mindustry.entities.type.Player;
import io.anuke.mindustry.entities.type.TileEntity;
import io.anuke.mindustry.gen.Call;
import io.anuke.mindustry.type.Item; import io.anuke.mindustry.type.Item;
import io.anuke.mindustry.world.Block;
import io.anuke.mindustry.world.Tile; import io.anuke.mindustry.world.Tile;
import io.anuke.mindustry.world.blocks.distribution.Sorter; import io.anuke.mindustry.world.blocks.ItemSelection;
import io.anuke.mindustry.world.meta.BlockGroup;
public class ItemSource extends Sorter{ import java.io.*;
import static io.anuke.mindustry.Vars.content;
public class ItemSource extends Block{
private static Item lastItem;
public ItemSource(String name){ public ItemSource(String name){
super(name); super(name);
hasItems = true; hasItems = true;
update = true; update = true;
solid = true; solid = true;
group = BlockGroup.transportation;
configurable = true;
}
@Remote(targets = Loc.both, called = Loc.both, forward = true)
public static void setItemSourceItem(Player player, Tile tile, Item item){
ItemSourceEntity entity = tile.entity();
if(entity != null){
entity.outputItem = item;
}
} }
@Override @Override
@ -26,16 +49,46 @@ public class ItemSource extends Sorter{
@Override @Override
public void update(Tile tile){ public void update(Tile tile){
SorterEntity entity = tile.entity(); ItemSourceEntity entity = tile.entity();
if(entity.sortItem == null) return; if(entity.outputItem == null) return;
entity.items.set(entity.sortItem, 1); entity.items.set(entity.outputItem, 1);
tryDump(tile, entity.sortItem); tryDump(tile, entity.outputItem);
entity.items.set(entity.sortItem, 0); entity.items.set(entity.outputItem, 0);
}
@Override
public void buildTable(Tile tile, Table table){
ItemSourceEntity entity = tile.entity();
ItemSelection.buildItemTable(table, () -> entity.outputItem, item -> {
lastItem = item;
Call.setItemSourceItem(null, tile, item);
});
} }
@Override @Override
public boolean acceptItem(Item item, Tile tile, Tile source){ public boolean acceptItem(Item item, Tile tile, Tile source){
return false; return false;
} }
@Override
public TileEntity newEntity(){
return new ItemSourceEntity();
}
public class ItemSourceEntity extends TileEntity{
Item outputItem;
@Override
public void write(DataOutput stream) throws IOException{
super.write(stream);
stream.writeShort(outputItem == null ? -1 : outputItem.id);
}
@Override
public void read(DataInput stream, byte revision) throws IOException{
super.read(stream, revision);
outputItem = content.item(stream.readShort());
}
}
} }