diff --git a/core/assets/bundles/bundle.properties b/core/assets/bundles/bundle.properties index b86238df13..5180498c74 100644 --- a/core/assets/bundles/bundle.properties +++ b/core/assets/bundles/bundle.properties @@ -23,7 +23,7 @@ text.server.closing=[accent]Closing server... text.server.kicked.kick=You have been kicked from the server! text.server.kicked.invalidPassword=Invalid password! text.server.kicked.clientOutdated=Outdated client! Update your game! -text.server.kicked.serverOutdated=Outdated client! Update your game! +text.server.kicked.serverOutdated=Outdated server! Ask the host to update! text.server.connected={0} has joined. text.server.disconnected={0} has disconnected. text.nohost=Can't host server on a custom map! diff --git a/core/src/io/anuke/mindustry/Vars.java b/core/src/io/anuke/mindustry/Vars.java index ab6e78cc64..e60b6236ba 100644 --- a/core/src/io/anuke/mindustry/Vars.java +++ b/core/src/io/anuke/mindustry/Vars.java @@ -9,6 +9,8 @@ import io.anuke.mindustry.entities.Player; import io.anuke.mindustry.entities.TileEntity; import io.anuke.mindustry.entities.effect.Shield; import io.anuke.mindustry.entities.enemies.Enemy; +import io.anuke.mindustry.net.ClientDebug; +import io.anuke.mindustry.net.ServerDebug; import io.anuke.ucore.UCore; import io.anuke.ucore.entities.Entities; import io.anuke.ucore.entities.EntityGroup; @@ -47,8 +49,9 @@ public class Vars{ //how much the zoom changes every zoom button press public static final int zoomScale = Math.round(Unit.dp.scl(1)); //if true, player speed will be increased, massive amounts of resources will be given on start, and other debug options will be available - public static boolean debug = false; - public static boolean debugNet = false; + public static boolean debug = true; + public static boolean debugNet = true; + public static boolean console = false; //whether the player can clip through walls public static boolean noclip = false; //whether to draw chunk borders @@ -83,6 +86,9 @@ public class Vars{ public static final GameState state = new GameState(); + public static final ServerDebug serverDebug = new ServerDebug(); + public static final ClientDebug clientDebug = new ClientDebug(); + public static Control control; public static Logic logic; public static Renderer renderer; diff --git a/core/src/io/anuke/mindustry/core/Control.java b/core/src/io/anuke/mindustry/core/Control.java index a984036bf3..7f24463d93 100644 --- a/core/src/io/anuke/mindustry/core/Control.java +++ b/core/src/io/anuke/mindustry/core/Control.java @@ -4,7 +4,7 @@ import com.badlogic.gdx.Gdx; import com.badlogic.gdx.Input.Buttons; import io.anuke.mindustry.core.GameState.State; import io.anuke.mindustry.entities.Player; -import io.anuke.mindustry.game.DefaultKeybinds; +import io.anuke.mindustry.input.DefaultKeybinds; import io.anuke.mindustry.game.EventType.*; import io.anuke.mindustry.game.Tutorial; import io.anuke.mindustry.game.UpgradeInventory; @@ -266,6 +266,10 @@ public class Control extends Module{ Gdx.input = proxy; } + if(Inputs.keyTap("console")){ + console = !console; + } + if(KeyBinds.getSection("default").device.type == DeviceType.controller){ if(Inputs.keyTap("select")){ Inputs.getProcessor().touchDown(Gdx.input.getX(), Gdx.input.getY(), 0, Buttons.LEFT); diff --git a/core/src/io/anuke/mindustry/core/Logic.java b/core/src/io/anuke/mindustry/core/Logic.java index c3b98d766e..d7baf51cec 100644 --- a/core/src/io/anuke/mindustry/core/Logic.java +++ b/core/src/io/anuke/mindustry/core/Logic.java @@ -131,7 +131,7 @@ public class Logic extends Module { } } - if(state.wavetime <= 0 || state.extrawavetime <= 0){ + if(!Net.client() && (state.wavetime <= 0 || state.extrawavetime <= 0)){ runWave(); } diff --git a/core/src/io/anuke/mindustry/core/NetClient.java b/core/src/io/anuke/mindustry/core/NetClient.java index 2c165167b0..fd284bcb61 100644 --- a/core/src/io/anuke/mindustry/core/NetClient.java +++ b/core/src/io/anuke/mindustry/core/NetClient.java @@ -114,6 +114,8 @@ public class NetClient extends Module { Net.handleClient(SyncPacket.class, packet -> { if (!gotData) return; + int players = 0; + int enemies = 0; ByteBuffer data = ByteBuffer.wrap(packet.data); @@ -126,9 +128,11 @@ public class NetClient extends Module { SyncEntity entity = (SyncEntity) group.getByID(id); + if(entity instanceof Player) players ++; + if(entity instanceof Enemy) enemies ++; + if (entity == null || id == player.id) { if (id != player.id) { - Log.info("Requesting entity {0}, group {1}.", id, group.getType().toString().replace("class io.anuke.mindustry.entities.", "")); EntityRequestPacket req = new EntityRequestPacket(); req.id = id; Net.send(req, SendMode.udp); @@ -138,6 +142,10 @@ public class NetClient extends Module { entity.read(data); } } + + if(debugNet){ + clientDebug.setSyncDebug(players, enemies); + } }); Net.handleClient(StateSyncPacket.class, packet -> { @@ -161,6 +169,7 @@ public class NetClient extends Module { recieved.add(spawn.id); Enemy enemy = new Enemy(EnemyType.getByID(spawn.type)); + enemy.interpolator.target.set(spawn.x, spawn.y); enemy.set(spawn.x, spawn.y); enemy.tier = spawn.tier; enemy.lane = spawn.lane; @@ -169,6 +178,8 @@ public class NetClient extends Module { enemy.add(); Effects.effect(Fx.spawn, enemy); + + Log.info("Recieved enemy {0}", spawn.id); }); Net.handleClient(EnemyDeathPacket.class, spawn -> { @@ -264,6 +275,8 @@ public class NetClient extends Module { player.interpolator.target.set(player.x, player.y); player.add(); + Log.info("Recieved player {0}", packet.id); + Platform.instance.updateRPC(); }); @@ -316,6 +329,11 @@ public class NetClient extends Module { return name == null ? null : "[#" + colorArray[id % colorArray.length].toString().toUpperCase() + "]" + name; } + public void clearRecieved(){ + recieved.clear(); + dead.clear(); + } + void sync(){ if(Timers.get("syncPlayer", playerSyncTime)){ byte[] bytes = new byte[player.getWriteSize()]; diff --git a/core/src/io/anuke/mindustry/core/NetServer.java b/core/src/io/anuke/mindustry/core/NetServer.java index 640f8a75b6..0746761f56 100644 --- a/core/src/io/anuke/mindustry/core/NetServer.java +++ b/core/src/io/anuke/mindustry/core/NetServer.java @@ -157,7 +157,7 @@ public class NetServer extends Module{ Net.handleServer(WeaponSwitchPacket.class, (id, packet) -> { packet.playerid = connections.get(id).id; - Net.sendExcept(player.clientid, packet, SendMode.tcp); + Net.sendExcept(id, packet, SendMode.tcp); }); Net.handleServer(BlockTapPacket.class, (id, packet) -> { @@ -194,8 +194,6 @@ public class NetServer extends Module{ e.type = enemy.type.id; e.health = (short) enemy.health; Net.sendTo(dest, e, SendMode.tcp); - } else { - Log.err("Entity request target not found!"); } }); diff --git a/core/src/io/anuke/mindustry/core/ServerControl.java b/core/src/io/anuke/mindustry/core/ServerControl.java index 160678ef4d..18d6adcaf8 100644 --- a/core/src/io/anuke/mindustry/core/ServerControl.java +++ b/core/src/io/anuke/mindustry/core/ServerControl.java @@ -9,6 +9,7 @@ import io.anuke.mindustry.game.GameMode; import io.anuke.mindustry.io.SaveIO; import io.anuke.mindustry.net.Net; import io.anuke.mindustry.net.Packets.ChatPacket; +import io.anuke.mindustry.ui.fragments.DebugFragment; import io.anuke.mindustry.world.Map; import io.anuke.ucore.core.Effects; import io.anuke.ucore.core.Sounds; @@ -119,7 +120,8 @@ public class ServerControl extends Module { if(state.is(State.menu)){ info("&lyStatus: &rserver closed"); }else{ - info("&lyStatus: &lcPlaying on map &fi{0}&fb &lb/&lc Wave {1} &lb/&lcDifficulty {2}", Strings.capitalize(world.getMap().name), state.wave, state.difficulty.name()); + info("&lyStatus: &lcPlaying on map &fi{0}&fb &lb/&lc Wave {1} &lb/&lc {2}", + Strings.capitalize(world.getMap().name), state.wave, Strings.capitalize(state.difficulty.name())); if(playerGroup.size() > 0) { info("&lyPlayers: {0}", playerGroup.size()); for (Player p : playerGroup.all()) { @@ -138,7 +140,7 @@ public class ServerControl extends Module { } netCommon.sendMessage("[pink][[Server]:[] " + arg[0]); - info("&ly[Server]: &lb{0}", arg[0]); + info("&lyServer: &lb{0}", arg[0]); }).mergeArgs(); handler.register("difficulty", "", "Set game difficulty.", arg -> { @@ -188,6 +190,10 @@ public class ServerControl extends Module { info("Saved to slot {0}.", slot); }); + + handler.register("info", "", "Print debug info", arg -> { + info(DebugFragment.debugInfo()); + }); } private void readCommands(){ diff --git a/core/src/io/anuke/mindustry/core/UI.java b/core/src/io/anuke/mindustry/core/UI.java index 09f8297edd..85483571e3 100644 --- a/core/src/io/anuke/mindustry/core/UI.java +++ b/core/src/io/anuke/mindustry/core/UI.java @@ -55,6 +55,7 @@ public class UI extends SceneModule{ public final BackgroundFragment backfrag = new BackgroundFragment(); public final LoadingFragment loadfrag = new LoadingFragment(); public final BlockConfigFragment configfrag = new BlockConfigFragment(); + public final DebugFragment debugfrag = new DebugFragment(); private Locale lastLocale; @@ -160,6 +161,7 @@ public class UI extends SceneModule{ toolfrag.build(); chatfrag.build(); listfrag.build(); + debugfrag.build(); loadfrag.build(); build.end(); diff --git a/core/src/io/anuke/mindustry/entities/enemies/EnemyType.java b/core/src/io/anuke/mindustry/entities/enemies/EnemyType.java index eb72c3565a..ea12b1e595 100644 --- a/core/src/io/anuke/mindustry/entities/enemies/EnemyType.java +++ b/core/src/io/anuke/mindustry/entities/enemies/EnemyType.java @@ -139,14 +139,14 @@ public class EnemyType { } public void move(Enemy enemy){ - float speed = this.speed + 0.04f * enemy.tier; - float range = this.range + enemy.tier * 5; - - if(Net.client() && Net.active()){ + if(Net.client()){ enemy.interpolate(); //TODO? better structure for interpolation return; } + float speed = this.speed + 0.04f * enemy.tier; + float range = this.range + enemy.tier * 5; + Tile core = world.getCore(); if(enemy.idletime > maxIdleLife){ @@ -194,8 +194,12 @@ public class EnemyType { enemy.move(vec.x * Timers.delta(), vec.y * Timers.delta()); updateTargeting(enemy, nearCore); + + behavior(enemy); } + public void behavior(Enemy enemy){} + public void updateTargeting(Enemy enemy, boolean nearCore){ if(enemy.target != null && enemy.target instanceof TileEntity && ((TileEntity)enemy.target).dead){ enemy.target = null; diff --git a/core/src/io/anuke/mindustry/entities/enemies/StandardEnemy.java b/core/src/io/anuke/mindustry/entities/enemies/StandardEnemy.java deleted file mode 100644 index 02159828f5..0000000000 --- a/core/src/io/anuke/mindustry/entities/enemies/StandardEnemy.java +++ /dev/null @@ -1,4 +0,0 @@ -package io.anuke.mindustry.entities.enemies; - -public class StandardEnemy { -} diff --git a/core/src/io/anuke/mindustry/entities/enemies/types/BlastType.java b/core/src/io/anuke/mindustry/entities/enemies/types/BlastType.java index 5dd3483e95..40dc7d4838 100644 --- a/core/src/io/anuke/mindustry/entities/enemies/types/BlastType.java +++ b/core/src/io/anuke/mindustry/entities/enemies/types/BlastType.java @@ -1,7 +1,6 @@ package io.anuke.mindustry.entities.enemies.types; import com.badlogic.gdx.math.Vector2; -import static io.anuke.mindustry.Vars.*; import io.anuke.mindustry.entities.Bullet; import io.anuke.mindustry.entities.BulletType; import io.anuke.mindustry.entities.TileEntity; @@ -9,6 +8,8 @@ import io.anuke.mindustry.entities.enemies.Enemy; import io.anuke.mindustry.entities.enemies.EnemyType; import io.anuke.ucore.util.Tmp; +import static io.anuke.mindustry.Vars.tilesize; + public class BlastType extends EnemyType { public BlastType() { @@ -22,8 +23,7 @@ public class BlastType extends EnemyType { } @Override - public void move(Enemy enemy){ - super.move(enemy); + public void behavior(Enemy enemy){ float range = 10f; Vector2 offset = Tmp.v3.setZero(); diff --git a/core/src/io/anuke/mindustry/entities/enemies/types/FortressType.java b/core/src/io/anuke/mindustry/entities/enemies/types/FortressType.java index 8c59030ee6..3b3f08adf4 100644 --- a/core/src/io/anuke/mindustry/entities/enemies/types/FortressType.java +++ b/core/src/io/anuke/mindustry/entities/enemies/types/FortressType.java @@ -1,6 +1,5 @@ package io.anuke.mindustry.entities.enemies.types; -import static io.anuke.mindustry.Vars.*; import io.anuke.mindustry.entities.BulletType; import io.anuke.mindustry.entities.enemies.Enemy; import io.anuke.mindustry.entities.enemies.EnemyType; @@ -10,6 +9,8 @@ import io.anuke.ucore.core.Effects; import io.anuke.ucore.core.Timers; import io.anuke.ucore.util.Angles; +import static io.anuke.mindustry.Vars.world; + public class FortressType extends EnemyType { final int maxSpawn = 6; final float spawnTime = 190; @@ -29,7 +30,7 @@ public class FortressType extends EnemyType { } @Override - public void move(Enemy enemy){ + public void behavior(Enemy enemy){ if(enemy.distanceTo(world.getCore().worldx(), world.getCore().worldy()) <= 90f){ @@ -47,8 +48,6 @@ public class FortressType extends EnemyType { enemy.spawned ++; } - }else { - super.move(enemy); } } diff --git a/core/src/io/anuke/mindustry/entities/enemies/types/HealerType.java b/core/src/io/anuke/mindustry/entities/enemies/types/HealerType.java index 9e45a19de9..c2552f4fea 100644 --- a/core/src/io/anuke/mindustry/entities/enemies/types/HealerType.java +++ b/core/src/io/anuke/mindustry/entities/enemies/types/HealerType.java @@ -35,8 +35,7 @@ public class HealerType extends EnemyType { } @Override - public void move(Enemy enemy){ - super.move(enemy); + public void behavior(Enemy enemy){ if(enemy.idletime > 60f*3){ //explode after 3 seconds of stillness explode(enemy); diff --git a/core/src/io/anuke/mindustry/game/Difficulty.java b/core/src/io/anuke/mindustry/game/Difficulty.java index ed84960259..0acfd411b9 100644 --- a/core/src/io/anuke/mindustry/game/Difficulty.java +++ b/core/src/io/anuke/mindustry/game/Difficulty.java @@ -14,11 +14,11 @@ import io.anuke.mindustry.world.blocks.types.production.Smelter; import io.anuke.ucore.util.Bundles; public enum Difficulty { - easy(4f, 2f, new DestrutiveHeuristic(b -> b instanceof Generator)), - normal(2f, 1f, new DestrutiveHeuristic(b -> b instanceof Smelter || b instanceof Generator)), - hard(1.5f, 0.5f, new DestrutiveHeuristic(b -> b instanceof Turret || b instanceof Generator || b instanceof Drill || b instanceof Smelter)), - insane(0.5f, 0.25f, new DestrutiveHeuristic(b -> b instanceof Generator || b instanceof Drill || b instanceof Smelter || b instanceof Router)), - purge(0.25f, 0.01f, new DestrutiveHeuristic(b -> b instanceof Generator || b instanceof Drill || b instanceof Router + easy(4f, 2f, 1f, new DestrutiveHeuristic(b -> b instanceof Generator)), + normal(2f, 1f, 1f, new DestrutiveHeuristic(b -> b instanceof Smelter || b instanceof Generator)), + hard(1.5f, 0.5f, 0.75f, new DestrutiveHeuristic(b -> b instanceof Turret || b instanceof Generator || b instanceof Drill || b instanceof Smelter)), + insane(0.5f, 0.25f, 0.5f, new DestrutiveHeuristic(b -> b instanceof Generator || b instanceof Drill || b instanceof Smelter || b instanceof Router)), + purge(0.25f, 0.01f, 0.25f, new DestrutiveHeuristic(b -> b instanceof Generator || b instanceof Drill || b instanceof Router || b instanceof Smelter || b instanceof Conveyor || b instanceof LiquidBlock || b instanceof PowerBlock)); /**The scaling of how many waves it takes for one more enemy of a type to appear. @@ -27,13 +27,16 @@ public enum Difficulty { public final float enemyScaling; /**Multiplier of the time between waves.*/ public final float timeScaling; + /**Scaling of max time between waves. Default time is 4 minutes.*/ + public final float maxTimeScaling; /**Pathfdining heuristic for calculating tile costs.*/ public final Heuristic heuristic; - Difficulty(float enemyScaling, float timeScaling, Heuristic heuristic){ + Difficulty(float enemyScaling, float timeScaling, float maxTimeScaling, Heuristic heuristic){ this.enemyScaling = enemyScaling; this.timeScaling = timeScaling; this.heuristic = heuristic; + this.maxTimeScaling = maxTimeScaling; } @Override diff --git a/core/src/io/anuke/mindustry/game/DefaultKeybinds.java b/core/src/io/anuke/mindustry/input/DefaultKeybinds.java similarity index 95% rename from core/src/io/anuke/mindustry/game/DefaultKeybinds.java rename to core/src/io/anuke/mindustry/input/DefaultKeybinds.java index 73005e7f12..1cd7fda6b2 100644 --- a/core/src/io/anuke/mindustry/game/DefaultKeybinds.java +++ b/core/src/io/anuke/mindustry/input/DefaultKeybinds.java @@ -1,4 +1,4 @@ -package io.anuke.mindustry.game; +package io.anuke.mindustry.input; import com.badlogic.gdx.Application.ApplicationType; import com.badlogic.gdx.Gdx; @@ -25,6 +25,7 @@ public class DefaultKeybinds { "rotate", new Axis(Input.SCROLL), "player_list", Input.TAB, "chat", Input.ENTER, + "console", Input.GRAVE, "weapon_1", Input.NUM_1, "weapon_2", Input.NUM_2, "weapon_3", Input.NUM_3, @@ -51,6 +52,7 @@ public class DefaultKeybinds { "rotate", new Axis(Input.CONTROLLER_A, Input.CONTROLLER_B), "player_list", Input.CONTROLLER_START, "chat", Input.ENTER, + "console", Input.GRAVE, "weapon_1", Input.NUM_1, "weapon_2", Input.NUM_2, "weapon_3", Input.NUM_3, diff --git a/core/src/io/anuke/mindustry/net/ClientDebug.java b/core/src/io/anuke/mindustry/net/ClientDebug.java new file mode 100644 index 0000000000..60b0eb0bdf --- /dev/null +++ b/core/src/io/anuke/mindustry/net/ClientDebug.java @@ -0,0 +1,51 @@ +package io.anuke.mindustry.net; + +import com.badlogic.gdx.utils.OrderedMap; +import com.badlogic.gdx.utils.TimeUtils; +import com.badlogic.gdx.utils.reflect.ClassReflection; + +public class ClientDebug { + private OrderedMap, Long> last = new OrderedMap<>(); + private int syncPlayers = 0; + private int syncEnemies = 0; + + public void handle(Object packet){ + last.put(packet.getClass(), TimeUtils.millis()); + } + + public void setSyncDebug(int players, int enemies){ + this.syncEnemies = enemies; + this.syncPlayers = players; + } + + public String getOut(){ + StringBuilder build = new StringBuilder(); + for(Class type : last.orderedKeys()){ + build.append(elapsed(type)); + build.append("\n"); + } + build.append("sync.players: "); + build.append(syncPlayers); + build.append("\n"); + build.append("sync.enemies: "); + build.append(syncEnemies); + build.append("\n"); + return build.toString(); + } + + private String elapsed(Class type){ + long t = last.get(type, -1L); + if(t == -1){ + return ClassReflection.getSimpleName(type) + ": "; + }else{ + float el = TimeUtils.timeSinceMillis(t) / 1000f; + String tu; + if(el > 1f){ + tu = (int)el + "s"; + }else{ + tu = (int)(el * 60) + "f"; + } + return ClassReflection.getSimpleName(type) + ": " + tu; + } + } +} diff --git a/core/src/io/anuke/mindustry/net/Net.java b/core/src/io/anuke/mindustry/net/Net.java index 5e495ccb43..f3b384c388 100644 --- a/core/src/io/anuke/mindustry/net/Net.java +++ b/core/src/io/anuke/mindustry/net/Net.java @@ -16,11 +16,10 @@ import io.anuke.ucore.util.Log; import java.io.IOException; -import static io.anuke.mindustry.Vars.headless; -import static io.anuke.mindustry.Vars.ui; +import static io.anuke.mindustry.Vars.*; public class Net{ - public static final int version = 13; + public static final int version = 14; private static boolean server; private static boolean active; @@ -141,6 +140,8 @@ public class Net{ /**Call to handle a packet being recieved for the client.*/ public static void handleClientReceived(Object object){ + if(debugNet) clientDebug.handle(object); + if(object instanceof StreamBegin) { StreamBegin b = (StreamBegin) object; streams.put(b.id, new StreamBuilder(b)); @@ -170,6 +171,8 @@ public class Net{ /**Call to handle a packet being recieved for the server.*/ public static void handleServerReceived(int connection, Object object){ + if(debugNet) serverDebug.handle(object); + if(serverListeners.get(object.getClass()) != null || listeners.get(object.getClass()) != null){ if(serverListeners.get(object.getClass()) != null) serverListeners.get(object.getClass()).accept(connection, object); if(listeners.get(object.getClass()) != null) listeners.get(object.getClass()).accept(object); diff --git a/core/src/io/anuke/mindustry/net/ServerDebug.java b/core/src/io/anuke/mindustry/net/ServerDebug.java new file mode 100644 index 0000000000..4e5f92bb0f --- /dev/null +++ b/core/src/io/anuke/mindustry/net/ServerDebug.java @@ -0,0 +1,8 @@ +package io.anuke.mindustry.net; + +public class ServerDebug { + + public void handle(Object packet){ + + } +} diff --git a/core/src/io/anuke/mindustry/ui/fragments/DebugFragment.java b/core/src/io/anuke/mindustry/ui/fragments/DebugFragment.java new file mode 100644 index 0000000000..387d6bad03 --- /dev/null +++ b/core/src/io/anuke/mindustry/ui/fragments/DebugFragment.java @@ -0,0 +1,120 @@ +package io.anuke.mindustry.ui.fragments; + +import com.badlogic.gdx.Gdx; +import io.anuke.mindustry.entities.enemies.Enemy; +import io.anuke.mindustry.entities.enemies.EnemyTypes; +import io.anuke.mindustry.net.Net; +import io.anuke.ucore.scene.builders.button; +import io.anuke.ucore.scene.builders.label; +import io.anuke.ucore.scene.builders.table; +import io.anuke.ucore.scene.ui.ScrollPane; +import io.anuke.ucore.scene.ui.layout.Table; +import io.anuke.ucore.util.Log; +import io.anuke.ucore.util.Log.LogHandler; + +import static io.anuke.mindustry.Vars.*; + +public class DebugFragment implements Fragment { + private static StringBuilder log = new StringBuilder(); + + static{ + Log.setLogger(new LogHandler(){ + @Override + public void print(String text, Object... args){ + super.print(text, args); + log.append(Log.format(text, args)); + log.append("\n"); + } + }); + } + + @Override + public void build(){ + new table(){{ + visible(() -> debug); + + atop().aright(); + + new table("pane"){{ + defaults().fillX(); + + new label("Debug"); + row(); + new button("noclip", "toggle", () -> noclip = !noclip); + row(); + new button("paths", "toggle", () -> showPaths = !showPaths); + row(); + new button("infammo", "toggle", () -> infiniteAmmo = !infiniteAmmo); + row(); + new button("wave", () -> logic.runWave()); + row(); + new button("clear", () -> { + enemyGroup.clear(); + state.enemies = 0; + netClient.clearRecieved(); + }); + row(); + new button("spawn", () -> new Enemy(EnemyTypes.standard).set(player.x, player.y).add()); + row(); + }}.end(); + + row(); + + }}.end(); + + + new table(){{ + visible(() -> console); + + atop().aleft(); + + new table("pane") {{ + defaults().fillX(); + + new label(DebugFragment::debugInfo); + row(); + new button("dump", () -> { + try{ + Gdx.files.local("packet-dump.txt").writeString(debugInfo(), false); + }catch (Exception e){ + ui.showError("Error dumping log."); + } + }); + }}.end(); + }}.end(); + + new table(){{ + visible(() -> console); + + atop(); + + Table table = new Table("pane"); + table.label(() -> log.toString()); + + ScrollPane pane = new ScrollPane(table, "clear"); + + get().add(pane); + }}.end(); + } + + public static String debugInfo(){ + return join( + "net.active: " + Net.active(), + "net.server: " + Net.server(), + "players: " + playerGroup.size(), + "enemies: " + enemyGroup.size(), + "tiles: " + tileGroup.size(), + "", + clientDebug.getOut() + ); + } + + private static String join(String... strings){ + StringBuilder builder = new StringBuilder(); + for (String string : strings) { + builder.append(string); + builder.append("\n"); + } + return builder.toString(); + } +} diff --git a/core/src/io/anuke/mindustry/ui/fragments/HudFragment.java b/core/src/io/anuke/mindustry/ui/fragments/HudFragment.java index 34f81f644a..4f46d6bbf8 100644 --- a/core/src/io/anuke/mindustry/ui/fragments/HudFragment.java +++ b/core/src/io/anuke/mindustry/ui/fragments/HudFragment.java @@ -7,7 +7,6 @@ import io.anuke.mindustry.core.GameState.State; import io.anuke.mindustry.net.Net; import io.anuke.ucore.core.Core; import io.anuke.ucore.core.Settings; -import io.anuke.ucore.core.Timers; import io.anuke.ucore.scene.actions.Actions; import io.anuke.ucore.scene.builders.imagebutton; import io.anuke.ucore.scene.builders.label; @@ -148,26 +147,6 @@ public class HudFragment implements Fragment{ }}.end(); }}.end(); - //profiling table - if(debug){ - new table(){{ - atop(); - new label("[green]density: " + Gdx.graphics.getDensity()).left(); - row(); - new label(() -> "[blue]requests: " + renderer.getBlocks().getRequests()).left(); - row(); - new label(() -> "[purple]tiles: " + tileGroup.size()).left(); - row(); - new label(() -> "[purple]enemies: " + enemyGroup.size()).left(); - row(); - new label(() -> "[orange]noclip: " + noclip).left(); - row(); - new label(() -> "[purple]time: " + (int)(Timers.time() / 10f) % 50).left(); - row(); - new label("[red]DEBUG MODE").scale(0.5f).left(); - }}.end(); - } - new table(){{ abottom(); visible(() -> !state.is(State.menu) && control.getSaves().isSaving()); @@ -176,14 +155,6 @@ public class HudFragment implements Fragment{ }}.end(); - if(debugNet) { - new table() {{ - new label(() -> "players: " + playerGroup.size()); - row(); - new label(() -> "" + playerGroup.all()); - }}.end(); - } - blockfrag.build(); } diff --git a/core/src/io/anuke/mindustry/world/blocks/types/defense/Door.java b/core/src/io/anuke/mindustry/world/blocks/types/defense/Door.java index ecb9601ef2..95ffcc8930 100644 --- a/core/src/io/anuke/mindustry/world/blocks/types/defense/Door.java +++ b/core/src/io/anuke/mindustry/world/blocks/types/defense/Door.java @@ -75,9 +75,13 @@ public class Door extends Wall{ return true; } } - - if(Tmp.r2.overlaps(player.hitbox.getRect(player.x, player.y))){ - return true; + + for(SolidEntity e : Entities.getNearby(playerGroup, x * tilesize, y * tilesize, tilesize * 2f)){ + Rectangle rect = e.hitbox.getRect(e.x, e.y); + + if(Tmp.r2.overlaps(rect)){ + return true; + } } return false; diff --git a/core/src/io/anuke/mindustry/world/blocks/types/defense/ShieldBlock.java b/core/src/io/anuke/mindustry/world/blocks/types/defense/ShieldBlock.java index b325c47cc6..d962589410 100644 --- a/core/src/io/anuke/mindustry/world/blocks/types/defense/ShieldBlock.java +++ b/core/src/io/anuke/mindustry/world/blocks/types/defense/ShieldBlock.java @@ -13,6 +13,7 @@ import io.anuke.ucore.entities.BulletEntity; import io.anuke.ucore.util.Mathf; import io.anuke.ucore.util.Strings; +import static io.anuke.mindustry.Vars.headless; import static io.anuke.mindustry.Vars.renderer; public class ShieldBlock extends PowerBlock{ @@ -76,7 +77,7 @@ public class ShieldBlock extends PowerBlock{ bullet.remove(); Effects.effect(bullet.damage > 5 ? Fx.shieldhit : Fx.laserhit, bullet); - renderer.addShieldHit(bullet.x, bullet.y); + if(!headless) renderer.addShieldHit(bullet.x, bullet.y); entity.power -= bullet.getDamage() * powerPerDamage; } diff --git a/core/src/io/anuke/mindustry/world/blocks/types/production/Generator.java b/core/src/io/anuke/mindustry/world/blocks/types/production/Generator.java index bb1850c8c5..b7d2ea563d 100644 --- a/core/src/io/anuke/mindustry/world/blocks/types/production/Generator.java +++ b/core/src/io/anuke/mindustry/world/blocks/types/production/Generator.java @@ -4,7 +4,6 @@ import com.badlogic.gdx.graphics.Color; import com.badlogic.gdx.math.GridPoint2; import com.badlogic.gdx.math.Vector2; import com.badlogic.gdx.utils.Array; -import static io.anuke.mindustry.Vars.*; import io.anuke.mindustry.core.GameState.State; import io.anuke.mindustry.graphics.Fx; import io.anuke.mindustry.world.Layer; @@ -20,7 +19,7 @@ import io.anuke.ucore.graphics.Lines; import io.anuke.ucore.graphics.Shapes; import io.anuke.ucore.util.*; -import static io.anuke.mindustry.Vars.state; +import static io.anuke.mindustry.Vars.*; public class Generator extends PowerBlock{ public static final int powerTime = 2; @@ -177,7 +176,8 @@ public class Generator extends PowerBlock{ if(target != null){ boolean interfering = isInterfering(target, rotation); - Tmp.v1.set(Angles.translation(rotation * 90, target.block().width * tilesize / 2 + 2f + (interfering ? Vector2.dst(tile.worldx(), tile.worldy(), target.worldx(), target.worldy()) / 2f - tilesize / 2f * target.block().width - 1 : 0))); + Tmp.v1.set(Angles.translation(rotation * 90, target.block().width * tilesize / 2 + 2f + + (interfering ? Vector2.dst(tile.worldx(), tile.worldy(), target.worldx(), target.worldy()) / 2f - tilesize / 2f * target.block().width + 1 : 0))); Angles.translation(rotation * 90, width * tilesize / 2 + 2f); @@ -191,7 +191,7 @@ public class Generator extends PowerBlock{ } } - float r = interfering ? 0.8f : 0f; + float r = interfering ? 0f : 0f; int relative = tile.relativeTo(target.x, target.y); diff --git a/kryonet/src/io/anuke/kryonet/KryoClient.java b/kryonet/src/io/anuke/kryonet/KryoClient.java index 5900285992..52cddac4e2 100644 --- a/kryonet/src/io/anuke/kryonet/KryoClient.java +++ b/kryonet/src/io/anuke/kryonet/KryoClient.java @@ -13,7 +13,6 @@ import io.anuke.mindustry.net.Net.SendMode; import io.anuke.mindustry.net.Packets.Connect; import io.anuke.mindustry.net.Packets.Disconnect; import io.anuke.ucore.function.Consumer; -import io.anuke.ucore.util.Log; import java.io.IOException; import java.net.DatagramPacket; @@ -43,7 +42,6 @@ public class KryoClient implements ClientProvider{ ByteBuffer buffer = ByteBuffer.wrap(datagramPacket.getData()); Host address = KryoRegistrator.readServerData(datagramPacket.getAddress(), buffer); addresses.put(datagramPacket.getAddress(), address); - Log.info("Host data found: {0} bytes.", buffer.capacity()); } @Override diff --git a/kryonet/src/io/anuke/kryonet/KryoServer.java b/kryonet/src/io/anuke/kryonet/KryoServer.java index 5bc3a1b442..4f6543449c 100644 --- a/kryonet/src/io/anuke/kryonet/KryoServer.java +++ b/kryonet/src/io/anuke/kryonet/KryoServer.java @@ -51,7 +51,6 @@ public class KryoServer implements ServerProvider { server = new Server(4096*2, 2048, connection -> new ByteSerializer()); //TODO tweak server.setDiscoveryHandler((datagramChannel, fromAddress) -> { ByteBuffer buffer = KryoRegistrator.writeServerData(); - Log.info("Replying to discover request with buffer of size {0}.", buffer.capacity()); buffer.position(0); datagramChannel.send(buffer, fromAddress); return true; diff --git a/server/src/io/anuke/mindustry/server/ServerLauncher.java b/server/src/io/anuke/mindustry/server/ServerLauncher.java index f21b0425cb..a39ade9f0f 100644 --- a/server/src/io/anuke/mindustry/server/ServerLauncher.java +++ b/server/src/io/anuke/mindustry/server/ServerLauncher.java @@ -5,6 +5,7 @@ import io.anuke.kryonet.KryoClient; import io.anuke.kryonet.KryoServer; import io.anuke.mindustry.MindustryServer; import io.anuke.mindustry.net.Net; +import io.anuke.ucore.util.Log; public class ServerLauncher{ @@ -13,6 +14,18 @@ public class ServerLauncher{ Net.setClientProvider(new KryoClient()); Net.setServerProvider(new KryoServer()); - new HeadlessApplication(new MindustryServer()); + new HeadlessApplication(new MindustryServer()){ + @Override + public boolean executeRunnables() { + try { + return super.executeRunnables(); + }catch(Throwable e) { + Log.err(e); + System.exit(-1); + return false; + } + } + }; + } } \ No newline at end of file