From 959f756ff543127f0ff6a075698ab9aa43c3e7a4 Mon Sep 17 00:00:00 2001 From: Anuken Date: Fri, 11 May 2018 07:59:10 -0700 Subject: [PATCH] Local multiplayer initial commit --- core/src/io/anuke/mindustry/Vars.java | 2 +- core/src/io/anuke/mindustry/core/Control.java | 96 +++----- .../io/anuke/mindustry/core/NetClient.java | 21 +- .../src/io/anuke/mindustry/core/Renderer.java | 229 ++---------------- .../io/anuke/mindustry/entities/Player.java | 38 ++- .../mindustry/graphics/OverlayRenderer.java | 218 +++++++++++++++++ .../anuke/mindustry/input/AndroidInput.java | 4 +- .../anuke/mindustry/input/DesktopInput.java | 28 +-- .../anuke/mindustry/input/InputHandler.java | 6 + .../src/io/anuke/mindustry/net/NetworkIO.java | 2 +- core/src/io/anuke/mindustry/net/Packets.java | 5 +- 11 files changed, 350 insertions(+), 299 deletions(-) create mode 100644 core/src/io/anuke/mindustry/graphics/OverlayRenderer.java diff --git a/core/src/io/anuke/mindustry/Vars.java b/core/src/io/anuke/mindustry/Vars.java index 75730d6277..ffea2bbf8f 100644 --- a/core/src/io/anuke/mindustry/Vars.java +++ b/core/src/io/anuke/mindustry/Vars.java @@ -143,7 +143,7 @@ public class Vars{ public static NetServer netServer; public static NetClient netClient; - public static Player player; + public static Player[] players; public static final EntityGroup playerGroup = Entities.addGroup(Player.class).enableMapping(); public static final EntityGroup tileGroup = Entities.addGroup(TileEntity.class, false); diff --git a/core/src/io/anuke/mindustry/core/Control.java b/core/src/io/anuke/mindustry/core/Control.java index e0e977a321..221bc8015b 100644 --- a/core/src/io/anuke/mindustry/core/Control.java +++ b/core/src/io/anuke/mindustry/core/Control.java @@ -26,6 +26,7 @@ import io.anuke.ucore.entities.Entities; import io.anuke.ucore.modules.Module; import io.anuke.ucore.scene.ui.layout.Unit; import io.anuke.ucore.util.Atlas; +import io.anuke.ucore.util.Input; import io.anuke.ucore.util.InputProxy; import io.anuke.ucore.util.Mathf; @@ -43,8 +44,7 @@ public class Control extends Module{ private Saves saves; - private float respawntime; - private InputHandler input; + private InputHandler[] inputs; private InputProxy proxy; private float controlx, controly; @@ -58,12 +58,6 @@ public class Control extends Module{ Gdx.input.setCatchBackKey(true); - if(mobile){ - input = new AndroidInput(); - }else{ - input = new DesktopInput(); - } - proxy = new InputProxy(Gdx.input){ @Override public int getY() { @@ -86,8 +80,6 @@ public class Control extends Module{ } }; - Inputs.addProcessor(input); - Effects.setShakeFalloff(10000f); Core.atlas = new Atlas("sprites.atlas"); @@ -110,7 +102,6 @@ public class Control extends Module{ Settings.defaultList( "ip", "localhost", "port", port+"", - "name", mobile || gwt ? "player" : UCore.getProperty("user.name"), "servers", "", "color", Color.rgba8888(playerColors[8]), "lastBuild", 0 @@ -118,11 +109,7 @@ public class Control extends Module{ KeyBinds.load(); - player = new Player(); - player.name = Settings.getString("name"); - player.mech = mobile ? Mechs.standardShip : Mechs.standard; - player.color.set(Settings.getInt("color")); - player.isLocal = true; + addPlayer(0); saves.load(); @@ -133,23 +120,20 @@ public class Control extends Module{ }); Events.on(PlayEvent.class, () -> { - player.set(world.getSpawnX(), world.getSpawnY()); + for(Player player : players){ + player.set(world.getSpawnX(), world.getSpawnY()); + } - Core.camera.position.set(player.x, player.y, 0); + Core.camera.position.set(world.getSpawnX(), world.getSpawnY(), 0); state.set(State.playing); }); Events.on(ResetEvent.class, () -> { - player.weapon = Weapons.blaster; - player.team = Team.blue; - player.inventory.clear(); - player.upgrades.clear(); + for(Player player : players){ + player.reset(); + } - player.add(); - player.heal(); - - respawntime = -1; hiscore = false; ui.hudfrag.fadeRespawn(false); @@ -173,20 +157,35 @@ public class Control extends Module{ Effects.shake(5, 6, Core.camera.position.x, Core.camera.position.y); - //TODO effects??? - //Sounds.play("corexplode"); - /* - for(int i = 0; i < 16; i ++){ - Timers.run(i*2, ()-> Effects.effect(Fx.explosion, world.getCore().worldx()+Mathf.range(40), world.getCore().worldy()+Mathf.range(40))); - } - Effects.effect(Fx.coreexplosion, world.getCore().worldx(), world.getCore().worldy());*/ - + //TODO game over effect ui.restart.show(); Timers.runTask(30f, () -> state.set(State.menu)); }); } + //TODO drop player method + public void addPlayer(int index){ + Player player = new Player(); + player.name = Settings.getString("name-" + index, "player"); + player.mech = mobile ? Mechs.standardShip : Mechs.standard; + player.color.set(Settings.getInt("color")); + player.isLocal = true; + player.playerIndex = index; + players[index] = player; + + InputHandler input; + + if(mobile){ + input = new AndroidInput(player); + }else{ + input = new DesktopInput(player); + } + + inputs[index] = input; + Inputs.addProcessor(input); + } + //FIXME figure out what's causing this problem in the first place public void triggerInputUpdate(){ Gdx.input = proxy; @@ -204,8 +203,8 @@ public class Control extends Module{ return controlling; } - public InputHandler input(){ - return input; + public InputHandler input(int index){ + return inputs[index]; } public void playMap(Map map){ @@ -225,14 +224,6 @@ public class Control extends Module{ return hiscore; } - public float getRespawnTime(){ - return respawntime; - } - - public void setRespawnTime(float respawntime){ - this.respawntime = respawntime; - } - public Tutorial tutorial(){ return tutorial; } @@ -319,7 +310,9 @@ public class Control extends Module{ saves.update(); if(!state.is(State.menu)){ - input.update(); + for(InputHandler input : inputs){ + input.update(); + } if(Inputs.keyTap("pause") && !ui.restart.isShown() && (state.is(State.paused) || state.is(State.playing))){ state.set(state.is(State.playing) ? State.paused : State.playing); @@ -343,19 +336,6 @@ public class Control extends Module{ Entities.update(effectGroup); Entities.update(groundEffectGroup); - if(respawntime > 0){ - - respawntime -= Timers.delta(); - - if(respawntime <= 0){ - player.set(world.getSpawnX(), world.getSpawnY()); - player.heal(); - player.add(); - Effects.sound("respawn"); - ui.hudfrag.fadeRespawn(false); - } - } - if(tutorial.active()){ tutorial.update(); } diff --git a/core/src/io/anuke/mindustry/core/NetClient.java b/core/src/io/anuke/mindustry/core/NetClient.java index 768304e2b2..16b328c8df 100644 --- a/core/src/io/anuke/mindustry/core/NetClient.java +++ b/core/src/io/anuke/mindustry/core/NetClient.java @@ -168,9 +168,12 @@ public class NetClient extends Module { Placement.placeBlock(placer.team, packet.x, packet.y, Block.getByID(packet.block), packet.rotation, true, Timers.get("placeblocksound", 10)); - if(packet.playerid == player.id){ - Tile tile = world.tile(packet.x, packet.y); - if(tile != null) Block.getByID(packet.block).placed(tile); + for(Player player : players) { + if (packet.playerid == player.id) { + Tile tile = world.tile(packet.x, packet.y); + if (tile != null) Block.getByID(packet.block).placed(tile); + break; + } } }); @@ -272,7 +275,9 @@ public class NetClient extends Module { Weapon weapon = Upgrade.getByID(packet.id); state.inventory.removeItems(UpgradeRecipes.get(weapon)); - player.upgrades.add(weapon); + for(Player player : players) { + player.upgrades.add(weapon); + } Effects.sound("purchase"); }); } @@ -329,9 +334,11 @@ public class NetClient extends Module { requests = 0; if(timer.get(0, playerSyncTime)){ - PositionPacket packet = new PositionPacket(); - packet.player = player; - Net.send(packet, SendMode.udp); + for(Player player : players) { + PositionPacket packet = new PositionPacket(); + packet.player = player; + Net.send(packet, SendMode.udp); + } } if(timer.get(1, 60)){ diff --git a/core/src/io/anuke/mindustry/core/Renderer.java b/core/src/io/anuke/mindustry/core/Renderer.java index e5e9e86018..6d9694fe18 100644 --- a/core/src/io/anuke/mindustry/core/Renderer.java +++ b/core/src/io/anuke/mindustry/core/Renderer.java @@ -23,10 +23,7 @@ import io.anuke.mindustry.entities.effect.GroundEffectEntity.GroundEffect; import io.anuke.mindustry.entities.units.BaseUnit; import io.anuke.mindustry.game.Team; import io.anuke.mindustry.game.TeamInfo.TeamData; -import io.anuke.mindustry.graphics.BlockRenderer; -import io.anuke.mindustry.graphics.Layer; -import io.anuke.mindustry.graphics.MinimapRenderer; -import io.anuke.mindustry.graphics.Shaders; +import io.anuke.mindustry.graphics.*; import io.anuke.mindustry.input.InputHandler; import io.anuke.mindustry.input.PlaceMode; import io.anuke.mindustry.ui.fragments.ToolFragment; @@ -59,8 +56,10 @@ public class Renderer extends RendererModule{ private FloatArray shieldHits = new FloatArray(); private Array shieldDraws = new Array<>(); private Rectangle rect = new Rectangle(), rect2 = new Rectangle(); + private Vector2 avgPosition = new Vector2(); private BlockRenderer blocks = new BlockRenderer(); private MinimapRenderer minimap = new MinimapRenderer(); + private OverlayRenderer overlays = new OverlayRenderer(); public Renderer() { Lines.setCircleVertices(14); @@ -139,7 +138,9 @@ public class Renderer extends RendererModule{ if(Mathf.in(camera.zoom, targetzoom, 0.005f)){ camera.zoom = 1f; Graphics.setCameraScale(targetscale); - control.input().resetCursor(); + for(Player player : players) { + control.input(player.playerIndex).resetCursor(); + } } }else{ camera.zoom = Mathf.lerpDelta(camera.zoom, 1f, 0.2f); @@ -150,15 +151,17 @@ public class Renderer extends RendererModule{ }else{ boolean smoothcam = Settings.getBool("smoothcam"); + Vector2 position = averagePosition(); if(!smoothcam){ - setCamera(player.x, player.y); + setCamera(position.x, position.y); }else{ - smoothCamera(player.x, player.y, mobile ? 0.3f : 0.14f); + smoothCamera(position.x, position.y, mobile ? 0.3f : 0.14f); } - if(Settings.getBool("pixelate")) - limitCamera(4f, player.x, player.y); + if(Settings.getBool("pixelate") && players.length == 1) { + limitCamera(4f, position.x, position.y); + } float prex = camera.position.x, prey = camera.position.y; updateShake(0.75f); @@ -167,11 +170,6 @@ public class Renderer extends RendererModule{ float deltax = camera.position.x - prex, deltay = camera.position.y - prey; - if(mobile){ - player.x += camera.position.x - prevx; - player.y += camera.position.y - prevy; - } - float lastx = camera.position.x, lasty = camera.position.y; if(snapCamera && smoothcam && Settings.getBool("pixelate")){ @@ -229,7 +227,7 @@ public class Renderer extends RendererModule{ //drawShield(); - drawOverlay(); + overlays.draw(); if(pixelate) Graphics.flushSurface(); @@ -267,8 +265,10 @@ public class Renderer extends RendererModule{ @Override public void resize(int width, int height){ super.resize(width, height); - control.input().resetCursor(); - camera.position.set(player.x, player.y, 0); + for(Player player : players) { + control.input(player.playerIndex).resetCursor(); + } + camera.position.set(players[0].x, players[0].y, 0); } @Override @@ -276,6 +276,14 @@ public class Renderer extends RendererModule{ background.dispose(); } + public Vector2 averagePosition(){ + avgPosition.setZero(); + for(Player player : players){ + avgPosition.add(player.x, player.y); + } + return avgPosition; + } + public MinimapRenderer minimap() { return minimap; } @@ -412,193 +420,6 @@ public class Renderer extends RendererModule{ shieldDraws.add(call); } - void drawOverlay(){ - - //draw config selected block - if(ui.configfrag.isShown()){ - Tile tile = ui.configfrag.getSelectedTile(); - tile.block().drawConfigure(tile); - } - - int tilex = control.input().getBlockX(); - int tiley = control.input().getBlockY(); - - if(mobile){ - Vector2 vec = Graphics.world(Gdx.input.getX(0), Gdx.input.getY(0)); - tilex = Mathf.scl2(vec.x, tilesize); - tiley = Mathf.scl2(vec.y, tilesize); - } - - InputHandler input = control.input(); - - //draw placement box - if((input.recipe != null && state.inventory.hasItems(input.recipe.requirements) && (!ui.hasMouse() || mobile) - && control.input().drawPlace())){ - - input.placeMode.draw(control.input().getBlockX(), control.input().getBlockY(), - control.input().getBlockEndX(), control.input().getBlockEndY()); - - if(input.breakMode == PlaceMode.holdDelete) - input.breakMode.draw(tilex, tiley, 0, 0); - - }else if(input.breakMode.delete && control.input().drawPlace() - && (input.recipe == null || !state.inventory.hasItems(input.recipe.requirements)) - && (input.placeMode.delete || input.breakMode.both || !mobile)){ - - if(input.breakMode == PlaceMode.holdDelete) - input.breakMode.draw(tilex, tiley, 0, 0); - else - input.breakMode.draw(control.input().getBlockX(), control.input().getBlockY(), - control.input().getBlockEndX(), control.input().getBlockEndY()); - } - - if(ui.toolfrag.confirming){ - ToolFragment t = ui.toolfrag; - PlaceMode.areaDelete.draw(t.px, t.py, t.px2, t.py2); - } - - Draw.reset(); - - //draw selected block bars and info - if(input.recipe == null && !ui.hasMouse() && !ui.configfrag.isShown()){ - Tile tile = world.tileWorld(Graphics.mouseWorld().x, Graphics.mouseWorld().y); - - if(tile != null && tile.block() != Blocks.air){ - Tile target = tile; - if(tile.isLinked()) - target = tile.getLinked(); - - if(showBlockDebug && target.entity != null){ - Draw.color(Color.RED); - Lines.crect(target.drawx(), target.drawy(), target.block().size * tilesize, target.block().size * tilesize); - Vector2 v = new Vector2(); - - Draw.tcolor(Color.YELLOW); - Draw.tscl(0.25f); - Array arr = target.block().getDebugInfo(target); - StringBuilder result = new StringBuilder(); - for(int i = 0; i < arr.size/2; i ++){ - result.append(arr.get(i*2)); - result.append(": "); - result.append(arr.get(i*2 + 1)); - result.append("\n"); - } - Draw.textc(result.toString(), target.drawx(), target.drawy(), v); - Draw.color(0f, 0f, 0f, 0.5f); - Fill.rect(target.drawx(), target.drawy(), v.x, v.y); - Draw.textc(result.toString(), target.drawx(), target.drawy(), v); - Draw.tscl(fontscale); - Draw.reset(); - } - - if(Inputs.keyDown("block_info") && target.block().isAccessible()){ - Draw.color(Colors.get("accent")); - Lines.crect(target.drawx(), target.drawy(), target.block().size * tilesize, target.block().size * tilesize); - Draw.color(); - } - - if(target.entity != null) { - int bot = 0, top = 0; - for (BlockBar bar : target.block().bars.list()) { - float offset = Mathf.sign(bar.top) * (target.block().size / 2f * tilesize + 3f + 4f * ((bar.top ? top : bot))) + - (bar.top ? -1f : 0f); - - float value = bar.value.get(target); - - if(MathUtils.isEqual(value, -1f)) continue; - - drawBar(bar.type.color, target.drawx(), target.drawy() + offset, value); - - if (bar.top) - top++; - else - bot++; - } - } - - target.block().drawSelect(target); - } - } - - if(control.input().isDroppingItem()){ - Vector2 v = Graphics.mouseWorld(); - float size = 8; - Draw.rect(player.inventory.getItem().item.region, v.x, v.y, size, size); - Draw.color("accent"); - Lines.circle(v.x, v.y, 6 + Mathf.absin(Timers.time(), 5f, 1f)); - Draw.reset(); - - Tile tile = world.tileWorld(v.x, v.y); - if(tile != null) tile = tile.target(); - if(tile != null && tile.block().acceptStack(player.inventory.getItem().item, player.inventory.getItem().amount, tile, player) > 0){ - Draw.color("place"); - Lines.square(tile.drawx(), tile.drawy(), tile.block().size*tilesize/2f + 1 + Mathf.absin(Timers.time(), 5f, 1f)); - Draw.color(); - } - } - - if((!debug || showUI) && Settings.getBool("healthbars")){ - for(TeamData ally : (debug ? state.teams.getTeams() : state.teams.getTeams(true))){ - for(Unit e : unitGroups[ally.team.ordinal()].all()){ - drawStats(e); - } - } - - for(Unit e : playerGroup.all()){ - drawStats(e); - } - } - } - - void drawStats(Unit unit){ - if(unit.isDead()) return; - - float x = unit.getDrawPosition().x; - float y = unit.getDrawPosition().y; - - if(unit == player && snapCamera && Settings.getBool("smoothcam") && Settings.getBool("pixelate")) { - x = (int)x; - y = (int)y; - } - - drawEncloser(x, y - 8f, 2f); - drawBar(Color.SCARLET, x, y - 8f, unit.health / unit.maxhealth); - drawBar(Color.valueOf("32cf6d"), x, y - 9f, unit.inventory.totalAmmo() / (float) unit.inventory.ammoCapacity()); - } - - public void drawBar(Color color, float x, float y, float finion){ - finion = Mathf.clamp(finion); - - if(finion > 0) finion = Mathf.clamp(finion + 0.2f, 0.24f, 1f); - - float len = 3; - - float w = (int) (len * 2 * finion) + 0.5f; - - x -= 0.5f; - y += 0.5f; - - Draw.color(Color.BLACK); - Lines.line(x - len + 1, y, x + len + 0.5f, y); - Draw.color(color); - if(w >= 1) - Lines.line(x - len + 1, y, x - len + w, y); - Draw.reset(); - } - - public void drawEncloser(float x, float y, float height){ - x -= 0.5f; - y += 0.5f - (height-1f)/2f; - - float len = 3; - - Lines.stroke(2f + height); - Draw.color(Color.SLATE); - Lines.line(x - len - 0.5f, y, x + len + 1.5f, y, CapStyle.none); - - Draw.reset(); - } - public void setCameraScale(int amount){ targetscale = amount; clampScale(); diff --git a/core/src/io/anuke/mindustry/entities/Player.java b/core/src/io/anuke/mindustry/entities/Player.java index f23062f44f..a49b285102 100644 --- a/core/src/io/anuke/mindustry/entities/Player.java +++ b/core/src/io/anuke/mindustry/entities/Player.java @@ -49,9 +49,11 @@ public class Player extends Unit{ public boolean dashing = false; public int clientid = -1; + public int playerIndex = 0; public boolean isLocal = false; public Timer timer = new Timer(4); public float walktime; + public float respawntime; private Vector2 movement = new Vector2(); @@ -66,7 +68,7 @@ public class Player extends Unit{ @Override public void onRemoteShoot(BulletType type, float x, float y, float rotation, short data) { Weapon weapon = Upgrade.getByID(Bits.getLeftByte(data)); - weapon.shoot(player, x, y, rotation, Bits.getRightByte(data) == 1); + weapon.shoot(this, x, y, rotation, Bits.getRightByte(data) == 1); } @Override @@ -114,8 +116,7 @@ public class Player extends Unit{ DamageArea.dynamicExplosion(x, y, flammability, explosiveness, 0f, getSize()/2f, Palette.darkFlame); Effects.sound("die", this); - control.setRespawnTime(respawnduration); - ui.hudfrag.fadeRespawn(true); + respawntime = respawnduration; super.onDeath(); } @@ -217,6 +218,18 @@ public class Player extends Unit{ return; } + if(respawntime > 0){ + + respawntime -= Timers.delta(); + + if(respawntime <= 0){ + set(world.getSpawnX(), world.getSpawnY()); + heal(); + add(); + Effects.sound("respawn"); + } + } + if(isDead()) return; if(mech.flying){ @@ -229,6 +242,17 @@ public class Player extends Unit{ y = Mathf.clamp(y, 0, world.height() * tilesize); } + public void reset(){ + weapon = Weapons.blaster; + team = Team.blue; + respawntime = -1; + inventory.clear(); + upgrades.clear(); + + add(); + heal(); + } + protected void updateMech(){ Tile tile = world.tileWorld(x, y); @@ -266,8 +290,8 @@ public class Player extends Unit{ boolean shooting = control.input().canShoot() && control.input().isShooting() && inventory.hasAmmo(); if(shooting){ - weapon.update(player, true); - weapon.update(player, false); + weapon.update(this, true); + weapon.update(this, false); } movement.limit(speed); @@ -320,6 +344,7 @@ public class Player extends Unit{ stream.writeBoolean(isLocal); if(isLocal){ + stream.writeInt(playerIndex); super.writeSave(stream); stream.writeByte(upgrades.size); @@ -334,7 +359,8 @@ public class Player extends Unit{ boolean local = stream.readBoolean(); if(local){ - player.readSaveSuper(stream); + int index = stream.readInt(); + players[index].readSaveSuper(stream); } } diff --git a/core/src/io/anuke/mindustry/graphics/OverlayRenderer.java b/core/src/io/anuke/mindustry/graphics/OverlayRenderer.java new file mode 100644 index 0000000000..65c66d5a08 --- /dev/null +++ b/core/src/io/anuke/mindustry/graphics/OverlayRenderer.java @@ -0,0 +1,218 @@ +package io.anuke.mindustry.graphics; + +import com.badlogic.gdx.Gdx; +import com.badlogic.gdx.graphics.Color; +import com.badlogic.gdx.graphics.Colors; +import com.badlogic.gdx.math.MathUtils; +import com.badlogic.gdx.math.Vector2; +import com.badlogic.gdx.utils.Array; +import io.anuke.mindustry.content.blocks.Blocks; +import io.anuke.mindustry.entities.Unit; +import io.anuke.mindustry.game.TeamInfo.TeamData; +import io.anuke.mindustry.input.InputHandler; +import io.anuke.mindustry.input.PlaceMode; +import io.anuke.mindustry.ui.fragments.ToolFragment; +import io.anuke.mindustry.world.BlockBar; +import io.anuke.mindustry.world.Tile; +import io.anuke.ucore.core.Graphics; +import io.anuke.ucore.core.Inputs; +import io.anuke.ucore.core.Settings; +import io.anuke.ucore.core.Timers; +import io.anuke.ucore.graphics.CapStyle; +import io.anuke.ucore.graphics.Draw; +import io.anuke.ucore.graphics.Fill; +import io.anuke.ucore.graphics.Lines; +import io.anuke.ucore.util.Mathf; + +import static io.anuke.mindustry.Vars.*; +import static io.anuke.mindustry.Vars.playerGroup; + +public class OverlayRenderer { + + public void draw(){ + + //draw config selected block + if(ui.configfrag.isShown()){ + Tile tile = ui.configfrag.getSelectedTile(); + tile.block().drawConfigure(tile); + } + + int tilex = control.input().getBlockX(); + int tiley = control.input().getBlockY(); + + if(mobile){ + Vector2 vec = Graphics.world(Gdx.input.getX(0), Gdx.input.getY(0)); + tilex = Mathf.scl2(vec.x, tilesize); + tiley = Mathf.scl2(vec.y, tilesize); + } + + InputHandler input = control.input(); + + //draw placement box + if((input.recipe != null && state.inventory.hasItems(input.recipe.requirements) && (!ui.hasMouse() || mobile) + && control.input().drawPlace())){ + + input.placeMode.draw(control.input().getBlockX(), control.input().getBlockY(), + control.input().getBlockEndX(), control.input().getBlockEndY()); + + if(input.breakMode == PlaceMode.holdDelete) + input.breakMode.draw(tilex, tiley, 0, 0); + + }else if(input.breakMode.delete && control.input().drawPlace() + && (input.recipe == null || !state.inventory.hasItems(input.recipe.requirements)) + && (input.placeMode.delete || input.breakMode.both || !mobile)){ + + if(input.breakMode == PlaceMode.holdDelete) + input.breakMode.draw(tilex, tiley, 0, 0); + else + input.breakMode.draw(control.input().getBlockX(), control.input().getBlockY(), + control.input().getBlockEndX(), control.input().getBlockEndY()); + } + + if(ui.toolfrag.confirming){ + ToolFragment t = ui.toolfrag; + PlaceMode.areaDelete.draw(t.px, t.py, t.px2, t.py2); + } + + Draw.reset(); + + //draw selected block bars and info + if(input.recipe == null && !ui.hasMouse() && !ui.configfrag.isShown()){ + Tile tile = world.tileWorld(Graphics.mouseWorld().x, Graphics.mouseWorld().y); + + if(tile != null && tile.block() != Blocks.air){ + Tile target = tile; + if(tile.isLinked()) + target = tile.getLinked(); + + if(showBlockDebug && target.entity != null){ + Draw.color(Color.RED); + Lines.crect(target.drawx(), target.drawy(), target.block().size * tilesize, target.block().size * tilesize); + Vector2 v = new Vector2(); + + Draw.tcolor(Color.YELLOW); + Draw.tscl(0.25f); + Array arr = target.block().getDebugInfo(target); + StringBuilder result = new StringBuilder(); + for(int i = 0; i < arr.size/2; i ++){ + result.append(arr.get(i*2)); + result.append(": "); + result.append(arr.get(i*2 + 1)); + result.append("\n"); + } + Draw.textc(result.toString(), target.drawx(), target.drawy(), v); + Draw.color(0f, 0f, 0f, 0.5f); + Fill.rect(target.drawx(), target.drawy(), v.x, v.y); + Draw.textc(result.toString(), target.drawx(), target.drawy(), v); + Draw.tscl(fontscale); + Draw.reset(); + } + + if(Inputs.keyDown("block_info") && target.block().isAccessible()){ + Draw.color(Colors.get("accent")); + Lines.crect(target.drawx(), target.drawy(), target.block().size * tilesize, target.block().size * tilesize); + Draw.color(); + } + + if(target.entity != null) { + int bot = 0, top = 0; + for (BlockBar bar : target.block().bars.list()) { + float offset = Mathf.sign(bar.top) * (target.block().size / 2f * tilesize + 3f + 4f * ((bar.top ? top : bot))) + + (bar.top ? -1f : 0f); + + float value = bar.value.get(target); + + if(MathUtils.isEqual(value, -1f)) continue; + + drawBar(bar.type.color, target.drawx(), target.drawy() + offset, value); + + if (bar.top) + top++; + else + bot++; + } + } + + target.block().drawSelect(target); + } + } + + if(control.input().isDroppingItem()){ + Vector2 v = Graphics.mouseWorld(); + float size = 8; + Draw.rect(player.inventory.getItem().item.region, v.x, v.y, size, size); + Draw.color("accent"); + Lines.circle(v.x, v.y, 6 + Mathf.absin(Timers.time(), 5f, 1f)); + Draw.reset(); + + Tile tile = world.tileWorld(v.x, v.y); + if(tile != null) tile = tile.target(); + if(tile != null && tile.block().acceptStack(player.inventory.getItem().item, player.inventory.getItem().amount, tile, player) > 0){ + Draw.color("place"); + Lines.square(tile.drawx(), tile.drawy(), tile.block().size*tilesize/2f + 1 + Mathf.absin(Timers.time(), 5f, 1f)); + Draw.color(); + } + } + + if((!debug || showUI) && Settings.getBool("healthbars")){ + for(TeamData ally : (debug ? state.teams.getTeams() : state.teams.getTeams(true))){ + for(Unit e : unitGroups[ally.team.ordinal()].all()){ + drawStats(e); + } + } + + for(Unit e : playerGroup.all()){ + drawStats(e); + } + } + } + + void drawStats(Unit unit){ + if(unit.isDead()) return; + + float x = unit.getDrawPosition().x; + float y = unit.getDrawPosition().y; + + if(unit == players[0] && players.length == 1 && snapCamera && Settings.getBool("smoothcam") && Settings.getBool("pixelate")) { + x = (int)x; + y = (int)y; + } + + drawEncloser(x, y - 8f, 2f); + drawBar(Color.SCARLET, x, y - 8f, unit.health / unit.maxhealth); + drawBar(Color.valueOf("32cf6d"), x, y - 9f, unit.inventory.totalAmmo() / (float) unit.inventory.ammoCapacity()); + } + + public void drawBar(Color color, float x, float y, float finion){ + finion = Mathf.clamp(finion); + + if(finion > 0) finion = Mathf.clamp(finion + 0.2f, 0.24f, 1f); + + float len = 3; + + float w = (int) (len * 2 * finion) + 0.5f; + + x -= 0.5f; + y += 0.5f; + + Draw.color(Color.BLACK); + Lines.line(x - len + 1, y, x + len + 0.5f, y); + Draw.color(color); + if(w >= 1) + Lines.line(x - len + 1, y, x - len + w, y); + Draw.reset(); + } + + public void drawEncloser(float x, float y, float height){ + x -= 0.5f; + y += 0.5f - (height-1f)/2f; + + float len = 3; + + Lines.stroke(2f + height); + Draw.color(Color.SLATE); + Lines.line(x - len - 0.5f, y, x + len + 1.5f, y, CapStyle.none); + + Draw.reset(); + } +} diff --git a/core/src/io/anuke/mindustry/input/AndroidInput.java b/core/src/io/anuke/mindustry/input/AndroidInput.java index 7a859da9f1..8bda577484 100644 --- a/core/src/io/anuke/mindustry/input/AndroidInput.java +++ b/core/src/io/anuke/mindustry/input/AndroidInput.java @@ -4,6 +4,7 @@ import com.badlogic.gdx.Gdx; import com.badlogic.gdx.input.GestureDetector; import com.badlogic.gdx.math.Vector2; import io.anuke.mindustry.core.GameState.State; +import io.anuke.mindustry.entities.Player; import io.anuke.mindustry.net.Net; import io.anuke.mindustry.net.NetEvents; import io.anuke.mindustry.resource.ItemStack; @@ -26,7 +27,8 @@ public class AndroidInput extends InputHandler{ private float warmup; private float warmupDelay = 20; - public AndroidInput(){ + public AndroidInput(Player player){ + super(player); Inputs.addProcessor(new GestureDetector(20, 0.5f, 2, 0.15f, new GestureHandler(this))); } diff --git a/core/src/io/anuke/mindustry/input/DesktopInput.java b/core/src/io/anuke/mindustry/input/DesktopInput.java index db747fb1c6..766f2ceed6 100644 --- a/core/src/io/anuke/mindustry/input/DesktopInput.java +++ b/core/src/io/anuke/mindustry/input/DesktopInput.java @@ -3,6 +3,7 @@ package io.anuke.mindustry.input; import com.badlogic.gdx.Gdx; import com.badlogic.gdx.math.Vector2; import io.anuke.mindustry.core.GameState.State; +import io.anuke.mindustry.entities.Player; import io.anuke.mindustry.net.Net; import io.anuke.mindustry.net.NetEvents; import io.anuke.mindustry.resource.Weapon; @@ -23,7 +24,10 @@ public class DesktopInput extends InputHandler{ float endx, endy; private boolean enableHold = false; private boolean beganBreak; - private boolean rotated = false, rotatedAlt, zoomed; + + public DesktopInput(Player player){ + super(player); + } @Override public float getCursorEndX(){ return endx; } @Override public float getCursorEndY(){ return endy; } @@ -75,27 +79,13 @@ public class DesktopInput extends InputHandler{ if(Inputs.getAxisActive("zoom") && (Inputs.keyDown("zoom_hold") || controller) && !state.is(State.menu) && !ui.hasDialog()){ - if((!zoomed || !controller)) { - renderer.scaleCamera((int) Inputs.getAxis("zoom")); - } - zoomed = true; - }else{ - zoomed = false; + renderer.scaleCamera((int) Inputs.getAxisTapped("zoom")); } renderer.minimap().zoomBy(-(int)Inputs.getAxisTapped("zoom_minimap")); - if(!rotated) { - rotation += Inputs.getAxis("rotate_alt"); - rotated = true; - } - if(!Inputs.getAxisActive("rotate_alt")) rotated = false; - - if(!rotatedAlt) { - rotation += Inputs.getAxis("rotate"); - rotatedAlt = true; - } - if(!Inputs.getAxisActive("rotate")) rotatedAlt = false; + rotation += Inputs.getAxisTapped("rotate_alt"); + rotation += Inputs.getAxis("rotate"); rotation = Mathf.mod(rotation, 4); @@ -192,7 +182,7 @@ public class DesktopInput extends InputHandler{ } if(recipe != null){ - showCursor = validPlace(tilex(), tiley(), control.input().recipe.result) && control.input().cursorNear(); + showCursor = validPlace(tilex(), tiley(), recipe.result) && cursorNear(); } if(canBeginShoot){ diff --git a/core/src/io/anuke/mindustry/input/InputHandler.java b/core/src/io/anuke/mindustry/input/InputHandler.java index 8ff5a7bd71..bfe1ea788f 100644 --- a/core/src/io/anuke/mindustry/input/InputHandler.java +++ b/core/src/io/anuke/mindustry/input/InputHandler.java @@ -5,6 +5,7 @@ import com.badlogic.gdx.InputAdapter; import com.badlogic.gdx.math.Interpolation; import com.badlogic.gdx.math.Vector2; import io.anuke.mindustry.entities.ItemAnimationEffect; +import io.anuke.mindustry.entities.Player; import io.anuke.mindustry.net.Net; import io.anuke.mindustry.net.NetEvents; import io.anuke.mindustry.resource.ItemStack; @@ -25,6 +26,7 @@ public abstract class InputHandler extends InputAdapter{ public float breaktime = 0; public Recipe recipe; public int rotation; + public Player player; public PlaceMode placeMode = mobile ? PlaceMode.cursor : PlaceMode.hold; public PlaceMode breakMode = mobile ? PlaceMode.none : PlaceMode.holdDelete; public PlaceMode lastPlaceMode = placeMode; @@ -35,6 +37,10 @@ public abstract class InputHandler extends InputAdapter{ private Translator stackTrns = new Translator(); + public InputHandler(Player player){ + this.player = player; + } + public abstract void update(); public abstract float getCursorX(); public abstract float getCursorY(); diff --git a/core/src/io/anuke/mindustry/net/NetworkIO.java b/core/src/io/anuke/mindustry/net/NetworkIO.java index afd64a0cee..3fa9e0326d 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 { public static ByteBuffer writeServerData(){ int maxlen = 32; - String host = (headless ? "Server" : player.name); + String host = (headless ? "Server" : players[0].name); String map = world.getMap().name; host = host.substring(0, Math.min(host.length(), maxlen)); diff --git a/core/src/io/anuke/mindustry/net/Packets.java b/core/src/io/anuke/mindustry/net/Packets.java index 97ba244375..1e1a48fd4b 100644 --- a/core/src/io/anuke/mindustry/net/Packets.java +++ b/core/src/io/anuke/mindustry/net/Packets.java @@ -85,9 +85,10 @@ public class Packets { public static class ConnectPacket implements Packet{ public int version; - public String name; + public int players; + public String[] names; public boolean android; - public int color; + public int[] colors; public byte[] uuid; @Override