From 3aedc07ad099c8509d327c502cd7c60d0b74b50d Mon Sep 17 00:00:00 2001 From: Anuken Date: Tue, 21 Aug 2018 16:37:57 -0400 Subject: [PATCH] Initial continuous server implementation --- core/src/io/anuke/mindustry/core/Logic.java | 2 - .../io/anuke/mindustry/core/NetClient.java | 59 +++++++++++++------ .../io/anuke/mindustry/core/NetServer.java | 22 +++---- .../mindustry/entities/units/BaseUnit.java | 2 +- .../src/io/anuke/mindustry/net/NetworkIO.java | 2 + core/src/io/anuke/mindustry/ui/ItemImage.java | 4 +- .../world/blocks/storage/CoreBlock.java | 6 -- .../anuke/mindustry/server/ServerControl.java | 41 ++++++++++--- 8 files changed, 89 insertions(+), 49 deletions(-) diff --git a/core/src/io/anuke/mindustry/core/Logic.java b/core/src/io/anuke/mindustry/core/Logic.java index c703bce362..cbc0b61a87 100644 --- a/core/src/io/anuke/mindustry/core/Logic.java +++ b/core/src/io/anuke/mindustry/core/Logic.java @@ -66,8 +66,6 @@ public class Logic extends Module{ } } - - Events.fire(PlayEvent.class); } diff --git a/core/src/io/anuke/mindustry/core/NetClient.java b/core/src/io/anuke/mindustry/core/NetClient.java index ae883975c0..b3dc579d96 100644 --- a/core/src/io/anuke/mindustry/core/NetClient.java +++ b/core/src/io/anuke/mindustry/core/NetClient.java @@ -80,18 +80,8 @@ public class NetClient extends Module{ player.isAdmin = false; - Net.setClientLoaded(false); - removed.clear(); - timeoutTime = 0f; - connecting = true; - quiet = false; - lastSent = 0; - lastSnapshotBase = null; - currentSnapshot = null; - currentSnapshotID = -1; - lastSnapshotBaseID = -1; + reset(); - ui.chatfrag.clearMessages(); ui.loadfrag.hide(); ui.loadfrag.show("$text.connecting.data"); @@ -102,8 +92,6 @@ public class NetClient extends Module{ Net.disconnect(); }); - Entities.clear(); - ConnectPacket c = new ConnectPacket(); c.name = player.name; c.mobile = mobile; @@ -161,6 +149,29 @@ public class NetClient extends Module{ ui.loadfrag.hide(); } + @Remote(variants = Variant.both) + public static void onInfoMessage(String message){ + threads.runGraphics(() -> ui.showInfo(message)); + } + + @Remote(variants = Variant.both) + public static void onWorldDataBegin(){ + Entities.clear(); + ui.chatfrag.clearMessages(); + Net.setClientLoaded(false); + + threads.runGraphics(() -> { + ui.loadfrag.show("$text.connecting.data"); + + ui.loadfrag.setButton(() -> { + ui.loadfrag.hide(); + netClient.connecting = false; + netClient.quiet = true; + Net.disconnect(); + }); + }); + } + @Remote(variants = Variant.one) public static void onPositionSet(float x, float y){ players[0].x = x; @@ -285,7 +296,6 @@ public class NetClient extends Module{ //go through each entity for(int j = 0; j < amount; j++){ - int position = netClient.byteStream.position(); //save position to check read/write correctness int id = input.readInt(); byte typeID = input.readByte(); @@ -304,11 +314,6 @@ public class NetClient extends Module{ //read the entity entity.read(input, timestamp); - byte readLength = input.readByte(); - //if(netClient.byteStream.position() - position - 1 != readLength){ - // throw new RuntimeException("Error reading entity of type '" + group.getType() + "': Read length mismatch [write=" + readLength + ", read=" + (netClient.byteStream.position() - position - 1) + "]"); - //} - if(add){ entity.add(); netClient.addRemovedEntity(entity.getID()); @@ -352,6 +357,22 @@ public class NetClient extends Module{ Timers.runTask(40f, Platform.instance::updateRPC); } + private void reset(){ + Net.setClientLoaded(false); + removed.clear(); + timeoutTime = 0f; + connecting = true; + quiet = false; + lastSent = 0; + lastSnapshotBase = null; + currentSnapshot = null; + currentSnapshotID = -1; + lastSnapshotBaseID = -1; + + Entities.clear(); + ui.chatfrag.clearMessages(); + } + public void beginConnecting(){ connecting = true; } diff --git a/core/src/io/anuke/mindustry/core/NetServer.java b/core/src/io/anuke/mindustry/core/NetServer.java index d792d56d9b..ae8f41b2fb 100644 --- a/core/src/io/anuke/mindustry/core/NetServer.java +++ b/core/src/io/anuke/mindustry/core/NetServer.java @@ -190,15 +190,7 @@ public class NetServer extends Module{ trace.playerid = player.id; - //TODO try DeflaterOutputStream - ByteArrayOutputStream stream = new ByteArrayOutputStream(); - DeflaterOutputStream def = new DeflaterOutputStream(stream); - NetworkIO.writeWorld(player, def); - WorldStream data = new WorldStream(); - data.stream = new ByteArrayInputStream(stream.toByteArray()); - Net.sendStream(id, data); - - Log.info("Packed {0} uncompressed bytes of WORLD data.", stream.size()); + sendWorldData(player, id); Platform.instance.updateRPC(); }); @@ -317,6 +309,17 @@ public class NetServer extends Module{ } } + public void sendWorldData(Player player, int clientID){ + ByteArrayOutputStream stream = new ByteArrayOutputStream(); + DeflaterOutputStream def = new DeflaterOutputStream(stream); + NetworkIO.writeWorld(player, def); + WorldStream data = new WorldStream(); + data.stream = new ByteArrayInputStream(stream.toByteArray()); + Net.sendStream(clientID, data); + + Log.info("Packed {0} compressed bytes of world data.", stream.size()); + } + public static void onDisconnect(Player player){ if(player.con.hasConnected){ Call.sendMessage("[accent]" + player.name + "[accent] has disconnected."); @@ -483,7 +486,6 @@ public class NetServer extends Module{ int length = syncStream.position() - position; //length must always be less than 127 bytes if(length > 127) throw new RuntimeException("Write size for entity of type " + group.getType() + " must not exceed 127!"); - dataStream.writeByte(length); } } } diff --git a/core/src/io/anuke/mindustry/entities/units/BaseUnit.java b/core/src/io/anuke/mindustry/entities/units/BaseUnit.java index 29465610d6..e661ab6590 100644 --- a/core/src/io/anuke/mindustry/entities/units/BaseUnit.java +++ b/core/src/io/anuke/mindustry/entities/units/BaseUnit.java @@ -320,7 +320,7 @@ public abstract class BaseUnit extends Unit implements ShooterTrait{ if(target != null) behavior(); - if(!isWave){ + if(!isWave && !isFlying()){ x = Mathf.clamp(x, 0, world.width() * tilesize); y = Mathf.clamp(y, 0, world.height() * tilesize); } diff --git a/core/src/io/anuke/mindustry/net/NetworkIO.java b/core/src/io/anuke/mindustry/net/NetworkIO.java index 17d4024396..b7de7e5a82 100644 --- a/core/src/io/anuke/mindustry/net/NetworkIO.java +++ b/core/src/io/anuke/mindustry/net/NetworkIO.java @@ -118,6 +118,8 @@ public class NetworkIO{ i += consecutives; } + stream.write(Team.all.length); + //write team data for(Team team : Team.all){ TeamData data = state.teams.get(team); diff --git a/core/src/io/anuke/mindustry/ui/ItemImage.java b/core/src/io/anuke/mindustry/ui/ItemImage.java index 5dab85a67d..2ef09241ad 100644 --- a/core/src/io/anuke/mindustry/ui/ItemImage.java +++ b/core/src/io/anuke/mindustry/ui/ItemImage.java @@ -14,7 +14,7 @@ public class ItemImage extends Stack{ public ItemImage(TextureRegion region, Supplier text){ Table t = new Table().left().bottom(); - t.label(text).color(Color.DARK_GRAY).padBottom(-22).get().setFontScale(Unit.dp.scl(0.5f)); + t.label(text).color(Color.DARK_GRAY).padBottom(-21).get().setFontScale(Unit.dp.scl(0.5f)); t.row(); t.label(text).get().setFontScale(Unit.dp.scl(0.5f)); @@ -25,7 +25,7 @@ public class ItemImage extends Stack{ public ItemImage(ItemStack stack){ Table t = new Table().left().bottom(); - t.add(stack.amount + "").color(Color.DARK_GRAY).padBottom(-22).get().setFontScale(Unit.dp.scl(0.5f)); + t.add(stack.amount + "").color(Color.DARK_GRAY).padBottom(-21).get().setFontScale(Unit.dp.scl(0.5f)); t.row(); t.add(stack.amount + "").get().setFontScale(Unit.dp.scl(0.5f)); 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 abbfb90dfe..0f818edd42 100644 --- a/core/src/io/anuke/mindustry/world/blocks/storage/CoreBlock.java +++ b/core/src/io/anuke/mindustry/world/blocks/storage/CoreBlock.java @@ -1,7 +1,6 @@ package io.anuke.mindustry.world.blocks.storage; import com.badlogic.gdx.graphics.g2d.TextureRegion; -import com.badlogic.gdx.math.Rectangle; import io.anuke.annotations.Annotations.Loc; import io.anuke.annotations.Annotations.Remote; import io.anuke.mindustry.Vars; @@ -38,12 +37,7 @@ import java.io.IOException; import static io.anuke.mindustry.Vars.*; public class CoreBlock extends StorageBlock{ - private static Rectangle rect = new Rectangle(); - - protected int timerSupply = timers++; - protected float supplyRadius = 50f; - protected float supplyInterval = 5f; protected float droneRespawnDuration = 60 * 6; protected UnitType droneType = UnitTypes.drone; diff --git a/server/src/io/anuke/mindustry/server/ServerControl.java b/server/src/io/anuke/mindustry/server/ServerControl.java index e063d664f9..365a43fde9 100644 --- a/server/src/io/anuke/mindustry/server/ServerControl.java +++ b/server/src/io/anuke/mindustry/server/ServerControl.java @@ -9,13 +9,16 @@ import io.anuke.mindustry.game.Difficulty; import io.anuke.mindustry.game.EventType.GameOverEvent; import io.anuke.mindustry.game.GameMode; import io.anuke.mindustry.game.Team; -import io.anuke.mindustry.gen.Call; -import io.anuke.mindustry.maps.Map; -import io.anuke.mindustry.io.SaveIO; import io.anuke.mindustry.game.Version; -import io.anuke.mindustry.net.*; +import io.anuke.mindustry.gen.Call; +import io.anuke.mindustry.io.SaveIO; +import io.anuke.mindustry.maps.Map; +import io.anuke.mindustry.net.Administration; import io.anuke.mindustry.net.Administration.PlayerInfo; +import io.anuke.mindustry.net.EditLog; +import io.anuke.mindustry.net.Net; import io.anuke.mindustry.net.Packets.KickReason; +import io.anuke.mindustry.net.TraceInfo; import io.anuke.mindustry.type.Item; import io.anuke.mindustry.type.ItemType; import io.anuke.mindustry.ui.fragments.DebugFragment; @@ -87,9 +90,9 @@ public class ServerControl extends Module{ Events.on(GameOverEvent.class, () -> { info("Game over!"); - netServer.kickAll(KickReason.gameover); if(mode != ShuffleMode.off){ + Call.onInfoMessage("Game over!"); if(world.getSector() == null){ if(world.maps().all().size > 0){ Array maps = mode == ShuffleMode.both ? world.maps().all() : @@ -103,9 +106,9 @@ public class ServerControl extends Module{ info("Selected next map to be {0}.", map.name); - logic.reset(); - world.loadMap(map); - state.set(State.playing); + Map fmap = map; + + play(() -> world.loadMap(fmap)); } }else{ if(gameOvers >= 2){ @@ -118,6 +121,7 @@ public class ServerControl extends Module{ info("Re-trying sector map: {0} {1}", Settings.getInt("sector_x"), Settings.getInt("sector_y")); } }else{ + netServer.kickAll(KickReason.gameover); state.set(State.menu); Net.closeServer(); } @@ -845,8 +849,26 @@ public class ServerControl extends Module{ if(world.sectors().get(x, y) == null){ world.sectors().createSector(x, y); } - world.loadSector(world.sectors().get(x, y)); + + world.sectors().get(x, y).completedMissions = 0; + + play(() -> world.loadSector(world.sectors().get(x, y))); + } + + private void play(Runnable run){ + Array players = new Array<>(); + for(Player p : playerGroup.all()){ + players.add(p); + p.setDead(true); + } + logic.reset(); + Call.onWorldDataBegin(); + run.run(); logic.play(); + for(Player p : players){ + p.add(); + netServer.sendWorldData(p, p.con.id); + } } private void host(){ @@ -864,6 +886,7 @@ public class ServerControl extends Module{ if(state.is(State.playing) && world.getSector() != null){ //all assigned missions are complete if(world.getSector().completedMissions >= world.getSector().missions.size){ + Log.info("Mission complete."); world.sectors().completeSector(world.getSector().x, world.getSector().y); world.sectors().save(); gameOvers = 0;