diff --git a/TODO.md b/TODO.md index 4323a44a92..8118e89982 100644 --- a/TODO.md +++ b/TODO.md @@ -15,12 +15,12 @@ _(These are not planned in the near future at all, and have been suggested befor ### Already Suggested _(not necessarily planned!)_ - "more blocks" "more turrets" "more content" "more X/Y/Z" -- Multiplayer - Building of units (tanks, drones, _soldiers_, doesn't matter) - Enemy bases, fighting against AI, capture points - Co-op of any sort - Campaign, challenge mode -- Multiple cores +- PvP mode +- Multiple cores, movable cores - Movable turrets - Batteries or storage for anything - Destroy map indestructible blocks @@ -28,7 +28,7 @@ _(not necessarily planned!)_ - Steam release - Research system, tech tree, persistent upgrades, upgrades at all - Missile enemies/turrets/weapons (both homing and non-homing) -- Better graphics +- 'Better graphics' - Enemies dropping resources - Final objectives/non-endless mode - Fusion reactor @@ -37,7 +37,6 @@ _(not necessarily planned!)_ - Day/night cycle - Solar panels - Deflector shields -- Autosave - Underground blocks - Configurable outputs/inputs - Getting items out of the core @@ -53,24 +52,15 @@ _(not necessarily planned!)_ - Minimap - Underground conduits - More indicators for core damaged/attacked -- Delete saves, export saves, import saves - Display playtime in saves -- Edit descriptions for conveyor tunnels to be more clear about how to use them -- New map format system to display -- Better placement controls, break while placing -- Hide UI elements - New liquid conduit system ### Major Bugs - Black screen when tabbing out on Android -- Infinite explosions that destroy blocks - Random map reload when playing, leading to a crash (UI cause?) - Google Payments verify crash - Google Payments IllegalArgument crash -### Misc -- Localization support. Change all in-game strings to localized strings. Check compatibility with GWT and Android libraries. - ### Possible Additions - Mech body upgrades - Uranium extractor / uranium->iron converter @@ -83,19 +73,14 @@ _(not necessarily planned!)_ - Better enemy effects and looks - Homing missile enemies and turrets - Reflective shield blocks -- Tech tree with bonuses to production or turrets - Spawn points changed into enemy bases with hostile turrets - Unit production ### Optimization -- Look into uses for `IntMap` -- Spread updating over multiple frames for large groups of specific tile entities (?) - Optimize enemy + bullet code and check quadtree leaf parameters -- Check for unnecessary use of `Timers#get()` - Optimize generator laser distribution, especially finding targets - Optimize UI - Check memory usage and GC, profile - Optimize health bars and enemies in general - Make drawing of enemies more efficient (don't call `flush()`?) -- Look into `NodeRecord` storage for pathfinder, since it's taking 2MB+ of memory! diff --git a/core/assets/version.properties b/core/assets/version.properties index 0a7996137e..c44cb6abb6 100644 --- a/core/assets/version.properties +++ b/core/assets/version.properties @@ -1,7 +1,7 @@ #Autogenerated file. Do not modify. -#Tue Feb 13 18:19:15 EST 2018 +#Wed Feb 14 17:49:43 EST 2018 version=beta -androidBuildCode=190 +androidBuildCode=219 name=Mindustry code=3.3 build=custom build diff --git a/core/src/io/anuke/mindustry/core/NetClient.java b/core/src/io/anuke/mindustry/core/NetClient.java index 78ad5851aa..7615e129e5 100644 --- a/core/src/io/anuke/mindustry/core/NetClient.java +++ b/core/src/io/anuke/mindustry/core/NetClient.java @@ -20,6 +20,7 @@ import io.anuke.mindustry.resource.Item; import io.anuke.mindustry.world.Map; import io.anuke.mindustry.world.Tile; import io.anuke.mindustry.world.blocks.ProductionBlocks; +import io.anuke.mindustry.world.blocks.types.distribution.Teleporter; import io.anuke.ucore.core.Timers; import io.anuke.ucore.entities.BaseBulletType; import io.anuke.ucore.entities.Entities; @@ -226,14 +227,7 @@ public class NetClient extends Module { while (stream.available() > 0) { int pos = stream.readInt(); - //TODO what if there's no entity? new code - Tile tile = world.tile(pos % world.width(), pos / world.width()); - - byte times = stream.readByte(); - - for (int i = 0; i < times; i++) { - tile.entity.timer.getTimes()[i] = stream.readFloat(); - } + Tile tile = world.tile(pos); short data = stream.readShort(); tile.setPackedData(data); @@ -286,6 +280,9 @@ public class NetClient extends Module { Tile next = tile.getNearby(packet.rotation); tile.entity.items[packet.itemid] --; next.block().handleItem(Item.getByID(packet.itemid), next, tile); + + if(tile.block() instanceof Teleporter) + Log.info("Recieved dump for teleporter! items: {0}", tile.entity.totalItems()); }; if(threads.isEnabled()){ @@ -308,6 +305,21 @@ public class NetClient extends Module { r.run(); } }); + + Net.handleClient(ItemOffloadPacket.class, packet -> { + Runnable r = () -> { + Tile tile = world.tile(packet.position); + if (tile == null || tile.entity == null) return; + Tile next = tile.getNearby(tile.getRotation()); + next.block().handleItem(Item.getByID(packet.itemid), next, tile); + }; + + if(threads.isEnabled()){ + threads.run(r); + }else{ + r.run(); + } + }); } @Override diff --git a/core/src/io/anuke/mindustry/core/NetServer.java b/core/src/io/anuke/mindustry/core/NetServer.java index a476d8f5a9..9949295432 100644 --- a/core/src/io/anuke/mindustry/core/NetServer.java +++ b/core/src/io/anuke/mindustry/core/NetServer.java @@ -1,9 +1,6 @@ package io.anuke.mindustry.core; -import com.badlogic.gdx.utils.ByteArray; -import com.badlogic.gdx.utils.IntMap; -import com.badlogic.gdx.utils.ObjectMap; -import com.badlogic.gdx.utils.TimeUtils; +import com.badlogic.gdx.utils.*; import io.anuke.mindustry.core.GameState.State; import io.anuke.mindustry.entities.Player; import io.anuke.mindustry.entities.SyncEntity; @@ -12,6 +9,7 @@ import io.anuke.mindustry.io.Platform; import io.anuke.mindustry.io.Version; import io.anuke.mindustry.net.Net; import io.anuke.mindustry.net.Net.SendMode; +import io.anuke.mindustry.net.NetConnection; import io.anuke.mindustry.net.NetworkIO; import io.anuke.mindustry.net.Packets.*; import io.anuke.mindustry.resource.Upgrade; @@ -24,6 +22,7 @@ import io.anuke.ucore.entities.Entities; import io.anuke.ucore.entities.EntityGroup; import io.anuke.ucore.modules.Module; import io.anuke.ucore.util.Log; +import io.anuke.ucore.util.Mathf; import io.anuke.ucore.util.Timer; import java.io.ByteArrayInputStream; @@ -36,9 +35,11 @@ import static io.anuke.mindustry.Vars.*; public class NetServer extends Module{ private final static float serverSyncTime = 4, itemSyncTime = 10, blockSyncTime = 120; + private final static boolean sendBlockSync = false; private final static int timerEntitySync = 0; private final static int timerStateSync = 1; + private final static int timerBlockSync = 2; /**Maps connection IDs to players.*/ private IntMap connections = new IntMap<>(); @@ -301,8 +302,8 @@ public class NetServer extends Module{ Net.send(packet, SendMode.udp); } - /* - if(Timers.get("serverBlockSync", blockSyncTime)){ + + if(sendBlockSync && timer.get(timerBlockSync, blockSyncTime)){ Array connections = Net.getConnections(); @@ -316,7 +317,7 @@ public class NetServer extends Module{ int h = 16; sendBlockSync(id, x, y, w, h); } - }*/ + } } public void sendBlockSync(int client, int x, int y, int viewx, int viewy){ @@ -334,29 +335,17 @@ public class NetServer extends Module{ for (int ry = -viewy / 2; ry <= viewy / 2; ry++) { Tile tile = world.tile(x + rx, y + ry); - if (tile == null || tile.entity == null) continue; + if (tile == null || tile.entity == null || !tile.block().syncEntity()) continue; stream.writeInt(tile.packedPosition()); - byte times = 0; - - for(; times < tile.entity.timer.getTimes().length; times ++){ - if(tile.entity.timer.getTimes()[times] <= 1f){ - break; - } - } - - stream.writeByte(times); - - for(int i = 0; i < times; i ++){ - stream.writeFloat(tile.entity.timer.getTimes()[i]); - } - stream.writeShort(tile.getPackedData()); tile.entity.write(stream); } } + Log.info("Sent {0} bytes of block data.", stream.size()); + }catch (IOException e){ throw new RuntimeException(e); } diff --git a/core/src/io/anuke/mindustry/core/Renderer.java b/core/src/io/anuke/mindustry/core/Renderer.java index 1d815792a7..51fd4ad0d6 100644 --- a/core/src/io/anuke/mindustry/core/Renderer.java +++ b/core/src/io/anuke/mindustry/core/Renderer.java @@ -6,6 +6,7 @@ import com.badlogic.gdx.graphics.Colors; import com.badlogic.gdx.graphics.Texture; import com.badlogic.gdx.graphics.Texture.TextureWrap; import com.badlogic.gdx.graphics.g2d.GlyphLayout; +import com.badlogic.gdx.math.MathUtils; import com.badlogic.gdx.math.Rectangle; import com.badlogic.gdx.math.Vector2; import com.badlogic.gdx.utils.Array; @@ -429,7 +430,7 @@ public class Renderer extends RendererModule{ Draw.reset(); - //draw selected block health + //draw selected block bars and info if(input.recipe == null && !ui.hasMouse()){ Tile tile = world.tileWorld(Graphics.mouseWorld().x, Graphics.mouseWorld().y); @@ -444,9 +445,6 @@ public class Renderer extends RendererModule{ Draw.color(); } - //if(target.entity != null) - // drawHealth(target.drawx(), target.drawy() - 3f - target.block().height / 2f * tilesize, target.entity.health, target.entity.tile.block().health); - if(target.entity != null) { int bot = 0, top = 0; for (BlockBar bar : target.block().bars) { @@ -455,7 +453,7 @@ public class Renderer extends RendererModule{ float value = bar.value.get(target); - if(value <= -1f) continue; + if(MathUtils.isEqual(value, -1f)) continue; drawBar(bar.color, target.drawx(), target.drawy() + offset, value); diff --git a/core/src/io/anuke/mindustry/net/NetEvents.java b/core/src/io/anuke/mindustry/net/NetEvents.java index 64e1e3af37..13df0fe211 100644 --- a/core/src/io/anuke/mindustry/net/NetEvents.java +++ b/core/src/io/anuke/mindustry/net/NetEvents.java @@ -144,4 +144,11 @@ public class NetEvents { packet.itemid = (byte)item.id; Net.send(packet, SendMode.udp); } + + public static void handleOffload(Tile tile, Item item){ + ItemOffloadPacket packet = new ItemOffloadPacket(); + packet.position = tile.packedPosition(); + packet.itemid = (byte)item.id; + Net.send(packet, SendMode.udp); + } } diff --git a/core/src/io/anuke/mindustry/net/Packets.java b/core/src/io/anuke/mindustry/net/Packets.java index 47bf18aabf..74e554cf18 100644 --- a/core/src/io/anuke/mindustry/net/Packets.java +++ b/core/src/io/anuke/mindustry/net/Packets.java @@ -523,7 +523,24 @@ public class Packets { } } - public static class ItemAddPacket implements Packet{ + public static class ItemAddPacket implements Packet, UnimportantPacket{ + public int position; + public byte itemid; + + @Override + public void write(ByteBuffer buffer) { + buffer.putInt(position); + buffer.put(itemid); + } + + @Override + public void read(ByteBuffer buffer) { + position = buffer.getInt(); + itemid = buffer.get(); + } + } + + public static class ItemOffloadPacket implements Packet{ public int position; public byte itemid; diff --git a/core/src/io/anuke/mindustry/net/Registrator.java b/core/src/io/anuke/mindustry/net/Registrator.java index e569bb4249..9bc1beb095 100644 --- a/core/src/io/anuke/mindustry/net/Registrator.java +++ b/core/src/io/anuke/mindustry/net/Registrator.java @@ -40,6 +40,7 @@ public class Registrator { EntitySpawnPacket.class, ItemTransferPacket.class, ItemAddPacket.class, + ItemOffloadPacket.class }; private static ObjectIntMap> ids = new ObjectIntMap<>(); diff --git a/core/src/io/anuke/mindustry/ui/dialogs/LevelDialog.java b/core/src/io/anuke/mindustry/ui/dialogs/LevelDialog.java index 19f8f95ab9..9a7c8d4424 100644 --- a/core/src/io/anuke/mindustry/ui/dialogs/LevelDialog.java +++ b/core/src/io/anuke/mindustry/ui/dialogs/LevelDialog.java @@ -50,11 +50,11 @@ public class LevelDialog extends FloatingDialog{ selmode.add("$text.level.mode").padRight(15f); for(GameMode mode : GameMode.values()){ - TextButton b = Elements.newButton("$mode."+mode.name()+".name", "toggle", ()->{ - state.mode = mode; - }); - group.add(b); - selmode.add(b).size(130f, 54f); + TextButton[] b = {null}; + b[0] = Elements.newButton("$mode." + mode.name() + ".name", "toggle", () -> state.mode = mode); + b[0].update(() -> b[0].setChecked(state.mode == mode)); + group.add(b[0]); + selmode.add(b[0]).size(130f, 54f); } content().add(selmode); diff --git a/core/src/io/anuke/mindustry/world/Block.java b/core/src/io/anuke/mindustry/world/Block.java index 1707bf76b9..95a92d1d31 100644 --- a/core/src/io/anuke/mindustry/world/Block.java +++ b/core/src/io/anuke/mindustry/world/Block.java @@ -172,6 +172,10 @@ public class Block{ return new TileEntity(); } + public boolean syncEntity(){ + return true; + } + /** * Tries to put this item into a nearby container, if there are no available * containers, it gets added to the block's inventory.*/ @@ -237,7 +241,7 @@ public class Block{ } /** - * Try offloading an item to a nearby container. Returns true if success. + * Try offloading an item to a nearby container in its facing direction. Returns true if success. */ protected boolean offloadDir(Tile tile, Item item){ Tile other = tile.getNearby(tile.getRotation()); diff --git a/core/src/io/anuke/mindustry/world/blocks/types/distribution/Conveyor.java b/core/src/io/anuke/mindustry/world/blocks/types/distribution/Conveyor.java index ff286cea59..2262004cd0 100644 --- a/core/src/io/anuke/mindustry/world/blocks/types/distribution/Conveyor.java +++ b/core/src/io/anuke/mindustry/world/blocks/types/distribution/Conveyor.java @@ -72,17 +72,23 @@ public class Conveyor extends Block{ byte rotation = tile.getRotation(); - for(int i = 0; i < entity.convey.size; i ++){ - ItemPos pos = drawpos.set(entity.convey.get(i), ItemPos.drawShorts); + try { - if(pos.item == null) continue; + for (int i = 0; i < entity.convey.size; i++) { + ItemPos pos = drawpos.set(entity.convey.get(i), ItemPos.drawShorts); - tr1.trns(rotation * 90, tilesize, 0); - tr2.trns(rotation * 90, -tilesize / 2, pos.x*tilesize/2); + if (pos.item == null) continue; - Draw.rect(pos.item.region, - tile.x * tilesize + tr1.x * pos.y + tr2.x, - tile.y * tilesize + tr1.y * pos.y + tr2.y, itemSize, itemSize); + tr1.trns(rotation * 90, tilesize, 0); + tr2.trns(rotation * 90, -tilesize / 2, pos.x * tilesize / 2); + + Draw.rect(pos.item.region, + tile.x * tilesize + tr1.x * pos.y + tr2.x, + tile.y * tilesize + tr1.y * pos.y + tr2.y, itemSize, itemSize); + } + + }catch (IndexOutOfBoundsException e){ + Log.err(e); } } @@ -94,7 +100,7 @@ public class Conveyor extends Block{ int minremove = Integer.MAX_VALUE; - for(int i = 0; i < entity.convey.size; i ++){ + for(int i = entity.convey.size - 1; i >= 0; i --){ long value = entity.convey.get(i); ItemPos pos = pos1.set(value, ItemPos.updateShorts); @@ -171,6 +177,11 @@ public class Conveyor extends Block{ } } + @Override + public boolean syncEntity(){ + return false; + } + /** * Conveyor data format: * [0] item ordinal diff --git a/core/src/io/anuke/mindustry/world/blocks/types/distribution/Teleporter.java b/core/src/io/anuke/mindustry/world/blocks/types/distribution/Teleporter.java index b7acb09e53..afb99a3062 100644 --- a/core/src/io/anuke/mindustry/world/blocks/types/distribution/Teleporter.java +++ b/core/src/io/anuke/mindustry/world/blocks/types/distribution/Teleporter.java @@ -7,6 +7,7 @@ import io.anuke.mindustry.entities.TileEntity; import io.anuke.mindustry.net.Net; import io.anuke.mindustry.net.NetEvents; import io.anuke.mindustry.resource.Item; +import io.anuke.mindustry.world.BlockBar; import io.anuke.mindustry.world.Tile; import io.anuke.mindustry.world.blocks.types.PowerBlock; import io.anuke.ucore.core.Timers; @@ -46,6 +47,8 @@ public class Teleporter extends PowerBlock{ solid = true; health = 80; powerCapacity = 30f; + + bars.add(new BlockBar(Color.RED, true, tile -> tile.entity.totalItems() / 4f)); } @Override @@ -135,7 +138,6 @@ public class Teleporter extends PowerBlock{ Array links = findLinks(tile); if(links.size > 0){ - if(Net.server() || !Net.active()){ Tile target = links.random(); target.entity.addItem(item, 1); @@ -169,7 +171,7 @@ public class Teleporter extends PowerBlock{ if(other.block() instanceof Teleporter){ if(other.entity().color != entity.color){ removal.add(other); - }else if(other.entity.totalItems() == 0){ + }else if(other.entity.totalItems() <= 0){ returns.add(other); } }else{