diff --git a/core/src/io/anuke/mindustry/world/Block.java b/core/src/io/anuke/mindustry/world/Block.java index 3c77052b8c..9a051da8e3 100644 --- a/core/src/io/anuke/mindustry/world/Block.java +++ b/core/src/io/anuke/mindustry/world/Block.java @@ -73,8 +73,6 @@ public class Block extends BlockStorage{ public Layer layer2 = null; /** whether this block can be replaced in all cases */ 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. */ public BlockGroup group = BlockGroup.none; /** List of block flags. Used for AI indexing. */ diff --git a/core/src/io/anuke/mindustry/world/DirectionalItemBuffer.java b/core/src/io/anuke/mindustry/world/DirectionalItemBuffer.java new file mode 100644 index 0000000000..2f5d7538b6 --- /dev/null +++ b/core/src/io/anuke/mindustry/world/DirectionalItemBuffer.java @@ -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; + } +} diff --git a/core/src/io/anuke/mindustry/world/blocks/distribution/Junction.java b/core/src/io/anuke/mindustry/world/blocks/distribution/Junction.java index 3760197ac8..de004f27f0 100644 --- a/core/src/io/anuke/mindustry/world/blocks/distribution/Junction.java +++ b/core/src/io/anuke/mindustry/world/blocks/distribution/Junction.java @@ -1,10 +1,11 @@ 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.gen.BufferItem; import io.anuke.mindustry.type.Item; -import io.anuke.mindustry.world.Block; -import io.anuke.mindustry.world.Tile; +import io.anuke.mindustry.world.*; import io.anuke.mindustry.world.meta.BlockGroup; import java.io.*; @@ -19,7 +20,6 @@ public class Junction extends Block{ super(name); update = true; solid = true; - instantTransfer = true; group = BlockGroup.transportation; } @@ -31,14 +31,13 @@ public class Junction extends Block{ @Override public void update(Tile tile){ JunctionEntity entity = tile.entity(); + DirectionalItemBuffer buffer = entity.buffer; for(int i = 0; i < 4; i++){ - Buffer buffer = entity.buffers[i]; - - if(buffer.index > 0){ - if(buffer.index > buffer.items.length) buffer.index = buffer.items.length; - long l = buffer.items[0]; - float time = Float.intBitsToFloat(Pack.leftInt(l)); + if(buffer.indexes[i] > 0){ + if(buffer.indexes[i] > capacity) buffer.indexes[i] = capacity; + long l = buffer.buffers[i][0]; + float time = BufferItem.time(l); if(Time.time() >= time + speed || Time.time() < time){ @@ -51,8 +50,8 @@ public class Junction extends Block{ } dest.block().handleItem(item, dest, tile); - System.arraycopy(buffer.items, 1, buffer.items, 0, buffer.index - 1); - buffer.index--; + System.arraycopy(buffer.buffers[i], 1, buffer.buffers[i], 0, buffer.indexes[i] - 1); + buffer.indexes[i] --; } } } @@ -61,9 +60,8 @@ public class Junction extends Block{ @Override public void handleItem(Item item, Tile tile, Tile source){ JunctionEntity entity = tile.entity(); - long value = Pack.longInt(Float.floatToIntBits(Time.time()), item.id); int relative = source.relativeTo(tile.x, tile.y); - entity.buffers[relative].add(value); + entity.buffer.accept(relative, item); } @Override @@ -71,7 +69,7 @@ public class Junction extends Block{ JunctionEntity entity = tile.entity(); 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; Tile to = tile.getNearby(relative); return to != null && to.link().entity != null; @@ -83,55 +81,18 @@ public class Junction extends Block{ } class JunctionEntity extends TileEntity{ - Buffer[] buffers = {new Buffer(), new Buffer(), new Buffer(), new Buffer()}; + DirectionalItemBuffer buffer = new DirectionalItemBuffer(capacity, speed); @Override public void write(DataOutput stream) throws IOException{ super.write(stream); - for(Buffer b : buffers){ - b.write(stream); - } + buffer.write(stream); } @Override public void read(DataInput stream, byte revision) throws IOException{ super.read(stream, revision); - for(Buffer b : buffers){ - 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; - } - } + buffer.read(stream); } } } diff --git a/core/src/io/anuke/mindustry/world/blocks/distribution/Sorter.java b/core/src/io/anuke/mindustry/world/blocks/distribution/Sorter.java index ff5888dfbf..548a18bc7d 100644 --- a/core/src/io/anuke/mindustry/world/blocks/distribution/Sorter.java +++ b/core/src/io/anuke/mindustry/world/blocks/distribution/Sorter.java @@ -10,8 +10,7 @@ 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.world.Block; -import io.anuke.mindustry.world.Tile; +import io.anuke.mindustry.world.*; import io.anuke.mindustry.world.blocks.ItemSelection; import io.anuke.mindustry.world.meta.BlockGroup; @@ -22,11 +21,13 @@ import static io.anuke.mindustry.Vars.content; public class Sorter extends Block{ private static Item lastItem; + protected int bufferCapacity = 20; + protected float speed = 20f; + public Sorter(String name){ super(name); update = true; solid = true; - instantTransfer = true; group = BlockGroup.transportation; configurable = true; } @@ -62,17 +63,34 @@ public class Sorter extends Block{ } @Override - public boolean acceptItem(Item item, Tile tile, Tile source){ - Tile to = getTileTarget(item, tile, source, false); + public void update(Tile tile){ + 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 public void handleItem(Item item, Tile tile, Tile source){ - Tile to = getTileTarget(item, tile, source, true); - - to.block().handleItem(item, to, tile); + SorterEntity entity = tile.entity(); + int buffer = tile.relativeTo(source.x, source.y); + if(entity.buffer.accepts(buffer)){ + entity.buffer.accept(buffer, item); + } } Tile getTileTarget(Item item, Tile dest, Tile source, boolean flip){ @@ -87,10 +105,8 @@ public class Sorter extends Block{ }else{ Tile a = 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) && - a.block().acceptItem(item, a, dest); - boolean bc = b != null && !(b.block().instantTransfer && source.block().instantTransfer) && - b.block().acceptItem(item, b, dest); + boolean ac = a != null && a.block().acceptItem(item, a, dest); + boolean bc = b != null && b.block().acceptItem(item, b, dest); if(ac && !bc){ to = a; @@ -101,12 +117,10 @@ public class Sorter extends Block{ }else{ if(dest.rotation() == 0){ to = a; - if(flip) - dest.rotation((byte)1); + if(flip) dest.rotation((byte)1); }else{ to = b; - if(flip) - dest.rotation((byte)0); + if(flip) dest.rotation((byte)0); } } } @@ -128,19 +142,22 @@ public class Sorter extends Block{ return new SorterEntity(); } - public static class SorterEntity extends TileEntity{ - public Item sortItem; + public class SorterEntity extends TileEntity{ + DirectionalItemBuffer buffer = new DirectionalItemBuffer(bufferCapacity, speed); + Item sortItem; @Override public void write(DataOutput stream) throws IOException{ super.write(stream); stream.writeShort(sortItem == null ? -1 : sortItem.id); + buffer.write(stream); } @Override public void read(DataInput stream, byte revision) throws IOException{ super.read(stream, revision); sortItem = content.item(stream.readShort()); + buffer.read(stream); } } } diff --git a/core/src/io/anuke/mindustry/world/blocks/sandbox/ItemSource.java b/core/src/io/anuke/mindustry/world/blocks/sandbox/ItemSource.java index c9b4e55d12..6c42b23832 100644 --- a/core/src/io/anuke/mindustry/world/blocks/sandbox/ItemSource.java +++ b/core/src/io/anuke/mindustry/world/blocks/sandbox/ItemSource.java @@ -1,16 +1,39 @@ 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.world.Block; 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){ super(name); hasItems = true; update = 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 @@ -26,16 +49,46 @@ public class ItemSource extends Sorter{ @Override public void update(Tile tile){ - SorterEntity entity = tile.entity(); - if(entity.sortItem == null) return; + ItemSourceEntity entity = tile.entity(); + if(entity.outputItem == null) return; - entity.items.set(entity.sortItem, 1); - tryDump(tile, entity.sortItem); - entity.items.set(entity.sortItem, 0); + entity.items.set(entity.outputItem, 1); + tryDump(tile, entity.outputItem); + 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 public boolean acceptItem(Item item, Tile tile, Tile source){ 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()); + } + } }