From 3c36749990f613789469d9bdb4625496d51dfcc8 Mon Sep 17 00:00:00 2001 From: Anuken Date: Tue, 17 Nov 2020 09:39:28 -0500 Subject: [PATCH] Implemented automatic co-op sector change sync --- core/assets/bundles/bundle.properties | 2 + core/src/mindustry/content/Planets.java | 12 ++++ core/src/mindustry/core/Control.java | 16 +++-- .../graphics/g3d/PlanetRenderer.java | 2 +- .../maps/planet/TantrosPlanetGenerator.java | 21 +++++++ core/src/mindustry/net/WorldReloader.java | 59 +++++++++++++++++++ core/src/mindustry/type/Planet.java | 4 +- .../mindustry/ui/dialogs/GameOverDialog.java | 51 +++++++++------- .../android/en-US/changelogs/29706.txt | 3 + .../src/mindustry/server/ServerControl.java | 24 ++------ 10 files changed, 146 insertions(+), 48 deletions(-) create mode 100644 core/src/mindustry/maps/planet/TantrosPlanetGenerator.java create mode 100644 core/src/mindustry/net/WorldReloader.java create mode 100644 fastlane/metadata/android/en-US/changelogs/29706.txt diff --git a/core/assets/bundles/bundle.properties b/core/assets/bundles/bundle.properties index c63f22c407..f0bd63ccee 100644 --- a/core/assets/bundles/bundle.properties +++ b/core/assets/bundles/bundle.properties @@ -17,7 +17,9 @@ linkfail = Failed to open link!\nThe URL has been copied to your clipboard. screenshot = Screenshot saved to {0} screenshot.invalid = Map too large, potentially not enough memory for screenshot. gameover = Game Over +gameover.disconnect = Disconnect gameover.pvp = The[accent] {0}[] team is victorious! +gameover.waiting = [accent]Waiting for next map... highscore = [accent]New highscore! copied = Copied. indev.popup = [accent]v6[] is currently in [accent]beta[].\n[lightgray]This means:[]\n[scarlet]- The campaign is unfinished[]\n- Everything you see is subject to change or removal.\n\nReport bugs or crashes on [accent]Github[]. diff --git a/core/src/mindustry/content/Planets.java b/core/src/mindustry/content/Planets.java index da7e05b7f5..57f8dbe728 100644 --- a/core/src/mindustry/content/Planets.java +++ b/core/src/mindustry/content/Planets.java @@ -9,6 +9,7 @@ import mindustry.type.*; public class Planets implements ContentList{ public static Planet sun, + //tantros, serpulo; @Override @@ -32,6 +33,17 @@ public class Planets implements ContentList{ ); }}; + /*tantros = new Planet("tantros", sun, 2, 0.8f){{ + generator = new TantrosPlanetGenerator(); + meshLoader = () -> new HexMesh(this, 4); + atmosphereColor = Color.valueOf("3db899"); + startSector = 10; + atmosphereRadIn = -0.01f; + atmosphereRadOut = 0.3f; + accessible = false; + visible = false; + }};*/ + serpulo = new Planet("serpulo", sun, 3, 1){{ generator = new SerpuloPlanetGenerator(); meshLoader = () -> new HexMesh(this, 6); diff --git a/core/src/mindustry/core/Control.java b/core/src/mindustry/core/Control.java index 168ba1ec74..ffb45b182f 100644 --- a/core/src/mindustry/core/Control.java +++ b/core/src/mindustry/core/Control.java @@ -22,6 +22,7 @@ import mindustry.input.*; import mindustry.io.*; import mindustry.io.SaveIO.*; import mindustry.maps.Map; +import mindustry.net.*; import mindustry.type.*; import mindustry.ui.dialogs.*; import mindustry.world.*; @@ -162,7 +163,7 @@ public class Control implements ApplicationListener, Loadable{ Events.on(GameOverEvent.class, e -> { if(state.isCampaign() && !net.client() && !headless){ - //delete the save, it is gone. + //save gameover sate immediately if(saves.getCurrent() != null && !state.rules.tutorial){ saves.getCurrent().save(); } @@ -279,6 +280,10 @@ public class Control implements ApplicationListener, Loadable{ } public void playSector(@Nullable Sector origin, Sector sector){ + playSector(origin, sector, new WorldReloader()); + } + + void playSector(@Nullable Sector origin, Sector sector, WorldReloader reloader){ ui.loadAnd(() -> { if(saves.getCurrent() != null && state.isGame()){ control.saves.getCurrent().save(); @@ -291,7 +296,7 @@ public class Control implements ApplicationListener, Loadable{ if(slot != null && !clearSectors){ try{ - net.reset(); + reloader.begin(); slot.load(); slot.setAutosave(true); state.rules.sector = sector; @@ -305,7 +310,7 @@ public class Control implements ApplicationListener, Loadable{ sector.save = null; slot.delete(); //play again - playSector(origin, sector); + playSector(origin, sector, reloader); return; } @@ -331,6 +336,7 @@ public class Control implements ApplicationListener, Loadable{ } state.set(State.playing); + reloader.end(); }catch(SaveException e){ Log.err(e); @@ -341,8 +347,7 @@ public class Control implements ApplicationListener, Loadable{ } ui.planet.hide(); }else{ - net.reset(); - logic.reset(); + reloader.begin(); world.loadSector(sector); state.rules.sector = sector; //assign origin when launching @@ -352,6 +357,7 @@ public class Control implements ApplicationListener, Loadable{ control.saves.saveSector(sector); Events.fire(new SectorLaunchEvent(sector)); Events.fire(Trigger.newGame); + reloader.end(); } }); } diff --git a/core/src/mindustry/graphics/g3d/PlanetRenderer.java b/core/src/mindustry/graphics/g3d/PlanetRenderer.java index 708ae4cb22..46fcef4edf 100644 --- a/core/src/mindustry/graphics/g3d/PlanetRenderer.java +++ b/core/src/mindustry/graphics/g3d/PlanetRenderer.java @@ -167,7 +167,7 @@ public class PlanetRenderer implements Disposable{ Vec3 center = planet.parent.position; float radius = planet.orbitRadius; - int points = (int)(radius * 50); + int points = (int)(radius * 10); Angles.circleVectors(points, radius, (cx, cy) -> batch.vertex(Tmp.v32.set(center).add(cx, 0, cy), Pal.gray)); batch.flush(Gl.lineLoop); } diff --git a/core/src/mindustry/maps/planet/TantrosPlanetGenerator.java b/core/src/mindustry/maps/planet/TantrosPlanetGenerator.java new file mode 100644 index 0000000000..fc8f23fd88 --- /dev/null +++ b/core/src/mindustry/maps/planet/TantrosPlanetGenerator.java @@ -0,0 +1,21 @@ +package mindustry.maps.planet; + +import arc.graphics.*; +import arc.math.*; +import arc.math.geom.*; +import mindustry.maps.generators.*; + +public class TantrosPlanetGenerator extends PlanetGenerator{ + Color c1 = Color.valueOf("5057a6"), c2 = Color.valueOf("272766"), out = new Color(); + + @Override + public float getHeight(Vec3 position){ + return 0; + } + + @Override + public Color getColor(Vec3 position){ + float depth = (float)noise.octaveNoise3D(2, 0.56, 1.7f, position.x, position.y, position.z) / 1.7f; + return c1.write(out).lerp(c2, Mathf.clamp(Mathf.round(depth, 0.15f))).a(0.6f); + } +} diff --git a/core/src/mindustry/net/WorldReloader.java b/core/src/mindustry/net/WorldReloader.java new file mode 100644 index 0000000000..23515aae87 --- /dev/null +++ b/core/src/mindustry/net/WorldReloader.java @@ -0,0 +1,59 @@ +package mindustry.net; + +import arc.struct.*; +import arc.struct.Seq.*; +import mindustry.gen.*; + +import static mindustry.Vars.*; + +/** Handles player state for sending to every connected player*/ +public class WorldReloader{ + Seq players = new Seq<>(); + boolean wasServer = false; + boolean began = false; + + /** Begins reloading the world. Sends world begin packets to each user and stores player state. + * If the current client is not a server, this resets state and disconnects. */ + public void begin(){ + //don't begin twice + if(began) return; + + if(wasServer = net.server()){ + players.clear(); + + for(Player p : Groups.player){ + if(p.isLocal()) continue; + + players.add(p); + p.clearUnit(); + } + + logic.reset(); + + Call.worldDataBegin(); + }else{ + net.reset(); + logic.reset(); + } + + began = true; + } + + /** Ends reloading the world. Sends world data to each player. + * If the current client was not a server, does nothing.*/ + public void end(){ + if(wasServer){ + for(Player p : players){ + if(p.con == null) continue; + + boolean wasAdmin = p.admin; + p.reset(); + p.admin = wasAdmin; + if(state.rules.pvp){ + p.team(netServer.assignTeam(p, new SeqIterable<>(players))); + } + netServer.sendWorldData(p); + } + } + } +} diff --git a/core/src/mindustry/type/Planet.java b/core/src/mindustry/type/Planet.java index eb345baa38..b1cb5f8a26 100644 --- a/core/src/mindustry/type/Planet.java +++ b/core/src/mindustry/type/Planet.java @@ -53,6 +53,8 @@ public class Planet extends UnlockableContent{ public int startSector = 0; /** Whether the bloom render effect is enabled. */ public boolean bloom = false; + /** Whether this planet is displayed. */ + public boolean visible = true; /** For suns, this is the color that shines on other planets. Does nothing for children. */ public Color lightColor = Color.white.cpy(); /** Atmosphere tint for landable planets. */ @@ -266,7 +268,7 @@ public class Planet extends UnlockableContent{ } public boolean visible(){ - return true; + return visible; } public void draw(Mat3D projection, Mat3D transform){ diff --git a/core/src/mindustry/ui/dialogs/GameOverDialog.java b/core/src/mindustry/ui/dialogs/GameOverDialog.java index 949125b93a..4c704f4f8e 100644 --- a/core/src/mindustry/ui/dialogs/GameOverDialog.java +++ b/core/src/mindustry/ui/dialogs/GameOverDialog.java @@ -1,6 +1,7 @@ package mindustry.ui.dialogs; import arc.*; +import mindustry.core.GameState.*; import mindustry.game.EventType.*; import mindustry.game.*; import mindustry.type.*; @@ -15,6 +16,8 @@ public class GameOverDialog extends BaseDialog{ super("@gameover"); setFillParent(true); shown(this::rebuild); + + Events.on(ResetEvent.class, e -> hide()); } public void show(Team winner){ @@ -49,47 +52,51 @@ public class GameOverDialog extends BaseDialog{ cont.pane(t -> { t.margin(13f); t.left().defaults().left(); - t.add(Core.bundle.format("stat.wave", state.stats.wavesLasted)); - t.row(); - t.add(Core.bundle.format("stat.enemiesDestroyed", state.stats.enemyUnitsDestroyed)); - t.row(); - t.add(Core.bundle.format("stat.built", state.stats.buildingsBuilt)); - t.row(); - t.add(Core.bundle.format("stat.destroyed", state.stats.buildingsDestroyed)); - t.row(); - t.add(Core.bundle.format("stat.deconstructed", state.stats.buildingsDeconstructed)); - t.row(); + t.add(Core.bundle.format("stat.wave", state.stats.wavesLasted)).row(); + t.add(Core.bundle.format("stat.enemiesDestroyed", state.stats.enemyUnitsDestroyed)).row(); + t.add(Core.bundle.format("stat.built", state.stats.buildingsBuilt)).row(); + t.add(Core.bundle.format("stat.destroyed", state.stats.buildingsDestroyed)).row(); + t.add(Core.bundle.format("stat.deconstructed", state.stats.buildingsDeconstructed)).row(); if(control.saves.getCurrent() != null){ - t.add(Core.bundle.format("stat.playtime", control.saves.getCurrent().getPlayTime())); - t.row(); + t.add(Core.bundle.format("stat.playtime", control.saves.getCurrent().getPlayTime())).row(); } if(state.isCampaign() && !state.stats.itemsDelivered.isEmpty()){ - t.add("@stat.delivered"); - t.row(); + t.add("@stat.delivered").row(); for(Item item : content.items()){ if(state.stats.itemsDelivered.get(item, 0) > 0){ t.table(items -> { items.add(" [lightgray]" + state.stats.itemsDelivered.get(item, 0)); items.image(item.icon(Cicon.small)).size(8 * 3).pad(4); - }).left(); - t.row(); + }).left().row(); } } } + if(state.isCampaign() && net.client()){ + t.add("@gameover.waiting").padTop(20f).row(); + } + }).pad(12); if(state.isCampaign()){ - buttons.button("@continue", () -> { - hide(); - logic.reset(); - ui.planet.show(); - }).size(130f, 60f); + if(net.client()){ + buttons.button("@gameover.disconnect", () -> { + logic.reset(); + net.reset(); + hide(); + state.set(State.menu); + }).size(170f, 60f); + }else{ + buttons.button("@continue", () -> { + hide(); + ui.planet.show(); + }).size(170f, 60f); + } }else{ buttons.button("@menu", () -> { hide(); logic.reset(); - }).size(130f, 60f); + }).size(140f, 60f); } } } diff --git a/fastlane/metadata/android/en-US/changelogs/29706.txt b/fastlane/metadata/android/en-US/changelogs/29706.txt new file mode 100644 index 0000000000..ab381c91e6 --- /dev/null +++ b/fastlane/metadata/android/en-US/changelogs/29706.txt @@ -0,0 +1,3 @@ +- Fixed file chooser crash [Android] +- Fixed time stopping after sector capture +- Moved Ruinous Shores map to more approppriate location diff --git a/server/src/mindustry/server/ServerControl.java b/server/src/mindustry/server/ServerControl.java index 57200d7178..c1683f42c8 100644 --- a/server/src/mindustry/server/ServerControl.java +++ b/server/src/mindustry/server/ServerControl.java @@ -3,7 +3,6 @@ package mindustry.server; import arc.*; import arc.files.*; import arc.struct.*; -import arc.struct.Seq.*; import arc.util.*; import arc.util.Timer; import arc.util.CommandHandler.*; @@ -22,6 +21,7 @@ import mindustry.maps.Maps.*; import mindustry.mod.Mods.*; import mindustry.net.Administration.*; import mindustry.net.Packets.*; +import mindustry.net.*; import mindustry.type.*; import java.io.*; @@ -964,30 +964,16 @@ public class ServerControl implements ApplicationListener{ private void play(boolean wait, Runnable run){ inExtraRound = true; Runnable r = () -> { - Seq players = new Seq<>(); - for(Player p : Groups.player){ - players.add(p); - p.clearUnit(); - } + var reloader = new WorldReloader(); - logic.reset(); + reloader.begin(); - Call.worldDataBegin(); run.run(); + state.rules = state.map.applyRules(lastMode); logic.play(); - for(Player p : players){ - if(p.con == null) continue; - - boolean wasAdmin = p.admin; - p.reset(); - p.admin = wasAdmin; - if(state.rules.pvp){ - p.team(netServer.assignTeam(p, new SeqIterable<>(players))); - } - netServer.sendWorldData(p); - } + reloader.end(); inExtraRound = false; };