From 7a049d64d87dfcf06c3cf1af537552401ce5ed91 Mon Sep 17 00:00:00 2001 From: Anuken Date: Tue, 26 Jun 2018 11:15:23 -0400 Subject: [PATCH] Many various bugfixes, more aggressive memory optimization --- build.gradle | 2 +- core/assets/bundles/bundle.properties | 4 ++ core/src/io/anuke/mindustry/Vars.java | 4 +- .../io/anuke/mindustry/ai/BlockIndexer.java | 4 +- .../src/io/anuke/mindustry/ai/Pathfinder.java | 4 +- .../src/io/anuke/mindustry/content/Items.java | 2 +- .../io/anuke/mindustry/core/NetClient.java | 4 ++ .../io/anuke/mindustry/core/NetServer.java | 14 ++++--- .../src/io/anuke/mindustry/core/Renderer.java | 2 +- .../anuke/mindustry/core/ThreadHandler.java | 4 +- .../mindustry/editor/MapEditorDialog.java | 2 +- .../anuke/mindustry/editor/MapLoadDialog.java | 10 ++++- .../anuke/mindustry/editor/MapRenderer.java | 2 +- .../io/anuke/mindustry/entities/Player.java | 2 +- .../src/io/anuke/mindustry/entities/Unit.java | 2 +- .../io/anuke/mindustry/entities/Units.java | 4 +- .../mindustry/entities/bullet/Bullet.java | 2 +- .../entities/traits/BuilderTrait.java | 9 ++++- .../mindustry/entities/traits/SyncTrait.java | 2 +- .../io/anuke/mindustry/game/Difficulty.java | 7 +++- core/src/io/anuke/mindustry/game/Team.java | 2 + .../mindustry/graphics/BlockRenderer.java | 7 ++-- .../anuke/mindustry/input/InputHandler.java | 2 + core/src/io/anuke/mindustry/io/MapIO.java | 2 +- core/src/io/anuke/mindustry/io/TypeIO.java | 2 +- .../anuke/mindustry/io/versions/Save16.java | 4 +- .../src/io/anuke/mindustry/net/NetworkIO.java | 4 +- core/src/io/anuke/mindustry/ui/IntFormat.java | 23 +++++++++++ core/src/io/anuke/mindustry/ui/ItemImage.java | 2 +- .../mindustry/ui/dialogs/MapsDialog.java | 4 ++ .../mindustry/ui/fragments/HudFragment.java | 37 +++++++++++------- core/src/io/anuke/mindustry/world/Tile.java | 2 +- .../anuke/mindustry/world/blocks/Floor.java | 39 +++++++++++-------- .../mindustry/world/blocks/OreBlock.java | 11 +----- .../mindustry/world/blocks/defense/Door.java | 13 ++++++- .../world/blocks/production/MechFactory.java | 10 ++++- .../world/blocks/storage/CoreBlock.java | 15 ++++++- .../world/blocks/units/Reconstructor.java | 9 ++++- .../world/mapgen/WorldGenerator.java | 2 +- 39 files changed, 189 insertions(+), 87 deletions(-) create mode 100644 core/src/io/anuke/mindustry/ui/IntFormat.java diff --git a/build.gradle b/build.gradle index 84625ad2b1..dba7e3ef23 100644 --- a/build.gradle +++ b/build.gradle @@ -27,7 +27,7 @@ allprojects { gdxVersion = '1.9.8' roboVMVersion = '2.3.0' aiVersion = '1.8.1' - uCoreVersion = '19fbbd3b3a' + uCoreVersion = 'da40998ac6' getVersionString = { String buildVersion = getBuildVersion() diff --git a/core/assets/bundles/bundle.properties b/core/assets/bundles/bundle.properties index 8bdd5a4a7e..e68ba78dff 100644 --- a/core/assets/bundles/bundle.properties +++ b/core/assets/bundles/bundle.properties @@ -29,6 +29,7 @@ text.addplayers=Add/Remove Players text.newgame=New Game text.quit=Quit text.maps=Maps +text.maps.none=[LIGHT_GRAY]No maps found! text.about.button=About text.name=Name: text.unlocked=New Block Unlocked! @@ -219,6 +220,9 @@ text.menu=Menu text.play=Play text.load=Load text.save=Save +text.fps=FPS: {0} +text.tps=TPS: {0} +text.ping=Ping: {0}ms text.language.restart=Please restart your game for the language settings to take effect. text.settings.language=Language text.settings=Settings diff --git a/core/src/io/anuke/mindustry/Vars.java b/core/src/io/anuke/mindustry/Vars.java index dd8b92431c..5f08d35f69 100644 --- a/core/src/io/anuke/mindustry/Vars.java +++ b/core/src/io/anuke/mindustry/Vars.java @@ -154,11 +154,11 @@ public class Vars{ puddleGroup = Entities.addGroup(Puddle.class, false).enableMapping(); itemGroup = Entities.addGroup(ItemDrop.class).enableMapping(); fireGroup = Entities.addGroup(Fire.class, false).enableMapping(); - unitGroups = new EntityGroup[Team.values().length]; + unitGroups = new EntityGroup[Team.all.length]; threads = new ThreadHandler(Platform.instance.getThreadProvider()); - for(Team team : Team.values()){ + for(Team team : Team.all){ unitGroups[team.ordinal()] = Entities.addGroup(BaseUnit.class).enableMapping(); } diff --git a/core/src/io/anuke/mindustry/ai/BlockIndexer.java b/core/src/io/anuke/mindustry/ai/BlockIndexer.java index d487305009..38a3f8309f 100644 --- a/core/src/io/anuke/mindustry/ai/BlockIndexer.java +++ b/core/src/io/anuke/mindustry/ai/BlockIndexer.java @@ -73,8 +73,8 @@ public class BlockIndexer { ores = null; //create bitset for each team type that contains each quadrant - structQuadrants = new Bits[Team.values().length]; - for(int i = 0; i < Team.values().length; i ++){ + structQuadrants = new Bits[Team.all.length]; + for(int i = 0; i < Team.all.length; i ++){ structQuadrants[i] = new Bits(Mathf.ceil(world.width() / (float)structQuadrantSize) * Mathf.ceil(world.height() / (float)structQuadrantSize)); } diff --git a/core/src/io/anuke/mindustry/ai/Pathfinder.java b/core/src/io/anuke/mindustry/ai/Pathfinder.java index a8e02a4177..7a02b7c7a0 100644 --- a/core/src/io/anuke/mindustry/ai/Pathfinder.java +++ b/core/src/io/anuke/mindustry/ai/Pathfinder.java @@ -116,7 +116,7 @@ public class Pathfinder { private void createFor(Team team){ PathData path = new PathData(); path.search ++; - path.frontier.ensureCapacity(world.width() * world.height() / 2); + path.frontier.ensureCapacity((world.width() + world.height()) * 3); paths[team.ordinal()] = path; @@ -167,7 +167,7 @@ public class Pathfinder { private void clear(){ Timers.mark(); - paths = new PathData[Team.values().length]; + paths = new PathData[Team.all.length]; blocked.clear(); for(TeamData data : state.teams.getTeams()){ diff --git a/core/src/io/anuke/mindustry/content/Items.java b/core/src/io/anuke/mindustry/content/Items.java index 2822651db3..547d4ecb24 100644 --- a/core/src/io/anuke/mindustry/content/Items.java +++ b/core/src/io/anuke/mindustry/content/Items.java @@ -15,7 +15,7 @@ public class Items implements ContentList{ public void load() { stone = new Item("stone", Color.valueOf("777777")) {{ - hardness = 2; + hardness = 3; }}; tungsten = new Item("tungsten", Color.valueOf("a0b0c8")) {{ diff --git a/core/src/io/anuke/mindustry/core/NetClient.java b/core/src/io/anuke/mindustry/core/NetClient.java index ea1d4e7d72..ffd9e7f7ac 100644 --- a/core/src/io/anuke/mindustry/core/NetClient.java +++ b/core/src/io/anuke/mindustry/core/NetClient.java @@ -241,6 +241,10 @@ public class NetClient extends Module { //get data input for reading from the stream DataInputStream input = netClient.dataStream; + + //read wave info + state.wavetime = input.readFloat(); + state.wave = input.readInt(); byte cores = input.readByte(); for (int i = 0; i < cores; i++) { diff --git a/core/src/io/anuke/mindustry/core/NetServer.java b/core/src/io/anuke/mindustry/core/NetServer.java index 6895ca219b..879eec9d95 100644 --- a/core/src/io/anuke/mindustry/core/NetServer.java +++ b/core/src/io/anuke/mindustry/core/NetServer.java @@ -328,11 +328,9 @@ public class NetServer extends Module{ //reset stream to begin writing syncStream.reset(); - int totalGroups = 0; - - for (EntityGroup group : Entities.getAllGroups()) { - if (!group.isEmpty() && (group.all().get(0) instanceof SyncTrait)) totalGroups ++; - } + //write wave data + dataStream.writeFloat(state.wavetime); + dataStream.writeInt(state.wave); Array cores = state.teams.get(player.getTeam()).cores; @@ -347,6 +345,12 @@ public class NetServer extends Module{ //write timestamp dataStream.writeLong(TimeUtils.millis()); + int totalGroups = 0; + + for (EntityGroup group : Entities.getAllGroups()) { + if (!group.isEmpty() && (group.all().get(0) instanceof SyncTrait)) totalGroups ++; + } + //write total amount of serializable groups dataStream.writeByte(totalGroups); diff --git a/core/src/io/anuke/mindustry/core/Renderer.java b/core/src/io/anuke/mindustry/core/Renderer.java index ecbfc5d94f..d5a05bf508 100644 --- a/core/src/io/anuke/mindustry/core/Renderer.java +++ b/core/src/io/anuke/mindustry/core/Renderer.java @@ -252,7 +252,7 @@ public class Renderer extends RendererModule{ } private void drawAllTeams(boolean flying){ - for(Team team : Team.values()){ + for(Team team : Team.all){ EntityGroup group = unitGroups[team.ordinal()]; if(group.count(p -> p.isFlying() == flying) + diff --git a/core/src/io/anuke/mindustry/core/ThreadHandler.java b/core/src/io/anuke/mindustry/core/ThreadHandler.java index 0f35d0bc53..46890f322f 100644 --- a/core/src/io/anuke/mindustry/core/ThreadHandler.java +++ b/core/src/io/anuke/mindustry/core/ThreadHandler.java @@ -61,7 +61,7 @@ public class ThreadHandler { } } - public int getFPS(){ + public int getTPS(){ return (int)(60/delta); } @@ -112,7 +112,7 @@ public class ThreadHandler { } public boolean doInterpolate(){ - return enabled && Math.abs(Gdx.graphics.getFramesPerSecond() - getFPS()) > 15; + return enabled && Math.abs(Gdx.graphics.getFramesPerSecond() - getTPS()) > 15; } public boolean isOnThread(){ diff --git a/core/src/io/anuke/mindustry/editor/MapEditorDialog.java b/core/src/io/anuke/mindustry/editor/MapEditorDialog.java index f2c5757f74..8563e01eee 100644 --- a/core/src/io/anuke/mindustry/editor/MapEditorDialog.java +++ b/core/src/io/anuke/mindustry/editor/MapEditorDialog.java @@ -457,7 +457,7 @@ public class MapEditorDialog extends Dialog implements Disposable{ int i = 0; - for(Team team : Team.values()){ + for(Team team : Team.all){ ImageButton button = new ImageButton("white", "toggle"); button.margin(4f, 4f, 10f, 4f); button.getImageCell().grow(); diff --git a/core/src/io/anuke/mindustry/editor/MapLoadDialog.java b/core/src/io/anuke/mindustry/editor/MapLoadDialog.java index f6e921cbee..52fd0eb2a3 100644 --- a/core/src/io/anuke/mindustry/editor/MapLoadDialog.java +++ b/core/src/io/anuke/mindustry/editor/MapLoadDialog.java @@ -3,9 +3,11 @@ package io.anuke.mindustry.editor; import io.anuke.mindustry.io.Map; import io.anuke.mindustry.ui.BorderImage; import io.anuke.mindustry.ui.dialogs.FloatingDialog; +import io.anuke.ucore.core.Core; import io.anuke.ucore.function.Consumer; import io.anuke.ucore.scene.ui.ButtonGroup; import io.anuke.ucore.scene.ui.ScrollPane; +import io.anuke.ucore.scene.ui.ScrollPane.ScrollPaneStyle; import io.anuke.ucore.scene.ui.TextButton; import io.anuke.ucore.scene.ui.layout.Table; @@ -65,7 +67,13 @@ public class MapLoadDialog extends FloatingDialog{ if (++i % maxcol == 0) table.row(); } - content().add("$text.editor.loadmap"); + if(world.maps().all().size == 0){ + pane.setStyle(Core.skin.get("clear", ScrollPaneStyle.class)); + table.add("$text.maps.none").center(); + }else { + content().add("$text.editor.loadmap"); + } + content().row(); content().add(pane); } diff --git a/core/src/io/anuke/mindustry/editor/MapRenderer.java b/core/src/io/anuke/mindustry/editor/MapRenderer.java index e76f935d93..3b6870bb1a 100644 --- a/core/src/io/anuke/mindustry/editor/MapRenderer.java +++ b/core/src/io/anuke/mindustry/editor/MapRenderer.java @@ -106,7 +106,7 @@ public class MapRenderer implements Disposable{ byte btr = editor.getMap().read(wx, wy, DataPosition.rotationTeam); byte elev = editor.getMap().read(wx, wy, DataPosition.elevation); byte rotation = Bits.getLeftByte(btr); - Team team = Team.values()[Bits.getRightByte(btr)]; + Team team = Team.all[Bits.getRightByte(btr)]; Block floor = Block.getByID(bf); Block wall = Block.getByID(bw); diff --git a/core/src/io/anuke/mindustry/entities/Player.java b/core/src/io/anuke/mindustry/entities/Player.java index 574bff7127..c196719a45 100644 --- a/core/src/io/anuke/mindustry/entities/Player.java +++ b/core/src/io/anuke/mindustry/entities/Player.java @@ -502,7 +502,7 @@ public class Player extends Unit implements BuilderTrait, CarryTrait { movement.setZero(); - String section = "player_" + (playerIndex + 1); + String section = control.input(playerIndex).section; float xa = Inputs.getAxis(section, "move_x"); float ya = Inputs.getAxis(section, "move_y"); diff --git a/core/src/io/anuke/mindustry/entities/Unit.java b/core/src/io/anuke/mindustry/entities/Unit.java index 27abe68f0c..0500feb549 100644 --- a/core/src/io/anuke/mindustry/entities/Unit.java +++ b/core/src/io/anuke/mindustry/entities/Unit.java @@ -136,7 +136,7 @@ public abstract class Unit extends DestructibleEntity implements SaveTrait, Targ this.status.readSave(stream); this.inventory.readSave(stream); - this.team = Team.values()[team]; + this.team = Team.all[team]; this.health = health; this.x = x; this.y = y; diff --git a/core/src/io/anuke/mindustry/entities/Units.java b/core/src/io/anuke/mindustry/entities/Units.java index ad4a81fdc0..e549b63fe5 100644 --- a/core/src/io/anuke/mindustry/entities/Units.java +++ b/core/src/io/anuke/mindustry/entities/Units.java @@ -220,7 +220,7 @@ public class Units { /**Iterates over all units in a rectangle.*/ public static void getNearby(Rectangle rect, Consumer cons){ - for(Team team : Team.values()){ + for(Team team : Team.all){ EntityGroup group = unitGroups[team.ordinal()]; if(!group.isEmpty()){ EntityPhysics.getNearby(group, rect, entity -> cons.accept((Unit)entity)); @@ -253,7 +253,7 @@ public class Units { /**Iterates over all units.*/ public static void getAllUnits(Consumer cons){ - for(Team team : Team.values()){ + for(Team team : Team.all){ EntityGroup group = unitGroups[team.ordinal()]; for(Unit unit : group.all()){ cons.accept(unit); diff --git a/core/src/io/anuke/mindustry/entities/bullet/Bullet.java b/core/src/io/anuke/mindustry/entities/bullet/Bullet.java index a60beb6aea..1d48b7ae6c 100644 --- a/core/src/io/anuke/mindustry/entities/bullet/Bullet.java +++ b/core/src/io/anuke/mindustry/entities/bullet/Bullet.java @@ -145,7 +145,7 @@ public class Bullet extends BulletEntity implements TeamTrait, SyncT y = data.readFloat(); velocity.x = data.readFloat(); velocity.y = data.readFloat(); - team = Team.values()[data.readByte()]; + team = Team.all[data.readByte()]; type = BulletType.getByID(data.readByte()); } diff --git a/core/src/io/anuke/mindustry/entities/traits/BuilderTrait.java b/core/src/io/anuke/mindustry/entities/traits/BuilderTrait.java index fe8a73c604..7b13f97c63 100644 --- a/core/src/io/anuke/mindustry/entities/traits/BuilderTrait.java +++ b/core/src/io/anuke/mindustry/entities/traits/BuilderTrait.java @@ -39,7 +39,7 @@ import static io.anuke.mindustry.Vars.world; public interface BuilderTrait { //these are not instance variables! Translator[] tmptr = {new Translator(), new Translator(), new Translator(), new Translator()}; - float placeDistance = 200f; + float placeDistance = 140f; float mineDistance = 70f; /**Returns the queue for storing build requests.*/ @@ -118,7 +118,8 @@ public interface BuilderTrait { Tile tile = world.tile(current.x, current.y); - if(unit.distanceTo(tile) > placeDistance) { //out of range, skip it. + if(unit.distanceTo(tile) > placeDistance || //out of range, skip it + (current.lastEntity != null && current.lastEntity.isDead())) { //build/destroy request has died, skip it getPlaceQueue().removeFirst(); }else if(current.remove){ @@ -144,6 +145,7 @@ public interface BuilderTrait { //otherwise, update it. BreakEntity entity = tile.entity(); + current.lastEntity = entity; entity.addProgress(core, unit, 1f / entity.breakTime * Timers.delta() * getBuildPower(tile)); unit.rotation = Mathf.slerpDelta(unit.rotation, unit.angleTo(entity), 0.4f); @@ -174,6 +176,7 @@ public interface BuilderTrait { //otherwise, update it. BuildEntity entity = tile.entity(); + current.lastEntity = entity; entity.addProgress(core.items, 1f / entity.recipe.cost * Timers.delta() * getBuildPower(tile)); if(unit instanceof Player){ @@ -288,7 +291,9 @@ public interface BuilderTrait { public final int x, y, rotation; public final Recipe recipe; public final boolean remove; + public boolean requested; + public TileEntity lastEntity; public float progress; diff --git a/core/src/io/anuke/mindustry/entities/traits/SyncTrait.java b/core/src/io/anuke/mindustry/entities/traits/SyncTrait.java index 9e491f6b99..471b3226c4 100644 --- a/core/src/io/anuke/mindustry/entities/traits/SyncTrait.java +++ b/core/src/io/anuke/mindustry/entities/traits/SyncTrait.java @@ -14,7 +14,7 @@ public interface SyncTrait extends Entity, TypeTrait { /**Whether smoothing of entities is enabled when using multithreading; not yet implemented.*/ static boolean isSmoothing(){ - return threads.isEnabled() && threads.getFPS() <= Gdx.graphics.getFramesPerSecond() / 2f; + return threads.isEnabled() && threads.getTPS() <= Gdx.graphics.getFramesPerSecond() / 2f; } /**Sets the position of this entity and updated the interpolator.*/ diff --git a/core/src/io/anuke/mindustry/game/Difficulty.java b/core/src/io/anuke/mindustry/game/Difficulty.java index f0e4768765..ed11ea5338 100644 --- a/core/src/io/anuke/mindustry/game/Difficulty.java +++ b/core/src/io/anuke/mindustry/game/Difficulty.java @@ -18,6 +18,8 @@ public enum Difficulty { /**Scaling of max time between waves. Default time is 4 minutes.*/ public final float maxTimeScaling; + private String value; + Difficulty(float enemyScaling, float timeScaling, float maxTimeScaling){ this.enemyScaling = enemyScaling; this.timeScaling = timeScaling; @@ -26,6 +28,9 @@ public enum Difficulty { @Override public String toString() { - return Bundles.get("setting.difficulty." + name()); + if(value == null){ + value = Bundles.get("setting.difficulty." + name()); + } + return value; } } diff --git a/core/src/io/anuke/mindustry/game/Team.java b/core/src/io/anuke/mindustry/game/Team.java index d38200fcfc..0d97c39285 100644 --- a/core/src/io/anuke/mindustry/game/Team.java +++ b/core/src/io/anuke/mindustry/game/Team.java @@ -13,6 +13,8 @@ public enum Team { public final Color color; public final int intColor; + public final static Team[] all = values(); + Team(Color color){ this.color = color; intColor = Color.rgba8888(color); diff --git a/core/src/io/anuke/mindustry/graphics/BlockRenderer.java b/core/src/io/anuke/mindustry/graphics/BlockRenderer.java index d3d935a337..07464bba28 100644 --- a/core/src/io/anuke/mindustry/graphics/BlockRenderer.java +++ b/core/src/io/anuke/mindustry/graphics/BlockRenderer.java @@ -1,6 +1,7 @@ package io.anuke.mindustry.graphics; import com.badlogic.gdx.utils.Array; +import com.badlogic.gdx.utils.Sort; import io.anuke.mindustry.content.blocks.Blocks; import io.anuke.mindustry.game.Team; import io.anuke.mindustry.world.Block; @@ -10,8 +11,6 @@ import io.anuke.ucore.core.Graphics; import io.anuke.ucore.graphics.Draw; import io.anuke.ucore.util.Mathf; -import java.util.Arrays; - import static io.anuke.mindustry.Vars.*; import static io.anuke.ucore.core.Core.camera; @@ -106,8 +105,8 @@ public class BlockRenderer{ floorRenderer.drawLayer(CacheLayer.walls); floorRenderer.endDraw(); Graphics.begin(); - - Arrays.sort(requests.items, 0, requestidx); + + Sort.instance().sort(requests.items, 0, requestidx); iterateidx = 0; } diff --git a/core/src/io/anuke/mindustry/input/InputHandler.java b/core/src/io/anuke/mindustry/input/InputHandler.java index fa8cfef8d0..33a6bb331b 100644 --- a/core/src/io/anuke/mindustry/input/InputHandler.java +++ b/core/src/io/anuke/mindustry/input/InputHandler.java @@ -42,6 +42,7 @@ public abstract class InputHandler extends InputAdapter{ final static float backTrns = 3f; public final Player player; + public final String section; public final OverlayFragment frag = new OverlayFragment(this); public Recipe recipe; @@ -50,6 +51,7 @@ public abstract class InputHandler extends InputAdapter{ public InputHandler(Player player){ this.player = player; + this.section = "player_" + (player.playerIndex + 1); Timers.run(1f, () -> frag.build(Core.scene.getRoot())); } diff --git a/core/src/io/anuke/mindustry/io/MapIO.java b/core/src/io/anuke/mindustry/io/MapIO.java index db9bf5c14c..4ff93932b9 100644 --- a/core/src/io/anuke/mindustry/io/MapIO.java +++ b/core/src/io/anuke/mindustry/io/MapIO.java @@ -42,7 +42,7 @@ public class MapIO { Block floor = Block.getByID(marker.floor); Block wall = Block.getByID(marker.wall); int wallc = ColorMapper.getBlockColor(wall); - if(wallc == 0 && (wall.update || wall.solid || wall.breakable)) wallc = Team.values()[marker.team].intColor; + if(wallc == 0 && (wall.update || wall.solid || wall.breakable)) wallc = Team.all[marker.team].intColor; wallc = wallc == 0 ? ColorMapper.getBlockColor(floor) : wallc; if(marker.elevation > 0){ float scaling = 1f + marker.elevation/8f; diff --git a/core/src/io/anuke/mindustry/io/TypeIO.java b/core/src/io/anuke/mindustry/io/TypeIO.java index cca6710aa5..6945182e75 100644 --- a/core/src/io/anuke/mindustry/io/TypeIO.java +++ b/core/src/io/anuke/mindustry/io/TypeIO.java @@ -141,7 +141,7 @@ public class TypeIO { @ReadClass(Team.class) public static Team readTeam(ByteBuffer buffer){ - return Team.values()[buffer.get()]; + return Team.all[buffer.get()]; } @WriteClass(AdminAction.class) diff --git a/core/src/io/anuke/mindustry/io/versions/Save16.java b/core/src/io/anuke/mindustry/io/versions/Save16.java index 411223efc0..9e7b460c05 100644 --- a/core/src/io/anuke/mindustry/io/versions/Save16.java +++ b/core/src/io/anuke/mindustry/io/versions/Save16.java @@ -115,9 +115,9 @@ public class Save16 extends SaveFileVersion { byte team = Bits.getLeftByte(tr); byte rotation = Bits.getRightByte(tr); - Team t = Team.values()[team]; + Team t = Team.all[team]; - tile.setTeam(Team.values()[team]); + tile.setTeam(Team.all[team]); tile.entity.health = health; tile.setRotation(rotation); diff --git a/core/src/io/anuke/mindustry/net/NetworkIO.java b/core/src/io/anuke/mindustry/net/NetworkIO.java index b48c0abe11..bd1594253f 100644 --- a/core/src/io/anuke/mindustry/net/NetworkIO.java +++ b/core/src/io/anuke/mindustry/net/NetworkIO.java @@ -176,7 +176,7 @@ public class NetworkIO { byte tr = stream.readByte(); short health = stream.readShort(); - tile.setTeam(Team.values()[Bits.getLeftByte(tr)]); + tile.setTeam(Team.all[Bits.getLeftByte(tr)]); tile.setRotation(Bits.getRightByte(tr)); tile.entity.health = health; @@ -197,7 +197,7 @@ public class NetworkIO { byte teams = stream.readByte(); for (int i = 0; i < teams; i++) { - Team team = Team.values()[stream.readByte()]; + Team team = Team.all[stream.readByte()]; boolean ally = stream.readBoolean(); short cores = stream.readShort(); state.teams.add(team, ally); diff --git a/core/src/io/anuke/mindustry/ui/IntFormat.java b/core/src/io/anuke/mindustry/ui/IntFormat.java new file mode 100644 index 0000000000..ad753bd871 --- /dev/null +++ b/core/src/io/anuke/mindustry/ui/IntFormat.java @@ -0,0 +1,23 @@ +package io.anuke.mindustry.ui; + +import io.anuke.ucore.util.Bundles; + +/**A low-garbage way to format bundle strings.*/ +public class IntFormat { + private final StringBuilder builder = new StringBuilder(); + private final String text; + private int lastValue = Integer.MIN_VALUE; + + public IntFormat(String text) { + this.text = text; + } + + public CharSequence get(int value){ + if(lastValue != value){ + builder.setLength(0); + builder.append(Bundles.format(text, value)); + } + lastValue = value; + return builder; + } +} diff --git a/core/src/io/anuke/mindustry/ui/ItemImage.java b/core/src/io/anuke/mindustry/ui/ItemImage.java index e38ee4ac3d..fe7902a39d 100644 --- a/core/src/io/anuke/mindustry/ui/ItemImage.java +++ b/core/src/io/anuke/mindustry/ui/ItemImage.java @@ -11,7 +11,7 @@ import io.anuke.ucore.scene.ui.layout.Table; public class ItemImage extends Stack { private Image image; - public ItemImage(TextureRegion region, Supplier text, Color color) { + public ItemImage(TextureRegion region, Supplier text, Color color) { Table t = new Table().left().bottom(); t.label(text).get().setFontScale(0.5f); diff --git a/core/src/io/anuke/mindustry/ui/dialogs/MapsDialog.java b/core/src/io/anuke/mindustry/ui/dialogs/MapsDialog.java index 46ae2cd62b..f1abf8086c 100644 --- a/core/src/io/anuke/mindustry/ui/dialogs/MapsDialog.java +++ b/core/src/io/anuke/mindustry/ui/dialogs/MapsDialog.java @@ -93,6 +93,10 @@ public class MapsDialog extends FloatingDialog { i ++; } + if(world.maps().all().size == 0){ + maps.add("$text.maps.none"); + } + content().add(pane).uniformX(); } diff --git a/core/src/io/anuke/mindustry/ui/fragments/HudFragment.java b/core/src/io/anuke/mindustry/ui/fragments/HudFragment.java index 7047c60b89..563f0b0508 100644 --- a/core/src/io/anuke/mindustry/ui/fragments/HudFragment.java +++ b/core/src/io/anuke/mindustry/ui/fragments/HudFragment.java @@ -9,10 +9,10 @@ import com.badlogic.gdx.utils.Scaling; import io.anuke.mindustry.core.GameState.State; import io.anuke.mindustry.net.Net; import io.anuke.mindustry.type.Recipe; +import io.anuke.mindustry.ui.IntFormat; import io.anuke.mindustry.ui.Minimap; import io.anuke.ucore.core.Core; import io.anuke.ucore.core.Inputs; -import io.anuke.ucore.core.Settings; import io.anuke.ucore.scene.Element; import io.anuke.ucore.scene.Group; import io.anuke.ucore.scene.actions.Actions; @@ -35,10 +35,10 @@ public class HudFragment implements Fragment{ private ImageButton menu, flip; private Table respawntable; private Table wavetable; - private Label infolabel; + private Table infolabel; private Table lastUnlockTable; private Table lastUnlockLayout; - private boolean shown = true, done = true; + private boolean shown = true; private float dsize = 58; private float isize = 40; @@ -109,16 +109,20 @@ public class HudFragment implements Fragment{ row(); visible(() -> !state.is(State.menu)); - - infolabel = new Label(() -> (Settings.getBool("fps") ? (Gdx.graphics.getFramesPerSecond() + " FPS") + - (threads.isEnabled() ? " / " + threads.getFPS() + " TPS" : "") + (Net.client() && !gwt ? "\nPing: " + Net.getPing() : "") : "")); row(); - add(infolabel).size(-1); + new table(){{ + IntFormat fps = new IntFormat("text.fps"); + IntFormat tps = new IntFormat("text.tps"); + IntFormat ping = new IntFormat("text.ping"); + new label(() -> fps.get(Gdx.graphics.getFramesPerSecond())).padRight(10); + new label(() -> tps.get(threads.getTPS())).visible(() -> threads.isEnabled()); + row(); + new label(() -> ping.get(Net.getPing())).visible(() -> Net.client() && !gwt).colspan(2); + + infolabel = get(); + }}.size(-1).end(); }}.end(); - - - }}.end(); new table(){{ @@ -285,25 +289,30 @@ public class HudFragment implements Fragment{ private String getEnemiesRemaining() { if(state.enemies == 1) { return Bundles.format("text.enemies.single", state.enemies); - } else return Bundles.format("text.enemies", state.enemies); + } else { + return Bundles.format("text.enemies", state.enemies); + } } private void addWaveTable(){ float uheight = 66f; + IntFormat wavef = new IntFormat("text.wave"); + IntFormat timef = new IntFormat("text.wave.waiting"); + wavetable = new table("button"){{ aleft(); new table(){{ aleft(); - new label(() -> Bundles.format("text.wave", state.wave)).scale(fontScale *1.5f).left().padLeft(-6); + new label(() -> wavef.get(state.wave)).scale(fontScale *1.5f).left().padLeft(-6); row(); - new label(()-> state.enemies > 0 ? + new label(() -> state.enemies > 0 ? getEnemiesRemaining() : (state.mode.disableWaveTimer) ? "$text.waiting" - : Bundles.format("text.wave.waiting", (int) (state.wavetime / 60f))) + : timef.get((int) (state.wavetime / 60f))) .minWidth(126).padLeft(-6).left(); margin(10f); diff --git a/core/src/io/anuke/mindustry/world/Tile.java b/core/src/io/anuke/mindustry/world/Tile.java index ae8bcc6966..e8462bb8c3 100644 --- a/core/src/io/anuke/mindustry/world/Tile.java +++ b/core/src/io/anuke/mindustry/world/Tile.java @@ -137,7 +137,7 @@ public class Tile implements PosTrait, TargetTrait { } public Team getTeam(){ - return Team.values()[team]; + return Team.all[team]; } public byte getTeamID(){ diff --git a/core/src/io/anuke/mindustry/world/blocks/Floor.java b/core/src/io/anuke/mindustry/world/blocks/Floor.java index 65889a6199..d36356da03 100644 --- a/core/src/io/anuke/mindustry/world/blocks/Floor.java +++ b/core/src/io/anuke/mindustry/world/blocks/Floor.java @@ -17,7 +17,6 @@ import io.anuke.ucore.graphics.Draw; import io.anuke.ucore.util.Geometry; import io.anuke.ucore.util.Mathf; -import static io.anuke.mindustry.Vars.tilesize; import static io.anuke.mindustry.Vars.world; public class Floor extends Block{ @@ -31,6 +30,7 @@ public class Floor extends Block{ protected TextureRegion edgeRegion; protected TextureRegion[] edgeRegions; protected TextureRegion[] cliffRegions; + protected TextureRegion[] variantRegions; protected Vector2[] offsets; protected Predicate blends = block -> block != this && !block.blendOverride(this); protected boolean blend = true; @@ -72,6 +72,7 @@ public class Floor extends Block{ @Override public void load() { super.load(); + if(blend) { edgeRegion = Draw.hasRegion(name + "edge") ? Draw.region(name + "edge") : Draw.region(edge + "edge"); edgeRegions = new TextureRegion[8]; @@ -97,19 +98,23 @@ public class Floor extends Block{ offsets[i] = new Vector2(-4 + rx, -4 + ry); } - if(Draw.hasRegion(name + "-cliff")){ - cliffRegions = new TextureRegion[8]; - TextureRegion base = Draw.region(name + "-cliff"); + cliffRegions = new TextureRegion[4]; + cliffRegions[0] = Draw.region(name + "-cliff-edge-2"); + cliffRegions[1] = Draw.region(name + "-cliff-edge"); + cliffRegions[2] = Draw.region(name + "-cliff-edge-1"); + cliffRegions[3] = Draw.region(name + "-cliff-side"); + } - for(int i = 0; i < 8; i ++){ - int dx = Geometry.d8[i].x, dy = Geometry.d8[i].y; + //load variant regions for drawing + if(variants > 0){ + variantRegions = new TextureRegion[variants]; - TextureRegion region = new TextureRegion(); - region.setTexture(base.getTexture()); - region.setRegion(base.getRegionX() + tilesize + tilesize*dx, base.getRegionY() + tilesize - tilesize*dy, tilesize, tilesize); - cliffRegions[i] = region; - } + for (int i = 0; i < variants; i++) { + variantRegions[i] = Draw.region(name + (i + 1)); } + }else{ + variantRegions = new TextureRegion[1]; + variantRegions[0] = Draw.region(name); } } @@ -133,9 +138,9 @@ public class Floor extends Block{ public void draw(Tile tile){ MathUtils.random.setSeed(tile.id()); - Draw.rect(variants > 0 ? (name() + MathUtils.random(1, variants)) : name(), tile.worldx(), tile.worldy()); + Draw.rect(variantRegions[Mathf.randomSeed(tile.id(), 0, Math.max(0, variantRegions.length-1))], tile.worldx(), tile.worldy()); - if(Draw.hasRegion(name + "-cliff-side") && tile.cliffs != 0){ + if(tile.cliffs != 0){ for(int i = 0; i < 4; i ++){ if((tile.cliffs & (1 << i*2)) != 0) { Draw.colorl(i > 1 ? 0.6f : 1f); @@ -143,13 +148,13 @@ public class Floor extends Block{ boolean above = (tile.cliffs & (1 << ((i+1)%4)*2)) != 0, below = (tile.cliffs & (1 << (Mathf.mod(i-1, 4))*2)) != 0; if(above && below){ - Draw.rect(name + "-cliff-edge-2", tile.worldx(), tile.worldy(), i * 90); + Draw.rect(cliffRegions[0], tile.worldx(), tile.worldy(), i * 90); }else if(above){ - Draw.rect(name + "-cliff-edge", tile.worldx(), tile.worldy(), i * 90); + Draw.rect(cliffRegions[1], tile.worldx(), tile.worldy(), i * 90); }else if(below){ - Draw.rect(name + "-cliff-edge-1", tile.worldx(), tile.worldy(), i * 90); + Draw.rect(cliffRegions[2], tile.worldx(), tile.worldy(), i * 90); }else{ - Draw.rect(name + "-cliff-side", tile.worldx(), tile.worldy(), i * 90); + Draw.rect(cliffRegions[3], tile.worldx(), tile.worldy(), i * 90); } } } diff --git a/core/src/io/anuke/mindustry/world/blocks/OreBlock.java b/core/src/io/anuke/mindustry/world/blocks/OreBlock.java index 43de23835a..15f6ee790d 100644 --- a/core/src/io/anuke/mindustry/world/blocks/OreBlock.java +++ b/core/src/io/anuke/mindustry/world/blocks/OreBlock.java @@ -6,6 +6,7 @@ import io.anuke.mindustry.type.ItemStack; import io.anuke.mindustry.world.Block; import io.anuke.mindustry.world.Tile; import io.anuke.ucore.graphics.Draw; +import io.anuke.ucore.util.Mathf; public class OreBlock extends Floor { public Floor base; @@ -22,15 +23,7 @@ public class OreBlock extends Floor { @Override public void draw(Tile tile){ - - //Draw.rect(base.variants > 0 ? (base.name + MathUtils.random(1, base.variants)) : base.name, tile.worldx(), tile.worldy()); - - int rand = variants > 0 ? MathUtils.random(1, variants) : 0; - - // Draw.color(0f, 0f, 0f, 0.2f); - //Draw.rect(variants > 0 ? (drops.item.name + rand) : name, tile.worldx(), tile.worldy() - 1); - //Draw.color(); - Draw.rect(name + rand, tile.worldx(), tile.worldy()); + Draw.rect(variantRegions[Mathf.randomSeed(tile.id(), 0, Math.max(0, variantRegions.length-1))], tile.worldx(), tile.worldy()); drawEdges(tile, false); } diff --git a/core/src/io/anuke/mindustry/world/blocks/defense/Door.java b/core/src/io/anuke/mindustry/world/blocks/defense/Door.java index 6010f1953a..2ede85ae7e 100644 --- a/core/src/io/anuke/mindustry/world/blocks/defense/Door.java +++ b/core/src/io/anuke/mindustry/world/blocks/defense/Door.java @@ -1,5 +1,6 @@ package io.anuke.mindustry.world.blocks.defense; +import com.badlogic.gdx.graphics.g2d.TextureRegion; import com.badlogic.gdx.math.Rectangle; import io.anuke.mindustry.content.fx.BlockFx; import io.anuke.mindustry.entities.Player; @@ -22,13 +23,21 @@ public class Door extends Wall{ protected Effect openfx = BlockFx.dooropen; protected Effect closefx = BlockFx.doorclose; + protected TextureRegion openRegion; + public Door(String name) { super(name); solid = false; solidifes = true; consumesTap = true; } - + + @Override + public void load() { + super.load(); + openRegion = Draw.region(name + "-open"); + } + @Override public void draw(Tile tile){ DoorEntity entity = tile.entity(); @@ -36,7 +45,7 @@ public class Door extends Wall{ if(!entity.open){ Draw.rect(name, tile.drawx(), tile.drawy()); }else{ - Draw.rect(name + "-open", tile.drawx(), tile.drawy()); + Draw.rect(openRegion, tile.drawx(), tile.drawy()); } } diff --git a/core/src/io/anuke/mindustry/world/blocks/production/MechFactory.java b/core/src/io/anuke/mindustry/world/blocks/production/MechFactory.java index b10e45d086..fa1d9cc274 100644 --- a/core/src/io/anuke/mindustry/world/blocks/production/MechFactory.java +++ b/core/src/io/anuke/mindustry/world/blocks/production/MechFactory.java @@ -30,6 +30,8 @@ import static io.anuke.mindustry.Vars.tilesize; public class MechFactory extends Block{ protected Mech mech; + protected TextureRegion openRegion; + public MechFactory(String name){ super(name); update = true; @@ -51,11 +53,17 @@ public class MechFactory extends Block{ } } + @Override + public void load() { + super.load(); + openRegion = Draw.region(name + "-open"); + } + @Override public void draw(Tile tile) { MechFactoryEntity entity = tile.entity(); - Draw.rect(entity.open ? name + "-open" : name, tile.drawx(), tile.drawy()); + Draw.rect(entity.open ? openRegion : Draw.region(name), tile.drawx(), tile.drawy()); if(entity.player != null) { TextureRegion region = mech.iconRegion; diff --git a/core/src/io/anuke/mindustry/world/blocks/storage/CoreBlock.java b/core/src/io/anuke/mindustry/world/blocks/storage/CoreBlock.java index b35515a1fd..3bf387efce 100644 --- a/core/src/io/anuke/mindustry/world/blocks/storage/CoreBlock.java +++ b/core/src/io/anuke/mindustry/world/blocks/storage/CoreBlock.java @@ -47,6 +47,9 @@ public class CoreBlock extends StorageBlock { protected float droneRespawnDuration = 60*6; protected UnitType droneType = UnitTypes.drone; + protected TextureRegion openRegion; + protected TextureRegion topRegion; + public CoreBlock(String name) { super(name); @@ -61,6 +64,14 @@ public class CoreBlock extends StorageBlock { flags = EnumSet.of(BlockFlag.resupplyPoint, BlockFlag.target); } + @Override + public void load() { + super.load(); + + openRegion = Draw.region(name + "-open"); + topRegion = Draw.region(name + "-top"); + } + @Override public float handleDamage(Tile tile, float amount) { return debug ? 0 : amount; @@ -70,10 +81,10 @@ public class CoreBlock extends StorageBlock { public void draw(Tile tile) { CoreEntity entity = tile.entity(); - Draw.rect(entity.solid ? name : name + "-open", tile.drawx(), tile.drawy()); + Draw.rect(entity.solid ? Draw.region(name) : openRegion, tile.drawx(), tile.drawy()); Draw.alpha(entity.heat); - Draw.rect(name + "-top", tile.drawx(), tile.drawy()); + Draw.rect(topRegion, tile.drawx(), tile.drawy()); Draw.color(); if(entity.currentUnit != null) { diff --git a/core/src/io/anuke/mindustry/world/blocks/units/Reconstructor.java b/core/src/io/anuke/mindustry/world/blocks/units/Reconstructor.java index f1e3c8f461..4aec12e9bf 100644 --- a/core/src/io/anuke/mindustry/world/blocks/units/Reconstructor.java +++ b/core/src/io/anuke/mindustry/world/blocks/units/Reconstructor.java @@ -33,6 +33,7 @@ public class Reconstructor extends Block{ protected float arriveTime = 40f; protected float powerPerTeleport = 5f; protected Effect arriveEffect = Fx.spawn; + protected TextureRegion openRegion; public Reconstructor(String name) { super(name); @@ -42,6 +43,12 @@ public class Reconstructor extends Block{ configurable = true; } + @Override + public void load() { + super.load(); + openRegion = Draw.region(name + "-open"); + } + @Override public boolean isSolidFor(Tile tile) { ReconstructorEntity entity = tile.entity(); @@ -104,7 +111,7 @@ public class Reconstructor extends Block{ if(entity.solid){ Draw.rect(name, tile.drawx(), tile.drawy()); }else{ - Draw.rect(name + "-open", tile.drawx(), tile.drawy()); + Draw.rect(openRegion, tile.drawx(), tile.drawy()); } if(entity.current != null){ diff --git a/core/src/io/anuke/mindustry/world/mapgen/WorldGenerator.java b/core/src/io/anuke/mindustry/world/mapgen/WorldGenerator.java index 976bb426f6..273a6660be 100644 --- a/core/src/io/anuke/mindustry/world/mapgen/WorldGenerator.java +++ b/core/src/io/anuke/mindustry/world/mapgen/WorldGenerator.java @@ -53,7 +53,7 @@ public class WorldGenerator { Tile tile = new Tile(x, y, marker.floor, marker.wall == Blocks.blockpart.id ? 0 : marker.wall, marker.rotation, marker.team, marker.elevation); - Team team = Team.values()[marker.team]; + Team team = Team.all[marker.team]; if(tile.block().isMultiblock()){ multiblocks.add(tile.packedPosition());