From 6fe2697185de991ee72c0b0bb1f0c3f19cd4c844 Mon Sep 17 00:00:00 2001 From: Anuken Date: Sun, 26 Jan 2020 15:04:00 -0500 Subject: [PATCH] 2x faster conveyor optimization --- .../world/blocks/distribution/Conveyor.java | 244 ++++++++---------- gradle.properties | 2 +- 2 files changed, 113 insertions(+), 133 deletions(-) diff --git a/core/src/mindustry/world/blocks/distribution/Conveyor.java b/core/src/mindustry/world/blocks/distribution/Conveyor.java index 01453e2e82..5b1e09e10b 100644 --- a/core/src/mindustry/world/blocks/distribution/Conveyor.java +++ b/core/src/mindustry/world/blocks/distribution/Conveyor.java @@ -10,7 +10,6 @@ import arc.util.ArcAnnotate.*; import arc.util.*; import mindustry.content.*; import mindustry.entities.traits.BuilderTrait.*; -import mindustry.entities.traits.*; import mindustry.entities.type.*; import mindustry.gen.*; import mindustry.graphics.*; @@ -26,7 +25,6 @@ import static mindustry.Vars.*; public class Conveyor extends Block implements Autotiler{ private static final float itemSpace = 0.4f; - private static final float minmove = 1f / (Short.MAX_VALUE - 2); private static final int capacity = 4; private final Vec2 tr1 = new Vec2(); @@ -99,6 +97,7 @@ public class Conveyor extends Block implements Autotiler{ if(tile.front() != null && tile.front().entity != null){ entity.next = tile.front().entity; entity.nextc = entity.next instanceof ConveyorEntity ? (ConveyorEntity)entity.next : null; + entity.aligned = entity.nextc != null && tile.rotation() == entity.next.tile.rotation(); } } @@ -124,17 +123,17 @@ public class Conveyor extends Block implements Autotiler{ @Override public void drawLayer(Tile tile){ - ConveyorEntity entity = tile.ent(); + ConveyorEntity e = tile.ent(); byte rotation = tile.rotation(); - for(int i = 0; i < entity.count; i++){ - Item item = entity.ids[i]; + for(int i = 0; i < e.len; i++){ + Item item = e.ids[i]; tr1.trns(rotation * 90, tilesize, 0); - tr2.trns(rotation * 90, -tilesize / 2f, entity.xs[i] * tilesize / 2f); + tr2.trns(rotation * 90, -tilesize / 2f, e.xs[i] * tilesize / 2f); Draw.rect(item.icon(Cicon.medium), - (tile.x * tilesize + tr1.x * entity.ys[i] + tr2.x), - (tile.y * tilesize + tr1.y * entity.ys[i] + tr2.y), itemSize, itemSize); + (tile.x * tilesize + tr1.x * e.ys[i] + tr2.x), + (tile.y * tilesize + tr1.y * e.ys[i] + tr2.y), itemSize, itemSize); } } @@ -163,71 +162,56 @@ public class Conveyor extends Block implements Autotiler{ if(Math.abs(tile.worldx() - unit.x) < 1f) centerx = 0f; } - if(entity.count * itemSpace < 0.9f){ + if(entity.len * itemSpace < 0.9f){ unit.applyImpulse((tx * speed + centerx) * entity.delta(), (ty * speed + centery) * entity.delta()); } } @Override public void update(Tile tile){ - ConveyorEntity entity = tile.ent(); - entity.minitem = 1f; - @Nullable TileEntity next = entity.next; + ConveyorEntity e = tile.ent(); + e.minitem = 1f; + e.mid = 0; - float nextMax = entity.nextc != null - && next.block.acceptItem(null, next.tile, tile) ? - 1f - Math.max(itemSpace - entity.nextc.minitem, 0) : 1f; - int minremove = Integer.MAX_VALUE; + //skip updates if possible + if(e.items.total() == 0){ + e.clogHeat = 0f; + e.sleep(); + return; + } - for(int i = entity.count - 1; i >= 0; i--){ - float nextpos = (i == entity.count - 1 ? 100f : entity.ys[i + 1]) - itemSpace; - float maxmove = Math.min(nextpos - pos.y, speed * entity.delta()); + float nextMax = e.nextc != null && tile.rotation() == e.nextc.tile.rotation() /** TODO may not accept due to blockage or team */ ? 1f - Math.max(itemSpace - e.nextc.minitem, 0) : 1f; - if(maxmove > minmove){ - pos.y += maxmove; - if(Mathf.equal(pos.x, 0, 0.1f)){ - pos.x = 0f; + for(int i = e.len - 1; i >= 0; i--){ + float nextpos = (i == e.len - 1 ? 100f : e.ys[i + 1]) - itemSpace; + float maxmove = Math.min(nextpos - e.ys[i], speed * e.delta()); + + e.ys[i] += maxmove; + + if(e.ys[i] > nextMax) e.ys[i] = nextMax; + if(e.ys[i] > 0.5 && i > 0) e.mid = i - 1; + e.xs[i] = Mathf.approachDelta(e.xs[i], 0, 0.1f); + + if(e.ys[i] >= 0.9999f && offloadDir(tile, e.ids[i])){ + //align X position if passing forwards + if(e.nextc != null && e.aligned){ + e.nextc.xs[e.nextc.lastInserted] = e.xs[i]; } - pos.x = Mathf.lerpDelta(pos.x, 0, 0.1f); - } - - pos.y = Mathf.clamp(pos.y, 0, nextMax); - - if(pos.y >= 0.9999f && offloadDir(tile, pos.item)){ - if(next != null && next.block() instanceof Conveyor){ - ConveyorEntity othere = next.ent(); - - ItemPos ni = pos2.set(othere.convey.get(othere.lastInserted), ItemPos.updateShorts); - - if(next.rotation() == tile.rotation()){ - ni.x = pos.x; - } - othere.convey.set(othere.lastInserted, ni.pack()); - } - minremove = Math.min(i, minremove); - tile.entity.items.remove(pos.item, 1); - }else{ - value = pos.pack(); - - if(pos.y < entity.minitem) - entity.minitem = pos.y; - entity.convey.set(i, value); + //remove last item + e.len = Math.min(i, e.len); + e.items.remove(e.ids[i], 1); + }else if(e.ys[i] < e.minitem){ + e.minitem = e.ys[i]; } } - if(entity.minitem < itemSpace){ - entity.clogHeat = Mathf.lerpDelta(entity.clogHeat, 1f, 0.02f); + if(e.minitem < itemSpace){ + e.clogHeat = Mathf.lerpDelta(e.clogHeat, 1f, 0.02f); }else{ - entity.clogHeat = Mathf.lerpDelta(entity.clogHeat, 0f, 1f); + e.clogHeat = 0f; } - if(entity.items.total() == 0){ - entity.sleep(); - }else{ - entity.noSleep(); - } - - if(minremove != Integer.MAX_VALUE) entity.convey.truncate(minremove); + e.noSleep(); } @Override @@ -247,22 +231,21 @@ public class Conveyor extends Block implements Autotiler{ @Override public int removeStack(Tile tile, Item item, int amount){ - ConveyorEntity entity = tile.ent(); - entity.noSleep(); + ConveyorEntity e = tile.ent(); + e.noSleep(); int removed = 0; for(int j = 0; j < amount; j++){ - for(int i = 0; i < entity.convey.size; i++){ - long val = entity.convey.get(i); - ItemPos pos = pos1.set(val, ItemPos.drawShorts); - if(pos.item == item){ - entity.convey.removeValue(val); - entity.items.remove(item, 1); - removed++; + for(int i = 0; i < e.len; i++){ + if(e.ids[i] == item){ + e.remove(i); + e.items.remove(item, 1); + removed ++; break; } } } + return removed; } @@ -279,52 +262,50 @@ public class Conveyor extends Block implements Autotiler{ @Override public void handleStack(Item item, int amount, Tile tile, Unit source){ - ConveyorEntity entity = tile.ent(); + ConveyorEntity e = tile.ent(); for(int i = amount - 1; i >= 0; i--){ - long result = ItemPos.packItem(item, 0f, i * itemSpace); - entity.convey.insert(0, result); - entity.items.add(item, 1); + e.add(0); + e.xs[0] = 0; + e.ys[0] = i * itemSpace; + e.ids[0] = item; + e.items.add(item, 1); } - entity.noSleep(); + e.noSleep(); } @Override public boolean acceptItem(Item item, Tile tile, Tile source){ + ConveyorEntity e = tile.ent(); + if(e.len >= capacity) return false; int direction = source == null ? 0 : Math.abs(source.relativeTo(tile.x, tile.y) - tile.rotation()); - float minitem = tile.ent().minitem; - return (((direction == 0) && minitem >= itemSpace) || - ((direction % 2 == 1) && minitem > 0.52f)) && (source == null || !(source.block().rotate && (source.rotation() + 2) % 4 == tile.rotation())); + return (((direction == 0) && e.minitem >= itemSpace) || ((direction % 2 == 1) && e.minitem > 0.5f + itemSpace)) && (source == null || !(source.block().rotate && (source.rotation() + 2) % 4 == tile.rotation())); } @Override public void handleItem(Item item, Tile tile, Tile source){ - byte rotation = tile.rotation(); + ConveyorEntity e = tile.ent(); + if(e.len >= capacity) return; - int ch = Math.abs(source.relativeTo(tile.x, tile.y) - rotation); - int ang = ((source.relativeTo(tile.x, tile.y) - rotation)); + byte r = tile.rotation(); + int ang = ((source.relativeTo(tile.x, tile.y) - r)); + float x = (ang == -1 || ang == 3) ? 1 : (ang == 1 || ang == -3) ? -1 : 0; - float pos = ch == 0 ? 0 : ch % 2 == 1 ? 0.5f : 1f; - float y = (ang == -1 || ang == 3) ? 1 : (ang == 1 || ang == -3) ? -1 : 0; + e.noSleep(); + e.items.add(item, 1); - ConveyorEntity entity = tile.ent(); - entity.noSleep(); - long result = ItemPos.packItem(item, y * 0.9f, pos); - - tile.entity.items.add(item, 1); - - for(int i = 0; i < entity.convey.size; i++){ - if(compareItems(result, entity.convey.get(i)) < 0){ - entity.convey.insert(i, result); - entity.lastInserted = (byte)i; - return; - } + if(Math.abs(source.relativeTo(tile.x, tile.y) - r) == 0){ //idx = 0 + e.add(0); + e.xs[0] = x; + e.ys[0] = 0; + e.ids[0] = item; + }else{ //idx = mid + e.add(e.mid); + e.xs[e.mid] = x; + e.ys[e.mid] = 0.5f; + e.ids[e.mid] = item; } - - //this item must be greater than anything there... - entity.convey.add(result); - entity.lastInserted = (byte)(entity.convey.size - 1); } public static class ConveyorEntity extends TileEntity{ @@ -333,12 +314,14 @@ public class Conveyor extends Block implements Autotiler{ float[] xs = new float[capacity]; float[] ys = new float[capacity]; //amount of items, always < capacity - int count = 0; + int len = 0; //next entity @Nullable TileEntity next; @Nullable ConveyorEntity nextc; + //whether the next conveyor's rotation == tile rotation + boolean aligned; - byte lastInserted; + int lastInserted, mid; float minitem = 1; int blendbits; @@ -346,53 +329,50 @@ public class Conveyor extends Block implements Autotiler{ float clogHeat = 0f; + final void add(int o){ + for(int i = Math.max(o + 1, len); i > o; i--){ + ids[i] = ids[i - 1]; + xs[i] = xs[i - 1]; + ys[i] = ys[i - 1]; + } + + len++; + } + + final void remove(int o){ + for(int i = o; i < len - 1; i++){ + ids[i] = ids[i + 1]; + xs[i] = xs[i + 1]; + ys[i] = ys[i + 1]; + } + + len--; + } + @Override public void write(DataOutput stream) throws IOException{ super.write(stream); - stream.writeInt(count); + stream.writeInt(len); - for(int i = 0; i < count; i++){ - stream.writeInt(ItemPos.toInt(convey.get(i))); + for(int i = 0; i < len; i++){ + stream.writeInt(Pack.intBytes((byte)ids[i].id, (byte)(xs[i] * 127), (byte)(ys[i] * 255 - 128), (byte)0)); } } @Override public void read(DataInput stream, byte revision) throws IOException{ super.read(stream, revision); - count = 0; - int amount = stream.readInt(); - convey.ensureCapacity(Math.min(amount, 10)); + len = Math.min(stream.readInt(), capacity); - for(int i = 0; i < amount; i++){ - convey.add(ItemPos.toLong(stream.readInt())); + for(int i = 0; i < len; i++){ + int val = stream.readInt(); + byte id = (byte)(val >> 24); + float x = (float)((byte)(val >> 16)) / 127f; + float y = ((float)((byte)(val >> 8)) + 128f) / 255f; + ids[i] = content.item(id); + xs[i] = x; + ys[i] = i; } } - - static int toInt(int index){ - short itemid = values[0]; - float x = values[1] / (float)Short.MAX_VALUE; - float y = ((float)values[2]) / Short.MAX_VALUE + 1f; - - byte[] bytes = writeByte; - bytes[0] = (byte)itemid; - bytes[1] = (byte)(x * 127); - bytes[2] = (byte)(y * 255 - 128); - - return Pack.intBytes(bytes); - } - - static long toLong(int value){ - byte[] values = Pack.bytes(value, writeByte); - - short itemid = content.item(values[0]).id; - float x = values[1] / 127f; - float y = ((int)values[2] + 128) / 255f; - - short[] shorts = writeShort; - shorts[0] = itemid; - shorts[1] = (short)(x * Short.MAX_VALUE); - shorts[2] = (short)((y - 1f) * Short.MAX_VALUE); - return Pack.longShorts(shorts); - } } } \ No newline at end of file diff --git a/gradle.properties b/gradle.properties index 10cb482437..e3312d11f3 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,3 +1,3 @@ org.gradle.daemon=true org.gradle.jvmargs=-Xms256m -Xmx1024m -archash=aa8dafc3ff72c8f7776deb4597682e56b8697bc7 +archash=649641d8936160221ce24c47f5b0ad10606de289