diff --git a/.gitignore b/.gitignore index 58d2076cc4..7f9cd9abe6 100644 --- a/.gitignore +++ b/.gitignore @@ -10,6 +10,7 @@ /desktop/gifexport/ /core/lib/ /kryonet/build/ +/server/build/ /android/assets/mindustry-maps/ /android/assets/mindustry-saves/ /core/assets/gifexport/ diff --git a/android/src/io/anuke/mindustry/AndroidLauncher.java b/android/src/io/anuke/mindustry/AndroidLauncher.java index be320a49f5..77b79e5c31 100644 --- a/android/src/io/anuke/mindustry/AndroidLauncher.java +++ b/android/src/io/anuke/mindustry/AndroidLauncher.java @@ -11,7 +11,7 @@ import com.badlogic.gdx.backends.android.AndroidApplication; import com.badlogic.gdx.backends.android.AndroidApplicationConfiguration; import io.anuke.kryonet.KryoClient; import io.anuke.kryonet.KryoServer; -import io.anuke.mindustry.io.PlatformFunction; +import io.anuke.mindustry.io.Platform; import io.anuke.mindustry.net.Net; import io.anuke.ucore.scene.ui.TextField; import io.anuke.ucore.scene.ui.layout.Unit; @@ -24,7 +24,6 @@ import java.util.Locale; public class AndroidLauncher extends AndroidApplication{ boolean doubleScaleTablets = true; - int WRITE_REQUEST_CODE = 1; @Override @@ -33,11 +32,15 @@ public class AndroidLauncher extends AndroidApplication{ AndroidApplicationConfiguration config = new AndroidApplicationConfiguration(); config.useImmersiveMode = true; - - Mindustry.hasDiscord = isPackageInstalled("com.discord"); - Mindustry.platforms = new PlatformFunction(){ + + Platform.instance = new Platform(){ DateFormat format = SimpleDateFormat.getDateTimeInstance(); + @Override + public boolean hasDiscord() { + return isPackageInstalled("com.discord"); + } + @Override public String format(Date date){ return format.format(date); diff --git a/build.gradle b/build.gradle index 15d43a075c..129a12bd77 100644 --- a/build.gradle +++ b/build.gradle @@ -22,7 +22,7 @@ allprojects { appName = "Mindustry" gdxVersion = '1.9.8' aiVersion = '1.8.1' - uCoreVersion = 'ab9f87c' + uCoreVersion = '4dee898' } repositories { @@ -113,6 +113,17 @@ project(":core") { } } +project(":server") { + apply plugin: "java" + + dependencies { + compile project(":core") + compile project(":kryonet") + compile "com.badlogicgames.gdx:gdx-backend-headless:$gdxVersion" + compile "com.badlogicgames.gdx:gdx-platform:$gdxVersion:natives-desktop" + } +} + project(":kryonet") { apply plugin: "java" diff --git a/core/assets/bundles/bundle.properties b/core/assets/bundles/bundle.properties index e95a85c40f..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! @@ -95,6 +95,7 @@ text.enemies={0} Enemies text.enemies.single={0} Enemy text.loadimage=Load Image text.saveimage=Save Image +text.oregen=Ore Generation text.editor.badsize=[orange]Invalid image dimensions![]\nValid map dimensions: {0} text.editor.errorimageload=Error loading image file:\n[orange]{0} text.editor.errorimagesave=Error saving image file:\n[orange]{0} diff --git a/core/assets/ui/uiskin.json b/core/assets/ui/uiskin.json index e5359e086b..5a83f28256 100644 --- a/core/assets/ui/uiskin.json +++ b/core/assets/ui/uiskin.json @@ -97,7 +97,7 @@ io.anuke.ucore.scene.ui.Label$LabelStyle: { menuitem-shortcut: {font: default-font, fontColor: menuitem } }, io.anuke.ucore.scene.ui.TextField$TextFieldStyle: { - default: {font: default-font, fontColor: white, disabledFontColor: grey, selection: selection, background: button, cursor: cursor, messageFont: default-font, messageFontColor: grey } + default: {font: default-font-chat, fontColor: white, disabledFontColor: grey, selection: selection, background: button, cursor: cursor, messageFont: default-font, messageFontColor: grey } } io.anuke.ucore.scene.ui.CheckBox$CheckBoxStyle: { default: {checkboxOn: check-on, checkboxOff: check-off, checkboxOnOver: check-on-over, checkboxOver: check-over, font: default-font, fontColor: white, disabledFontColor: grey } diff --git a/core/src/io/anuke/mindustry/Mindustry.java b/core/src/io/anuke/mindustry/Mindustry.java index 571f125284..2e978ad57c 100644 --- a/core/src/io/anuke/mindustry/Mindustry.java +++ b/core/src/io/anuke/mindustry/Mindustry.java @@ -1,106 +1,28 @@ package io.anuke.mindustry; -import com.badlogic.gdx.Gdx; -import com.badlogic.gdx.files.FileHandle; -import com.badlogic.gdx.utils.Array; -import com.badlogic.gdx.utils.I18NBundle; import io.anuke.mindustry.core.*; -import io.anuke.mindustry.core.GameState.State; -import io.anuke.mindustry.io.PlatformFunction; -import io.anuke.mindustry.net.Net; -import io.anuke.mindustry.world.BlockLoader; -import io.anuke.ucore.UCore; -import io.anuke.ucore.core.Core; -import io.anuke.ucore.core.Inputs; -import io.anuke.ucore.core.Settings; -import io.anuke.ucore.core.Timers; +import io.anuke.mindustry.io.BlockLoader; +import io.anuke.mindustry.io.BundleLoader; import io.anuke.ucore.modules.ModuleCore; +import io.anuke.ucore.util.Log; -import java.util.Locale; +import static io.anuke.mindustry.Vars.*; public class Mindustry extends ModuleCore { - public static boolean hasDiscord = true; - public static Array args = new Array<>(); - public static PlatformFunction platforms = new PlatformFunction(){}; - public static boolean externalBundle = false; - + @Override public void init(){ - Settings.defaults("locale", "default"); - Settings.load("io.anuke.moment"); - loadBundle(); + Log.setUseColors(false); + BundleLoader.load(); BlockLoader.load(); - module(Vars.world = new World()); - module(Vars.control = new Control()); - module(Vars.renderer = new Renderer()); - module(Vars.ui = new UI()); - module(Vars.netServer = new NetServer()); - module(Vars.netClient = new NetClient()); - } - - @Override - public void dispose() { - GameState.set(State.menu); - platforms.onGameExit(); - Net.dispose(); - super.dispose(); - } - - public Locale getLocale(){ - String loc = Settings.getString("locale"); - if(loc.equals("default")){ - return Locale.getDefault(); - }else{ - Locale lastLocale; - if (loc.contains("_")) { - String[] split = loc.split("_"); - lastLocale = new Locale(split[0], split[1]); - } else { - lastLocale = new Locale(loc); - } - - return lastLocale; - } - } - - public void loadBundle(){ - I18NBundle.setExceptionOnMissingKey(false); - - if(externalBundle){ - try { - FileHandle handle = Gdx.files.local("bundle"); - - Locale locale = Locale.ENGLISH; - Core.bundle = I18NBundle.createBundle(handle, locale); - }catch (Exception e){ - UCore.error(e); - platforms.showError("Failed to find bundle!\nMake sure you have bundle.properties in the same directory\nas the jar file.\n\nIf the problem persists, try running it through the command prompt:\n" + - "Hold left-shift, then right click and select 'open command prompt here'.\nThen, type in 'java -jar mindustry.jar' without quotes."); - Gdx.app.exit(); - } - }else{ - FileHandle handle = Gdx.files.internal("bundles/bundle"); - - Locale locale = getLocale(); - UCore.log("Got locale: " + locale); - Core.bundle = I18NBundle.createBundle(handle, locale); - } - } - - @Override - public void postInit(){ - Vars.control.reset(); - } - - @Override - public void render(){ - super.render(); - - if(!GameState.is(State.paused) || Net.active()){ - Timers.update(); - } - - Inputs.update(); + module(logic = new Logic()); + module(world = new World()); + module(control = new Control()); + module(renderer = new Renderer()); + module(ui = new UI()); + module(netServer = new NetServer()); + module(netClient = new NetClient()); + module(netCommon = new NetCommon()); } } diff --git a/core/src/io/anuke/mindustry/MindustryServer.java b/core/src/io/anuke/mindustry/MindustryServer.java new file mode 100644 index 0000000000..f4aba94386 --- /dev/null +++ b/core/src/io/anuke/mindustry/MindustryServer.java @@ -0,0 +1,25 @@ +package io.anuke.mindustry; + +import io.anuke.mindustry.core.*; +import io.anuke.mindustry.io.BlockLoader; +import io.anuke.mindustry.io.BundleLoader; +import io.anuke.ucore.modules.ModuleCore; + +import static io.anuke.mindustry.Vars.*; + +public class MindustryServer extends ModuleCore { + + @Override + public void init(){ + headless = true; + + BundleLoader.load(); + BlockLoader.load(); + + module(logic = new Logic()); + module(world = new World()); + module(netServer = new NetServer()); + module(netCommon = new NetCommon()); + module(serverControl = new ServerControl()); + } +} diff --git a/core/src/io/anuke/mindustry/Vars.java b/core/src/io/anuke/mindustry/Vars.java index c37b09c776..6fe1a0228b 100644 --- a/core/src/io/anuke/mindustry/Vars.java +++ b/core/src/io/anuke/mindustry/Vars.java @@ -3,10 +3,17 @@ package io.anuke.mindustry; import com.badlogic.gdx.Application.ApplicationType; import com.badlogic.gdx.Gdx; import com.badlogic.gdx.files.FileHandle; - import io.anuke.mindustry.core.*; +import io.anuke.mindustry.entities.Bullet; 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; import io.anuke.ucore.scene.ui.layout.Unit; public class Vars{ @@ -43,7 +50,8 @@ public class Vars{ 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 debugNet = true; + public static boolean console = false; //whether the player can clip through walls public static boolean noclip = false; //whether to draw chunk borders @@ -57,6 +65,8 @@ public class Vars{ //whether to hide ui, only on debug public static boolean showUI = true; + public static boolean headless = false; + public static float controllerMin = 0.25f; public static float baseControllerSpeed = 11f; @@ -68,21 +78,32 @@ public class Vars{ //only if smoothCamera public static boolean snapCamera = true; - //turret and enemy shootInternal speed inverse multiplier - public static final float multiplier = android ? 3 : 2; - public static final int tilesize = 8; //server port public static final int port = 6567; public static final int webPort = 6568; - + + 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; public static UI ui; public static World world; + public static NetCommon netCommon; public static NetServer netServer; public static NetClient netClient; + public static ServerControl serverControl; public static Player player; + + public static final EntityGroup playerGroup = Entities.addGroup(Player.class).enableMapping(); + public static final EntityGroup enemyGroup = Entities.addGroup(Enemy.class).enableMapping(); + public static final EntityGroup tileGroup = Entities.addGroup(TileEntity.class, false); + public static final EntityGroup bulletGroup = Entities.addGroup(Bullet.class); + public static final EntityGroup shieldGroup = Entities.addGroup(Shield.class); } diff --git a/core/src/io/anuke/mindustry/ai/Heuristics.java b/core/src/io/anuke/mindustry/ai/Heuristics.java index c4c8f982b8..3a2e7885cb 100644 --- a/core/src/io/anuke/mindustry/ai/Heuristics.java +++ b/core/src/io/anuke/mindustry/ai/Heuristics.java @@ -1,11 +1,12 @@ package io.anuke.mindustry.ai; import com.badlogic.gdx.ai.pfa.Heuristic; -import io.anuke.mindustry.Vars; import io.anuke.mindustry.world.Block; import io.anuke.mindustry.world.Tile; import io.anuke.ucore.function.Predicate; +import static io.anuke.mindustry.Vars.tilesize; + public class Heuristics { /**How many times more it costs to go through a destructible block than an empty block.*/ static final float solidMultiplier = 5f; @@ -23,11 +24,11 @@ public class Heuristics { //If either one of the tiles is a breakable solid block (that is, it's player-made), //increase the cost by the tilesize times the solid block multiplier //Also add the block health, so blocks with more health cost more to traverse - if(node.breakable() && node.block().solid) cost += Vars.tilesize* solidMultiplier + node.block().health; - if(other.breakable() && other.block().solid) cost += Vars.tilesize* solidMultiplier + other.block().health; + if(node.breakable() && node.block().solid) cost += tilesize* solidMultiplier + node.block().health; + if(other.breakable() && other.block().solid) cost += tilesize* solidMultiplier + other.block().health; //if this block has solid blocks near it, increase the cost, as we don't want enemies hugging walls - if(node.occluded) cost += Vars.tilesize*occludedMultiplier; + if(node.occluded) cost += tilesize*occludedMultiplier; return cost; } @@ -50,11 +51,11 @@ public class Heuristics { //If either one of the tiles is a breakable solid block (that is, it's player-made), //increase the cost by the tilesize times the solid block multiplier //Also add the block health, so blocks with more health cost more to traverse - if(node.breakable() && node.block().solid) cost += Vars.tilesize* solidMultiplier + node.block().health; - if(other.breakable() && other.block().solid) cost += Vars.tilesize* solidMultiplier + other.block().health; + if(node.breakable() && node.block().solid) cost += tilesize* solidMultiplier + node.block().health; + if(other.breakable() && other.block().solid) cost += tilesize* solidMultiplier + other.block().health; //if this block has solid blocks near it, increase the cost, as we don't want enemies hugging walls - if(node.occluded) cost += Vars.tilesize*occludedMultiplier; + if(node.occluded) cost += tilesize*occludedMultiplier; if(other.getLinked() != null) other = other.getLinked(); if(node.getLinked() != null) node = node.getLinked(); diff --git a/core/src/io/anuke/mindustry/ai/Pathfind.java b/core/src/io/anuke/mindustry/ai/Pathfind.java index 3a83166a24..cf39c79c20 100644 --- a/core/src/io/anuke/mindustry/ai/Pathfind.java +++ b/core/src/io/anuke/mindustry/ai/Pathfind.java @@ -4,16 +4,17 @@ import com.badlogic.gdx.ai.pfa.PathFinderRequest; import com.badlogic.gdx.ai.pfa.PathSmoother; import com.badlogic.gdx.math.MathUtils; import com.badlogic.gdx.math.Vector2; -import io.anuke.mindustry.Vars; import io.anuke.mindustry.entities.enemies.Enemy; import io.anuke.mindustry.game.SpawnPoint; import io.anuke.mindustry.world.Tile; -import io.anuke.ucore.UCore; import io.anuke.ucore.core.Timers; import io.anuke.ucore.util.Angles; +import io.anuke.ucore.util.Log; import io.anuke.ucore.util.Mathf; import io.anuke.ucore.util.Tmp; +import static io.anuke.mindustry.Vars.*; + public class Pathfind{ /**Maximum time taken per frame on pathfinding for a single path.*/ private static final long maxTime = 1000000 * 5; @@ -39,11 +40,11 @@ public class Pathfind{ enemy.node = -1; } - if(enemy.node < 0 || Vars.control.getSpawnPoints().get(enemy.lane).pathTiles == null){ + if(enemy.node < 0 || world.getSpawns().get(enemy.lane).pathTiles == null){ return vector.set(enemy.x, enemy.y); } - Tile[] path = Vars.control.getSpawnPoints().get(enemy.lane).pathTiles; + Tile[] path = world.getSpawns().get(enemy.lane).pathTiles; if(enemy.node >= path.length){ enemy.node = -1; @@ -60,7 +61,7 @@ public class Pathfind{ Tile target = path[enemy.node]; //a bridge has been broken, re-path - if(!Vars.world.passable(target.x, target.y)){ + if(!world.passable(target.x, target.y)){ remakePath(); return vector.set(enemy.x, enemy.y); } @@ -108,8 +109,8 @@ public class Pathfind{ /**Re-calculate paths for all enemies. Runs when a path changes while moving.*/ private void remakePath(){ - for(int i = 0; i < Vars.control.enemyGroup.amount(); i ++){ - Enemy enemy = Vars.control.enemyGroup.all().get(i); + for(int i = 0; i < enemyGroup.size(); i ++){ + Enemy enemy = enemyGroup.all().get(i); enemy.node = -1; } @@ -121,9 +122,9 @@ public class Pathfind{ public void update(){ //go through each spawnpoint, and if it's not found a path yet, update it - for(SpawnPoint point : Vars.control.getSpawnPoints()){ - if(point.request == null){ - resetPathFor(point); + for(SpawnPoint point : world.getSpawns()){ + if(point.request == null || point.finder == null){ + continue; } if(!point.request.pathFound){ @@ -145,26 +146,26 @@ public class Pathfind{ //1300-1500ms, usually 1400 unoptimized on Caldera /**Benchmark pathfinding speed. Debugging stuff.*/ public void benchmark(){ - SpawnPoint point = Vars.control.getSpawnPoints().first(); + SpawnPoint point = world.getSpawns().first(); int amount = 100; //warmup for(int i = 0; i < 100; i ++){ - point.finder.searchNodePath(point.start, Vars.control.getCore(), Vars.control.getDifficulty().heuristic, point.path); + point.finder.searchNodePath(point.start, world.getCore(), state.difficulty.heuristic, point.path); point.path.clear(); } Timers.mark(); for(int i = 0; i < amount; i ++){ - point.finder.searchNodePath(point.start, Vars.control.getCore(), Vars.control.getDifficulty().heuristic, point.path); + point.finder.searchNodePath(point.start, world.getCore(), state.difficulty.heuristic, point.path); point.path.clear(); } - UCore.log("Time elapsed: " + Timers.elapsed() + "ms\nAverage MS per path: " + Timers.elapsed()/amount); + Log.info("Time elapsed: {0}ms\nAverage MS per path: {1}", Timers.elapsed(), Timers.elapsed()/amount); } /**Reset and clear the paths.*/ public void resetPaths(){ - for(SpawnPoint point : Vars.control.getSpawnPoints()){ + for(SpawnPoint point : world.getSpawns()){ resetPathFor(point); } } @@ -176,21 +177,21 @@ public class Pathfind{ point.pathTiles = null; - point.request = new PathFinderRequest<>(point.start, Vars.control.getCore(), Vars.control.getDifficulty().heuristic, point.path); + point.request = new PathFinderRequest<>(point.start, world.getCore(), state.difficulty.heuristic, point.path); point.request.statusChanged = true; //IMPORTANT! } /**For an enemy that was just loaded from a save, find the node in the path it should be following.*/ void findNode(Enemy enemy){ - if(enemy.lane >= Vars.control.getSpawnPoints().size || enemy.lane < 0){ + if(enemy.lane >= world.getSpawns().size || enemy.lane < 0){ enemy.lane = 0; } - if(Vars.control.getSpawnPoints().get(enemy.lane).pathTiles == null){ + if(world.getSpawns().get(enemy.lane).pathTiles == null){ return; } - Tile[] path = Vars.control.getSpawnPoints().get(enemy.lane).pathTiles; + Tile[] path = world.getSpawns().get(enemy.lane).pathTiles; int closest = findClosest(path, enemy.x, enemy.y); diff --git a/core/src/io/anuke/mindustry/ai/Raycaster.java b/core/src/io/anuke/mindustry/ai/Raycaster.java index e012820ee9..31005103a1 100644 --- a/core/src/io/anuke/mindustry/ai/Raycaster.java +++ b/core/src/io/anuke/mindustry/ai/Raycaster.java @@ -5,7 +5,7 @@ import com.badlogic.gdx.ai.utils.Ray; import com.badlogic.gdx.ai.utils.RaycastCollisionDetector; import com.badlogic.gdx.math.Vector2; -import io.anuke.mindustry.Vars; +import static io.anuke.mindustry.Vars.*; import io.anuke.mindustry.world.Tile; import io.anuke.ucore.util.Geometry; import io.anuke.ucore.util.Mathf; @@ -17,7 +17,7 @@ public class Raycaster implements RaycastCollisionDetector{ public boolean collides(Ray ray){ found = false; - Geometry.iterateLine(0f, ray.start.x, ray.start.y, ray.end.x, ray.end.y, Vars.tilesize, (x, y)->{ + Geometry.iterateLine(0f, ray.start.x, ray.start.y, ray.end.x, ray.end.y, tilesize, (x, y)->{ if(solid(x, y)){ found = true; return; @@ -71,7 +71,7 @@ public class Raycaster implements RaycastCollisionDetector{ } private boolean solid(float x, float y){ - Tile tile = Vars.world.tile(Mathf.scl2(x, Vars.tilesize), Mathf.scl2(y, Vars.tilesize)); + Tile tile = world.tile(Mathf.scl2(x, tilesize), Mathf.scl2(y, tilesize)); if(tile == null || tile.solid()) return true; diff --git a/core/src/io/anuke/mindustry/ai/TileGraph.java b/core/src/io/anuke/mindustry/ai/TileGraph.java index 1bc156e85b..710cdadafc 100644 --- a/core/src/io/anuke/mindustry/ai/TileGraph.java +++ b/core/src/io/anuke/mindustry/ai/TileGraph.java @@ -2,7 +2,7 @@ package io.anuke.mindustry.ai; import com.badlogic.gdx.ai.pfa.Connection; import com.badlogic.gdx.utils.Array; -import io.anuke.mindustry.Vars; +import static io.anuke.mindustry.Vars.*; import io.anuke.mindustry.world.Tile; /**Tilegraph that ignores player-made tiles.*/ @@ -31,6 +31,6 @@ public class TileGraph implements OptimizedGraph { @Override public int getNodeCount(){ - return Vars.world.width() * Vars.world.height(); + return world.width() * world.height(); } } diff --git a/core/src/io/anuke/mindustry/core/Control.java b/core/src/io/anuke/mindustry/core/Control.java index 145e28ae9c..7f24463d93 100644 --- a/core/src/io/anuke/mindustry/core/Control.java +++ b/core/src/io/anuke/mindustry/core/Control.java @@ -1,102 +1,58 @@ package io.anuke.mindustry.core; -import com.badlogic.gdx.Application.ApplicationType; import com.badlogic.gdx.Gdx; import com.badlogic.gdx.Input.Buttons; -import com.badlogic.gdx.Input.Keys; -import com.badlogic.gdx.utils.Array; -import io.anuke.mindustry.Mindustry; -import io.anuke.mindustry.Vars; import io.anuke.mindustry.core.GameState.State; -import io.anuke.mindustry.entities.Bullet; 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.entities.enemies.EnemyTypes; -import io.anuke.mindustry.game.*; +import io.anuke.mindustry.input.DefaultKeybinds; +import io.anuke.mindustry.game.EventType.*; +import io.anuke.mindustry.game.Tutorial; +import io.anuke.mindustry.game.UpgradeInventory; import io.anuke.mindustry.graphics.Fx; import io.anuke.mindustry.input.AndroidInput; import io.anuke.mindustry.input.DesktopInput; import io.anuke.mindustry.input.InputHandler; +import io.anuke.mindustry.io.Platform; import io.anuke.mindustry.io.Saves; import io.anuke.mindustry.net.Net; -import io.anuke.mindustry.resource.Item; -import io.anuke.mindustry.resource.ItemStack; import io.anuke.mindustry.resource.Weapon; -import io.anuke.mindustry.world.Block; import io.anuke.mindustry.world.Map; -import io.anuke.mindustry.world.Tile; -import io.anuke.mindustry.world.blocks.ProductionBlocks; import io.anuke.ucore.UCore; import io.anuke.ucore.core.*; -import io.anuke.ucore.core.Inputs.Axis; import io.anuke.ucore.core.Inputs.DeviceType; import io.anuke.ucore.entities.Entities; -import io.anuke.ucore.entities.EntityGroup; -import io.anuke.ucore.graphics.Lines; 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; -import java.util.Arrays; - import static io.anuke.mindustry.Vars.*; +/**Control module. + * Handles all input, saving, keybinds and keybinds. + * Should not handle any game-critical state. + * This class is not created in the headless server.*/ public class Control extends Module{ - Tutorial tutorial = new Tutorial(); - boolean hiscore = false; - - final Array weapons = new Array<>(); - final int[] items = new int[Item.getAllItems().size]; + private UpgradeInventory upgrades = new UpgradeInventory(); + private Tutorial tutorial = new Tutorial(); + private boolean hiscore = false; - public final EntityGroup playerGroup = Entities.addGroup(Player.class).enableMapping(); - public final EntityGroup enemyGroup = Entities.addGroup(Enemy.class).enableMapping(); - public final EntityGroup tileGroup = Entities.addGroup(TileEntity.class, false); - public final EntityGroup bulletGroup = Entities.addGroup(Bullet.class); - public final EntityGroup shieldGroup = Entities.addGroup(Shield.class); - - Array spawns; - int wave = 1; - int lastUpdated = -1; - float wavetime; - float extrawavetime; - int enemies = 0; - GameMode mode = GameMode.waves; - Difficulty difficulty = Difficulty.normal; - - Tile core; - Array spawnpoints = new Array<>(); - boolean shouldUpdateItems = false; - boolean wasPaused = false; + private boolean wasPaused = false; - Saves saves; + private Saves saves; - float respawntime; - InputHandler input; - boolean friendlyFire; + private float respawntime; + private InputHandler input; private InputProxy proxy; private float controlx, controly; private boolean controlling; public Control(){ - if(Mindustry.args.contains("-debug", false)) - Vars.debug = true; saves = new Saves(); - Inputs.useControllers(!Vars.gwt); - - log("Total blocks loaded: " + Block.getAllBlocks().size); - - for(Block block : Block.getAllBlocks()){ - block.postInit(); - } - - Lines.setCircleVertices(14); + Inputs.useControllers(!gwt); Gdx.input.setCatchBackKey(true); @@ -142,134 +98,94 @@ public class Control extends Module{ Sounds.setFalloff(9000f); Musics.load("1.ogg", "2.ogg", "3.ogg", "4.ogg"); - - KeyBinds.defaults( - "move_x", new Axis(Input.A, Input.D), - "move_y", new Axis(Input.S, Input.W), - "select", Input.MOUSE_LEFT, - "break", Input.MOUSE_RIGHT, - "shoot", Input.MOUSE_LEFT, - "zoom_hold", Input.CONTROL_LEFT, - "zoom", new Axis(Input.SCROLL), - "menu", Gdx.app.getType() == ApplicationType.Android ? Input.BACK : Input.ESCAPE, - "pause", Input.SPACE, - "dash", Input.SHIFT_LEFT, - "rotate_alt", new Axis(Input.R, Input.E), - "rotate", new Axis(Input.SCROLL), - "player_list", Input.TAB, - "chat", Input.ENTER, - "weapon_1", Input.NUM_1, - "weapon_2", Input.NUM_2, - "weapon_3", Input.NUM_3, - "weapon_4", Input.NUM_4, - "weapon_5", Input.NUM_5, - "weapon_6", Input.NUM_6 - ); - KeyBinds.defaults( - DeviceType.controller, - "move_x", new Axis(Input.CONTROLLER_L_STICK_HORIZONTAL_AXIS), - "move_y", new Axis(Input.CONTROLLER_L_STICK_VERTICAL_AXIS), - "cursor_x", new Axis(Input.CONTROLLER_R_STICK_HORIZONTAL_AXIS), - "cursor_y", new Axis(Input.CONTROLLER_R_STICK_VERTICAL_AXIS), - "select", Input.CONTROLLER_R_BUMPER, - "break", Input.CONTROLLER_L_BUMPER, - "shoot", Input.CONTROLLER_R_TRIGGER, - "zoom_hold", Input.ANY_KEY, - "zoom", new Axis(Input.CONTROLLER_DPAD_DOWN, Input.CONTROLLER_DPAD_UP), - "menu", Input.CONTROLLER_X, - "pause", Input.CONTROLLER_L_TRIGGER, - "dash", Input.CONTROLLER_Y, - "rotate_alt", new Axis(Input.CONTROLLER_DPAD_RIGHT, Input.CONTROLLER_DPAD_LEFT), - "rotate", new Axis(Input.CONTROLLER_A, Input.CONTROLLER_B), - "player_list", Input.CONTROLLER_START, - "chat", Input.ENTER, - "weapon_1", Input.NUM_1, - "weapon_2", Input.NUM_2, - "weapon_3", Input.NUM_3, - "weapon_4", Input.NUM_4, - "weapon_5", Input.NUM_5, - "weapon_6", Input.NUM_6 - ); + DefaultKeybinds.load(); - for(int i = 0; i < Vars.saveSlots; i ++){ - Settings.defaults("save-" + i + "-autosave", !Vars.gwt); + for(int i = 0; i < saveSlots; i ++){ + Settings.defaults("save-" + i + "-autosave", !gwt); Settings.defaults("save-" + i + "-name", "untitled"); Settings.defaults("save-" + i + "-data", "empty"); } Settings.defaultList( "ip", "localhost", - "port", Vars.port+"", - "name", Vars.android || Vars.gwt ? "player" : UCore.getProperty("user.name"), + "port", port+"", + "name", android || gwt ? "player" : UCore.getProperty("user.name"), "servers", "" ); KeyBinds.load(); - for(Map map : Vars.world.maps().list()){ + for(Map map : world.maps().list()){ Settings.defaults("hiscore" + map.name, 0); } player = new Player(); player.name = Settings.getString("name"); - player.isAndroid = Vars.android; + player.isAndroid = android; player.isLocal = true; - - spawns = WaveCreator.getSpawns(); saves.load(); + + Events.on(StateChangeEvent.class, (from, to) -> { + if((from == State.playing && to == State.menu) || (from == State.menu && to != State.menu)){ + Timers.runTask(5f, Platform.instance::updateRPC); + } + }); + + Events.on(PlayEvent.class, () -> { + renderer.clearTiles(); + + player.set(world.getSpawnX(), world.getSpawnY()); + + Core.camera.position.set(player.x, player.y, 0); + + ui.hudfrag.updateItems(); + + state.set(State.playing); + }); + + Events.on(ResetEvent.class, () -> { + player.weaponLeft = player.weaponRight = Weapon.blaster; + + player.add(); + player.heal(); + + respawntime = -1; + hiscore = false; + + ui.hudfrag.updateItems(); + ui.hudfrag.updateWeapons(); + }); + + Events.on(WaveEvent.class, () -> { + Sounds.play("spawn"); + + int last = Settings.getInt("hiscore" + world.getMap().name); + + if(state.wave > last && !state.mode.infiniteResources && !state.mode.toggleWaves){ + Settings.putInt("hiscore" + world.getMap().name, state.wave); + Settings.save(); + hiscore = true; + } + + Platform.instance.updateRPC(); + }); + + Events.on(GameOverEvent.class, () -> { + Effects.shake(5, 6, Core.camera.position.x, Core.camera.position.y); + 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()); + + ui.restart.show(); + }); } - - public void reset(){ - weapons.clear(); - - weapons.add(Weapon.blaster); - player.weaponLeft = player.weaponRight = weapons.first(); - - lastUpdated = -1; - wave = 1; - extrawavetime = maxwavespace; - wavetime = waveSpacing(); - Entities.clear(); - enemies = 0; - player.add(); - - player.heal(); - clearItems(); - spawnpoints.clear(); - respawntime = -1; - hiscore = false; - - for(Block block : Block.getAllBlocks()){ - block.onReset(); - } - - ui.hudfrag.updateItems(); - ui.hudfrag.updateWeapons(); - } - - public void play(){ - if(core == null) return; - renderer.clearTiles(); - - player.x = core.worldx(); - player.y = core.worldy() - Vars.tilesize*2; - - Core.camera.position.set(player.x, player.y, 0); - - //multiplying by 2 so you start with more time in the beginning - wavetime = waveSpacing()*2; - - //hacky, but I doubt anyone will use this many resources - if(mode.infiniteResources){ - Arrays.fill(items, 999999999); - } - - ui.hudfrag.updateItems(); - - GameState.set(State.playing); + public UpgradeInventory upgrades() { + return upgrades; } public Saves getSaves(){ @@ -279,179 +195,28 @@ public class Control extends Module{ public boolean showCursor(){ return controlling; } - - public boolean isFriendlyFire() { - return friendlyFire; - } - - public void setFriendlyFire(boolean friendlyFire) { - if(this.friendlyFire != friendlyFire && Net.active() && Net.server()){ - Vars.netServer.handleFriendlyFireChange(friendlyFire); - } - this.friendlyFire = friendlyFire; - } - - public Tile getCore(){ - return core; - } - public Array getSpawnPoints(){ - return spawnpoints; - } - - public void setCore(Tile tile){ - this.core = tile; - } - - public InputHandler getInput(){ + public InputHandler input(){ return input; } - public void addSpawnPoint(Tile tile){ - SpawnPoint point = new SpawnPoint(); - point.start = tile; - spawnpoints.add(point); - } - public void playMap(Map map){ ui.loadfrag.show(); saves.resetSave(); Timers.run(16, ()->{ - reset(); + logic.reset(); world.loadMap(map); - play(); + logic.play(); }); Timers.run(18, ()-> ui.loadfrag.hide()); } - public GameMode getMode(){ - return mode; - } - - public void setMode(GameMode mode){ - this.mode = mode; - } - - public boolean hasWeapon(Weapon weapon){ - return weapons.contains(weapon, true); - } - - public void addWeapon(Weapon weapon){ - weapons.add(weapon); - } - - public Array getWeapons(){ - return weapons; - } - - public void setWaveData(int enemies, int wave, float wavetime){ - this.wave = wave; - this.wavetime = wavetime; - this.enemies = enemies; - this.extrawavetime = maxwavespace; - } - - public void runWave(){ - - if(Net.client() && Net.active()){ - return; - } - - Sounds.play("spawn"); - - if(lastUpdated < wave + 1){ - world.pathfinder().resetPaths(); - lastUpdated = wave + 1; - } - - for(EnemySpawn spawn : spawns){ - for(int lane = 0; lane < spawnpoints.size; lane ++){ - int fl = lane; - Tile tile = spawnpoints.get(lane).start; - int spawnamount = spawn.evaluate(wave, lane); - - for(int i = 0; i < spawnamount; i ++){ - float range = 12f; - - Timers.run(i*5f, () -> { - - Enemy enemy = new Enemy(spawn.type); - enemy.set(tile.worldx() + Mathf.range(range), tile.worldy() + Mathf.range(range)); - enemy.lane = fl; - enemy.tier = spawn.tier(wave, fl); - enemy.add(); - - Effects.effect(Fx.spawn, enemy); - - enemies ++; - }); - } - } - } - - wave ++; - - int last = Settings.getInt("hiscore" + world.getMap().name); - - if(wave > last && !mode.infiniteResources && !mode.toggleWaves){ - Settings.putInt("hiscore" + world.getMap().name, wave); - Settings.save(); - hiscore = true; - } - - wavetime = waveSpacing(); - extrawavetime = maxwavespace; - - Mindustry.platforms.updateRPC(); - } - - public void enemyDeath(){ - enemies --; - } - - public void coreDestroyed(){ - - Effects.shake(5, 6, Core.camera.position.x, Core.camera.position.y); - Sounds.play("corexplode"); - for(int i = 0; i < 16; i ++){ - Timers.run(i*2, ()-> Effects.effect(Fx.explosion, core.worldx()+Mathf.range(40), core.worldy()+Mathf.range(40))); - } - Effects.effect(Fx.coreexplosion, core.worldx(), core.worldy()); - - ui.restart.show(); - if(Net.active() && Net.server()) netServer.handleGameOver(); - } - - public boolean isGameOver(){ - return core != null && core.block() != ProductionBlocks.core; - } - - float waveSpacing(){ - return wavespace*getDifficulty().timeScaling; - } - - public Difficulty getDifficulty(){ - return difficulty; - } - - public void setDifficulty(Difficulty d){ - this.difficulty = d; - } - public boolean isHighScore(){ return hiscore; } - - public int getEnemiesRemaining(){ - return enemies; - } - - public float getWaveCountdown(){ - return wavetime; - } - + public float getRespawnTime(){ return respawntime; } @@ -460,80 +225,26 @@ public class Control extends Module{ this.respawntime = respawntime; } - public int getWave(){ - return wave; - } - - public Tutorial getTutorial(){ + public Tutorial tutorial(){ return tutorial; } - - public void clearItems(){ - Arrays.fill(items, 0); - - addItem(Item.stone, 40); - - if(debug){ - Arrays.fill(items, 99999); - } - } - - public int getAmount(Item item){ - return items[item.id]; - } - - public void addItem(Item item, int amount){ - items[item.id] += amount; - shouldUpdateItems = true; - } - - public boolean hasItems(ItemStack[] items){ - for(ItemStack stack : items) - if(!hasItem(stack)) - return false; - return true; - } - - public boolean hasItems(ItemStack[] items, int scaling){ - for(ItemStack stack : items) - if(!hasItem(stack.item, stack.amount * scaling)) - return false; - return true; - } - - public boolean hasItem(ItemStack req){ - return items[req.item.id] >= req.amount; - } - - public boolean hasItem(Item item, int amount){ - return items[item.id] >= amount; - } - - public void removeItem(ItemStack req){ - items[req.item.id] -= req.amount; - if(items[req.item.id] < 0) items[req.item.id] = 0; //prevents negative item glitches in multiplayer - shouldUpdateItems = true; - } - - public void removeItems(ItemStack... reqs){ - for(ItemStack req : reqs) - removeItem(req); - } - - public int[] getItems(){ - return items; + + @Override + public void dispose(){ + Platform.instance.onGameExit(); + Net.dispose(); } @Override public void pause(){ - wasPaused = GameState.is(State.paused); - if(GameState.is(State.playing)) GameState.set(State.paused); + wasPaused = state.is(State.paused); + if(state.is(State.playing)) state.set(State.paused); } @Override public void resume(){ - if(GameState.is(State.paused) && !wasPaused){ - GameState.set(State.playing); + if(state.is(State.paused) && !wasPaused){ + state.set(State.playing); } } @@ -545,7 +256,7 @@ public class Control extends Module{ Entities.collisions().setCollider(tilesize, world::solid); - Mindustry.platforms.updateRPC(); + Platform.instance.updateRPC(); } @Override @@ -555,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); @@ -567,10 +282,10 @@ public class Control extends Module{ float xa = Inputs.getAxis("cursor_x"); float ya = Inputs.getAxis("cursor_y"); - if(Math.abs(xa) > Vars.controllerMin || Math.abs(ya) > Vars.controllerMin) { + if(Math.abs(xa) > controllerMin || Math.abs(ya) > controllerMin) { float scl = Settings.getInt("sensitivity")/100f * Unit.dp.scl(1f); - controlx += xa*Vars.baseControllerSpeed*scl; - controly -= ya*Vars.baseControllerSpeed*scl; + controlx += xa*baseControllerSpeed*scl; + controly -= ya*baseControllerSpeed*scl; controlling = true; Inputs.getProcessor().touchDragged(Gdx.input.getX(), Gdx.input.getY(), 0); @@ -592,86 +307,40 @@ public class Control extends Module{ saves.update(); - if(debug && GameState.is(State.playing)){ - //debug actions - if(Inputs.keyTap(Keys.P)){ - Effects.effect(Fx.shellsmoke, player); - Effects.effect(Fx.shellexplosion, player); - } - - if(Inputs.keyTap(Keys.C)){ - enemyGroup.clear(); - enemies = 0; - } - - if(Inputs.keyTap(Keys.F)){ - wavetime = 0f; - } - - if(Inputs.keyTap(Keys.G)){ - Vars.world.pathfinder().benchmark(); - } - - if(Inputs.keyDown(Keys.I)){ - wavetime -= delta() * 10f; - } - - if(Inputs.keyTap(Keys.U)){ - Vars.showPaths = !Vars.showPaths; - } - - if(Inputs.keyTap(Keys.O)){ - Vars.noclip = !Vars.noclip; - } - - if(Inputs.keyTap(Keys.Y)){ - if(Inputs.keyDown(Keys.SHIFT_LEFT)){ - new Enemy(EnemyTypes.healer).set(player.x, player.y).add(); - }else{ - float px = player.x, py = player.y; - Timers.run(30f, ()-> new Enemy(EnemyTypes.fortress).set(px, py).add()); - } - } - } - - if(shouldUpdateItems && (Timers.get("updateItems", 8) || GameState.is(State.paused))){ + if(state.inventory.isUpdated() && (Timers.get("updateItems", 8) || state.is(State.paused))){ ui.hudfrag.updateItems(); - shouldUpdateItems = false; + state.inventory.setUpdated(false); } - if(!GameState.is(State.menu)){ + if(!state.is(State.menu)){ input.update(); - - if(core.block() != ProductionBlocks.core && !ui.restart.isShown()){ - coreDestroyed(); - } - if(Inputs.keyTap("pause") && !ui.restart.isShown() && !Net.active() && (GameState.is(State.paused) || GameState.is(State.playing))){ - GameState.set(GameState.is(State.playing) ? State.paused : State.playing); + if(Inputs.keyTap("pause") && !ui.restart.isShown() && !Net.active() && (state.is(State.paused) || state.is(State.playing))){ + state.set(state.is(State.playing) ? State.paused : State.playing); } if(Inputs.keyTap("menu")){ - if(GameState.is(State.paused)){ + if(state.is(State.paused)){ ui.paused.hide(); - GameState.set(State.playing); + state.set(State.playing); }else if (!ui.restart.isShown()){ if(ui.chatfrag.chatOpen()) { ui.chatfrag.hide(); }else{ ui.paused.show(); - GameState.set(State.paused); + state.set(State.paused); } } } - if(!GameState.is(State.paused) || Net.active()){ + if(!state.is(State.paused) || Net.active()){ if(respawntime > 0){ respawntime -= delta(); if(respawntime <= 0){ - player.set(core.worldx(), core.worldy()-Vars.tilesize*2); + player.set(world.getSpawnX(), world.getSpawnY()); player.heal(); player.add(); Effects.sound("respawn"); @@ -682,35 +351,8 @@ public class Control extends Module{ if(tutorial.active()){ tutorial.update(); } - - if(!tutorial.active() && !mode.toggleWaves){ - - if(enemies <= 0){ - wavetime -= delta(); - - if(lastUpdated < wave + 1 && wavetime < Vars.aheadPathfinding){ //start updating beforehand - world.pathfinder().resetPaths(); - lastUpdated = wave + 1; - } - }else{ - extrawavetime -= delta(); - } - } - - if(wavetime <= 0 || extrawavetime <= 0){ - runWave(); - } - - Entities.update(Entities.defaultGroup()); - Entities.update(bulletGroup); - Entities.update(enemyGroup); - Entities.update(tileGroup); - Entities.update(shieldGroup); - Entities.update(playerGroup); - - Entities.collideGroups(enemyGroup, bulletGroup); - Entities.collideGroups(playerGroup, bulletGroup); } } + } } diff --git a/core/src/io/anuke/mindustry/core/GameState.java b/core/src/io/anuke/mindustry/core/GameState.java index c4b1951573..b8c2010342 100644 --- a/core/src/io/anuke/mindustry/core/GameState.java +++ b/core/src/io/anuke/mindustry/core/GameState.java @@ -1,21 +1,33 @@ package io.anuke.mindustry.core; -import io.anuke.mindustry.Mindustry; -import io.anuke.ucore.core.Timers; +import io.anuke.mindustry.game.Difficulty; +import io.anuke.mindustry.game.EventType.StateChangeEvent; +import io.anuke.mindustry.game.GameMode; +import io.anuke.mindustry.game.Inventory; +import io.anuke.ucore.core.Events; public class GameState{ - private static State state = State.menu; + private State state = State.menu; + + public final Inventory inventory = new Inventory(); + + public int wave = 1; + public int lastUpdated = -1; + public float wavetime; + public float extrawavetime; + public int enemies = 0; + public boolean gameOver = false; + public GameMode mode = GameMode.waves; + public Difficulty difficulty = Difficulty.normal; + public boolean friendlyFire; - public static void set(State astate){ - - if((astate == State.playing && state == State.menu) || (astate == State.menu && state != State.menu)){ - Timers.runTask(5f, Mindustry.platforms::updateRPC); - } - + public void set(State astate){ + //TODO update RPC handler + Events.fire(StateChangeEvent.class, state, astate); state = astate; } - public static boolean is(State astate){ + public boolean is(State astate){ return state == astate; } diff --git a/core/src/io/anuke/mindustry/core/Logic.java b/core/src/io/anuke/mindustry/core/Logic.java new file mode 100644 index 0000000000..fafb3bfc9c --- /dev/null +++ b/core/src/io/anuke/mindustry/core/Logic.java @@ -0,0 +1,152 @@ +package io.anuke.mindustry.core; + +import com.badlogic.gdx.utils.Array; +import io.anuke.mindustry.Vars; +import io.anuke.mindustry.core.GameState.State; +import io.anuke.mindustry.entities.enemies.Enemy; +import io.anuke.mindustry.game.EnemySpawn; +import io.anuke.mindustry.game.EventType.GameOverEvent; +import io.anuke.mindustry.game.EventType.PlayEvent; +import io.anuke.mindustry.game.EventType.ResetEvent; +import io.anuke.mindustry.game.SpawnPoint; +import io.anuke.mindustry.game.WaveCreator; +import io.anuke.mindustry.graphics.Fx; +import io.anuke.mindustry.net.Net; +import io.anuke.mindustry.net.NetEvents; +import io.anuke.mindustry.world.Tile; +import io.anuke.mindustry.world.blocks.ProductionBlocks; +import io.anuke.ucore.core.Effects; +import io.anuke.ucore.core.Events; +import io.anuke.ucore.core.Timers; +import io.anuke.ucore.entities.Entities; +import io.anuke.ucore.modules.Module; +import io.anuke.ucore.util.Mathf; + +import static io.anuke.mindustry.Vars.*; + +/**Logic module. + * Handles all logic for entities and waves. + * Handles game state events. + * Does not store any game state itself. + * + * This class should not call any outside methods to change state of modules, but instead fire events. + */ +public class Logic extends Module { + private final Array spawns = WaveCreator.getSpawns(); + + @Override + public void init(){ + Entities.initPhysics(); + Entities.collisions().setCollider(tilesize, world::solid); + } + + public void play(){ + state.wavetime = wavespace * state.difficulty.timeScaling * 2; + + if(state.mode.infiniteResources){ + state.inventory.fill(); + } + + Events.fire(PlayEvent.class); + } + + public void reset(){ + state.wave = 1; + state.extrawavetime = maxwavespace; + state.wavetime = wavespace * state.difficulty.timeScaling; + state.enemies = 0; + state.lastUpdated = -1; + state.gameOver = false; + state.inventory.clearItems(); + + Entities.clear(); + + Events.fire(ResetEvent.class); + } + + public void runWave(){ + + if(state.lastUpdated < state.wave + 1){ + world.pathfinder().resetPaths(); + state.lastUpdated = state.wave + 1; + } + + for(EnemySpawn spawn : spawns){ + Array spawns = world.getSpawns(); + + for(int lane = 0; lane < spawns.size; lane ++){ + int fl = lane; + Tile tile = spawns.get(lane).start; + int spawnamount = spawn.evaluate(state.wave, lane); + + for(int i = 0; i < spawnamount; i ++){ + float range = 12f; + + Timers.run(i*5f, () -> { + + Enemy enemy = new Enemy(spawn.type); + enemy.set(tile.worldx() + Mathf.range(range), tile.worldy() + Mathf.range(range)); + enemy.lane = fl; + enemy.tier = spawn.tier(state.wave, fl); + enemy.add(); + + Effects.effect(Fx.spawn, enemy); + + state.enemies ++; + }); + } + } + } + + state.wave ++; + state.wavetime = wavespace * state.difficulty.timeScaling; + state.extrawavetime = maxwavespace; + } + + @Override + public void update(){ + if(!state.is(State.paused) || Net.active()){ + Timers.update(); + } + + if(!state.is(State.menu)){ + + if(world.getCore().block() != ProductionBlocks.core && !state.gameOver){ + state.gameOver = true; + NetEvents.handleGameOver(); + Events.fire(GameOverEvent.class); + } + + if(!state.is(State.paused) || Net.active()){ + + if(!state.mode.toggleWaves){ + + if(state.enemies <= 0){ + state.wavetime -= delta(); + + if(state.lastUpdated < state.wave + 1 && state.wavetime < Vars.aheadPathfinding){ //start updating beforehand + world.pathfinder().resetPaths(); + state.lastUpdated = state.wave + 1; + } + }else{ + state.extrawavetime -= delta(); + } + } + + if(!Net.client() && (state.wavetime <= 0 || state.extrawavetime <= 0)){ + runWave(); + } + + Entities.update(Entities.defaultGroup()); + Entities.update(bulletGroup); + Entities.update(enemyGroup); + Entities.update(tileGroup); + Entities.update(shieldGroup); + Entities.update(playerGroup); + + Entities.collideGroups(enemyGroup, bulletGroup); + Entities.collideGroups(playerGroup, bulletGroup); + } + } + } +} diff --git a/core/src/io/anuke/mindustry/core/NetClient.java b/core/src/io/anuke/mindustry/core/NetClient.java index e7c66c9499..cdaabb1ebf 100644 --- a/core/src/io/anuke/mindustry/core/NetClient.java +++ b/core/src/io/anuke/mindustry/core/NetClient.java @@ -1,12 +1,8 @@ package io.anuke.mindustry.core; import com.badlogic.gdx.Gdx; -import com.badlogic.gdx.graphics.Color; -import com.badlogic.gdx.graphics.Pixmap; import com.badlogic.gdx.utils.IntSet; import com.badlogic.gdx.utils.TimeUtils; -import io.anuke.mindustry.Mindustry; -import io.anuke.mindustry.Vars; import io.anuke.mindustry.core.GameState.State; import io.anuke.mindustry.entities.Bullet; import io.anuke.mindustry.entities.BulletType; @@ -15,17 +11,15 @@ import io.anuke.mindustry.entities.SyncEntity; import io.anuke.mindustry.entities.enemies.Enemy; import io.anuke.mindustry.entities.enemies.EnemyType; import io.anuke.mindustry.graphics.Fx; +import io.anuke.mindustry.io.Platform; import io.anuke.mindustry.net.Net; import io.anuke.mindustry.net.Net.SendMode; import io.anuke.mindustry.net.NetworkIO; import io.anuke.mindustry.net.Packets.*; -import io.anuke.mindustry.resource.Recipe; -import io.anuke.mindustry.resource.Recipes; import io.anuke.mindustry.resource.Upgrade; import io.anuke.mindustry.resource.Weapon; -import io.anuke.mindustry.world.Block; +import io.anuke.mindustry.world.Map; import io.anuke.mindustry.world.Tile; -import io.anuke.ucore.UCore; import io.anuke.ucore.core.Effects; import io.anuke.ucore.core.Timers; import io.anuke.ucore.entities.BaseBulletType; @@ -33,90 +27,91 @@ import io.anuke.ucore.entities.Entities; import io.anuke.ucore.entities.Entity; import io.anuke.ucore.entities.EntityGroup; import io.anuke.ucore.modules.Module; +import io.anuke.ucore.util.Log; import java.io.DataInputStream; import java.io.IOException; import java.nio.ByteBuffer; -import static io.anuke.mindustry.Vars.ui; +import static io.anuke.mindustry.Vars.*; public class NetClient extends Module { - public static final Color[] colorArray = {Color.ORANGE, Color.SCARLET, Color.LIME, Color.PURPLE, - Color.GOLD, Color.PINK, Color.SKY, Color.GOLD, Color.VIOLET, - Color.GREEN, Color.CORAL, Color.CYAN, Color.CHARTREUSE}; boolean connecting = false; boolean gotData = false; boolean kicked = false; IntSet recieved = new IntSet(); + IntSet dead = new IntSet(); float playerSyncTime = 2; float dataTimeout = 60*18; //18 seconds timeout public NetClient(){ - Net.handle(Connect.class, packet -> { + Net.handleClient(Connect.class, packet -> { Net.setClientLoaded(false); recieved.clear(); + dead.clear(); connecting = true; gotData = false; kicked = false; - Vars.ui.loadfrag.hide(); - Vars.ui.loadfrag.show("$text.connecting.data"); + ui.loadfrag.hide(); + ui.loadfrag.show("$text.connecting.data"); Entities.clear(); ConnectPacket c = new ConnectPacket(); - c.name = Vars.player.name; - c.android = Vars.android; + c.name = player.name; + c.android = android; Net.send(c, SendMode.tcp); Timers.runTask(dataTimeout, () -> { if (!gotData) { Gdx.app.error("Mindustry", "Failed to load data!"); - Vars.ui.loadfrag.hide(); + ui.loadfrag.hide(); Net.disconnect(); } }); }); - Net.handle(Disconnect.class, packet -> { + Net.handleClient(Disconnect.class, packet -> { if (kicked) return; - Timers.runFor(3f, Vars.ui.loadfrag::hide); + Timers.runFor(3f, ui.loadfrag::hide); - GameState.set(State.menu); + state.set(State.menu); - Vars.ui.showError("$text.disconnect"); + ui.showError("$text.disconnect"); connecting = false; - Mindustry.platforms.updateRPC(); + Platform.instance.updateRPC(); }); - Net.handle(WorldData.class, data -> { - UCore.log("Recieved world data: " + data.stream.available() + " bytes."); + Net.handleClient(WorldData.class, data -> { + Log.info("Recieved world data: {0} bytes.", data.stream.available()); NetworkIO.loadWorld(data.stream); - Vars.player.set(Vars.control.core.worldx(), Vars.control.core.worldy() - Vars.tilesize * 2); - UCore.log(Vars.control.core); + player.set(world.getSpawnX(), world.getSpawnY()); gotData = true; finishConnecting(); }); - Net.handle(CustomMapPacket.class, packet -> { - UCore.log("Recieved custom map: " + packet.stream.available() + " bytes."); + Net.handleClient(CustomMapPacket.class, packet -> { + Log.info("Recieved custom map: {0} bytes.", packet.stream.available()); //custom map is always sent before world data - Pixmap pixmap = NetworkIO.loadMap(packet.stream); + Map map = NetworkIO.loadMap(packet.stream); - Vars.world.maps().setNetworkMap(pixmap); + world.maps().setNetworkMap(map); MapAckPacket ack = new MapAckPacket(); Net.send(ack, SendMode.tcp); }); - Net.handle(SyncPacket.class, packet -> { + Net.handleClient(SyncPacket.class, packet -> { if (!gotData) return; + int players = 0; + int enemies = 0; ByteBuffer data = ByteBuffer.wrap(packet.data); @@ -129,9 +124,11 @@ public class NetClient extends Module { SyncEntity entity = (SyncEntity) group.getByID(id); - if (entity == null || id == Vars.player.id) { - if (id != Vars.player.id) { - UCore.log("Requesting entity " + id, "group " + group.getType()); + if(entity instanceof Player) players ++; + if(entity instanceof Enemy) enemies ++; + + if (entity == null || id == player.id) { + if (id != player.id) { EntityRequestPacket req = new EntityRequestPacket(); req.id = id; Net.send(req, SendMode.udp); @@ -141,44 +138,34 @@ public class NetClient extends Module { entity.read(data); } } + + if(debugNet){ + clientDebug.setSyncDebug(players, enemies); + } }); - Net.handle(ShootPacket.class, packet -> { - Player player = Vars.control.playerGroup.getByID(packet.playerid); + Net.handleClient(StateSyncPacket.class, packet -> { - Weapon weapon = (Weapon) Upgrade.getByID(packet.weaponid); - weapon.shoot(player, packet.x, packet.y, packet.rotation); - }); + System.arraycopy(packet.items, 0, state.inventory.getItems(), 0, packet.items.length); - Net.handle(PlacePacket.class, packet -> { - Recipe recipe = Recipes.getByResult(Block.getByID(packet.block)); - if (recipe != null) Vars.control.removeItems(recipe.requirements); - Vars.control.input.placeBlockInternal(packet.x, packet.y, Block.getByID(packet.block), packet.rotation, true, false); - }); - - Net.handle(BreakPacket.class, packet -> { - Vars.control.input.breakBlockInternal(packet.x, packet.y, false); - }); - - Net.handle(StateSyncPacket.class, packet -> { - - System.arraycopy(packet.items, 0, Vars.control.items, 0, packet.items.length); - - Vars.control.setWaveData(packet.enemies, packet.wave, packet.countdown); + state.enemies = packet.enemies; + state.wavetime = packet.countdown; + state.wave = packet.wave; Timers.resetTime(packet.time + (float) (TimeUtils.timeSinceMillis(packet.timestamp) / 1000.0 * 60.0)); - Vars.ui.hudfrag.updateItems(); + ui.hudfrag.updateItems(); }); - Net.handle(EnemySpawnPacket.class, spawn -> { + Net.handleClient(EnemySpawnPacket.class, spawn -> { //duplicates. - if (Vars.control.enemyGroup.getByID(spawn.id) != null || - recieved.contains(spawn.id)) return; + if (enemyGroup.getByID(spawn.id) != null || + recieved.contains(spawn.id) || dead.contains(spawn.id)) return; 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; @@ -187,35 +174,38 @@ public class NetClient extends Module { enemy.add(); Effects.effect(Fx.spawn, enemy); + + Log.info("Recieved enemy {0}", spawn.id); }); - Net.handle(EnemyDeathPacket.class, spawn -> { - Enemy enemy = Vars.control.enemyGroup.getByID(spawn.id); - if (enemy != null) enemy.onDeath(); + Net.handleClient(EnemyDeathPacket.class, spawn -> { + Enemy enemy = enemyGroup.getByID(spawn.id); + if (enemy != null) enemy.type.onDeath(enemy, true); + dead.add(spawn.id); }); - Net.handle(BulletPacket.class, packet -> { + Net.handleClient(BulletPacket.class, packet -> { //TODO shoot effects for enemies, clientside as well as serverside BulletType type = (BulletType) BaseBulletType.getByID(packet.type); - Entity owner = Vars.control.enemyGroup.getByID(packet.owner); + Entity owner = enemyGroup.getByID(packet.owner); new Bullet(type, owner, packet.x, packet.y, packet.angle).add(); }); - Net.handle(BlockDestroyPacket.class, packet -> { - Tile tile = Vars.world.tile(packet.position % Vars.world.width(), packet.position / Vars.world.width()); + Net.handleClient(BlockDestroyPacket.class, packet -> { + Tile tile = world.tile(packet.position % world.width(), packet.position / world.width()); if (tile != null && tile.entity != null) { - if (tile.entity != null) tile.entity.onDeath(true); + tile.entity.onDeath(true); } }); - Net.handle(BlockUpdatePacket.class, packet -> { - Tile tile = Vars.world.tile(packet.position % Vars.world.width(), packet.position / Vars.world.width()); + Net.handleClient(BlockUpdatePacket.class, packet -> { + Tile tile = world.tile(packet.position % world.width(), packet.position / world.width()); if (tile != null && tile.entity != null) { tile.entity.health = packet.health; } }); - Net.handle(BlockSyncPacket.class, packet -> { + Net.handleClient(BlockSyncPacket.class, packet -> { if (!gotData) return; DataInputStream stream = new DataInputStream(packet.stream); @@ -229,7 +219,7 @@ public class NetClient extends Module { int pos = stream.readInt(); //TODO what if there's no entity? new code - Tile tile = Vars.world.tile(pos % Vars.world.width(), pos / Vars.world.width()); + Tile tile = world.tile(pos % world.width(), pos / world.width()); byte times = stream.readByte(); @@ -245,27 +235,28 @@ public class NetClient extends Module { } catch (IOException e) { throw new RuntimeException(e); } catch (Exception e) { - UCore.error(e); + Log.err(e); //do nothing else... //TODO fix } }); - Net.handle(DisconnectPacket.class, packet -> { - Player player = Vars.control.playerGroup.getByID(packet.playerid); + Net.handleClient(DisconnectPacket.class, packet -> { + Player player = playerGroup.getByID(packet.playerid); if (player != null) { player.remove(); } - Mindustry.platforms.updateRPC(); + Platform.instance.updateRPC(); }); - Net.handle(PlayerSpawnPacket.class, packet -> { + Net.handleClient(PlayerSpawnPacket.class, packet -> { //duplicates. - if (Vars.control.enemyGroup.getByID(packet.id) != null || + if (enemyGroup.getByID(packet.id) != null || recieved.contains(packet.id)) return; + recieved.add(packet.id); Player player = new Player(); @@ -281,58 +272,32 @@ public class NetClient extends Module { player.interpolator.target.set(player.x, player.y); player.add(); - Mindustry.platforms.updateRPC(); + Log.info("Recieved player {0}", packet.id); + + Platform.instance.updateRPC(); }); - Net.handle(ChatPacket.class, packet -> Vars.ui.chatfrag.addMessage(packet.text, Vars.netClient.colorizeName(packet.id, packet.name))); - - Net.handle(KickPacket.class, packet -> { + Net.handleClient(KickPacket.class, packet -> { kicked = true; Net.disconnect(); - GameState.set(State.menu); - Vars.ui.showError("$text.server.kicked." + packet.reason.name()); - Vars.ui.loadfrag.hide(); + state.set(State.menu); + ui.showError("$text.server.kicked." + packet.reason.name()); + ui.loadfrag.hide(); }); - Net.handle(WeaponSwitchPacket.class, packet -> { - Player player = Vars.control.playerGroup.getByID(packet.playerid); - - if (player == null) return; - - player.weaponLeft = (Weapon) Upgrade.getByID(packet.left); - player.weaponRight = (Weapon) Upgrade.getByID(packet.right); - }); - - Net.handle(BlockTapPacket.class, packet -> { - Tile tile = Vars.world.tile(packet.position); - if (tile != null) tile.block().tapped(tile); - }); - - Net.handle(BlockConfigPacket.class, packet -> { - Tile tile = Vars.world.tile(packet.position); - if (tile != null) tile.block().configure(tile, packet.data); - }); - - Net.handle(GameOverPacket.class, packet -> { + Net.handleClient(GameOverPacket.class, packet -> { kicked = true; ui.restart.show(); }); - Net.handle(FriendlyFireChangePacket.class, packet -> Vars.control.setFriendlyFire(packet.enabled)); - - Net.handle(PlayerDeathPacket.class, packet -> { - Player player = Vars.control.playerGroup.getByID(packet.id); - if(player == null) return; - - player.doRespawn(); - }); + Net.handleClient(FriendlyFireChangePacket.class, packet -> state.friendlyFire = packet.enabled); } @Override public void update(){ - if(!Net.client() || !Net.active()) return; + if(!Net.client()) return; - if(!GameState.is(State.menu) && Net.active()){ + if(!state.is(State.menu)){ if(gotData) sync(); }else if(!connecting){ Net.disconnect(); @@ -341,11 +306,11 @@ public class NetClient extends Module { private void finishConnecting(){ Net.send(new ConnectConfirmPacket(), SendMode.tcp); - GameState.set(State.playing); + state.set(State.playing); Net.setClientLoaded(true); connecting = false; - Vars.ui.loadfrag.hide(); - Vars.ui.join.hide(); + ui.loadfrag.hide(); + ui.join.hide(); } public void beginConnecting(){ @@ -357,85 +322,16 @@ public class NetClient extends Module { Net.disconnect(); } - public String colorizeName(int id, String name){ - return name == null ? null : "[#" + colorArray[id % colorArray.length].toString().toUpperCase() + "]" + name; - } - - public void handlePlayerDeath(){ - PlayerDeathPacket packet = new PlayerDeathPacket(); - packet.id = Vars.player.id; - Net.send(packet, SendMode.tcp); - } - - public void handleBlockConfig(Tile tile, byte data){ - BlockConfigPacket packet = new BlockConfigPacket(); - packet.data = data; - packet.position = tile.packedPosition(); - Net.send(packet, SendMode.tcp); - } - - public void handleBlockTap(Tile tile){ - BlockTapPacket packet = new BlockTapPacket(); - packet.position = tile.packedPosition(); - Net.send(packet, SendMode.tcp); - } - - public void handleWeaponSwitch(){ - WeaponSwitchPacket packet = new WeaponSwitchPacket(); - packet.left = Vars.player.weaponLeft.id; - packet.right = Vars.player.weaponRight.id; - packet.playerid = Vars.player.id; - Net.send(packet, SendMode.tcp); - } - - public void handleUpgrade(Weapon weapon){ - UpgradePacket packet = new UpgradePacket(); - packet.id = weapon.id; - Net.send(packet, SendMode.tcp); - } - - public void handleSendMessage(String message){ - ChatPacket packet = new ChatPacket(); - packet.text = message; - packet.name = Vars.player.name; - packet.id = Vars.player.id; - Net.send(packet, SendMode.tcp); - - Vars.ui.chatfrag.addMessage(packet.text, colorizeName(Vars.player.id, Vars.player.name)); - } - - public void handleShoot(Weapon weapon, float x, float y, float angle){ - ShootPacket packet = new ShootPacket(); - packet.weaponid = weapon.id; - packet.x = x; - packet.y = y; - packet.rotation = angle; - packet.playerid = Vars.player.id; - Net.send(packet, SendMode.udp); - } - - public void handlePlace(int x, int y, Block block, int rotation){ - PlacePacket packet = new PlacePacket(); - packet.x = (short)x; - packet.y = (short)y; - packet.rotation = (byte)rotation; - packet.playerid = Vars.player.id; - packet.block = block.id; - Net.send(packet, SendMode.tcp); - } - - public void handleBreak(int x, int y){ - BreakPacket packet = new BreakPacket(); - packet.x = (short)x; - packet.y = (short)y; - Net.send(packet, SendMode.tcp); + public void clearRecieved(){ + recieved.clear(); + dead.clear(); } void sync(){ if(Timers.get("syncPlayer", playerSyncTime)){ - byte[] bytes = new byte[Vars.player.getWriteSize()]; + byte[] bytes = new byte[player.getWriteSize()]; ByteBuffer buffer = ByteBuffer.wrap(bytes); - Vars.player.write(buffer); + player.write(buffer); PositionPacket packet = new PositionPacket(); packet.data = bytes; diff --git a/core/src/io/anuke/mindustry/core/NetCommon.java b/core/src/io/anuke/mindustry/core/NetCommon.java new file mode 100644 index 0000000000..4e2142e74a --- /dev/null +++ b/core/src/io/anuke/mindustry/core/NetCommon.java @@ -0,0 +1,91 @@ +package io.anuke.mindustry.core; + +import com.badlogic.gdx.graphics.Color; +import io.anuke.mindustry.entities.Player; +import io.anuke.mindustry.net.Net; +import io.anuke.mindustry.net.Net.SendMode; +import io.anuke.mindustry.net.Packets.*; +import io.anuke.mindustry.resource.Recipe; +import io.anuke.mindustry.resource.Recipes; +import io.anuke.mindustry.resource.Upgrade; +import io.anuke.mindustry.resource.Weapon; +import io.anuke.mindustry.world.Block; +import io.anuke.mindustry.world.Tile; +import io.anuke.ucore.modules.Module; + +import static io.anuke.mindustry.Vars.*; + +public class NetCommon extends Module { + public static final Color[] colorArray = {Color.ORANGE, Color.SCARLET, Color.LIME, Color.PURPLE, + Color.GOLD, Color.PINK, Color.SKY, Color.GOLD, Color.VIOLET, + Color.GREEN, Color.CORAL, Color.CYAN, Color.CHARTREUSE}; + + public NetCommon(){ + + Net.handle(ShootPacket.class, (packet) -> { + Player player = playerGroup.getByID(packet.playerid); + + Weapon weapon = (Weapon) Upgrade.getByID(packet.weaponid); + weapon.shoot(player, packet.x, packet.y, packet.rotation); + }); + + Net.handle(PlacePacket.class, (packet) -> { + if(headless) + world.placeBlock(packet.x, packet.y, Block.getByID(packet.block), packet.rotation); + else + control.input().placeBlockInternal(packet.x, packet.y, Block.getByID(packet.block), packet.rotation, true, false); + + Recipe recipe = Recipes.getByResult(Block.getByID(packet.block)); + if (recipe != null) state.inventory.removeItems(recipe.requirements); + }); + + Net.handle(BreakPacket.class, (packet) -> { + if(headless) + world.removeBlock(world.tile(packet.x, packet.y)); + else + control.input().breakBlockInternal(packet.x, packet.y, false); + }); + + Net.handle(ChatPacket.class, (packet) -> { + ui.chatfrag.addMessage(packet.text, colorizeName(packet.id, packet.name)); + }); + + Net.handle(WeaponSwitchPacket.class, (packet) -> { + Player player = playerGroup.getByID(packet.playerid); + + if (player == null) return; + + player.weaponLeft = (Weapon) Upgrade.getByID(packet.left); + player.weaponRight = (Weapon) Upgrade.getByID(packet.right); + }); + + Net.handle(BlockTapPacket.class, (packet) -> { + Tile tile = world.tile(packet.position); + tile.block().tapped(tile); + }); + + Net.handle(BlockConfigPacket.class, (packet) -> { + Tile tile = world.tile(packet.position); + if (tile != null) tile.block().configure(tile, packet.data); + }); + + Net.handle(PlayerDeathPacket.class, (packet) -> { + Player player = playerGroup.getByID(packet.id); + if(player == null) return; + + player.doRespawn(); + }); + } + + public void sendMessage(String message){ + ChatPacket packet = new ChatPacket(); + packet.name = null; + packet.text = message; + Net.send(packet, SendMode.tcp); + if(!headless) ui.chatfrag.addMessage(message, null); + } + + public String colorizeName(int id, String name){ + return name == null ? null : "[#" + colorArray[id % colorArray.length].toString().toUpperCase() + "]" + name; + } +} diff --git a/core/src/io/anuke/mindustry/core/NetServer.java b/core/src/io/anuke/mindustry/core/NetServer.java index 63bda321cc..b2ecb90cab 100644 --- a/core/src/io/anuke/mindustry/core/NetServer.java +++ b/core/src/io/anuke/mindustry/core/NetServer.java @@ -2,29 +2,26 @@ package io.anuke.mindustry.core; import com.badlogic.gdx.Gdx; import com.badlogic.gdx.utils.*; -import io.anuke.mindustry.Mindustry; -import io.anuke.mindustry.Vars; import io.anuke.mindustry.core.GameState.State; -import io.anuke.mindustry.entities.BulletType; import io.anuke.mindustry.entities.Player; import io.anuke.mindustry.entities.SyncEntity; -import io.anuke.mindustry.entities.TileEntity; import io.anuke.mindustry.entities.enemies.Enemy; -import io.anuke.mindustry.net.NetConnection; -import io.anuke.mindustry.net.NetworkIO; +import io.anuke.mindustry.io.Platform; import io.anuke.mindustry.net.Net; import io.anuke.mindustry.net.Net.SendMode; +import io.anuke.mindustry.net.NetConnection; +import io.anuke.mindustry.net.NetworkIO; import io.anuke.mindustry.net.Packets.*; -import io.anuke.mindustry.resource.*; -import io.anuke.mindustry.world.Block; +import io.anuke.mindustry.resource.Upgrade; +import io.anuke.mindustry.resource.UpgradeRecipes; +import io.anuke.mindustry.resource.Weapon; import io.anuke.mindustry.world.Tile; -import io.anuke.ucore.UCore; import io.anuke.ucore.core.Timers; import io.anuke.ucore.entities.Entities; -import io.anuke.ucore.entities.Entity; import io.anuke.ucore.entities.EntityGroup; import io.anuke.ucore.modules.Module; import io.anuke.ucore.util.Bundles; +import io.anuke.ucore.util.Log; import io.anuke.ucore.util.Mathf; import java.io.ByteArrayInputStream; @@ -33,6 +30,8 @@ import java.io.DataOutputStream; import java.io.IOException; import java.nio.ByteBuffer; +import static io.anuke.mindustry.Vars.*; + public class NetServer extends Module{ /**Maps connection IDs to players.*/ IntMap connections = new IntMap<>(); @@ -42,7 +41,7 @@ public class NetServer extends Module{ public NetServer(){ - Net.handleServer(Connect.class, (id, connect) -> UCore.log("Connection found: " + connect.addressTCP)); + Net.handleServer(Connect.class, (id, connect) -> {}); Net.handleServer(ConnectPacket.class, (id, packet) -> { @@ -51,31 +50,31 @@ public class NetServer extends Module{ return; } - UCore.log("Sending world data to client (ID=" + id + ")"); + Log.info("Sending world data to client (ID = {0})", id); Player player = new Player(); player.clientid = id; player.name = packet.name; player.isAndroid = packet.android; - player.set(Vars.control.core.worldx(), Vars.control.core.worldy() - Vars.tilesize * 2); + player.set(world.getSpawnX(), world.getSpawnY()); player.interpolator.last.set(player.x, player.y); player.interpolator.target.set(player.x, player.y); connections.put(id, player); - if(Vars.world.getMap().custom){ + if(world.getMap().custom){ ByteArrayOutputStream stream = new ByteArrayOutputStream(); - NetworkIO.writeMap(Vars.world.getMap().pixmap, stream); + NetworkIO.writeMap(world.getMap(), stream); CustomMapPacket data = new CustomMapPacket(); data.stream = new ByteArrayInputStream(stream.toByteArray()); Net.sendStream(id, data); - UCore.log("Sending custom map: Packed " + stream.size() + " uncompressed bytes of MAP data."); + Log.info("Sending custom map: Packed {0}uncompressed bytes of MAP data.", stream.size()); }else{ //hack-- simulate the map ack packet recieved to send the world data to the client. Net.handleServerReceived(id, new MapAckPacket()); } - Mindustry.platforms.updateRPC(); + Platform.instance.updateRPC(); }); Net.handleServer(MapAckPacket.class, (id, packet) -> { @@ -87,7 +86,7 @@ public class NetServer extends Module{ data.stream = new ByteArrayInputStream(stream.toByteArray()); Net.sendStream(id, data); - UCore.log("Packed " + stream.size() + " uncompressed bytes of WORLD data."); + Log.info("Packed {0} uncompressed bytes of WORLD data.", stream.size()); }); Net.handleServer(ConnectConfirmPacket.class, (id, packet) -> { @@ -96,7 +95,7 @@ public class NetServer extends Module{ if (player == null) return; player.add(); - sendMessage("[accent]" + Bundles.format("text.server.connected", player.name)); + netCommon.sendMessage("[accent]" + Bundles.format("text.server.connected", player.name)); }); Net.handleServer(Disconnect.class, (id, packet) -> { @@ -107,7 +106,7 @@ public class NetServer extends Module{ return; } - sendMessage("[accent]" + Bundles.format("text.server.disconnected", player.name)); + netCommon.sendMessage("[accent]" + Bundles.format("text.server.disconnected", player.name)); player.remove(); DisconnectPacket dc = new DisconnectPacket(); @@ -115,7 +114,7 @@ public class NetServer extends Module{ Net.send(dc, SendMode.tcp); - Mindustry.platforms.updateRPC(); + Platform.instance.updateRPC(); }); Net.handleServer(PositionPacket.class, (id, packet) -> { @@ -124,44 +123,25 @@ public class NetServer extends Module{ }); Net.handleServer(ShootPacket.class, (id, packet) -> { - Player player = connections.get(id); - - Weapon weapon = (Weapon) Upgrade.getByID(packet.weaponid); - weapon.shoot(player, packet.x, packet.y, packet.rotation); - packet.playerid = player.id; - + packet.playerid = connections.get(id).id; Net.sendExcept(id, packet, SendMode.udp); }); Net.handleServer(PlacePacket.class, (id, packet) -> { - Vars.control.input.placeBlockInternal(packet.x, packet.y, Block.getByID(packet.block), packet.rotation, true, false); packet.playerid = connections.get(id).id; - - Recipe recipe = Recipes.getByResult(Block.getByID(packet.block)); - if (recipe != null) Vars.control.removeItems(recipe.requirements); - Net.sendExcept(id, packet, SendMode.tcp); }); Net.handleServer(BreakPacket.class, (id, packet) -> { - Vars.control.input.breakBlockInternal(packet.x, packet.y, false); packet.playerid = connections.get(id).id; - Net.sendExcept(id, packet, SendMode.tcp); }); Net.handleServer(ChatPacket.class, (id, packet) -> { Player player = connections.get(id); - - if (player == null) { - Gdx.app.error("Mindustry", "Could not find player for chat: " + id); - return; //GHOSTS AAAA - } - packet.name = player.name; packet.id = player.id; Net.sendExcept(player.clientid, packet, SendMode.tcp); - Vars.ui.chatfrag.addMessage(packet.text, Vars.netClient.colorizeName(packet.id, packet.name)); }); Net.handleServer(UpgradePacket.class, (id, packet) -> { @@ -172,41 +152,27 @@ public class NetServer extends Module{ if (!weapons.containsKey(player.name)) weapons.put(player.name, new ByteArray()); if (!weapons.get(player.name).contains(weapon.id)) weapons.get(player.name).add(weapon.id); - Vars.control.removeItems(UpgradeRecipes.get(weapon)); + state.inventory.removeItems(UpgradeRecipes.get(weapon)); }); Net.handleServer(WeaponSwitchPacket.class, (id, packet) -> { - Player player = connections.get(id); - - if (player == null) return; - - packet.playerid = player.id; - - player.weaponLeft = (Weapon) Upgrade.getByID(packet.left); - player.weaponRight = (Weapon) Upgrade.getByID(packet.right); - - Net.sendExcept(player.clientid, packet, SendMode.tcp); + packet.playerid = connections.get(id).id; + Net.sendExcept(id, packet, SendMode.tcp); }); Net.handleServer(BlockTapPacket.class, (id, packet) -> { - Tile tile = Vars.world.tile(packet.position); - tile.block().tapped(tile); - Net.sendExcept(id, packet, SendMode.tcp); }); Net.handleServer(BlockConfigPacket.class, (id, packet) -> { - Tile tile = Vars.world.tile(packet.position); - if (tile != null) tile.block().configure(tile, packet.data); - Net.sendExcept(id, packet, SendMode.tcp); }); Net.handleServer(EntityRequestPacket.class, (cid, packet) -> { int id = packet.id; int dest = cid; - if (Vars.control.playerGroup.getByID(id) != null) { - Player player = Vars.control.playerGroup.getByID(id); + if (playerGroup.getByID(id) != null) { + Player player = playerGroup.getByID(id); PlayerSpawnPacket p = new PlayerSpawnPacket(); p.x = player.x; p.y = player.y; @@ -217,9 +183,8 @@ public class NetServer extends Module{ p.android = player.isAndroid; Net.sendTo(dest, p, SendMode.tcp); - log("Replying to entity request (" + id + "): player, " + id); - } else if (Vars.control.enemyGroup.getByID(id) != null) { - Enemy enemy = Vars.control.enemyGroup.getByID(id); + } else if (enemyGroup.getByID(id) != null) { + Enemy enemy = enemyGroup.getByID(id); EnemySpawnPacket e = new EnemySpawnPacket(); e.x = enemy.x; e.y = enemy.y; @@ -229,90 +194,30 @@ public class NetServer extends Module{ e.type = enemy.type.id; e.health = (short) enemy.health; Net.sendTo(dest, e, SendMode.tcp); - log("Replying to entity request(" + id + "): enemy, " + id); - } else { - Gdx.app.error("Mindustry", "Entity request target not found!"); } }); Net.handleServer(PlayerDeathPacket.class, (id, packet) -> { - Player player = connections.get(id); - if(player == null) return; - - packet.id = player.id; - - player.doRespawn(); + packet.id = connections.get(id).id; Net.sendExcept(id, packet, SendMode.tcp); }); } - public void sendMessage(String message){ - ChatPacket packet = new ChatPacket(); - packet.name = null; - packet.text = message; - Net.send(packet, SendMode.tcp); - Vars.ui.chatfrag.addMessage(message, null); - } - - public void handleFriendlyFireChange(boolean enabled){ - FriendlyFireChangePacket packet = new FriendlyFireChangePacket(); - packet.enabled = enabled; - - sendMessage(enabled ? "[accent]Friendly fire enabled." : "[accent]Friendly fire disabled."); - - Net.send(packet, SendMode.tcp); - } - - public void handleGameOver(){ - Net.send(new GameOverPacket(), SendMode.tcp); - Timers.runTask(30f, () -> GameState.set(State.menu)); - } - - public void handleBullet(BulletType type, Entity owner, float x, float y, float angle, short damage){ - BulletPacket packet = new BulletPacket(); - packet.x = x; - packet.y = y; - packet.angle = angle; - packet.damage = damage; - packet.owner = owner.id; - packet.type = type.id; - Net.send(packet, SendMode.udp); - } - - public void handleEnemyDeath(Enemy enemy){ - EnemyDeathPacket packet = new EnemyDeathPacket(); - packet.id = enemy.id; - Net.send(packet, SendMode.tcp); - } - - public void handleBlockDestroyed(TileEntity entity){ - BlockDestroyPacket packet = new BlockDestroyPacket(); - packet.position = entity.tile.packedPosition(); - Net.send(packet, SendMode.tcp); - } - - public void handleBlockDamaged(TileEntity entity){ - BlockUpdatePacket packet = new BlockUpdatePacket(); - packet.health = (int)entity.health; - packet.position = entity.tile.packedPosition(); - Net.send(packet, SendMode.udp); - } - public void update(){ - if(!Net.server()) return; - - if(!GameState.is(State.menu) && Net.active()){ - sync(); - }else if(!closing){ + if(!headless && !closing && Net.server() && state.is(State.menu)){ closing = true; weapons.clear(); - Vars.ui.loadfrag.show("$text.server.closing"); + ui.loadfrag.show("$text.server.closing"); Timers.runTask(5f, () -> { Net.closeServer(); - Vars.ui.loadfrag.hide(); + ui.loadfrag.hide(); closing = false; }); } + + if(!state.is(State.menu) && Net.server()){ + sync(); + } } void sync(){ @@ -320,12 +225,12 @@ public class NetServer extends Module{ if(Timers.get("serverSync", serverSyncTime)){ //scan through all groups with syncable entities for(EntityGroup group : Entities.getAllGroups()) { - if(group.amount() == 0 || !(group.all().first() instanceof SyncEntity)) continue; + if(group.size() == 0 || !(group.all().first() instanceof SyncEntity)) continue; //get write size for one entity (adding 4, as you need to write the ID as well) int writesize = SyncEntity.getWriteSize((Class)group.getType()) + 4; //amount of entities - int amount = group.amount(); + int amount = group.size(); //maximum amount of entities per packet int maxsize = 64; @@ -383,10 +288,10 @@ public class NetServer extends Module{ if(Timers.get("serverItemSync", itemSyncTime)){ StateSyncPacket packet = new StateSyncPacket(); - packet.items = Vars.control.items; - packet.countdown = Vars.control.getWaveCountdown(); - packet.enemies = Vars.control.getEnemiesRemaining(); - packet.wave = Vars.control.getWave(); + packet.items = state.inventory.getItems(); + packet.countdown = state.wavetime; + packet.enemies = state.enemies; + packet.wave = state.wave; packet.time = Timers.time(); packet.timestamp = TimeUtils.millis(); @@ -401,8 +306,8 @@ public class NetServer extends Module{ int id = connections.get(i).id; Player player = this.connections.get(id); if(player == null) continue; - int x = Mathf.scl2(player.x, Vars.tilesize); - int y = Mathf.scl2(player.y, Vars.tilesize); + int x = Mathf.scl2(player.x, tilesize); + int y = Mathf.scl2(player.y, tilesize); int w = 16; int h = 12; sendBlockSync(id, x, y, w, h); @@ -423,7 +328,7 @@ public class NetServer extends Module{ for (int rx = -viewx / 2; rx <= viewx / 2; rx++) { for (int ry = -viewy / 2; ry <= viewy / 2; ry++) { - Tile tile = Vars.world.tile(x + rx, y + ry); + Tile tile = world.tile(x + rx, y + ry); if (tile == null || tile.entity == null) continue; @@ -453,7 +358,6 @@ public class NetServer extends Module{ } packet.stream = new ByteArrayInputStream(bs.toByteArray()); - //UCore.log("Sent block update stream to " + client + " / " + packet.stream.available()); Net.sendStream(client, packet); } diff --git a/core/src/io/anuke/mindustry/core/Renderer.java b/core/src/io/anuke/mindustry/core/Renderer.java index 95de6aac16..98b2d9099f 100644 --- a/core/src/io/anuke/mindustry/core/Renderer.java +++ b/core/src/io/anuke/mindustry/core/Renderer.java @@ -10,16 +10,15 @@ import com.badlogic.gdx.math.Vector2; import com.badlogic.gdx.utils.Array; import com.badlogic.gdx.utils.FloatArray; import com.badlogic.gdx.utils.Pools; -import io.anuke.mindustry.Vars; import io.anuke.mindustry.core.GameState.State; import io.anuke.mindustry.entities.Player; import io.anuke.mindustry.entities.enemies.Enemy; +import io.anuke.mindustry.game.SpawnPoint; import io.anuke.mindustry.graphics.BlockRenderer; import io.anuke.mindustry.graphics.Shaders; import io.anuke.mindustry.input.InputHandler; import io.anuke.mindustry.input.PlaceMode; import io.anuke.mindustry.ui.fragments.ToolFragment; -import io.anuke.mindustry.game.SpawnPoint; import io.anuke.mindustry.world.Tile; import io.anuke.mindustry.world.blocks.Blocks; import io.anuke.mindustry.world.blocks.ProductionBlocks; @@ -53,6 +52,8 @@ public class Renderer extends RendererModule{ private BlockRenderer blocks = new BlockRenderer(); public Renderer() { + Lines.setCircleVertices(14); + Core.cameraScale = baseCameraScale; Effects.setEffectProvider((name, color, x, y, rotation) -> { if(Settings.getBool("effects")){ @@ -94,25 +95,25 @@ public class Renderer extends RendererModule{ if(Mathf.in(camera.zoom, targetzoom, 0.005f)){ camera.zoom = 1f; Graphics.setCameraScale(targetscale); - control.input.resetCursor(); + control.input().resetCursor(); } }else{ camera.zoom = Mathf.lerp(camera.zoom, 1f, 0.2f * Timers.delta()); } - if(GameState.is(State.menu)){ + if(state.is(State.menu)){ clearScreen(); }else{ boolean smoothcam = Settings.getBool("smoothcam"); - if(control.core == null || control.core.block() == ProductionBlocks.core){ + if(world.getCore() == null || world.getCore().block() == ProductionBlocks.core){ if(!smoothcam){ setCamera(player.x, player.y); }else{ smoothCamera(player.x, player.y, android ? 0.3f : 0.14f); } }else{ - smoothCamera(control.core.worldx(), control.core.worldy(), 0.4f); + smoothCamera(world.getCore().worldx(), world.getCore().worldy(), 0.4f); } if(Settings.getBool("pixelate")) @@ -133,7 +134,7 @@ public class Renderer extends RendererModule{ float lastx = camera.position.x, lasty = camera.position.y; - if(Vars.snapCamera && smoothcam && Settings.getBool("pixelate")){ + if(snapCamera && smoothcam && Settings.getBool("pixelate")){ camera.position.set((int) camera.position.x, (int) camera.position.y, 0); } @@ -149,7 +150,7 @@ public class Renderer extends RendererModule{ camera.position.set(lastx - deltax, lasty - deltay, 0); - if(Vars.debug) record(); //this only does something if GdxGifRecorder is on the class path, which it usually isn't + if(debug) record(); //this only does something if GdxGifRecorder is on the class path, which it usually isn't } } @@ -175,22 +176,22 @@ public class Renderer extends RendererModule{ blocks.drawBlocks(false); Graphics.shader(Shaders.outline, false); - Entities.draw(control.enemyGroup); + Entities.draw(enemyGroup); Graphics.shader(); - Entities.draw(control.playerGroup, p -> !p.isAndroid); + Entities.draw(playerGroup, p -> !p.isAndroid); Entities.draw(Entities.defaultGroup()); blocks.drawBlocks(true); - Entities.draw(control.playerGroup, p -> p.isAndroid); - Entities.draw(control.bulletGroup); + Entities.draw(playerGroup, p -> p.isAndroid); + Entities.draw(bulletGroup); drawShield(); drawOverlay(); - if(Settings.getBool("indicators") && Vars.showUI){ + if(Settings.getBool("indicators") && showUI){ drawEnemyMarkers(); } @@ -205,7 +206,7 @@ public class Renderer extends RendererModule{ @Override public void resize(int width, int height){ super.resize(width, height); - control.input.resetCursor(); + control.input().resetCursor(); camera.position.set(player.x, player.y, 0); } @@ -217,25 +218,25 @@ public class Renderer extends RendererModule{ GlyphLayout layout = Pools.obtain(GlyphLayout.class); Draw.tscl(0.25f/2); - for(Player player : Vars.control.playerGroup.all()){ + for(Player player : playerGroup.all()){ if(!player.isLocal){ layout.setText(Core.font, player.name); Draw.color(0f, 0f, 0f, 0.3f); Draw.rect("blank", player.x, player.y + 8 - layout.height/2, layout.width + 2, layout.height + 2); Draw.color(); - Draw.tcolor(NetClient.colorArray[player.id % NetClient.colorArray.length]); + Draw.tcolor(NetCommon.colorArray[player.id % NetCommon.colorArray.length]); Draw.text(player.name, player.x, player.y + 8); Draw.tcolor(); } } Pools.free(layout); - Draw.tscl(Vars.fontscale); + Draw.tscl(fontscale); } void drawEnemyMarkers(){ Graphics.surface(indicatorSurface); Draw.color(Color.RED); - for(Enemy enemy : control.enemyGroup.all()){ + for(Enemy enemy : enemyGroup.all()){ if(Tmp.r1.setSize(camera.viewportWidth, camera.viewportHeight).setCenter(camera.position.x, camera.position.y).overlaps(enemy.hitbox.getRect(enemy.x, enemy.y))){ continue; @@ -252,11 +253,11 @@ public class Renderer extends RendererModule{ } void drawShield(){ - if(control.shieldGroup.amount() == 0 && shieldDraws.size == 0) return; + if(shieldGroup.size() == 0 && shieldDraws.size == 0) return; - Graphics.surface(Vars.renderer.shieldSurface, false); + Graphics.surface(renderer.shieldSurface, false); Draw.color(Color.ROYAL); - Entities.draw(control.shieldGroup); + Entities.draw(shieldGroup); for(Callable c : shieldDraws){ c.run(); } @@ -317,10 +318,10 @@ public class Renderer extends RendererModule{ void drawOverlay(){ //draw tutorial placement point - if(Vars.world.getMap().name.equals("tutorial") && Vars.control.tutorial.showBlock()){ - int x = control.core.x + Vars.control.tutorial.getPlacePoint().x; - int y = control.core.y + Vars.control.tutorial.getPlacePoint().y; - int rot = Vars.control.tutorial.getPlaceRotation(); + if(world.getMap().name.equals("tutorial") && control.tutorial().showBlock()){ + int x = world.getCore().x + control.tutorial().getPlacePoint().x; + int y = world.getCore().y + control.tutorial().getPlacePoint().y; + int rot = control.tutorial().getPlaceRotation(); Lines.stroke(1f); Draw.color(Color.YELLOW); @@ -335,48 +336,48 @@ public class Renderer extends RendererModule{ } //draw config selected block - if(Vars.ui.configfrag.isShown()){ + if(ui.configfrag.isShown()){ Tile tile = ui.configfrag.getSelectedTile(); Draw.color(Colors.get("accent")); Lines.stroke(1f); Lines.square(tile.drawx(), tile.drawy(), - tile.block().width * Vars.tilesize / 2f + 1f); + tile.block().width * tilesize / 2f + 1f); Draw.reset(); } - int tilex = control.input.getBlockX(); - int tiley = control.input.getBlockY(); + int tilex = control.input().getBlockX(); + int tiley = control.input().getBlockY(); - if(Vars.android){ + if(android){ 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.getInput(); + InputHandler input = control.input(); //draw placement box - if((input.recipe != null && Vars.control.hasItems(input.recipe.requirements) && (!ui.hasMouse() || android) - && control.input.drawPlace())){ + if((input.recipe != null && state.inventory.hasItems(input.recipe.requirements) && (!ui.hasMouse() || android) + && control.input().drawPlace())){ - input.placeMode.draw(control.input.getBlockX(), control.input.getBlockY(), control.input.getBlockEndX(), control.input.getBlockEndY()); + input.placeMode.draw(control.input().getBlockX(), control.input().getBlockY(), control.input().getBlockEndX(), control.input().getBlockEndY()); Lines.stroke(1f); Draw.color(Color.SCARLET); - for(SpawnPoint spawn : control.getSpawnPoints()){ + for(SpawnPoint spawn : world.getSpawns()){ Lines.dashCircle(spawn.start.worldx(), spawn.start.worldy(), enemyspawnspace); } if(input.breakMode == PlaceMode.holdDelete) input.breakMode.draw(tilex, tiley, 0, 0); - }else if(input.breakMode.delete && control.input.drawPlace() && input.recipe == null){ - input.breakMode.draw(control.input.getBlockX(), control.input.getBlockY(), - control.input.getBlockEndX(), control.input.getBlockEndY()); + }else if(input.breakMode.delete && control.input().drawPlace() && input.recipe == null){ + input.breakMode.draw(control.input().getBlockX(), control.input().getBlockY(), + control.input().getBlockEndX(), control.input().getBlockEndY()); } - if(Vars.ui.toolfrag.confirming){ - ToolFragment t = Vars.ui.toolfrag; + if(ui.toolfrag.confirming){ + ToolFragment t = ui.toolfrag; PlaceMode.areaDelete.draw(t.px, t.py, t.px2, t.py2); } @@ -384,7 +385,7 @@ public class Renderer extends RendererModule{ //draw selected block health if(input.recipe == null && !ui.hasMouse()){ - Tile tile = world.tile(tilex, tiley); + Tile tile = world.tileWorld(Graphics.mouseWorld().x, Graphics.mouseWorld().y); if(tile != null && tile.block() != Blocks.air){ Tile target = tile; @@ -392,27 +393,27 @@ public class Renderer extends RendererModule{ target = tile.getLinked(); if(target.entity != null) - drawHealth(target.drawx(), target.drawy() - 3f - target.block().height / 2f * Vars.tilesize, target.entity.health, target.entity.tile.block().health); + drawHealth(target.drawx(), target.drawy() - 3f - target.block().height / 2f * tilesize, target.entity.health, target.entity.tile.block().health); target.block().drawSelect(target); } } - if((!Vars.debug || Vars.showUI) && Settings.getBool("healthbars")){ + if((!debug || showUI) && Settings.getBool("healthbars")){ //draw entity health bars - for(Enemy entity : control.enemyGroup.all()){ + for(Enemy entity : enemyGroup.all()){ drawHealth(entity); } - for(Player player : Vars.control.playerGroup.all()){ + for(Player player : playerGroup.all()){ if(!player.isDead() && !player.isAndroid) drawHealth(player); } } } void drawHealth(DestructibleEntity dest){ - if(dest instanceof Player && Vars.snapCamera && Settings.getBool("smoothcam") && Settings.getBool("pixelate")){ + if(dest instanceof Player && snapCamera && Settings.getBool("smoothcam") && Settings.getBool("pixelate")){ drawHealth((int) dest.x, (int) dest.y - 7f, dest.health, dest.maxhealth); }else{ drawHealth(dest.x, dest.y - 7f, dest.health, dest.maxhealth); diff --git a/core/src/io/anuke/mindustry/core/ServerControl.java b/core/src/io/anuke/mindustry/core/ServerControl.java new file mode 100644 index 0000000000..71798a915a --- /dev/null +++ b/core/src/io/anuke/mindustry/core/ServerControl.java @@ -0,0 +1,325 @@ +package io.anuke.mindustry.core; + +import com.badlogic.gdx.ApplicationLogger; +import com.badlogic.gdx.Gdx; +import io.anuke.mindustry.core.GameState.State; +import io.anuke.mindustry.entities.Player; +import io.anuke.mindustry.game.Difficulty; +import io.anuke.mindustry.game.EventType.GameOverEvent; +import io.anuke.mindustry.game.GameMode; +import io.anuke.mindustry.io.SaveIO; +import io.anuke.mindustry.net.Net; +import io.anuke.mindustry.net.NetEvents; +import io.anuke.mindustry.net.Packets.ChatPacket; +import io.anuke.mindustry.net.Packets.KickReason; +import io.anuke.mindustry.ui.fragments.DebugFragment; +import io.anuke.mindustry.world.Map; +import io.anuke.ucore.core.Effects; +import io.anuke.ucore.core.Events; +import io.anuke.ucore.core.Sounds; +import io.anuke.ucore.core.Timers; +import io.anuke.ucore.modules.Module; +import io.anuke.ucore.util.CommandHandler; +import io.anuke.ucore.util.CommandHandler.Command; +import io.anuke.ucore.util.CommandHandler.Response; +import io.anuke.ucore.util.CommandHandler.ResponseType; +import io.anuke.ucore.util.Log; +import io.anuke.ucore.util.Strings; + +import java.io.IOException; +import java.util.Scanner; + +import static io.anuke.mindustry.Vars.*; +import static io.anuke.ucore.util.Log.*; + +; + +public class ServerControl extends Module { + private final CommandHandler handler = new CommandHandler(""); + private boolean shuffle = true; + + public ServerControl(){ + Effects.setScreenShakeProvider((a, b) -> {}); + Effects.setEffectProvider((a, b, c, d, e) -> {}); + Sounds.setHeadless(true); + + //override default handling of chat packets + Net.handle(ChatPacket.class, (packet) -> { + info("&y" + (packet.name == null ? "" : packet.name) + ": &lb{0}", packet.text); + }); + + //don't do anything at all for GDX logging + Gdx.app.setApplicationLogger(new ApplicationLogger() { + @Override public void log(String tag, String message) { } + @Override public void log(String tag, String message, Throwable exception) { } + @Override public void error(String tag, String message) { } + @Override public void error(String tag, String message, Throwable exception) { } + @Override public void debug(String tag, String message) { } + @Override public void debug(String tag, String message, Throwable exception) { } + }); + + registerCommands(); + Thread thread = new Thread(this::readCommands, "Server Controls"); + thread.setDaemon(true); + thread.start(); + + Events.on(GameOverEvent.class, () -> { + info("Game over!"); + + Timers.runTask(10f, () -> { + Net.closeServer(); + + if(shuffle) { + Map previous = world.getMap(); + Map map = previous; + while(map == previous) map = world.maps().getDefaultMaps().random(); + + info("Selected next map to be {0}.", map.name); + state.set(State.playing); + logic.reset(); + world.loadMap(map); + host(); + }else{ + state.set(State.menu); + } + }); + }); + + info("&lcServer loaded. Type &ly'help'&lc for help."); + } + + private void registerCommands(){ + handler.register("help", "Displays this command list.", arg -> { + info("Commands:"); + for(Command command : handler.getCommandList()){ + print(" &y" + command.text + (command.params.isEmpty() ? "" : " ") + command.params + " - &lm" + command.description); + } + }); + + handler.register("exit", "Exit the server application.", arg -> { + info("Shutting down server."); + Net.dispose(); + Gdx.app.exit(); + }); + + handler.register("stop", "Stop hosting the server.", arg -> { + Net.closeServer(); + state.set(State.menu); + }); + + handler.register("host", " ", "Open the server with a specific map.", arg -> { + if(state.is(State.playing)){ + err("Already hosting. Type 'stop' to stop hosting first."); + return; + } + + String search = arg[0]; + Map result = null; + for(Map map : world.maps().list()){ + if(map.name.equalsIgnoreCase(search)) + result = map; + } + + if(result == null){ + err("No map with name &y'{0}'&lr found.", search); + return; + } + + GameMode mode = null; + try{ + mode = GameMode.valueOf(arg[1]); + }catch (IllegalArgumentException e){ + err("No gamemode '{0}' found.", arg[1]); + return; + } + + info("Loading map..."); + state.mode = mode; + + logic.reset(); + world.loadMap(result); + state.set(State.playing); + info("Map loaded."); + + host(); + }); + + handler.register("status", "Display server status.", arg -> { + if(state.is(State.menu)){ + info("&lyStatus: &rserver closed"); + }else{ + 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(state.enemies > 0){ + info("&ly{0} enemies remaining.", state.enemies); + }else{ + info("&ly{0} seconds until next wave.", (int)(state.wavetime / 60)); + } + + if(playerGroup.size() > 0) { + info("&lyPlayers: {0}", playerGroup.size()); + for (Player p : playerGroup.all()) { + print(" &y" + p.name); + } + }else{ + info("&lyNo players connected."); + } + } + }); + + handler.register("say", "", "Send a message to all players.", arg -> { + if(!state.is(State.playing)) { + err("Not hosting. Host a game first."); + return; + } + + netCommon.sendMessage("[pink][[Server]:[] " + arg[0]); + info("&lyServer: &lb{0}", arg[0]); + }).mergeArgs(); + + handler.register("difficulty", "", "Set game difficulty.", arg -> { + try{ + Difficulty diff = Difficulty.valueOf(arg[0]); + state.difficulty = diff; + info("Difficulty set to '{0}'.", arg[0]); + }catch (IllegalArgumentException e){ + err("No difficulty with name '{0}' found.", arg[0]); + } + }); + + handler.register("friendlyfire", "", "Enable or disable friendly fire", arg -> { + String s = arg[0]; + if(s.equalsIgnoreCase("on")){ + NetEvents.handleFriendlyFireChange(true); + state.friendlyFire = true; + info("Friendly fire enabled."); + }else if(s.equalsIgnoreCase("off")){ + NetEvents.handleFriendlyFireChange(false); + state.friendlyFire = false; + info("Friendly fire disabled."); + }else{ + err("Incorrect command usage."); + } + }); + + handler.register("shuffle", "", "Enable or disable automatic random map shuffling after gameovers.", arg -> { + String s = arg[0]; + if(s.equalsIgnoreCase("on")){ + shuffle = true; + info("Map shuffling enabled."); + }else if(s.equalsIgnoreCase("off")){ + shuffle = false; + info("Map shuffling disabled."); + }else{ + err("Incorrect command usage."); + } + }); + + handler.register("kick", "", "Kick a person by name.", arg -> { + if(!state.is(State.playing)) { + err("Not hosting a game yet. Calm down."); + return; + } + + if(playerGroup.size() == 0){ + err("But this server is empty. A barren wasteland."); + return; + } + + Player target = null; + + for(Player player : playerGroup.all()){ + if(player.name.equalsIgnoreCase(arg[0])){ + target = player; + break; + } + } + + if(target != null){ + Net.kickConnection(target.clientid, KickReason.kick); + info("It is done."); + }else{ + info("Nobody with that name could be found..."); + } + }); + + handler.register("runwave", "Trigger the next wave.", arg -> { + if(!state.is(State.playing)) { + err("Not hosting. Host a game first."); + }else if(state.enemies > 0){ + err("There are still {0} enemies remaining.", state.enemies); + }else{ + logic.runWave(); + info("Wave spawned."); + } + }); + + handler.register("load", "", "Load a save from a slot.", arg -> { + if(state.is(State.playing)){ + err("Already hosting. Type 'stop' to stop hosting first."); + return; + }else if(!Strings.canParseInt(arg[0])){ + err("Invalid save slot '{0}'.", arg[0]); + return; + } + + int slot = Strings.parseInt(arg[0]); + + if(!SaveIO.isSaveValid(slot)){ + err("No save data found for slot."); + return; + } + + SaveIO.loadFromSlot(slot); + info("Save loaded."); + host(); + state.set(State.playing); + }); + + handler.register("save", "", "Save game state to a slot.", arg -> { + if(!state.is(State.playing)){ + err("Not hosting. Host a game first."); + return; + }else if(!Strings.canParseInt(arg[0])){ + err("Invalid save slot '{0}'.", arg[0]); + return; + } + + int slot = Strings.parseInt(arg[0]); + + SaveIO.saveToSlot(slot); + + info("Saved to slot {0}.", slot); + }); + + handler.register("info", "Print debug info", arg -> { + info(DebugFragment.debugInfo()); + }); + } + + private void readCommands(){ + Scanner scan = new Scanner(System.in); + while(true){ + String line = scan.nextLine(); + + Gdx.app.postRunnable(() -> { + Response response = handler.handleMessage(line); + + if (response.type == ResponseType.unknownCommand) { + err("Invalid command. Type 'help' for help."); + } else if (response.type == ResponseType.invalidArguments) { + err("Invalid command arguments. Usage: " + response.command.text + " " + response.command.params); + } + }); + } + } + + private void host(){ + try { + Net.host(port); + }catch (IOException e){ + Log.err(e); + state.set(State.menu); + } + } +} diff --git a/core/src/io/anuke/mindustry/core/UI.java b/core/src/io/anuke/mindustry/core/UI.java index 7f11db4338..85483571e3 100644 --- a/core/src/io/anuke/mindustry/core/UI.java +++ b/core/src/io/anuke/mindustry/core/UI.java @@ -5,12 +5,15 @@ import com.badlogic.gdx.graphics.Color; import com.badlogic.gdx.graphics.Colors; import com.badlogic.gdx.math.Interpolation; import com.badlogic.gdx.utils.Align; -import io.anuke.mindustry.Mindustry; import io.anuke.mindustry.Vars; +import io.anuke.mindustry.io.Platform; import io.anuke.mindustry.mapeditor.MapEditorDialog; import io.anuke.mindustry.ui.dialogs.*; import io.anuke.mindustry.ui.fragments.*; -import io.anuke.ucore.core.*; +import io.anuke.ucore.core.Core; +import io.anuke.ucore.core.Graphics; +import io.anuke.ucore.core.Settings; +import io.anuke.ucore.core.Timers; import io.anuke.ucore.function.Consumer; import io.anuke.ucore.function.Listenable; import io.anuke.ucore.graphics.Draw; @@ -52,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; @@ -157,6 +161,7 @@ public class UI extends SceneModule{ toolfrag.build(); chatfrag.build(); listfrag.build(); + debugfrag.build(); loadfrag.build(); build.end(); @@ -185,7 +190,7 @@ public class UI extends SceneModule{ content().margin(30).add(text).padRight(6f); TextField field = content().addField(def, t->{}).size(170f, 50f).get(); field.setTextFieldFilter((f, c) -> field.getText().length() < 12 && filter.acceptChar(f, c)); - Mindustry.platforms.addDialog(field); + Platform.instance.addDialog(field); buttons().defaults().size(120, 54).pad(4); buttons().addButton("$text.ok", () -> { confirmed.accept(field.getText()); diff --git a/core/src/io/anuke/mindustry/core/World.java b/core/src/io/anuke/mindustry/core/World.java index 1d98b3acdd..5ae8c51caf 100644 --- a/core/src/io/anuke/mindustry/core/World.java +++ b/core/src/io/anuke/mindustry/core/World.java @@ -4,15 +4,15 @@ import com.badlogic.gdx.math.GridPoint2; import com.badlogic.gdx.math.MathUtils; import com.badlogic.gdx.math.Vector2; import com.badlogic.gdx.utils.Array; -import io.anuke.mindustry.Vars; import io.anuke.mindustry.ai.Pathfind; import io.anuke.mindustry.entities.TileEntity; +import io.anuke.mindustry.game.SpawnPoint; import io.anuke.mindustry.io.Maps; import io.anuke.mindustry.net.Net; import io.anuke.mindustry.world.Block; -import io.anuke.mindustry.world.WorldGenerator; import io.anuke.mindustry.world.Map; import io.anuke.mindustry.world.Tile; +import io.anuke.mindustry.world.WorldGenerator; import io.anuke.mindustry.world.blocks.Blocks; import io.anuke.mindustry.world.blocks.DistributionBlocks; import io.anuke.mindustry.world.blocks.ProductionBlocks; @@ -23,17 +23,19 @@ import io.anuke.ucore.modules.Module; import io.anuke.ucore.util.Mathf; import io.anuke.ucore.util.Tmp; -import static io.anuke.mindustry.Vars.control; -import static io.anuke.mindustry.Vars.tilesize; +import static io.anuke.mindustry.Vars.*; public class World extends Module{ private int seed; private Map currentMap; private Tile[][] tiles; - private Tile[] temptiles = new Tile[4]; private Pathfind pathfind = new Pathfind(); - private io.anuke.mindustry.io.Maps maps = new io.anuke.mindustry.io.Maps(); + private Maps maps = new Maps(); + private Tile core; + private Array spawns = new Array<>(); + + private Tile[] temptiles = new Tile[4]; public World(){ maps.loadMaps(); @@ -42,7 +44,7 @@ public class World extends Module{ @Override public void update(){ - if(!(Net.active() && Net.client())) + if(!Net.client()) pathfind.update(); } @@ -50,6 +52,14 @@ public class World extends Module{ public void dispose(){ maps.dispose(); } + + public Array getSpawns(){ + return spawns; + } + + public Tile getCore(){ + return core; + } public Maps maps(){ return maps; @@ -58,6 +68,14 @@ public class World extends Module{ public Pathfind pathfinder(){ return pathfind; } + + public float getSpawnX(){ + return core.worldx(); + } + + public float getSpawnY(){ + return core.worldy() - tilesize*2; + } public boolean solid(int x, int y){ Tile tile = tile(x, y); @@ -175,28 +193,27 @@ public class World extends Module{ createTiles(); } - Vars.control.getSpawnPoints().clear(); + spawns.clear(); Entities.resizeTree(0, 0, map.getWidth() * tilesize, map.getHeight() * tilesize); this.seed = seed; - WorldGenerator.generate(map.pixmap, tiles); - if(control.getCore() == null) return; + core = WorldGenerator.generate(map.pixmap, tiles, spawns); - control.getInput().placeBlock(control.getCore().x, control.getCore().y, ProductionBlocks.core, 0, false, false); + placeBlock(core.x, core.y, ProductionBlocks.core, 0); if(!map.name.equals("tutorial")){ setDefaultBlocks(); }else{ - Vars.control.getTutorial().setDefaultBlocks(control.getCore().x, control.getCore().y); + control.tutorial().setDefaultBlocks(core.x, core.y); } pathfind.resetPaths(); } void setDefaultBlocks(){ - int x = control.getCore().x, y = control.getCore().y; + int x = core.x, y = core.y; int flip = Mathf.sign(!currentMap.flipBase); int fr = currentMap.flipBase ? 2 : 0; @@ -248,6 +265,32 @@ public class World extends Module{ } } } + + public void placeBlock(int x, int y, Block result, int rotation){ + Tile tile = world.tile(x, y); + + //just in case + if(tile == null) return; + + tile.setBlock(result, rotation); + + if(result.isMultiblock()){ + int offsetx = -(result.width-1)/2; + int offsety = -(result.height-1)/2; + + for(int dx = 0; dx < result.width; dx ++){ + for(int dy = 0; dy < result.height; dy ++){ + int worldx = dx + offsetx + x; + int worldy = dy + offsety + y; + if(!(worldx == x && worldy == y)){ + Tile toplace = world.tile(worldx, worldy); + if(toplace != null) + toplace.setLinked((byte)(dx + offsetx), (byte)(dy + offsety)); + } + } + } + } + } public TileEntity findTileTarget(float x, float y, Tile tile, float range, boolean damaged){ Entity closest = null; @@ -282,7 +325,8 @@ public class World extends Module{ return (TileEntity) closest; } - + + /**Raycast, but with world coordinates.*/ public GridPoint2 raycastWorld(float x, float y, float x2, float y2){ return raycast(Mathf.scl2(x, tilesize), Mathf.scl2(y, tilesize), Mathf.scl2(x2, tilesize), Mathf.scl2(y2, tilesize)); @@ -290,8 +334,7 @@ public class World extends Module{ /** * Input is in block coordinates, not world coordinates. - * @return null if no collisions found, block position otherwise. - */ + * @return null if no collisions found, block position otherwise.*/ public GridPoint2 raycast(int x0f, int y0f, int x1, int y1){ int x0 = x0f; int y0 = y0f; diff --git a/core/src/io/anuke/mindustry/entities/Bullet.java b/core/src/io/anuke/mindustry/entities/Bullet.java index 6089fd4cc0..40d77f07f2 100644 --- a/core/src/io/anuke/mindustry/entities/Bullet.java +++ b/core/src/io/anuke/mindustry/entities/Bullet.java @@ -1,13 +1,12 @@ package io.anuke.mindustry.entities; -import io.anuke.mindustry.Vars; import io.anuke.mindustry.world.Tile; import io.anuke.ucore.entities.BulletEntity; import io.anuke.ucore.entities.Entity; import io.anuke.ucore.entities.SolidEntity; import io.anuke.ucore.util.Mathf; -import static io.anuke.mindustry.Vars.tilesize; +import static io.anuke.mindustry.Vars.*; public class Bullet extends BulletEntity{ public boolean absorbed = false; @@ -36,7 +35,7 @@ public class Bullet extends BulletEntity{ int tilex = Mathf.scl2(x, tilesize); int tiley = Mathf.scl2(y, tilesize); - Tile tile = Vars.world.tile(tilex, tiley); + Tile tile = world.tile(tilex, tiley); TileEntity targetEntity = null; if(tile != null){ @@ -61,7 +60,7 @@ public class Bullet extends BulletEntity{ super.update(); } - + @Override public boolean collides(SolidEntity other){ if(owner instanceof TileEntity && other instanceof Player) @@ -82,7 +81,7 @@ public class Bullet extends BulletEntity{ @Override public Bullet add(){ - return super.add(Vars.control.bulletGroup); + return super.add(bulletGroup); } } diff --git a/core/src/io/anuke/mindustry/entities/Player.java b/core/src/io/anuke/mindustry/entities/Player.java index 32a7078e0c..6d413e0f28 100644 --- a/core/src/io/anuke/mindustry/entities/Player.java +++ b/core/src/io/anuke/mindustry/entities/Player.java @@ -1,13 +1,16 @@ package io.anuke.mindustry.entities; -import io.anuke.mindustry.Vars; import io.anuke.mindustry.graphics.Fx; import io.anuke.mindustry.net.Net; +import io.anuke.mindustry.net.NetEvents; import io.anuke.mindustry.resource.Mech; import io.anuke.mindustry.resource.Weapon; import io.anuke.mindustry.world.Tile; import io.anuke.mindustry.world.blocks.Blocks; -import io.anuke.ucore.core.*; +import io.anuke.ucore.core.Effects; +import io.anuke.ucore.core.Inputs; +import io.anuke.ucore.core.Settings; +import io.anuke.ucore.core.Timers; import io.anuke.ucore.entities.SolidEntity; import io.anuke.ucore.graphics.Draw; import io.anuke.ucore.util.Angles; @@ -38,7 +41,7 @@ public class Player extends SyncEntity{ public Player(){ hitbox.setSize(5); - hitboxTile.setSize(4f); + hitboxTile.setSize(5f); maxhealth = 200; heal(); @@ -46,7 +49,7 @@ public class Player extends SyncEntity{ @Override public void damage(int amount){ - if(!Vars.debug && !isAndroid) + if(!debug && !isAndroid) super.damage(amount); } @@ -54,7 +57,7 @@ public class Player extends SyncEntity{ public boolean collides(SolidEntity other){ if(other instanceof Bullet){ Bullet b = (Bullet)other; - if(!Vars.control.isFriendlyFire() && b.owner instanceof Player){ + if(!state.friendlyFire && b.owner instanceof Player){ return false; } } @@ -67,7 +70,7 @@ public class Player extends SyncEntity{ if(isLocal){ remove(); if(Net.active()){ - Vars.netClient.handlePlayerDeath(); + NetEvents.handlePlayerDeath(); } Effects.effect(Fx.explosion, this); @@ -77,7 +80,7 @@ public class Player extends SyncEntity{ //TODO respawning doesn't work properly for multiplayer at all if(isLocal) { - Vars.control.setRespawnTime(respawnduration); + control.setRespawnTime(respawnduration); ui.hudfrag.fadeRespawn(true); } } @@ -91,7 +94,7 @@ public class Player extends SyncEntity{ set(-9999, -9999); Timers.run(respawnduration, () -> { heal(); - set(Vars.control.getCore().worldx(), Vars.control.getCore().worldy()); + set(world.getSpawnX(), world.getSpawnY()); }); } @@ -101,8 +104,8 @@ public class Player extends SyncEntity{ angle = Mathf.lerpAngDelta(angle, targetAngle, 0.2f); } - if((Vars.debug && (!Vars.showPlayer || !Vars.showUI)) || (isAndroid && isLocal) ) return; - boolean snap = Vars.snapCamera && Settings.getBool("smoothcam") && Settings.getBool("pixelate") && isLocal; + if((debug && (!showPlayer || !showUI)) || (isAndroid && isLocal) ) return; + boolean snap = snapCamera && Settings.getBool("smoothcam") && Settings.getBool("pixelate") && isLocal; String part = isAndroid ? "ship" : "mech"; @@ -128,7 +131,7 @@ public class Player extends SyncEntity{ @Override public void update(){ - if(!isLocal || isAndroid || Vars.ui.chatfrag.chatOpen()){ + if(!isLocal || isAndroid || ui.chatfrag.chatOpen()){ if(!isDead() && !isLocal) interpolate(); return; } @@ -144,8 +147,9 @@ public class Player extends SyncEntity{ Tile tile = world.tileWorld(x, y); - if(tile != null && tile.floor().liquid && tile.block() == Blocks.air){ - damage(health+1); //drown + //if player is in solid block + if(tile != null && ((tile.floor().liquid && tile.block() == Blocks.air) || tile.solid())){ + damage(health+1); //die instantly } vector.set(0, 0); @@ -158,9 +162,9 @@ public class Player extends SyncEntity{ vector.y += ya*speed; vector.x += xa*speed; - boolean shooting = !Inputs.keyDown("dash") && Inputs.keyDown("shoot") && control.getInput().recipe == null - && !ui.hasMouse() && !control.getInput().onConfigurable(); - + boolean shooting = !Inputs.keyDown("dash") && Inputs.keyDown("shoot") && control.input().recipe == null + && !ui.hasMouse() && !control.input().onConfigurable(); + if(shooting){ weaponLeft.update(player, true); weaponRight.update(player, false); @@ -173,7 +177,7 @@ public class Player extends SyncEntity{ vector.limit(speed); - if(!Vars.noclip){ + if(!noclip){ move(vector.x*Timers.delta(), vector.y*Timers.delta()); }else{ x += vector.x*Timers.delta(); @@ -188,13 +192,13 @@ public class Player extends SyncEntity{ this.angle = Mathf.lerpAngDelta(this.angle, angle, 0.1f); } - x = Mathf.clamp(x, 0, Vars.world.width() * Vars.tilesize); - y = Mathf.clamp(y, 0, Vars.world.height() * Vars.tilesize); + x = Mathf.clamp(x, 0, world.width() * tilesize); + y = Mathf.clamp(y, 0, world.height() * tilesize); } @Override public Player add(){ - return add(Vars.control.playerGroup); + return add(playerGroup); } @Override diff --git a/core/src/io/anuke/mindustry/entities/TileEntity.java b/core/src/io/anuke/mindustry/entities/TileEntity.java index 28e86f42da..816ddb428b 100644 --- a/core/src/io/anuke/mindustry/entities/TileEntity.java +++ b/core/src/io/anuke/mindustry/entities/TileEntity.java @@ -1,13 +1,12 @@ package io.anuke.mindustry.entities; -import io.anuke.mindustry.Vars; import io.anuke.mindustry.entities.enemies.Enemy; import io.anuke.mindustry.graphics.Fx; import io.anuke.mindustry.net.Net; +import io.anuke.mindustry.net.NetEvents; import io.anuke.mindustry.resource.Item; import io.anuke.mindustry.world.Block; import io.anuke.mindustry.world.Tile; -import io.anuke.mindustry.world.blocks.ProductionBlocks; import io.anuke.mindustry.world.blocks.types.Wall; import io.anuke.ucore.core.Effects; import io.anuke.ucore.core.Timers; @@ -19,6 +18,9 @@ import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; +import static io.anuke.mindustry.Vars.tileGroup; +import static io.anuke.mindustry.Vars.world; + public class TileEntity extends Entity{ private static final boolean friendlyFire = false; @@ -64,14 +66,11 @@ public class TileEntity extends Entity{ } public void onDeath(boolean force){ - if(Net.active() && Net.server()){ - Vars.netServer.handleBlockDestroyed(this); + if(Net.server()){ + NetEvents.handleBlockDestroyed(this); } if(!Net.active() || Net.server() || force){ - if(tile.block() == ProductionBlocks.core){ - Vars.control.coreDestroyed(); - } if(!dead) { dead = true; @@ -79,7 +78,7 @@ public class TileEntity extends Entity{ block.onDestroyed(tile); - Vars.world.removeBlock(tile); + world.removeBlock(tile); remove(); } } @@ -96,8 +95,8 @@ public class TileEntity extends Entity{ health -= amount; if(health <= 0) onDeath(); - if(Net.active() && Net.server()){ - Vars.netServer.handleBlockDamaged(this); + if(Net.server()){ + NetEvents.handleBlockDamaged(this); } } @@ -150,6 +149,6 @@ public class TileEntity extends Entity{ @Override public TileEntity add(){ - return add(Vars.control.tileGroup); + return add(tileGroup); } } diff --git a/core/src/io/anuke/mindustry/entities/effect/DamageArea.java b/core/src/io/anuke/mindustry/entities/effect/DamageArea.java index 538f68ccb5..2789d8fc80 100644 --- a/core/src/io/anuke/mindustry/entities/effect/DamageArea.java +++ b/core/src/io/anuke/mindustry/entities/effect/DamageArea.java @@ -2,7 +2,6 @@ package io.anuke.mindustry.entities.effect; import com.badlogic.gdx.math.Rectangle; import com.badlogic.gdx.math.Vector2; -import io.anuke.mindustry.Vars; import io.anuke.mindustry.entities.Player; import io.anuke.mindustry.world.Tile; import io.anuke.ucore.core.Effects; @@ -16,6 +15,8 @@ import io.anuke.ucore.util.Angles; import io.anuke.ucore.util.Mathf; import io.anuke.ucore.util.Physics; +import static io.anuke.mindustry.Vars.*; + public class DamageArea{ private static Rectangle rect = new Rectangle(); @@ -59,14 +60,14 @@ public class DamageArea{ } }; - Entities.getNearby(Vars.control.enemyGroup, rect, cons); - if(Vars.control.isFriendlyFire()) Entities.getNearby(Vars.control.playerGroup, rect, cons); + Entities.getNearby(enemyGroup, rect, cons); + if(state.friendlyFire) Entities.getNearby(playerGroup, rect, cons); } public static void damageEntities(float x, float y, float radius, int damage){ damage(true, x, y, radius, damage); - for(Player player : Vars.control.playerGroup.all()){ + for(Player player : playerGroup.all()){ if(player.isAndroid) continue; int amount = calculateDamage(x, y, player.x, player.y, radius, damage); player.damage(amount); @@ -84,12 +85,12 @@ public class DamageArea{ }; if(enemies){ - Entities.getNearby(Vars.control.enemyGroup, x, y, radius*2, cons); + Entities.getNearby(enemyGroup, x, y, radius*2, cons); }else{ - int trad = (int)(radius / Vars.tilesize); + int trad = (int)(radius / tilesize); for(int dx = -trad; dx <= trad; dx ++){ for(int dy= -trad; dy <= trad; dy ++){ - Tile tile = Vars.world.tile(Mathf.scl2(x, Vars.tilesize) + dx, Mathf.scl2(y, Vars.tilesize) + dy); + Tile tile = world.tile(Mathf.scl2(x, tilesize) + dx, Mathf.scl2(y, tilesize) + dy); if(tile != null && tile.entity != null && Vector2.dst(dx, dy, 0, 0) <= trad){ int amount = calculateDamage(x, y, tile.worldx(), tile.worldy(), radius, damage); tile.entity.damage(amount); @@ -97,7 +98,7 @@ public class DamageArea{ } } - Entities.getNearby(Vars.control.playerGroup, x, y, radius*2, cons); + Entities.getNearby(playerGroup, x, y, radius*2, cons); } } diff --git a/core/src/io/anuke/mindustry/entities/effect/EMP.java b/core/src/io/anuke/mindustry/entities/effect/EMP.java index e1c245cf87..62dc2c81f1 100644 --- a/core/src/io/anuke/mindustry/entities/effect/EMP.java +++ b/core/src/io/anuke/mindustry/entities/effect/EMP.java @@ -4,7 +4,7 @@ import com.badlogic.gdx.graphics.Color; import com.badlogic.gdx.math.Vector2; import com.badlogic.gdx.utils.Array; -import io.anuke.mindustry.Vars; +import static io.anuke.mindustry.Vars.*; import io.anuke.mindustry.graphics.Fx; import io.anuke.mindustry.world.Tile; import io.anuke.mindustry.world.blocks.types.PowerAcceptor; @@ -29,15 +29,15 @@ public class EMP extends TimedEntity{ lifetime = 30f; - int worldx = Mathf.scl2(x, Vars.tilesize); - int worldy = Mathf.scl2(y, Vars.tilesize); + int worldx = Mathf.scl2(x, tilesize); + int worldy = Mathf.scl2(y, tilesize); array.clear(); for(int dx = -radius; dx <= radius; dx ++){ for(int dy = -radius; dy <= radius; dy ++){ if(Vector2.dst(dx, dy, 0, 0) < radius){ - Tile tile = Vars.world.tile(worldx + dx, worldy + dy); + Tile tile = world.tile(worldx + dx, worldy + dy); if(tile != null && tile.block().destructible){ array.add(tile); @@ -80,12 +80,12 @@ public class EMP extends TimedEntity{ } for(int i = 0; i < 14 - targets.size; i ++){ - Angles.translation(Mathf.randomSeed(i + id*77)*360f, radius * Vars.tilesize); + Angles.translation(Mathf.randomSeed(i + id*77)*360f, radius * tilesize); drawLine(x + Angles.x(), y + Angles.y()); } Lines.stroke(fract()*2f); - Lines.poly(x, y, 34, radius * Vars.tilesize); + Lines.poly(x, y, 34, radius * tilesize); Draw.reset(); } diff --git a/core/src/io/anuke/mindustry/entities/effect/Shield.java b/core/src/io/anuke/mindustry/entities/effect/Shield.java index a25743b091..405389e7e6 100644 --- a/core/src/io/anuke/mindustry/entities/effect/Shield.java +++ b/core/src/io/anuke/mindustry/entities/effect/Shield.java @@ -1,18 +1,19 @@ package io.anuke.mindustry.entities.effect; import com.badlogic.gdx.math.Interpolation; - -import io.anuke.mindustry.Vars; import io.anuke.mindustry.entities.enemies.Enemy; import io.anuke.mindustry.world.Tile; import io.anuke.mindustry.world.blocks.types.defense.ShieldBlock; -import io.anuke.ucore.graphics.Draw; import io.anuke.ucore.core.Timers; import io.anuke.ucore.entities.BulletEntity; import io.anuke.ucore.entities.Entities; import io.anuke.ucore.entities.Entity; +import io.anuke.ucore.graphics.Draw; import io.anuke.ucore.util.Mathf; +import static io.anuke.mindustry.Vars.bulletGroup; +import static io.anuke.mindustry.Vars.shieldGroup; + public class Shield extends Entity{ public boolean active; public boolean hitPlayers = false; @@ -52,7 +53,7 @@ public class Shield extends Entity{ ShieldBlock block = (ShieldBlock)tile.block(); - Entities.getNearby(Vars.control.bulletGroup, x, y, block.shieldRadius * 2*uptime + 10, entity->{ + Entities.getNearby(bulletGroup, x, y, block.shieldRadius * 2*uptime + 10, entity->{ BulletEntity bullet = (BulletEntity)entity; if((bullet.owner instanceof Enemy || hitPlayers)){ @@ -85,7 +86,7 @@ public class Shield extends Entity{ @Override public Shield add(){ - return super.add(Vars.control.shieldGroup); + return super.add(shieldGroup); } @Override diff --git a/core/src/io/anuke/mindustry/entities/effect/TeslaOrb.java b/core/src/io/anuke/mindustry/entities/effect/TeslaOrb.java index 5e781f2769..1bd5848d31 100644 --- a/core/src/io/anuke/mindustry/entities/effect/TeslaOrb.java +++ b/core/src/io/anuke/mindustry/entities/effect/TeslaOrb.java @@ -5,7 +5,7 @@ import com.badlogic.gdx.math.Vector2; import com.badlogic.gdx.utils.Array; import com.badlogic.gdx.utils.ObjectSet; -import io.anuke.mindustry.Vars; +import static io.anuke.mindustry.Vars.*; import io.anuke.mindustry.entities.enemies.Enemy; import io.anuke.mindustry.graphics.Fx; import io.anuke.ucore.graphics.Draw; @@ -44,7 +44,7 @@ public class TeslaOrb extends Entity{ break; } - Array enemies = Entities.getNearby(Vars.control.enemyGroup, curx, cury, range*2f); + Array enemies = Entities.getNearby(enemyGroup, curx, cury, range*2f); for(SolidEntity entity : enemies){ if(entity.distanceTo(curx, cury) < range && !hit.contains((Enemy)entity)){ diff --git a/core/src/io/anuke/mindustry/entities/enemies/Enemy.java b/core/src/io/anuke/mindustry/entities/enemies/Enemy.java index e2c6e61982..88cd9559ce 100644 --- a/core/src/io/anuke/mindustry/entities/enemies/Enemy.java +++ b/core/src/io/anuke/mindustry/entities/enemies/Enemy.java @@ -1,11 +1,11 @@ package io.anuke.mindustry.entities.enemies; import com.badlogic.gdx.math.Vector2; -import io.anuke.mindustry.Vars; import io.anuke.mindustry.entities.Bullet; import io.anuke.mindustry.entities.BulletType; import io.anuke.mindustry.entities.SyncEntity; import io.anuke.mindustry.net.Net; +import io.anuke.mindustry.net.NetEvents; import io.anuke.ucore.entities.Entity; import io.anuke.ucore.entities.SolidEntity; import io.anuke.ucore.util.Angles; @@ -14,6 +14,8 @@ import io.anuke.ucore.util.Timer; import java.nio.ByteBuffer; +import static io.anuke.mindustry.Vars.enemyGroup; + public class Enemy extends SyncEntity { public final EnemyType type; @@ -69,7 +71,7 @@ public class Enemy extends SyncEntity { @Override public void onDeath(){ - type.onDeath(this); + type.onDeath(this, false); } @Override @@ -88,7 +90,7 @@ public class Enemy extends SyncEntity { @Override public Enemy add(){ - return add(Vars.control.enemyGroup); + return add(enemyGroup); } @Override @@ -130,14 +132,14 @@ public class Enemy extends SyncEntity { public void shoot(BulletType bullet, float rotation){ - if(!(Net.active() && Net.client())) { + if(!(Net.client())) { Angles.translation(angle + rotation, type.length); Bullet out = new Bullet(bullet, this, x + Angles.x(), y + Angles.y(), this.angle + rotation).add(); - out.damage = (int) ((bullet.damage * (1 + (tier - 1) * 1f)) * Vars.multiplier); + out.damage = (int) ((bullet.damage * (1 + (tier - 1) * 1f))); type.onShoot(this, bullet, rotation); - if(Net.active() && Net.server()){ - Vars.netServer.handleBullet(bullet, this, x + Angles.x(), y + Angles.y(), this.angle + rotation, (short)out.damage); + if(Net.server()){ + NetEvents.handleBullet(bullet, this, x + Angles.x(), y + Angles.y(), this.angle + rotation, (short)out.damage); } } } diff --git a/core/src/io/anuke/mindustry/entities/enemies/EnemyType.java b/core/src/io/anuke/mindustry/entities/enemies/EnemyType.java index 59452857b2..03eed162a1 100644 --- a/core/src/io/anuke/mindustry/entities/enemies/EnemyType.java +++ b/core/src/io/anuke/mindustry/entities/enemies/EnemyType.java @@ -3,25 +3,25 @@ package io.anuke.mindustry.entities.enemies; import com.badlogic.gdx.graphics.Color; import com.badlogic.gdx.math.Vector2; import com.badlogic.gdx.utils.Array; -import io.anuke.mindustry.Vars; import io.anuke.mindustry.entities.BulletType; import io.anuke.mindustry.entities.Player; import io.anuke.mindustry.entities.TileEntity; import io.anuke.mindustry.graphics.Fx; import io.anuke.mindustry.graphics.Shaders; import io.anuke.mindustry.net.Net; +import io.anuke.mindustry.net.NetEvents; import io.anuke.mindustry.world.Tile; import io.anuke.mindustry.world.blocks.Blocks; -import io.anuke.ucore.graphics.Draw; import io.anuke.ucore.core.Effects; import io.anuke.ucore.core.Graphics; import io.anuke.ucore.core.Timers; import io.anuke.ucore.entities.Entities; +import io.anuke.ucore.graphics.Draw; import io.anuke.ucore.util.Mathf; import io.anuke.ucore.util.Strings; import io.anuke.ucore.util.Tmp; -import static io.anuke.mindustry.Vars.world; +import static io.anuke.mindustry.Vars.*; public class EnemyType { @@ -80,11 +80,11 @@ public class EnemyType { Graphics.flush(); - if(Vars.showPaths){ + if(showPaths){ Draw.tscl(0.25f); Draw.text((int)enemy.idletime + "\n" + Strings.toFixed(enemy.totalMove.x, 2) + ", " + Strings.toFixed(enemy.totalMove.x, 2), enemy.x, enemy.y); - Draw.tscl(Vars.fontscale); + Draw.tscl(fontscale); } Shaders.outline.lighten = 0f; @@ -134,20 +134,20 @@ public class EnemyType { enemy.angle = Mathf.slerp(enemy.angle, enemy.angleTo(enemy.target), turretrotatespeed * Timers.delta()); } - enemy.x = Mathf.clamp(enemy.x, 0, Vars.world.width() * Vars.tilesize); - enemy.y = Mathf.clamp(enemy.y, 0, Vars.world.height() * Vars.tilesize); + enemy.x = Mathf.clamp(enemy.x, 0, world.width() * tilesize); + enemy.y = Mathf.clamp(enemy.y, 0, world.height() * tilesize); } 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; } - Tile core = Vars.control.getCore(); + float speed = this.speed + 0.04f * enemy.tier; + float range = this.range + enemy.tier * 5; + + Tile core = world.getCore(); if(enemy.idletime > maxIdleLife){ enemy.onDeath(); @@ -161,7 +161,7 @@ public class EnemyType { vec = Tmp.v1.setZero(); if(targetCore) enemy.target = core.entity; }else{ - vec = Vars.world.pathfinder().find(enemy); + vec = world.pathfinder().find(enemy); vec.sub(enemy.x, enemy.y).limit(speed); } @@ -171,7 +171,7 @@ public class EnemyType { float attractRange = avoidRange + 7f; float avoidSpeed = this.speed/2.7f; - Entities.getNearby(Vars.control.enemyGroup, enemy.x, enemy.y, range, en -> { + Entities.getNearby(enemyGroup, enemy.x, enemy.y, range, en -> { Enemy other = (Enemy)en; if(other == enemy) return; float dst = other.distanceTo(enemy); @@ -194,22 +194,26 @@ 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; } if(enemy.timer.get(timerTarget, 15) && !nearCore){ - enemy.target = Vars.world.findTileTarget(enemy.x, enemy.y, null, range, false); + enemy.target = world.findTileTarget(enemy.x, enemy.y, null, range, false); //no tile found if(enemy.target == null){ - enemy.target = Entities.getClosest(Vars.control.playerGroup, enemy.x, enemy.y, range, e -> !((Player)e).isAndroid); + enemy.target = Entities.getClosest(playerGroup, enemy.x, enemy.y, range, e -> !((Player)e).isAndroid); } }else if(nearCore){ - enemy.target = Vars.control.getCore().entity; + enemy.target = world.getCore().entity; } if(enemy.target != null && bullet != null){ @@ -220,7 +224,7 @@ public class EnemyType { public void updateShooting(Enemy enemy){ float reload = this.reload / Math.max(enemy.tier / 1.5f, 1f); - if(enemy.timer.get(timerReload, reload * Vars.multiplier)){ + if(enemy.timer.get(timerReload, reload)){ shoot(enemy); } } @@ -232,16 +236,18 @@ public class EnemyType { public void onShoot(Enemy enemy, BulletType type, float rotation){} - public void onDeath(Enemy enemy){ - if(Net.active() && Net.server()){ - Vars.netServer.handleEnemyDeath(enemy); + public void onDeath(Enemy enemy, boolean force){ + if(Net.server()){ + NetEvents.handleEnemyDeath(enemy); } - Effects.effect(Fx.explosion, enemy); - Effects.shake(3f, 4f, enemy); - Effects.sound("bang2", enemy); - enemy.remove(); - enemy.dead = true; + if(!Net.client() || force) { + Effects.effect(Fx.explosion, enemy); + Effects.shake(3f, 4f, enemy); + Effects.sound("bang2", enemy); + enemy.remove(); + enemy.dead = true; + } } public void removed(Enemy enemy){ @@ -249,7 +255,7 @@ public class EnemyType { if(enemy.spawner != null){ enemy.spawner.spawned --; }else{ - Vars.control.enemyDeath(); + state.enemies --; } } } 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 e7ca5e17a8..823c7d9d75 100644 --- a/core/src/io/anuke/mindustry/entities/enemies/types/BlastType.java +++ b/core/src/io/anuke/mindustry/entities/enemies/types/BlastType.java @@ -1,8 +1,6 @@ package io.anuke.mindustry.entities.enemies.types; import com.badlogic.gdx.math.Vector2; - -import io.anuke.mindustry.Vars; import io.anuke.mindustry.entities.Bullet; import io.anuke.mindustry.entities.BulletType; import io.anuke.mindustry.entities.TileEntity; @@ -10,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() { @@ -23,15 +23,14 @@ 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(); if(enemy.target instanceof TileEntity){ TileEntity e = (TileEntity)enemy.target; - range = (e.tile.block().width * Vars.tilesize) /2f + 8f; + range = (e.tile.block().width * tilesize) /2f + 8f; offset.set(e.tile.block().getPlaceOffset()); } @@ -41,8 +40,8 @@ public class BlastType extends EnemyType { } @Override - public void onDeath(Enemy enemy){ - super.onDeath(enemy); + public void onDeath(Enemy enemy, boolean force){ + super.onDeath(enemy, force); explode(enemy); } 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 08f3ecc340..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 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,9 +30,9 @@ public class FortressType extends EnemyType { } @Override - public void move(Enemy enemy){ - if(enemy.distanceTo(Vars.control.getCore().worldx(), - Vars.control.getCore().worldy()) <= 90f){ + public void behavior(Enemy enemy){ + if(enemy.distanceTo(world.getCore().worldx(), + world.getCore().worldy()) <= 90f){ if(Timers.get(this, "spawn", spawnTime) && enemy.spawned < maxSpawn){ Angles.translation(enemy.angle, 20f); @@ -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 131f40005a..c2552f4fea 100644 --- a/core/src/io/anuke/mindustry/entities/enemies/types/HealerType.java +++ b/core/src/io/anuke/mindustry/entities/enemies/types/HealerType.java @@ -1,21 +1,23 @@ package io.anuke.mindustry.entities.enemies.types; import com.badlogic.gdx.math.MathUtils; - -import io.anuke.mindustry.Vars; import io.anuke.mindustry.entities.Bullet; import io.anuke.mindustry.entities.BulletType; import io.anuke.mindustry.entities.enemies.Enemy; import io.anuke.mindustry.entities.enemies.EnemyType; import io.anuke.mindustry.graphics.Fx; import io.anuke.mindustry.graphics.Shaders; -import io.anuke.ucore.core.*; +import io.anuke.ucore.core.Effects; +import io.anuke.ucore.core.Graphics; +import io.anuke.ucore.core.Timers; import io.anuke.ucore.entities.Entities; import io.anuke.ucore.graphics.Draw; import io.anuke.ucore.graphics.Hue; import io.anuke.ucore.graphics.Shapes; import io.anuke.ucore.util.Angles; +import static io.anuke.mindustry.Vars.enemyGroup; + public class HealerType extends EnemyType { public HealerType() { @@ -33,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); @@ -46,7 +47,7 @@ public class HealerType extends EnemyType { @Override public void updateTargeting(Enemy enemy, boolean nearCore){ if(enemy.timer.get(timerTarget, 15)){ - enemy.target = Entities.getClosest(Vars.control.enemyGroup, + enemy.target = Entities.getClosest(enemyGroup, enemy.x, enemy.y, range, e -> e instanceof Enemy && e != enemy && ((Enemy)e).healthfrac() < 1f); } diff --git a/core/src/io/anuke/mindustry/entities/enemies/types/TargetType.java b/core/src/io/anuke/mindustry/entities/enemies/types/TargetType.java index dc4443148c..b8e98a7b1e 100644 --- a/core/src/io/anuke/mindustry/entities/enemies/types/TargetType.java +++ b/core/src/io/anuke/mindustry/entities/enemies/types/TargetType.java @@ -1,16 +1,16 @@ package io.anuke.mindustry.entities.enemies.types; import com.badlogic.gdx.graphics.Color; - -import io.anuke.mindustry.Vars; import io.anuke.mindustry.entities.enemies.Enemy; import io.anuke.mindustry.entities.enemies.EnemyType; import io.anuke.mindustry.entities.enemies.EnemyTypes; -import io.anuke.ucore.graphics.Draw; import io.anuke.ucore.core.Timers; +import io.anuke.ucore.graphics.Draw; import io.anuke.ucore.graphics.Lines; import io.anuke.ucore.util.Mathf; +import static io.anuke.mindustry.Vars.control; + public class TargetType extends EnemyType { public TargetType(){ @@ -42,7 +42,7 @@ public class TargetType extends EnemyType { Draw.color(Color.YELLOW); - if(Vars.control.getTutorial().showTarget()){ + if(control.tutorial().showTarget()){ Lines.spikes(enemy.x, enemy.y, 11f + Mathf.sin(Timers.time(), 7f, 1f), 4f, 8, Timers.time()); } @@ -50,8 +50,8 @@ public class TargetType extends EnemyType { } @Override - public void onDeath(Enemy enemy){ - super.onDeath(enemy); + public void onDeath(Enemy enemy, boolean force){ + super.onDeath(enemy, force); Timers.run(100f, ()->{ new Enemy(EnemyTypes.target).set(enemy.x, enemy.y).add(); }); 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/EnemySpawn.java b/core/src/io/anuke/mindustry/game/EnemySpawn.java index bd44b16520..eff8e10a44 100644 --- a/core/src/io/anuke/mindustry/game/EnemySpawn.java +++ b/core/src/io/anuke/mindustry/game/EnemySpawn.java @@ -1,9 +1,10 @@ package io.anuke.mindustry.game; -import io.anuke.mindustry.Vars; import io.anuke.mindustry.entities.enemies.EnemyType; import io.anuke.ucore.util.Mathf; +import static io.anuke.mindustry.Vars.state; + public class EnemySpawn{ /**The enemy type spawned*/ public final EnemyType type; @@ -34,7 +35,7 @@ public class EnemySpawn{ if(wave < after || wave > before || (wave - after) % spacing != 0){ return 0; } - float scaling = this.scaling * Vars.control.getDifficulty().enemyScaling; + float scaling = this.scaling * state.difficulty.enemyScaling; return Math.min(amount-1 + Math.max((int)((wave / spacing) / scaling), 1) + (tier(wave, lane)-1) * tierscaleback, max); } diff --git a/core/src/io/anuke/mindustry/game/EventType.java b/core/src/io/anuke/mindustry/game/EventType.java new file mode 100644 index 0000000000..c900741b7e --- /dev/null +++ b/core/src/io/anuke/mindustry/game/EventType.java @@ -0,0 +1,90 @@ +package io.anuke.mindustry.game; + +import io.anuke.mindustry.core.GameState.State; +import io.anuke.mindustry.entities.BulletType; +import io.anuke.mindustry.entities.TileEntity; +import io.anuke.mindustry.entities.enemies.Enemy; +import io.anuke.mindustry.resource.Weapon; +import io.anuke.mindustry.world.Block; +import io.anuke.mindustry.world.Tile; +import io.anuke.ucore.entities.Entity; +import io.anuke.ucore.function.Event; + +public class EventType { + + public interface PlayEvent extends Event{ + void handle(); + } + + public interface ResetEvent extends Event{ + void handle(); + } + + public interface WaveEvent extends Event{ + void handle(); + } + + public interface GameOverEvent extends Event{ + void handle(); + } + + public interface StateChangeEvent extends Event{ + void handle(State from, State to); + } + + public interface FriendlyFireChange extends Event{ + void handle(boolean on); + } + + public interface BulletEvent extends Event{ + void handle(BulletType type, Entity owner, float x, float y, float angle, short damage); + } + + public interface EnemyDeathEvent extends Event{ + void handle(Enemy enemy); + } + + public interface BlockDestroyEvent extends Event{ + void handle(TileEntity entity); + } + + public interface BlockDamageEvent extends Event{ + void handle(TileEntity entity); + } + + public interface PlayerDeathEvent extends Event{ + void handle(); + } + + public interface BlockConfigEvent extends Event{ + void handle(Tile tile, byte data); + } + + public interface BlockTapEvent extends Event{ + void handle(Tile tile); + } + + public interface WeaponSwitchEvent extends Event{ + void handle(); + } + + public interface UpgradeEvent extends Event{ + void handle(Weapon weapon); + } + + public interface MessageSendEvent extends Event{ + void handle(String message); + } + + public interface ShootEvent extends Event{ + void handle(Weapon weapon, float x, float y, float angle); + } + + public interface PlaceEvent extends Event{ + void handle(int x, int y, Block block, int rotation); + } + + public interface BreakEvent extends Event{ + void handle(int x, int y); + } +} diff --git a/core/src/io/anuke/mindustry/game/Inventory.java b/core/src/io/anuke/mindustry/game/Inventory.java new file mode 100644 index 0000000000..c3b48b6459 --- /dev/null +++ b/core/src/io/anuke/mindustry/game/Inventory.java @@ -0,0 +1,86 @@ +package io.anuke.mindustry.game; + +import io.anuke.mindustry.resource.Item; +import io.anuke.mindustry.resource.ItemStack; + +import java.util.Arrays; + +import static io.anuke.mindustry.Vars.debug; + +public class Inventory { + private final int[] items = new int[Item.getAllItems().size]; + private boolean updated; + + public boolean isUpdated(){ + return updated; + } + + public void setUpdated(boolean updated){ + this.updated = updated; + } + + public void clearItems(){ + updated = true; + Arrays.fill(items, 0); + + addItem(Item.stone, 40); + + if(debug){ + Arrays.fill(items, 99999); + } + } + + public void fill(){ + Arrays.fill(items, 999999999); + } + + public int getAmount(Item item){ + return items[item.id]; + } + + public void addItem(Item item, int amount){ + updated = true; + items[item.id] += amount; + } + + public boolean hasItems(ItemStack[] items){ + for(ItemStack stack : items) + if(!hasItem(stack)) + return false; + return true; + } + + public boolean hasItems(ItemStack[] items, int scaling){ + for(ItemStack stack : items) + if(!hasItem(stack.item, stack.amount * scaling)) + return false; + return true; + } + + public boolean hasItem(ItemStack req){ + updated = true; + return items[req.item.id] >= req.amount; + } + + public boolean hasItem(Item item, int amount){ + updated = true; + return items[item.id] >= amount; + } + + public void removeItem(ItemStack req){ + updated = true; + items[req.item.id] -= req.amount; + if(items[req.item.id] < 0) items[req.item.id] = 0; //prevents negative item glitches in multiplayer + } + + public void removeItems(ItemStack... reqs){ + updated = true; + for(ItemStack req : reqs) + removeItem(req); + } + + public int[] getItems(){ + updated = true; + return items; + } +} diff --git a/core/src/io/anuke/mindustry/game/SpawnPoint.java b/core/src/io/anuke/mindustry/game/SpawnPoint.java index 3c647cab63..62e41e70bb 100644 --- a/core/src/io/anuke/mindustry/game/SpawnPoint.java +++ b/core/src/io/anuke/mindustry/game/SpawnPoint.java @@ -12,4 +12,8 @@ public class SpawnPoint{ public PathFinder finder; public SmoothGraphPath path = new SmoothGraphPath(); public PathFinderRequest request; + + public SpawnPoint(Tile start){ + this.start = start; + } } diff --git a/core/src/io/anuke/mindustry/game/Tutorial.java b/core/src/io/anuke/mindustry/game/Tutorial.java index 847b5f0f35..041a8b79f7 100644 --- a/core/src/io/anuke/mindustry/game/Tutorial.java +++ b/core/src/io/anuke/mindustry/game/Tutorial.java @@ -1,7 +1,6 @@ package io.anuke.mindustry.game; import com.badlogic.gdx.math.GridPoint2; -import io.anuke.mindustry.Vars; import io.anuke.mindustry.core.GameState; import io.anuke.mindustry.core.GameState.State; import io.anuke.mindustry.resource.Item; @@ -19,8 +18,7 @@ import io.anuke.ucore.util.Bundles; import io.anuke.ucore.util.Mathf; import io.anuke.ucore.util.Tmp; -import static io.anuke.mindustry.Vars.control; -import static io.anuke.mindustry.Vars.world; +import static io.anuke.mindustry.Vars.*; public class Tutorial{ private Stage stage; @@ -32,7 +30,7 @@ public class Tutorial{ } public boolean active(){ - return world.getMap() != null && world.getMap().name.equals("tutorial") && !GameState.is(State.menu); + return world.getMap() != null && world.getMap().name.equals("tutorial") && !state.is(State.menu); } public void buildUI(table table){ @@ -73,7 +71,7 @@ public class Tutorial{ //info.setText(stage.text); if(stage.showBlock){ - Tile tile = world.tile(control.getCore().x + stage.blockPlaceX, control.getCore().y + stage.blockPlaceY); + Tile tile = world.tile(world.getCore().x + stage.blockPlaceX, world.getCore().y + stage.blockPlaceY); if(tile.block() == stage.targetBlock && (tile.getRotation() == stage.blockRotation || stage.blockRotation == -1)){ move(true); @@ -88,7 +86,7 @@ public class Tutorial{ public void complete(){ //new TextDialog("Congratulations!", "You have completed the tutorial!").padText(Unit.dp.inPixels(10f)).show(); - GameState.set(State.menu); + state.set(State.menu); reset(); } @@ -104,7 +102,7 @@ public class Tutorial{ if(current < 0 || current >= Stage.values().length){ break; - }else if(Vars.android == Stage.values()[current].androidOnly || Vars.android != Stage.values()[current].desktopOnly){ + }else if(android == Stage.values()[current].androidOnly || android != Stage.values()[current].desktopOnly){ stage = Stage.values()[current]; stage.onSwitch(); break; @@ -121,7 +119,7 @@ public class Tutorial{ if(current < 0 || current >= Stage.values().length){ return false; - }else if(Vars.android == Stage.values()[current].androidOnly || Vars.android != Stage.values()[current].desktopOnly){ + }else if(android == Stage.values()[current].androidOnly || android != Stage.values()[current].desktopOnly){ return true; } } @@ -198,7 +196,7 @@ public class Tutorial{ } void onSwitch(){ - Vars.ui.find("sectionbuttondistribution").fireClick(); + ui.find("sectionbuttondistribution").fireClick(); } }, placeConveyorDesktop{ @@ -232,7 +230,7 @@ public class Tutorial{ } void onSwitch(){ - //Vars.player.recipe = null; + //player.recipe = null; } }, placeDrill{ @@ -247,7 +245,7 @@ public class Tutorial{ } void onSwitch(){ - Vars.ui.find("sectionbuttonproduction").fireClick(); + ui.find("sectionbuttonproduction").fireClick(); } }, blockInfo{ @@ -273,7 +271,7 @@ public class Tutorial{ } void onSwitch(){ - control.getInput().recipe = null; + control.input().recipe = null; } }, drillInfo{ @@ -291,12 +289,12 @@ public class Tutorial{ void onSwitch(){ for(int flip : new int[]{1, -1}){ - world.tile(control.getCore().x + flip, control.getCore().y - 2).setBlock(DistributionBlocks.conveyor, 2 * flip); - world.tile(control.getCore().x + flip*2, control.getCore().y - 2).setBlock(DistributionBlocks.conveyor, 2 * flip); - world.tile(control.getCore().x + flip*2, control.getCore().y - 3).setBlock(DistributionBlocks.conveyor, 2 * flip); - world.tile(control.getCore().x + flip*2, control.getCore().y - 3).setBlock(DistributionBlocks.conveyor, 1); - world.tile(control.getCore().x + flip*2, control.getCore().y - 4).setFloor(Blocks.stone); - world.tile(control.getCore().x + flip*2, control.getCore().y - 4).setBlock(ProductionBlocks.stonedrill); + world.tile(world.getCore().x + flip, world.getCore().y - 2).setBlock(DistributionBlocks.conveyor, 2 * flip); + world.tile(world.getCore().x + flip*2, world.getCore().y - 2).setBlock(DistributionBlocks.conveyor, 2 * flip); + world.tile(world.getCore().x + flip*2, world.getCore().y - 3).setBlock(DistributionBlocks.conveyor, 2 * flip); + world.tile(world.getCore().x + flip*2, world.getCore().y - 3).setBlock(DistributionBlocks.conveyor, 1); + world.tile(world.getCore().x + flip*2, world.getCore().y - 4).setFloor(Blocks.stone); + world.tile(world.getCore().x + flip*2, world.getCore().y - 4).setBlock(ProductionBlocks.stonedrill); } } @@ -335,7 +333,7 @@ public class Tutorial{ } void onSwitch(){ - Vars.ui.find("sectionbuttonweapon").fireClick(); + ui.find("sectionbuttonweapon").fireClick(); } }, placedTurretAmmo{ @@ -345,10 +343,10 @@ public class Tutorial{ void onSwitch(){ for(int i = 0; i < 4; i ++){ - world.tile(control.getCore().x + 2, control.getCore().y - 2 + i).setBlock(DistributionBlocks.conveyor, 1); + world.tile(world.getCore().x + 2, world.getCore().y - 2 + i).setBlock(DistributionBlocks.conveyor, 1); } - control.getInput().recipe = null; + control.input().recipe = null; } }, turretExplanation{ @@ -375,31 +373,7 @@ public class Tutorial{ } }, //TODO re-add tutorial on weapons - /* - purchaseWeapons{ - { - desktopOnly = true; - canBack = false; - } - - void onSwitch(){ - Vars.control.addItem(Item.steel, 60); - Vars.control.addItem(Item.iron, 60); - } - }, - switchWeapons{ - { - canBack = false; - desktopOnly = true; - } - - void onSwitch(){ - if(!Vars.control.getWeapons().contains(Weapon.triblaster, true)){ - Vars.control.getWeapons().add(Weapon.triblaster); - Vars.ui.hudfrag.updateWeapons(); - } - } - },*/ + spawnWave{ float warmup = 0f; { @@ -409,14 +383,14 @@ public class Tutorial{ void update(Tutorial t){ warmup += Timers.delta(); - if(Vars.control.getEnemiesRemaining() == 0 && warmup > 60f){ + if(state.enemies == 0 && warmup > 60f){ t.move(true); } } void onSwitch(){ warmup = 0f; - Vars.control.runWave(); + logic.runWave(); } }, pumpDesc{ @@ -436,9 +410,9 @@ public class Tutorial{ } void onSwitch(){ - Vars.ui.find("sectionbuttonproduction").fireClick(); - Vars.control.addItem(Item.steel, 60); - Vars.control.addItem(Item.iron, 60); + ui.find("sectionbuttonproduction").fireClick(); + state.inventory.addItem(Item.steel, 60); + state.inventory.addItem(Item.iron, 60); } }, conduitUse{ @@ -454,8 +428,8 @@ public class Tutorial{ } void onSwitch(){ - Vars.ui.find("sectionbuttondistribution").fireClick(); - world.tile(blockPlaceX + control.getCore().x, blockPlaceY + control.getCore().y).setBlock(Blocks.air); + ui.find("sectionbuttondistribution").fireClick(); + world.tile(blockPlaceX + world.getCore().x, blockPlaceY + world.getCore().y).setBlock(Blocks.air); } }, conduitUse2{ @@ -471,7 +445,7 @@ public class Tutorial{ } void onSwitch(){ - world.tile(blockPlaceX + control.getCore().x, blockPlaceY + control.getCore().y).setBlock(Blocks.air); + world.tile(blockPlaceX + world.getCore().x, blockPlaceY + world.getCore().y).setBlock(Blocks.air); } }, conduitUse3{ @@ -487,7 +461,7 @@ public class Tutorial{ } void onSwitch(){ - world.tile(blockPlaceX + control.getCore().x, blockPlaceY + control.getCore().y).setBlock(Blocks.air); + world.tile(blockPlaceX + world.getCore().x, blockPlaceY + world.getCore().y).setBlock(Blocks.air); } }, generator{ @@ -502,10 +476,10 @@ public class Tutorial{ } void onSwitch(){ - world.tile(blockPlaceX + control.getCore().x, blockPlaceY + control.getCore().y).setBlock(Blocks.air); - Vars.ui.find("sectionbuttonpower").fireClick(); - Vars.control.addItem(Item.steel, 60); - Vars.control.addItem(Item.iron, 60); + world.tile(blockPlaceX + world.getCore().x, blockPlaceY + world.getCore().y).setBlock(Blocks.air); + ui.find("sectionbuttonpower").fireClick(); + state.inventory.addItem(Item.steel, 60); + state.inventory.addItem(Item.iron, 60); } }, generatorExplain{ @@ -526,7 +500,7 @@ public class Tutorial{ } void onSwitch(){ - Vars.ui.find("sectionbuttonpower").fireClick(); + ui.find("sectionbuttonpower").fireClick(); } }, laserExplain{ @@ -552,7 +526,7 @@ public class Tutorial{ } void onSwitch(){ - Vars.ui.find("sectionbuttonpower").fireClick(); + ui.find("sectionbuttonpower").fireClick(); } }, healingTurretExplain{ @@ -573,9 +547,9 @@ public class Tutorial{ } void onSwitch(){ - Vars.control.addItem(Item.stone, 40); - Vars.control.addItem(Item.iron, 40); - Vars.ui.find("sectionbuttoncrafting").fireClick(); + state.inventory.addItem(Item.stone, 40); + state.inventory.addItem(Item.iron, 40); + ui.find("sectionbuttoncrafting").fireClick(); } }, @@ -586,18 +560,18 @@ public class Tutorial{ void onSwitch(){ for(int i = 0; i < 5; i ++){ - world.tile(control.getCore().x, control.getCore().y - 6 + i).setBlock(DistributionBlocks.conveyor, 1); + world.tile(world.getCore().x, world.getCore().y - 6 + i).setBlock(DistributionBlocks.conveyor, 1); } - world.tile(control.getCore().x, control.getCore().y - 6 + 1).setBlock(DistributionBlocks.tunnel, 3); - world.tile(control.getCore().x, control.getCore().y - 6 + 2).setBlock(DefenseBlocks.stonewall, 0); - world.tile(control.getCore().x, control.getCore().y - 6 + 3).setBlock(DistributionBlocks.tunnel, 1); + world.tile(world.getCore().x, world.getCore().y - 6 + 1).setBlock(DistributionBlocks.tunnel, 3); + world.tile(world.getCore().x, world.getCore().y - 6 + 2).setBlock(DefenseBlocks.stonewall, 0); + world.tile(world.getCore().x, world.getCore().y - 6 + 3).setBlock(DistributionBlocks.tunnel, 1); - world.tile(control.getCore().x+1, control.getCore().y - 8).setBlock(ProductionBlocks.irondrill); - world.tile(control.getCore().x-1, control.getCore().y - 8).setBlock(ProductionBlocks.coaldrill); + world.tile(world.getCore().x+1, world.getCore().y - 8).setBlock(ProductionBlocks.irondrill); + world.tile(world.getCore().x-1, world.getCore().y - 8).setBlock(ProductionBlocks.coaldrill); - world.tile(control.getCore().x+1, control.getCore().y - 7).setBlock(DistributionBlocks.conveyor, 2); - world.tile(control.getCore().x-1, control.getCore().y - 7).setBlock(DistributionBlocks.conveyor, 0); + world.tile(world.getCore().x+1, world.getCore().y - 7).setBlock(DistributionBlocks.conveyor, 2); + world.tile(world.getCore().x-1, world.getCore().y - 7).setBlock(DistributionBlocks.conveyor, 0); } }, tunnelExplain{ diff --git a/core/src/io/anuke/mindustry/game/UpgradeInventory.java b/core/src/io/anuke/mindustry/game/UpgradeInventory.java new file mode 100644 index 0000000000..24fadf2d12 --- /dev/null +++ b/core/src/io/anuke/mindustry/game/UpgradeInventory.java @@ -0,0 +1,25 @@ +package io.anuke.mindustry.game; + +import com.badlogic.gdx.utils.Array; +import io.anuke.mindustry.resource.Weapon; + +public class UpgradeInventory { + private final Array weapons = new Array<>(); + + public boolean hasWeapon(Weapon weapon){ + return weapons.contains(weapon, true); + } + + public void addWeapon(Weapon weapon){ + weapons.add(weapon); + } + + public Array getWeapons(){ + return weapons; + } + + public void reset(){ + weapons.clear(); + weapons.add(Weapon.blaster); + } +} diff --git a/core/src/io/anuke/mindustry/graphics/BlockRenderer.java b/core/src/io/anuke/mindustry/graphics/BlockRenderer.java index 78dc8e902c..7a610a5518 100644 --- a/core/src/io/anuke/mindustry/graphics/BlockRenderer.java +++ b/core/src/io/anuke/mindustry/graphics/BlockRenderer.java @@ -5,8 +5,6 @@ import com.badlogic.gdx.graphics.Color; import com.badlogic.gdx.graphics.GL20; import com.badlogic.gdx.graphics.OrthographicCamera; import com.badlogic.gdx.utils.Array; -import io.anuke.mindustry.Vars; -import io.anuke.mindustry.core.GameState; import io.anuke.mindustry.core.GameState.State; import io.anuke.mindustry.game.SpawnPoint; import io.anuke.mindustry.world.Block; @@ -15,9 +13,9 @@ import io.anuke.mindustry.world.Tile; import io.anuke.mindustry.world.blocks.Blocks; import io.anuke.mindustry.world.blocks.types.StaticBlock; import io.anuke.ucore.core.Core; -import io.anuke.ucore.graphics.Draw; import io.anuke.ucore.core.Graphics; import io.anuke.ucore.graphics.CacheBatch; +import io.anuke.ucore.graphics.Draw; import io.anuke.ucore.graphics.Lines; import io.anuke.ucore.util.Mathf; @@ -89,7 +87,7 @@ public class BlockRenderer{ if(!(block instanceof StaticBlock)){ if(block == Blocks.air){ - if(!GameState.is(State.paused)) tile.floor().update(tile); + if(!state.is(State.paused)) tile.floor().update(tile); }else{ if(!expanded){ @@ -190,11 +188,11 @@ public class BlockRenderer{ Draw.reset(); - if(Vars.showPaths && Vars.debug){ + if(showPaths && debug){ drawPaths(); } - if(Vars.debug && Vars.debugChunks){ + if(debug && debugChunks){ Draw.color(Color.YELLOW); Lines.stroke(1f); for(int x = -crangex; x <= crangex; x++){ @@ -213,7 +211,7 @@ public class BlockRenderer{ void drawPaths(){ Draw.color(Color.RED); - for(SpawnPoint point : control.getSpawnPoints()){ + for(SpawnPoint point : world.getSpawns()){ if(point.pathTiles != null){ for(int i = 1; i < point.pathTiles.length; i ++){ Lines.line(point.pathTiles[i-1].worldx(), point.pathTiles[i-1].worldy(), @@ -280,6 +278,6 @@ public class BlockRenderer{ private void createBatch(){ if(cbatch != null) cbatch.dispose(); - cbatch = new CacheBatch(Vars.world.width() * Vars.world.height() * 4); + cbatch = new CacheBatch(world.width() * world.height() * 4); } } diff --git a/core/src/io/anuke/mindustry/graphics/Fx.java b/core/src/io/anuke/mindustry/graphics/Fx.java index a54f16e981..179eb02676 100644 --- a/core/src/io/anuke/mindustry/graphics/Fx.java +++ b/core/src/io/anuke/mindustry/graphics/Fx.java @@ -2,15 +2,17 @@ package io.anuke.mindustry.graphics; import com.badlogic.gdx.graphics.Color; import com.badlogic.gdx.graphics.Colors; -import io.anuke.mindustry.Vars; -import io.anuke.ucore.graphics.Draw; import io.anuke.ucore.core.Effects.Effect; +import io.anuke.ucore.graphics.Draw; import io.anuke.ucore.graphics.Hue; import io.anuke.ucore.graphics.Lines; import io.anuke.ucore.graphics.Shapes; import io.anuke.ucore.util.Angles; import io.anuke.ucore.util.Mathf; +import static io.anuke.mindustry.Vars.respawnduration; +import static io.anuke.mindustry.Vars.tilesize; + public class Fx{ public static Color lightRed = Hue.mix(Color.WHITE, Color.FIREBRICK, 0.1f); public static Color lightOrange = Color.valueOf("f68021"); @@ -249,31 +251,31 @@ public class Fx{ place = new Effect(16, e -> { Lines.stroke(3f - e.ifract() * 2f); - Lines.square(e.x, e.y, Vars.tilesize / 2f + e.ifract() * 3f); + Lines.square(e.x, e.y, tilesize / 2f + e.ifract() * 3f); Draw.reset(); }), dooropen = new Effect(10, e -> { Lines.stroke(e.fract() * 1.6f); - Lines.square(e.x, e.y, Vars.tilesize / 2f + e.ifract() * 2f); + Lines.square(e.x, e.y, tilesize / 2f + e.ifract() * 2f); Draw.reset(); }), doorclose= new Effect(10, e -> { Lines.stroke(e.fract() * 1.6f); - Lines.square(e.x, e.y, Vars.tilesize / 2f + e.fract() * 2f); + Lines.square(e.x, e.y, tilesize / 2f + e.fract() * 2f); Draw.reset(); }), dooropenlarge = new Effect(10, e -> { Lines.stroke(e.fract() * 1.6f); - Lines.square(e.x, e.y, Vars.tilesize + e.ifract() * 2f); + Lines.square(e.x, e.y, tilesize + e.ifract() * 2f); Draw.reset(); }), doorcloselarge = new Effect(10, e -> { Lines.stroke(e.fract() * 1.6f); - Lines.square(e.x, e.y, Vars.tilesize + e.fract() * 2f); + Lines.square(e.x, e.y, tilesize + e.fract() * 2f); Draw.reset(); }), @@ -502,7 +504,7 @@ public class Fx{ Draw.reset(); }), - respawn = new Effect(Vars.respawnduration, e -> { + respawn = new Effect(respawnduration, e -> { Draw.tcolor(Color.SCARLET); Draw.tscl(0.25f); Draw.text("Respawning in " + (int)((e.lifetime-e.time)/60), e.x, e.y); diff --git a/core/src/io/anuke/mindustry/input/AndroidInput.java b/core/src/io/anuke/mindustry/input/AndroidInput.java index 73731f875f..026bec9c32 100644 --- a/core/src/io/anuke/mindustry/input/AndroidInput.java +++ b/core/src/io/anuke/mindustry/input/AndroidInput.java @@ -3,10 +3,9 @@ package io.anuke.mindustry.input; import com.badlogic.gdx.Gdx; import com.badlogic.gdx.input.GestureDetector; import com.badlogic.gdx.math.Vector2; -import io.anuke.mindustry.Vars; -import io.anuke.mindustry.core.GameState; import io.anuke.mindustry.core.GameState.State; import io.anuke.mindustry.net.Net; +import io.anuke.mindustry.net.NetEvents; import io.anuke.mindustry.resource.ItemStack; import io.anuke.mindustry.world.Tile; import io.anuke.ucore.core.Graphics; @@ -73,7 +72,7 @@ public class AndroidInput extends InputHandler{ warmup = 0; - if(!GameState.is(State.menu)){ + if(!state.is(State.menu)){ Tile cursor = world.tile(Mathf.scl2(Graphics.mouseWorld().x, tilesize), Mathf.scl2(Graphics.mouseWorld().y, tilesize)); if(cursor != null && !ui.hasMouse(screenX, screenY)){ Tile linked = cursor.isLinked() ? cursor.getLinked() : cursor; @@ -85,7 +84,7 @@ public class AndroidInput extends InputHandler{ if(linked != null) { linked.block().tapped(linked); - if(Net.active()) netClient.handleBlockTap(linked); + if(Net.active()) NetEvents.handleBlockTap(linked); } } } @@ -125,8 +124,8 @@ public class AndroidInput extends InputHandler{ float xa = Inputs.getAxis("move_x"); float ya = Inputs.getAxis("move_y"); - if(Math.abs(xa) < Vars.controllerMin) xa = 0; - if(Math.abs(ya) < Vars.controllerMin) ya = 0; + if(Math.abs(xa) < controllerMin) xa = 0; + if(Math.abs(ya) < controllerMin) ya = 0; player.x += xa * 4f; player.y += ya * 4f; @@ -173,15 +172,15 @@ public class AndroidInput extends InputHandler{ public boolean tryPlaceBlock(int x, int y, boolean sound){ if(recipe != null && validPlace(x, y, recipe.result) && cursorNear() && - Vars.control.hasItems(recipe.requirements)){ + state.inventory.hasItems(recipe.requirements)){ placeBlock(x, y, recipe.result, rotation, true, sound); for(ItemStack stack : recipe.requirements){ - Vars.control.removeItem(stack); + state.inventory.removeItem(stack); } - if(!Vars.control.hasItems(recipe.requirements)){ + if(!state.inventory.hasItems(recipe.requirements)){ Cursors.restoreCursor(); } return true; diff --git a/core/src/io/anuke/mindustry/input/DefaultKeybinds.java b/core/src/io/anuke/mindustry/input/DefaultKeybinds.java new file mode 100644 index 0000000000..1cd7fda6b2 --- /dev/null +++ b/core/src/io/anuke/mindustry/input/DefaultKeybinds.java @@ -0,0 +1,64 @@ +package io.anuke.mindustry.input; + +import com.badlogic.gdx.Application.ApplicationType; +import com.badlogic.gdx.Gdx; +import io.anuke.ucore.core.Inputs.Axis; +import io.anuke.ucore.core.Inputs.DeviceType; +import io.anuke.ucore.core.KeyBinds; +import io.anuke.ucore.util.Input; + +public class DefaultKeybinds { + + public static void load(){ + KeyBinds.defaults( + "move_x", new Axis(Input.A, Input.D), + "move_y", new Axis(Input.S, Input.W), + "select", Input.MOUSE_LEFT, + "break", Input.MOUSE_RIGHT, + "shoot", Input.MOUSE_LEFT, + "zoom_hold", Input.CONTROL_LEFT, + "zoom", new Axis(Input.SCROLL), + "menu", Gdx.app.getType() == ApplicationType.Android ? Input.BACK : Input.ESCAPE, + "pause", Input.SPACE, + "dash", Input.SHIFT_LEFT, + "rotate_alt", new Axis(Input.R, Input.E), + "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, + "weapon_4", Input.NUM_4, + "weapon_5", Input.NUM_5, + "weapon_6", Input.NUM_6 + ); + + KeyBinds.defaults( + DeviceType.controller, + "move_x", new Axis(Input.CONTROLLER_L_STICK_HORIZONTAL_AXIS), + "move_y", new Axis(Input.CONTROLLER_L_STICK_VERTICAL_AXIS), + "cursor_x", new Axis(Input.CONTROLLER_R_STICK_HORIZONTAL_AXIS), + "cursor_y", new Axis(Input.CONTROLLER_R_STICK_VERTICAL_AXIS), + "select", Input.CONTROLLER_R_BUMPER, + "break", Input.CONTROLLER_L_BUMPER, + "shoot", Input.CONTROLLER_R_TRIGGER, + "zoom_hold", Input.ANY_KEY, + "zoom", new Axis(Input.CONTROLLER_DPAD_DOWN, Input.CONTROLLER_DPAD_UP), + "menu", Input.CONTROLLER_X, + "pause", Input.CONTROLLER_L_TRIGGER, + "dash", Input.CONTROLLER_Y, + "rotate_alt", new Axis(Input.CONTROLLER_DPAD_RIGHT, Input.CONTROLLER_DPAD_LEFT), + "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, + "weapon_4", Input.NUM_4, + "weapon_5", Input.NUM_5, + "weapon_6", Input.NUM_6 + ); + } +} diff --git a/core/src/io/anuke/mindustry/input/DesktopInput.java b/core/src/io/anuke/mindustry/input/DesktopInput.java index 2d42e5f80e..3c54073b7a 100644 --- a/core/src/io/anuke/mindustry/input/DesktopInput.java +++ b/core/src/io/anuke/mindustry/input/DesktopInput.java @@ -2,11 +2,9 @@ package io.anuke.mindustry.input; import com.badlogic.gdx.Gdx; import com.badlogic.gdx.math.Vector2; -import io.anuke.mindustry.Vars; -import io.anuke.mindustry.core.GameState; import io.anuke.mindustry.core.GameState.State; import io.anuke.mindustry.net.Net; -import io.anuke.mindustry.resource.Weapon; +import io.anuke.mindustry.net.NetEvents; import io.anuke.mindustry.world.Tile; import io.anuke.ucore.core.Graphics; import io.anuke.ucore.core.Inputs; @@ -60,7 +58,7 @@ public class DesktopInput extends InputHandler{ boolean controller = KeyBinds.getSection("default").device.type == DeviceType.controller; if(Inputs.getAxisActive("zoom") && (Inputs.keyDown("zoom_hold") || controller) - && !GameState.is(State.menu) && !ui.hasDialog()){ + && !state.is(State.menu) && !ui.hasDialog()){ if((!zoomed || !controller)) { renderer.scaleCamera((int) Inputs.getAxis("zoom")); } @@ -89,11 +87,11 @@ public class DesktopInput extends InputHandler{ breakMode = PlaceMode.hold; } - for(int i = 1; i <= 6 && i <= control.getWeapons().size; i ++){ + for(int i = 1; i <= 6 && i <= control.upgrades().getWeapons().size; i ++){ if(Inputs.keyTap("weapon_" + i)){ - player.weaponLeft = player.weaponRight = control.getWeapons().get(i - 1); - if(Net.active()) Vars.netClient.handleWeaponSwitch(); - Vars.ui.hudfrag.updateWeapons(); + player.weaponLeft = player.weaponRight = control.upgrades().getWeapons().get(i - 1); + if(Net.active()) NetEvents.handleWeaponSwitch(); + ui.hudfrag.updateWeapons(); } } @@ -109,7 +107,7 @@ public class DesktopInput extends InputHandler{ if(linked != null) { linked.block().tapped(linked); - if(Net.active()) netClient.handleBlockTap(linked); + if(Net.active()) NetEvents.handleBlockTap(linked); } } @@ -151,16 +149,6 @@ public class DesktopInput extends InputHandler{ recipe.result.height % 2 == 0) ? Mathf.scl(Graphics.mouseWorld().y, tilesize) : Mathf.scl2(Graphics.mouseWorld().y, tilesize); } - - public int currentWeapon(){ - int i = 0; - for(Weapon weapon : control.getWeapons()){ - if(weapon == weapon) - return i; - i ++; - } - return 0; - } @Override public boolean keyDown(int keycode) { diff --git a/core/src/io/anuke/mindustry/input/GestureHandler.java b/core/src/io/anuke/mindustry/input/GestureHandler.java index c04a94ed2a..0b67076a93 100644 --- a/core/src/io/anuke/mindustry/input/GestureHandler.java +++ b/core/src/io/anuke/mindustry/input/GestureHandler.java @@ -3,7 +3,6 @@ package io.anuke.mindustry.input; import com.badlogic.gdx.Gdx; import com.badlogic.gdx.input.GestureDetector.GestureAdapter; import com.badlogic.gdx.math.Vector2; -import io.anuke.mindustry.Vars; import io.anuke.ucore.core.Core; import io.anuke.ucore.core.Inputs; import io.anuke.ucore.scene.ui.layout.Unit; @@ -31,29 +30,30 @@ public class GestureHandler extends GestureAdapter{ public boolean tap (float x, float y, int count, int button) { if(ui.hasMouse() || input.brokeBlock) return false; - if(!control.getInput().placeMode.pan || control.getInput().recipe == null){ + if(!control.input().placeMode.pan || control.input().recipe == null){ input.mousex = x; input.mousey = y; - if(control.getInput().recipe == null) - control.getInput().breakMode.tapped(input.getBlockX(), input.getBlockY()); + if(control.input().recipe == null) + control.input().breakMode.tapped(input.getBlockX(), input.getBlockY()); else - control.getInput().placeMode.tapped(input.getBlockX(), input.getBlockY()); + control.input().placeMode.tapped(input.getBlockX(), input.getBlockY()); } return false; } @Override public boolean pan(float x, float y, float deltaX, float deltaY){ - if(Vars.control.showCursor() && !Inputs.keyDown("select")) return false; + if(control.showCursor() && !Inputs.keyDown("select")) return false; - if(!Vars.control.showCursor() && !(control.getInput().recipe != null && Vars.control.hasItems(control.getInput().recipe.requirements) && control.getInput().placeMode.lockCamera) && - !(control.getInput().recipe == null && control.getInput().breakMode.lockCamera)){ + if(!control.showCursor() && !(control.input().recipe != null + && state.inventory.hasItems(control.input().recipe.requirements) && control.input().placeMode.lockCamera) && + !(control.input().recipe == null && control.input().breakMode.lockCamera)){ float dx = deltaX*Core.camera.zoom/Core.cameraScale, dy = deltaY*Core.camera.zoom/Core.cameraScale; player.x -= dx; player.y += dy; player.targetAngle = Mathf.atan2(dx, -dy); - }else if(control.getInput().placeMode.lockCamera && (control.getInput().placeMode.pan && control.getInput().recipe != null)){ + }else if(control.input().placeMode.lockCamera && (control.input().placeMode.pan && control.input().recipe != null)){ input.mousex += deltaX; input.mousey += deltaY; } @@ -63,7 +63,7 @@ public class GestureHandler extends GestureAdapter{ @Override public boolean pinch (Vector2 initialPointer1, Vector2 initialPointer2, Vector2 pointer1, Vector2 pointer2) { - if(control.getInput().recipe == null && !control.getInput().breakMode.lockCamera) + if(control.input().recipe == null && !control.input().breakMode.lockCamera) return false; if(pinch1.x < 0){ diff --git a/core/src/io/anuke/mindustry/input/InputHandler.java b/core/src/io/anuke/mindustry/input/InputHandler.java index 94ff64ac30..a21104a25c 100644 --- a/core/src/io/anuke/mindustry/input/InputHandler.java +++ b/core/src/io/anuke/mindustry/input/InputHandler.java @@ -5,15 +5,15 @@ import com.badlogic.gdx.math.GridPoint2; import com.badlogic.gdx.math.Rectangle; import com.badlogic.gdx.math.Vector2; import com.badlogic.gdx.utils.Array; -import io.anuke.mindustry.Vars; import io.anuke.mindustry.entities.Player; +import io.anuke.mindustry.game.SpawnPoint; import io.anuke.mindustry.graphics.Fx; import io.anuke.mindustry.net.Net; +import io.anuke.mindustry.net.NetEvents; import io.anuke.mindustry.resource.ItemStack; import io.anuke.mindustry.resource.Recipe; import io.anuke.mindustry.resource.Recipes; import io.anuke.mindustry.world.Block; -import io.anuke.mindustry.game.SpawnPoint; import io.anuke.mindustry.world.Tile; import io.anuke.mindustry.world.blocks.Blocks; import io.anuke.mindustry.world.blocks.ProductionBlocks; @@ -27,7 +27,6 @@ import io.anuke.ucore.util.Mathf; import io.anuke.ucore.util.Tmp; import static io.anuke.mindustry.Vars.*; -import static io.anuke.mindustry.Vars.player; public abstract class InputHandler extends InputAdapter{ public float breaktime = 0; @@ -43,15 +42,15 @@ public abstract class InputHandler extends InputAdapter{ public abstract float getCursorY(); public abstract float getCursorEndX(); public abstract float getCursorEndY(); - public int getBlockX(){ return Mathf.sclb(Graphics.world(getCursorX(), getCursorY()).x, Vars.tilesize, round2()); } - public int getBlockY(){ return Mathf.sclb(Graphics.world(getCursorX(), getCursorY()).y, Vars.tilesize, round2()); } - public int getBlockEndX(){ return Mathf.sclb(Graphics.world(getCursorEndX(), getCursorEndY()).x, Vars.tilesize, round2()); } - public int getBlockEndY(){ return Mathf.sclb(Graphics.world(getCursorEndX(), getCursorEndY()).y, Vars.tilesize, round2()); } + public int getBlockX(){ return Mathf.sclb(Graphics.world(getCursorX(), getCursorY()).x, tilesize, round2()); } + public int getBlockY(){ return Mathf.sclb(Graphics.world(getCursorX(), getCursorY()).y, tilesize, round2()); } + public int getBlockEndX(){ return Mathf.sclb(Graphics.world(getCursorEndX(), getCursorEndY()).x, tilesize, round2()); } + public int getBlockEndY(){ return Mathf.sclb(Graphics.world(getCursorEndX(), getCursorEndY()).y, tilesize, round2()); } public void resetCursor(){} public boolean drawPlace(){ return true; } public boolean onConfigurable(){ - Tile tile = Vars.world.tile(getBlockX(), getBlockY()); + Tile tile = world.tile(getBlockX(), getBlockY()); return tile != null && (tile.block().isConfigurable(tile) || (tile.isLinked() && tile.getLinked().block().isConfigurable(tile))); } @@ -62,15 +61,15 @@ public abstract class InputHandler extends InputAdapter{ public boolean tryPlaceBlock(int x, int y, boolean sound){ if(recipe != null && validPlace(x, y, recipe.result) && !ui.hasMouse() && cursorNear() && - Vars.control.hasItems(recipe.requirements)){ + state.inventory.hasItems(recipe.requirements)){ placeBlock(x, y, recipe.result, rotation, true, sound); for(ItemStack stack : recipe.requirements){ - Vars.control.removeItem(stack); + state.inventory.removeItem(stack); } - if(!Vars.control.hasItems(recipe.requirements)){ + if(!state.inventory.hasItems(recipe.requirements)){ Cursors.restoreCursor(); } return true; @@ -92,17 +91,17 @@ public abstract class InputHandler extends InputAdapter{ public boolean validPlace(int x, int y, Block type){ - for(SpawnPoint spawn : control.getSpawnPoints()){ + for(SpawnPoint spawn : world.getSpawns()){ if(Vector2.dst(x * tilesize, y * tilesize, spawn.start.worldx(), spawn.start.worldy()) < enemyspawnspace){ return false; } } - Tmp.r2.setSize(type.width * Vars.tilesize, type.height * Vars.tilesize); + Tmp.r2.setSize(type.width * tilesize, type.height * tilesize); Vector2 offset = type.getPlaceOffset(); - Tmp.r2.setCenter(offset.x + x * Vars.tilesize, offset.y + y * Vars.tilesize); + Tmp.r2.setCenter(offset.x + x * tilesize, offset.y + y * tilesize); - for(SolidEntity e : Entities.getNearby(control.enemyGroup, x * tilesize, y * tilesize, tilesize * 2f)){ + for(SolidEntity e : Entities.getNearby(enemyGroup, x * tilesize, y * tilesize, tilesize * 2f)){ Rectangle rect = e.hitbox.getRect(e.x, e.y); if(Tmp.r2.overlaps(rect)){ @@ -111,7 +110,7 @@ public abstract class InputHandler extends InputAdapter{ } if(type.solid || type.solidifes) { - for (Player player : Vars.control.playerGroup.all()) { + for (Player player : playerGroup.all()) { if (!player.isAndroid && Tmp.r2.overlaps(player.hitbox.getRect(player.x, player.y))) { return false; } @@ -122,18 +121,18 @@ public abstract class InputHandler extends InputAdapter{ if(tile == null) return false; - if(!type.isMultiblock() && Vars.control.getTutorial().active() && - Vars.control.getTutorial().showBlock()){ + if(!type.isMultiblock() && control.tutorial().active() && + control.tutorial().showBlock()){ - GridPoint2 point = Vars.control.getTutorial().getPlacePoint(); - int rotation = Vars.control.getTutorial().getPlaceRotation(); - Block block = Vars.control.getTutorial().getPlaceBlock(); + GridPoint2 point = control.tutorial().getPlacePoint(); + int rotation = control.tutorial().getPlaceRotation(); + Block block = control.tutorial().getPlaceBlock(); - if(type != block || point.x != x - control.getCore().x || point.y != y - control.getCore().y + if(type != block || point.x != x - world.getCore().x || point.y != y - world.getCore().y || (rotation != -1 && rotation != this.rotation)){ return false; } - }else if(Vars.control.getTutorial().active()){ + }else if(control.tutorial().active()){ return false; } @@ -166,14 +165,14 @@ public abstract class InputHandler extends InputAdapter{ return false; } - if(Vars.control.getTutorial().active()){ + if(control.tutorial().active()){ - if(Vars.control.getTutorial().showBlock()){ - GridPoint2 point = Vars.control.getTutorial().getPlacePoint(); - int rotation = Vars.control.getTutorial().getPlaceRotation(); - Block block = Vars.control.getTutorial().getPlaceBlock(); + if(control.tutorial().showBlock()){ + GridPoint2 point = control.tutorial().getPlacePoint(); + int rotation = control.tutorial().getPlaceRotation(); + Block block = control.tutorial().getPlaceBlock(); - if(block != Blocks.air || point.x != x - control.getCore().x || point.y != y - control.getCore().y + if(block != Blocks.air || point.x != x - world.getCore().x || point.y != y - world.getCore().y || (rotation != -1 && rotation != this.rotation)){ return false; } @@ -190,7 +189,7 @@ public abstract class InputHandler extends InputAdapter{ placeBlockInternal(x, y, result, rotation, effects, sound); if(Net.active() && result != ProductionBlocks.core){ - Vars.netClient.handlePlace(x, y, result, rotation); + NetEvents.handlePlace(x, y, result, rotation); } } @@ -217,11 +216,11 @@ public abstract class InputHandler extends InputAdapter{ toplace.setLinked((byte)(dx + offsetx), (byte)(dy + offsety)); } - if(effects) Effects.effect(Fx.place, worldx * Vars.tilesize, worldy * Vars.tilesize); + if(effects) Effects.effect(Fx.place, worldx * tilesize, worldy * tilesize); } } }else{ - if(effects) Effects.effect(Fx.place, x * Vars.tilesize, y * Vars.tilesize); + if(effects) Effects.effect(Fx.place, x * tilesize, y * tilesize); } if(effects && sound) Sounds.play("place"); @@ -233,7 +232,7 @@ public abstract class InputHandler extends InputAdapter{ breakBlockInternal(x, y, sound); if(Net.active()){ - Vars.netClient.handleBreak(x, y); + NetEvents.handleBreak(x, y); } } @@ -254,12 +253,12 @@ public abstract class InputHandler extends InputAdapter{ if(result != null){ for(ItemStack stack : result.requirements){ - Vars.control.addItem(stack.item, (int)(stack.amount * Vars.breakDropAmount)); + state.inventory.addItem(stack.item, (int)(stack.amount * breakDropAmount)); } } if(tile.block().drops != null){ - Vars.control.addItem(tile.block().drops.item, tile.block().drops.amount); + state.inventory.addItem(tile.block().drops.item, tile.block().drops.amount); } //Effects.shake(3f, 1f, player); diff --git a/core/src/io/anuke/mindustry/input/PlaceMode.java b/core/src/io/anuke/mindustry/input/PlaceMode.java index a7806eff7e..d7c3ca9acc 100644 --- a/core/src/io/anuke/mindustry/input/PlaceMode.java +++ b/core/src/io/anuke/mindustry/input/PlaceMode.java @@ -4,12 +4,11 @@ import com.badlogic.gdx.Gdx; import com.badlogic.gdx.graphics.Colors; import com.badlogic.gdx.math.MathUtils; import com.badlogic.gdx.math.Vector2; -import io.anuke.mindustry.Vars; import io.anuke.mindustry.ui.fragments.ToolFragment; import io.anuke.mindustry.world.Block; import io.anuke.mindustry.world.Tile; -import io.anuke.ucore.graphics.Draw; import io.anuke.ucore.core.Timers; +import io.anuke.ucore.graphics.Draw; import io.anuke.ucore.graphics.Lines; import io.anuke.ucore.scene.utils.Cursors; import io.anuke.ucore.util.Bundles; @@ -27,26 +26,26 @@ public enum PlaceMode{ } public void draw(int tilex, int tiley, int endx, int endy){ - float x = tilex * Vars.tilesize; - float y = tiley * Vars.tilesize; + float x = tilex * tilesize; + float y = tiley * tilesize; - boolean valid = control.getInput().validPlace(tilex, tiley, control.getInput().recipe.result) && (android || control.getInput().cursorNear()); + boolean valid = control.input().validPlace(tilex, tiley, control.input().recipe.result) && (android || control.input().cursorNear()); - Vector2 offset = control.getInput().recipe.result.getPlaceOffset(); + Vector2 offset = control.input().recipe.result.getPlaceOffset(); float si = MathUtils.sin(Timers.time() / 6f) + 1.5f; Draw.color(valid ? Colors.get("place") : Colors.get("placeInvalid")); Lines.stroke(2f); - Lines.crect(x + offset.x, y + offset.y, tilesize * control.getInput().recipe.result.width + si, - tilesize * control.getInput().recipe.result.height + si); + Lines.crect(x + offset.x, y + offset.y, tilesize * control.input().recipe.result.width + si, + tilesize * control.input().recipe.result.height + si); - control.getInput().recipe.result.drawPlace(tilex, tiley, control.getInput().rotation, valid); + control.input().recipe.result.drawPlace(tilex, tiley, control.input().rotation, valid); Lines.stroke(2f); - if(control.getInput().recipe.result.rotate){ + if(control.input().recipe.result.rotate){ Draw.color(Colors.get("placeRotate")); - Tmp.v1.set(7, 0).rotate(control.getInput().rotation * 90); + Tmp.v1.set(7, 0).rotate(control.input().rotation * 90); Lines.line(x, y, x + Tmp.v1.x, y + Tmp.v1.y); } @@ -57,7 +56,7 @@ public enum PlaceMode{ } public void tapped(int tilex, int tiley){ - control.getInput().tryPlaceBlock(tilex, tiley, true); + control.input().tryPlaceBlock(tilex, tiley, true); } }, touch{ @@ -69,7 +68,7 @@ public enum PlaceMode{ } public void tapped(int x, int y){ - control.getInput().tryPlaceBlock(x, y, true); + control.input().tryPlaceBlock(x, y, true); } }, none{ @@ -89,12 +88,12 @@ public enum PlaceMode{ public void draw(int tilex, int tiley, int endx, int endy){ Tile tile = world.tile(tilex, tiley); - if(tile != null && control.getInput().validBreak(tilex, tiley)){ + if(tile != null && control.input().validBreak(tilex, tiley)){ if(tile.isLinked()) tile = tile.getLinked(); - float fract = control.getInput().breaktime / tile.getBreakTime(); + float fract = control.input().breaktime / tile.getBreakTime(); - if(android && control.getInput().breaktime > 0){ + if(android && control.input().breaktime > 0){ Draw.color(Colors.get("breakStart"), Colors.get("break"), fract); Lines.poly(tile.drawx(), tile.drawy(), 25, 4 + (1f - fract) * 26); } @@ -112,7 +111,7 @@ public enum PlaceMode{ } public void tapped(int x, int y){ - control.getInput().tryDeleteBlock(x, y, true); + control.input().tryDeleteBlock(x, y, true); } }, areaDelete{ @@ -152,10 +151,10 @@ public enum PlaceMode{ Lines.stroke(1f); for(int cx = tilex; cx <= endx; cx ++){ for(int cy = tiley; cy <= endy; cy ++){ - Tile tile = Vars.world.tile(cx, cy); + Tile tile = world.tile(cx, cy); if(tile != null && tile.getLinked() != null) tile = tile.getLinked(); - if(tile != null && control.getInput().validBreak(tile.x, tile.y)){ + if(tile != null && control.input().validBreak(tile.x, tile.y)){ Lines.crect(tile.drawx(), tile.drawy(), tile.block().width * t, tile.block().height * t); } @@ -163,7 +162,7 @@ public enum PlaceMode{ } Lines.stroke(2f); - Draw.color(control.getInput().cursorNear() ? Colors.get("break") : Colors.get("breakInvalid")); + Draw.color(control.input().cursorNear() ? Colors.get("break") : Colors.get("breakInvalid")); Lines.rect(x, y, x2 - x, y2 - y); Draw.alpha(0.3f); Draw.crect("blank", x, y, x2 - x, y2 - y); @@ -176,8 +175,8 @@ public enum PlaceMode{ tilex = this.tilex; tiley = this.tiley; endx = this.endx; endy = this.endy; - if(Vars.android){ - ToolFragment t = Vars.ui.toolfrag; + if(android){ + ToolFragment t = ui.toolfrag; if(!t.confirming || t.px != tilex || t.py != tiley || t.px2 != endx || t.py2 != endy) { t.confirming = true; t.px = tilex; @@ -192,7 +191,7 @@ public enum PlaceMode{ for(int cx = tilex; cx <= endx; cx ++){ for(int cy = tiley; cy <= endy; cy ++){ - if(control.getInput().tryDeleteBlock(cx, cy, first)){ + if(control.input().tryDeleteBlock(cx, cy, first)){ first = false; } } @@ -242,12 +241,12 @@ public enum PlaceMode{ } public void draw(int tilex, int tiley, int endx, int endy){ - if(Vars.android && !Gdx.input.isTouched(0) && !Vars.control.showCursor()){ + if(android && !Gdx.input.isTouched(0) && !control.showCursor()){ return; } - float t = Vars.tilesize; - Block block = control.getInput().recipe.result; + float t = tilesize; + Block block = control.input().recipe.result; Vector2 offset = block.getPlaceOffset(); process(tilex, tiley, endx, endy); @@ -276,7 +275,7 @@ public enum PlaceMode{ cursor.draw(tilex, tiley, endx, endy); }else{ Lines.stroke(2f); - Draw.color(control.getInput().cursorNear() ? Colors.get("place") : Colors.get("placeInvalid")); + Draw.color(control.input().cursorNear() ? Colors.get("place") : Colors.get("placeInvalid")); Lines.rect(x, y, x2 - x, y2 - y); Draw.alpha(0.3f); Draw.crect("blank", x, y, x2 - x, y2 - y); @@ -289,15 +288,15 @@ public enum PlaceMode{ int px = tx + cx * Mathf.sign(ex - tx), py = ty + cy * Mathf.sign(ey - ty); - if(!control.getInput().validPlace(px, py, control.getInput().recipe.result) - || !control.hasItems(control.getInput().recipe.requirements, amount)){ + if(!control.input().validPlace(px, py, control.input().recipe.result) + || !state.inventory.hasItems(control.input().recipe.requirements, amount)){ Lines.crect(px * t + offset.x, py * t + offset.y, t*block.width, t*block.height); } amount ++; } } - if(control.getInput().recipe.result.rotate){ + if(control.input().recipe.result.rotate){ float cx = tx * t, cy = ty * t; Draw.color(Colors.get("placeRotate")); Tmp.v1.set(7, 0).rotate(rotation * 90); @@ -310,12 +309,12 @@ public enum PlaceMode{ public void released(int tilex, int tiley, int endx, int endy){ process(tilex, tiley, endx, endy); - control.getInput().rotation = this.rotation; + control.input().rotation = this.rotation; boolean first = true; for(int x = 0; x <= Math.abs(this.endx - this.tilex); x ++){ for(int y = 0; y <= Math.abs(this.endy - this.tiley); y ++){ - if(control.getInput().tryPlaceBlock( + if(control.input().tryPlaceBlock( tilex + x * Mathf.sign(endx - tilex), tiley + y * Mathf.sign(endy - tiley), first)){ first = false; @@ -349,7 +348,7 @@ public enum PlaceMode{ else if(endy < tiley) rotation = 3; else - rotation = control.getInput().rotation; + rotation = control.input().rotation; if(endx < tilex){ int t = endx; diff --git a/core/src/io/anuke/mindustry/world/BlockLoader.java b/core/src/io/anuke/mindustry/io/BlockLoader.java similarity index 95% rename from core/src/io/anuke/mindustry/world/BlockLoader.java rename to core/src/io/anuke/mindustry/io/BlockLoader.java index 9586bb18e2..a423a866e8 100644 --- a/core/src/io/anuke/mindustry/world/BlockLoader.java +++ b/core/src/io/anuke/mindustry/io/BlockLoader.java @@ -1,8 +1,10 @@ -package io.anuke.mindustry.world; +package io.anuke.mindustry.io; import com.badlogic.gdx.utils.IntMap; import com.badlogic.gdx.utils.ObjectIntMap; +import io.anuke.mindustry.world.Block; import io.anuke.mindustry.world.blocks.*; +import io.anuke.ucore.util.Log; public class BlockLoader { static final ObjectIntMap defaultMap = map( @@ -120,6 +122,8 @@ public class BlockLoader { Block block = Block.getByName(string); blockmap.put(defaultMap.get(string, -1), block); } + + Log.info("Total blocks loaded: {0}", Block.getAllBlocks().size); } public static Block getByOldID(int id){ diff --git a/core/src/io/anuke/mindustry/io/BundleLoader.java b/core/src/io/anuke/mindustry/io/BundleLoader.java new file mode 100644 index 0000000000..eb61211344 --- /dev/null +++ b/core/src/io/anuke/mindustry/io/BundleLoader.java @@ -0,0 +1,63 @@ +package io.anuke.mindustry.io; + +import com.badlogic.gdx.Gdx; +import com.badlogic.gdx.files.FileHandle; +import com.badlogic.gdx.utils.I18NBundle; +import io.anuke.ucore.core.Core; +import io.anuke.ucore.core.Settings; +import io.anuke.ucore.util.Log; + +import java.util.Locale; + +import static io.anuke.mindustry.Vars.headless; + +public class BundleLoader { + private static boolean externalBundle = false; + + public static void load(){ + Settings.defaults("locale", "default"); + Settings.load("io.anuke.moment"); + loadBundle(); + } + + private static Locale getLocale(){ + String loc = Settings.getString("locale"); + if(loc.equals("default")){ + return Locale.getDefault(); + }else{ + Locale lastLocale; + if (loc.contains("_")) { + String[] split = loc.split("_"); + lastLocale = new Locale(split[0], split[1]); + } else { + lastLocale = new Locale(loc); + } + + return lastLocale; + } + } + + private static void loadBundle(){ + I18NBundle.setExceptionOnMissingKey(false); + + if(externalBundle){ + try { + FileHandle handle = Gdx.files.local("bundle"); + + Locale locale = Locale.ENGLISH; + Core.bundle = I18NBundle.createBundle(handle, locale); + }catch (Exception e){ + Log.err(e); + Platform.instance.showError("Failed to find bundle!\nMake sure you have bundle.properties in the same directory\nas the jar file.\n\nIf the problem persists, try running it through the command prompt:\n" + + "Hold left-shift, then right click and select 'open command prompt here'.\nThen, type in 'java -jar mindustry.jar' without quotes."); + Gdx.app.exit(); + } + }else{ + FileHandle handle = Gdx.files.internal("bundles/bundle"); + + Locale locale = getLocale(); + if(!headless) Log.info("Got locale: {0}", locale); + Core.bundle = I18NBundle.createBundle(handle, locale); + } + } +} diff --git a/core/src/io/anuke/mindustry/io/Maps.java b/core/src/io/anuke/mindustry/io/Maps.java index cbac09284a..fbc56678a4 100644 --- a/core/src/io/anuke/mindustry/io/Maps.java +++ b/core/src/io/anuke/mindustry/io/Maps.java @@ -8,15 +8,17 @@ import com.badlogic.gdx.graphics.Texture; import com.badlogic.gdx.utils.*; import com.badlogic.gdx.utils.Json.Serializer; import com.badlogic.gdx.utils.JsonWriter.OutputType; -import io.anuke.mindustry.Vars; import io.anuke.mindustry.world.Map; -import io.anuke.ucore.UCore; import io.anuke.ucore.core.Settings; import io.anuke.ucore.graphics.Pixmaps; +import io.anuke.ucore.util.Log; + +import static io.anuke.mindustry.Vars.*; public class Maps implements Disposable{ private IntMap maps = new IntMap<>(); private ObjectMap mapNames = new ObjectMap<>(); + private Array defaultMaps = new Array<>(); private Map networkMap; private int lastID; private Json json = new Json(); @@ -31,17 +33,17 @@ public class Maps implements Disposable{ return maps.values(); } - public void setNetworkMap(Pixmap pixmap){ + public Array getDefaultMaps(){ + return defaultMaps; + } + + public void setNetworkMap(Map map){ if(networkMap != null){ networkMap.pixmap.dispose(); networkMap = null; } - networkMap = new Map(); - networkMap.custom = true; - networkMap.pixmap = pixmap; - networkMap.visible = false; - networkMap.name = "network map"; - networkMap.id = -1; + + networkMap = map; } public Map getMap(int id){ @@ -60,10 +62,10 @@ public class Maps implements Disposable{ throw new RuntimeException("Failed to load maps!"); } - if(!Vars.gwt) { - if (!loadMapFile(Vars.customMapDirectory.child("maps.json"))) { + if(!gwt) { + if (!loadMapFile(customMapDirectory.child("maps.json"))) { try { - Vars.customMapDirectory.child("maps.json").writeString("{}", false); + customMapDirectory.child("maps.json").writeString("{}", false); } catch (Exception e) { throw new RuntimeException("Failed to create custom map directory!"); } @@ -80,7 +82,7 @@ public class Maps implements Disposable{ out.add(m); } } - saveMaps(out, Vars.customMapDirectory.child("maps.json")); + saveMaps(out, customMapDirectory.child("maps.json")); } public void saveAndReload(Map map, Pixmap out){ @@ -107,7 +109,7 @@ public class Maps implements Disposable{ } saveCustomMap(map); - Vars.ui.levels.reload(); + ui.levels.reload(); } public void saveMaps(Array array, FileHandle file){ @@ -136,8 +138,8 @@ public class Maps implements Disposable{ mapNames.remove(toSave.name); maps.put(toSave.id, toSave); mapNames.put(toSave.name, toSave); - Pixmaps.write(toSave.pixmap, Vars.customMapDirectory.child(toSave.name + ".png")); - saveMaps(out, Vars.customMapDirectory.child("maps.json")); + Pixmaps.write(toSave.pixmap, customMapDirectory.child(toSave.name + ".png")); + saveMaps(out, customMapDirectory.child("maps.json")); } private boolean loadMapFile(FileHandle file){ @@ -146,15 +148,18 @@ public class Maps implements Disposable{ if(arr != null){ //can be an empty map file for(Map map : arr){ map.pixmap = new Pixmap(file.sibling(map.name + ".png")); - map.texture = new Texture(map.pixmap); + if(!headless) map.texture = new Texture(map.pixmap); maps.put(map.id, map); mapNames.put(map.name, map); lastID = Math.max(lastID, map.id); + if(!map.custom){ + defaultMaps.add(map); + } } } return true; }catch(Exception e){ - if(!Vars.android) UCore.error(e); + if(!android) Log.err(e); Gdx.app.error("Mindustry-Maps", "Failed loading map file: " + file); return false; } @@ -163,7 +168,7 @@ public class Maps implements Disposable{ @Override public void dispose(){ for(Map map : maps.values()){ - map.texture.dispose(); + if(map.texture != null) map.texture.dispose(); map.pixmap.dispose(); } maps.clear(); diff --git a/core/src/io/anuke/mindustry/io/PlatformFunction.java b/core/src/io/anuke/mindustry/io/Platform.java similarity index 83% rename from core/src/io/anuke/mindustry/io/PlatformFunction.java rename to core/src/io/anuke/mindustry/io/Platform.java index 46e7881bfc..e51fe1a177 100644 --- a/core/src/io/anuke/mindustry/io/PlatformFunction.java +++ b/core/src/io/anuke/mindustry/io/Platform.java @@ -5,7 +5,9 @@ import io.anuke.ucore.scene.ui.TextField; import java.util.Date; import java.util.Locale; -public abstract class PlatformFunction{ +public abstract class Platform { + public static Platform instance = new Platform() {}; + public String format(Date date){return "invalid";} public String format(int number){return "invalid";} public void showError(String text){} @@ -16,6 +18,7 @@ public abstract class PlatformFunction{ public void updateRPC(){} public void onGameExit(){} public void openDonations(){} + public boolean hasDiscord(){return true;} public void requestWritePerms(){} public String getLocaleName(Locale locale){ return locale.toString(); diff --git a/core/src/io/anuke/mindustry/io/SaveIO.java b/core/src/io/anuke/mindustry/io/SaveIO.java index 270d771c03..49d049523c 100644 --- a/core/src/io/anuke/mindustry/io/SaveIO.java +++ b/core/src/io/anuke/mindustry/io/SaveIO.java @@ -4,7 +4,6 @@ import com.badlogic.gdx.files.FileHandle; import com.badlogic.gdx.utils.Array; import com.badlogic.gdx.utils.Base64Coder; import com.badlogic.gdx.utils.IntMap; -import io.anuke.mindustry.Vars; import io.anuke.mindustry.io.versions.Save12; import io.anuke.mindustry.io.versions.Save13; import io.anuke.mindustry.io.versions.Save14; @@ -13,13 +12,16 @@ import io.anuke.ucore.core.Settings; import java.io.*; +import static io.anuke.mindustry.Vars.gwt; +import static io.anuke.mindustry.Vars.saveDirectory; + public class SaveIO{ public static final IntMap versions = new IntMap<>(); public static final Array versionArray = Array.with( - new Save12(), - new Save13(), - new Save14(), - new Save15() + new Save12(), + new Save13(), + new Save14(), + new Save15() ); static{ @@ -29,7 +31,7 @@ public class SaveIO{ } public static void saveToSlot(int slot){ - if(Vars.gwt){ + if(gwt){ ByteArrayOutputStream stream = new ByteArrayOutputStream(); write(stream); Settings.putString("save-"+slot+"-data", new String(Base64Coder.encode(stream.toByteArray()))); @@ -48,7 +50,7 @@ public class SaveIO{ } public static void loadFromSlot(int slot){ - if(Vars.gwt){ + if(gwt){ String string = Settings.getString("save-"+slot+"-data"); ByteArrayInputStream stream = new ByteArrayInputStream(Base64Coder.decode(string)); load(stream); @@ -58,7 +60,7 @@ public class SaveIO{ } public static DataInputStream getSlotStream(int slot){ - if(Vars.gwt){ + if(gwt){ String string = Settings.getString("save-"+slot+"-data"); byte[] bytes = Base64Coder.decode(string); return new DataInputStream(new ByteArrayInputStream(bytes)); @@ -108,7 +110,7 @@ public class SaveIO{ } public static FileHandle fileFor(int slot){ - return Vars.saveDirectory.child(slot + ".mins"); + return saveDirectory.child(slot + ".mins"); } public static void write(FileHandle file){ diff --git a/core/src/io/anuke/mindustry/io/SaveMeta.java b/core/src/io/anuke/mindustry/io/SaveMeta.java index cc797361b0..9e35bffa56 100644 --- a/core/src/io/anuke/mindustry/io/SaveMeta.java +++ b/core/src/io/anuke/mindustry/io/SaveMeta.java @@ -1,7 +1,6 @@ package io.anuke.mindustry.io; -import io.anuke.mindustry.Mindustry; -import io.anuke.mindustry.Vars; +import static io.anuke.mindustry.Vars.*; import io.anuke.mindustry.game.GameMode; import io.anuke.mindustry.world.Map; @@ -16,9 +15,9 @@ public class SaveMeta { public SaveMeta(int version, long date, int mode, int map, int wave){ this.version = version; - this.date = Mindustry.platforms.format(new Date(date)); + this.date = Platform.instance.format(new Date(date)); this.mode = GameMode.values()[mode]; - this.map = Vars.world.maps().getMap(map); + this.map = world.maps().getMap(map); this.wave = wave; } } diff --git a/core/src/io/anuke/mindustry/io/Saves.java b/core/src/io/anuke/mindustry/io/Saves.java index 021b460934..80985885cb 100644 --- a/core/src/io/anuke/mindustry/io/Saves.java +++ b/core/src/io/anuke/mindustry/io/Saves.java @@ -3,8 +3,6 @@ package io.anuke.mindustry.io; import com.badlogic.gdx.files.FileHandle; import com.badlogic.gdx.utils.Array; import com.badlogic.gdx.utils.async.AsyncExecutor; -import io.anuke.mindustry.Vars; -import io.anuke.mindustry.core.GameState; import io.anuke.mindustry.core.GameState.State; import io.anuke.mindustry.game.GameMode; import io.anuke.mindustry.world.Map; @@ -13,6 +11,9 @@ import io.anuke.ucore.core.Timers; import java.io.IOException; +import static io.anuke.mindustry.Vars.saveSlots; +import static io.anuke.mindustry.Vars.state; + public class Saves { private int nextSlot; private Array saves = new Array<>(); @@ -24,7 +25,7 @@ public class Saves { public void load(){ saves.clear(); - for(int i = 0; i < Vars.saveSlots; i ++){ + for(int i = 0; i < saveSlots; i ++){ if(SaveIO.isSaveValid(i)){ SaveSlot slot = new SaveSlot(i); saves.add(slot); @@ -39,11 +40,11 @@ public class Saves { } public void update(){ - if(GameState.is(State.menu)){ + if(state.is(State.menu)){ current = null; } - if(!GameState.is(State.menu) && !Vars.control.isGameOver() && current != null && current.isAutosave()){ + if(!state.is(State.menu) && !state.gameOver && current != null && current.isAutosave()){ time += Timers.delta(); if(time > Settings.getInt("saveinterval")*60) { saving = true; @@ -70,7 +71,7 @@ public class Saves { } public boolean canAddSave(){ - return nextSlot < Vars.saveSlots; + return nextSlot < saveSlots; } public void addSave(String name){ diff --git a/core/src/io/anuke/mindustry/io/versions/Save12.java b/core/src/io/anuke/mindustry/io/versions/Save12.java index 04b92d0e02..ba588a1cd7 100644 --- a/core/src/io/anuke/mindustry/io/versions/Save12.java +++ b/core/src/io/anuke/mindustry/io/versions/Save12.java @@ -5,12 +5,12 @@ import com.badlogic.gdx.utils.TimeUtils; import io.anuke.mindustry.Vars; import io.anuke.mindustry.entities.enemies.Enemy; import io.anuke.mindustry.entities.enemies.EnemyType; +import io.anuke.mindustry.game.GameMode; +import io.anuke.mindustry.io.BlockLoader; import io.anuke.mindustry.io.SaveFileVersion; import io.anuke.mindustry.resource.Item; import io.anuke.mindustry.resource.Upgrade; import io.anuke.mindustry.resource.Weapon; -import io.anuke.mindustry.world.BlockLoader; -import io.anuke.mindustry.game.GameMode; import io.anuke.mindustry.world.Tile; import io.anuke.mindustry.world.blocks.Blocks; import io.anuke.ucore.core.Core; @@ -21,7 +21,7 @@ import java.io.DataOutputStream; import java.io.IOException; import java.util.Arrays; -import static io.anuke.mindustry.Vars.android; +import static io.anuke.mindustry.Vars.*; public class Save12 extends SaveFileVersion { @@ -48,36 +48,36 @@ public class Save12 extends SaveFileVersion { Vars.player.x = playerx; Vars.player.y = playery; Vars.player.health = playerhealth; - Vars.control.setMode(GameMode.values()[mode]); + state.mode = GameMode.values()[mode]; Core.camera.position.set(playerx, playery, 0); //weapons - Vars.control.getWeapons().clear(); - Vars.control.getWeapons().add(Weapon.blaster); + control.upgrades().getWeapons().clear(); + control.upgrades().getWeapons().add(Weapon.blaster); Vars.player.weaponLeft = Vars.player.weaponRight = Weapon.blaster; int weapons = stream.readByte(); for(int i = 0; i < weapons; i ++){ - Vars.control.addWeapon((Weapon)Upgrade.getByID(stream.readByte())); + control.upgrades().addWeapon((Weapon)Upgrade.getByID(stream.readByte())); } - Vars.ui.hudfrag.updateWeapons(); + ui.hudfrag.updateWeapons(); //inventory int totalItems = stream.readByte(); - Arrays.fill(Vars.control.getItems(), 0); + Arrays.fill(state.inventory.getItems(), 0); for(int i = 0; i < totalItems; i ++){ Item item = Item.getByID(stream.readByte()); int amount = stream.readInt(); - Vars.control.getItems()[item.id] = amount; + state.inventory.getItems()[item.id] = amount; } - Vars.ui.hudfrag.updateItems(); + ui.hudfrag.updateItems(); //enemies @@ -102,14 +102,16 @@ public class Save12 extends SaveFileVersion { enemy.x = x; enemy.y = y; enemy.tier = tier; - enemy.add(Vars.control.enemyGroup); + enemy.add(enemyGroup); enemiesToUpdate.add(enemy); }catch (Exception e){ throw new RuntimeException(e); } } - Vars.control.setWaveData(enemies, wave, wavetime); + state.enemies = enemies; + state.wave = wave; + state.wavetime = wavetime; if(!android) Vars.player.add(); @@ -119,20 +121,20 @@ public class Save12 extends SaveFileVersion { int seed = stream.readInt(); int tiles = stream.readInt(); - Vars.world.loadMap(Vars.world.maps().getMap(mapid), seed); - Vars.renderer.clearTiles(); + world.loadMap(world.maps().getMap(mapid), seed); + renderer.clearTiles(); for(Enemy enemy : enemiesToUpdate){ enemy.node = -2; } - for(int x = 0; x < Vars.world.width(); x ++){ - for(int y = 0; y < Vars.world.height(); y ++){ - Tile tile = Vars.world.tile(x, y); + for(int x = 0; x < world.width(); x ++){ + for(int y = 0; y < world.height(); y ++){ + Tile tile = world.tile(x, y); //remove breakables like rocks if(tile.breakable()){ - Vars.world.tile(x, y).setBlock(Blocks.air); + world.tile(x, y).setBlock(Blocks.air); } } } @@ -143,7 +145,7 @@ public class Save12 extends SaveFileVersion { boolean hasEntity = stream.readBoolean(); int blockid = stream.readInt(); - Tile tile = Vars.world.tile(pos % Vars.world.width(), pos / Vars.world.width()); + Tile tile = world.tile(pos % world.width(), pos / world.width()); tile.setBlock(BlockLoader.getByOldID(blockid)); tile.link = link; @@ -174,31 +176,31 @@ public class Save12 extends SaveFileVersion { stream.writeLong(TimeUtils.millis()); //last saved //--GENERAL STATE-- - stream.writeByte(Vars.control.getMode().ordinal()); //gamemode - stream.writeByte(Vars.world.getMap().id); //map ID + stream.writeByte(state.mode.ordinal()); //gamemode + stream.writeByte(world.getMap().id); //map ID - stream.writeInt(Vars.control.getWave()); //wave - stream.writeFloat(Vars.control.getWaveCountdown()); //wave countdown + stream.writeInt(state.wave); //wave + stream.writeFloat(state.wavetime); //wave countdown stream.writeFloat(Vars.player.x); //player x/y stream.writeFloat(Vars.player.y); stream.writeInt(Vars.player.health); //player health - stream.writeByte(Vars.control.getWeapons().size - 1); //amount of weapons + stream.writeByte(control.upgrades().getWeapons().size - 1); //amount of weapons //start at 1, because the first weapon is always the starter - ignore that - for(int i = 1; i < Vars.control.getWeapons().size; i ++){ - stream.writeByte(Vars.control.getWeapons().get(i).id); //weapon ordinal + for(int i = 1; i < control.upgrades().getWeapons().size; i ++){ + stream.writeByte(control.upgrades().getWeapons().get(i).id); //weapon ordinal } //--INVENTORY-- - int l = Vars.control.getItems().length; + int l = state.inventory.getItems().length; int itemsize = 0; for(int i = 0; i < l; i ++){ - if(Vars.control.getItems()[i] > 0){ + if(state.inventory.getItems()[i] > 0){ itemsize ++; } } @@ -206,15 +208,15 @@ public class Save12 extends SaveFileVersion { stream.writeByte(itemsize); //amount of items for(int i = 0; i < l; i ++){ - if(Vars.control.getItems()[i] > 0){ + if(state.inventory.getItems()[i] > 0){ stream.writeByte(i); //item ID - stream.writeInt(Vars.control.getItems()[i]); //item amount + stream.writeInt(state.inventory.getItems()[i]); //item amount } } //--ENEMIES-- - Array enemies = Vars.control.enemyGroup.all(); + Array enemies = enemyGroup.all(); stream.writeInt(enemies.size); //enemy amount @@ -231,13 +233,13 @@ public class Save12 extends SaveFileVersion { //--MAP DATA-- //seed - stream.writeInt(Vars.world.getSeed()); + stream.writeInt(world.getSeed()); int totalblocks = 0; - for(int x = 0; x < Vars.world.width(); x ++){ - for(int y = 0; y < Vars.world.height(); y ++){ - Tile tile = Vars.world.tile(x, y); + for(int x = 0; x < world.width(); x ++){ + for(int y = 0; y < world.height(); y ++){ + Tile tile = world.tile(x, y); if(tile.breakable()){ totalblocks ++; @@ -248,13 +250,13 @@ public class Save12 extends SaveFileVersion { //tile amount stream.writeInt(totalblocks); - for(int x = 0; x < Vars.world.width(); x ++){ - for(int y = 0; y < Vars.world.height(); y ++){ - Tile tile = Vars.world.tile(x, y); + for(int x = 0; x < world.width(); x ++){ + for(int y = 0; y < world.height(); y ++){ + Tile tile = world.tile(x, y); if(tile.breakable()){ - stream.writeInt(x + y*Vars.world.width()); //tile pos + stream.writeInt(x + y*world.width()); //tile pos stream.writeByte(tile.link); stream.writeBoolean(tile.entity != null); //whether it has a tile entity stream.writeInt(tile.block().id); //block ID diff --git a/core/src/io/anuke/mindustry/io/versions/Save13.java b/core/src/io/anuke/mindustry/io/versions/Save13.java index 8c6f6ab4db..41ff466d69 100644 --- a/core/src/io/anuke/mindustry/io/versions/Save13.java +++ b/core/src/io/anuke/mindustry/io/versions/Save13.java @@ -6,11 +6,14 @@ import io.anuke.mindustry.Vars; import io.anuke.mindustry.entities.enemies.Enemy; import io.anuke.mindustry.entities.enemies.EnemyType; import io.anuke.mindustry.game.GameMode; +import io.anuke.mindustry.io.BlockLoader; import io.anuke.mindustry.io.SaveFileVersion; import io.anuke.mindustry.resource.Item; import io.anuke.mindustry.resource.Upgrade; import io.anuke.mindustry.resource.Weapon; -import io.anuke.mindustry.world.*; +import io.anuke.mindustry.world.Block; +import io.anuke.mindustry.world.Tile; +import io.anuke.mindustry.world.WorldGenerator; import io.anuke.mindustry.world.blocks.Blocks; import io.anuke.mindustry.world.blocks.types.BlockPart; import io.anuke.mindustry.world.blocks.types.Rock; @@ -22,7 +25,7 @@ import java.io.DataOutputStream; import java.io.IOException; import java.util.Arrays; -import static io.anuke.mindustry.Vars.android; +import static io.anuke.mindustry.Vars.*; public class Save13 extends SaveFileVersion { @@ -49,36 +52,36 @@ public class Save13 extends SaveFileVersion { Vars.player.x = playerx; Vars.player.y = playery; Vars.player.health = playerhealth; - Vars.control.setMode(GameMode.values()[mode]); + state.mode = GameMode.values()[mode]; Core.camera.position.set(playerx, playery, 0); //weapons - Vars.control.getWeapons().clear(); - Vars.control.getWeapons().add(Weapon.blaster); + control.upgrades().getWeapons().clear(); + control.upgrades().getWeapons().add(Weapon.blaster); Vars.player.weaponLeft = Vars.player.weaponRight = Weapon.blaster; int weapons = stream.readByte(); for(int i = 0; i < weapons; i ++){ - Vars.control.addWeapon((Weapon) Upgrade.getByID(stream.readByte())); + control.upgrades().addWeapon((Weapon) Upgrade.getByID(stream.readByte())); } - Vars.ui.hudfrag.updateWeapons(); + ui.hudfrag.updateWeapons(); //inventory int totalItems = stream.readByte(); - Arrays.fill(Vars.control.getItems(), 0); + Arrays.fill(state.inventory.getItems(), 0); for(int i = 0; i < totalItems; i ++){ Item item = Item.getByID(stream.readByte()); int amount = stream.readInt(); - Vars.control.getItems()[item.id] = amount; + state.inventory.getItems()[item.id] = amount; } - Vars.ui.hudfrag.updateItems(); + ui.hudfrag.updateItems(); //enemies @@ -103,14 +106,16 @@ public class Save13 extends SaveFileVersion { enemy.x = x; enemy.y = y; enemy.tier = tier; - enemy.add(Vars.control.enemyGroup); + enemy.add(enemyGroup); enemiesToUpdate.add(enemy); }catch (Exception e){ throw new RuntimeException(e); } } - Vars.control.setWaveData(enemies, wave, wavetime); + state.enemies = enemies; + state.wave = wave; + state.wavetime = wavetime; if(!android) Vars.player.add(); @@ -119,8 +124,8 @@ public class Save13 extends SaveFileVersion { int seed = stream.readInt(); - Vars.world.loadMap(Vars.world.maps().getMap(mapid), seed); - Vars.renderer.clearTiles(); + world.loadMap(world.maps().getMap(mapid), seed); + renderer.clearTiles(); for(Enemy enemy : enemiesToUpdate){ enemy.node = -2; @@ -128,20 +133,20 @@ public class Save13 extends SaveFileVersion { int rocks = stream.readInt(); - for(int x = 0; x < Vars.world.width(); x ++){ - for(int y = 0; y < Vars.world.height(); y ++){ - Tile tile = Vars.world.tile(x, y); + for(int x = 0; x < world.width(); x ++){ + for(int y = 0; y < world.height(); y ++){ + Tile tile = world.tile(x, y); //remove breakables like rocks if(tile.breakable()){ - Vars.world.tile(x, y).setBlock(Blocks.air); + world.tile(x, y).setBlock(Blocks.air); } } } for(int i = 0; i < rocks; i ++){ int pos = stream.readInt(); - Tile tile = Vars.world.tile(pos % Vars.world.width(), pos / Vars.world.width()); + Tile tile = world.tile(pos % world.width(), pos / world.width()); Block result = WorldGenerator.rocks.get(tile.floor()); if(result != null) tile.setBlock(result); } @@ -152,7 +157,7 @@ public class Save13 extends SaveFileVersion { int pos = stream.readInt(); int blockid = stream.readInt(); - Tile tile = Vars.world.tile(pos % Vars.world.width(), pos / Vars.world.width()); + Tile tile = world.tile(pos % world.width(), pos / world.width()); tile.setBlock(BlockLoader.getByOldID(blockid)); if(blockid == Blocks.blockpart.id){ @@ -185,31 +190,31 @@ public class Save13 extends SaveFileVersion { stream.writeLong(TimeUtils.millis()); //last saved //--GENERAL STATE-- - stream.writeByte(Vars.control.getMode().ordinal()); //gamemode - stream.writeByte(Vars.world.getMap().id); //map ID + stream.writeByte(state.mode.ordinal()); //gamemode + stream.writeByte(world.getMap().id); //map ID - stream.writeInt(Vars.control.getWave()); //wave - stream.writeFloat(Vars.control.getWaveCountdown()); //wave countdown + stream.writeInt(state.wave); //wave + stream.writeFloat(state.wavetime); //wave countdown stream.writeFloat(Vars.player.x); //player x/y stream.writeFloat(Vars.player.y); stream.writeInt(Vars.player.health); //player health - stream.writeByte(Vars.control.getWeapons().size - 1); //amount of weapons + stream.writeByte(control.upgrades().getWeapons().size - 1); //amount of weapons //start at 1, because the first weapon is always the starter - ignore that - for(int i = 1; i < Vars.control.getWeapons().size; i ++){ - stream.writeByte(Vars.control.getWeapons().get(i).id); //weapon ordinal + for(int i = 1; i < control.upgrades().getWeapons().size; i ++){ + stream.writeByte(control.upgrades().getWeapons().get(i).id); //weapon ordinal } //--INVENTORY-- - int l = Vars.control.getItems().length; + int l = state.inventory.getItems().length; int itemsize = 0; for(int i = 0; i < l; i ++){ - if(Vars.control.getItems()[i] > 0){ + if(state.inventory.getItems()[i] > 0){ itemsize ++; } } @@ -217,14 +222,14 @@ public class Save13 extends SaveFileVersion { stream.writeByte(itemsize); //amount of items for(int i = 0; i < l; i ++){ - if(Vars.control.getItems()[i] > 0){ + if(state.inventory.getItems()[i] > 0){ stream.writeByte(i); //item ID - stream.writeInt(Vars.control.getItems()[i]); //item amount + stream.writeInt(state.inventory.getItems()[i]); //item amount } } //--ENEMIES-- - Array enemies = Vars.control.enemyGroup.all(); + Array enemies = enemyGroup.all(); stream.writeInt(enemies.size); //enemy amount @@ -241,14 +246,14 @@ public class Save13 extends SaveFileVersion { //--MAP DATA-- //seed - stream.writeInt(Vars.world.getSeed()); + stream.writeInt(world.getSeed()); int totalblocks = 0; int totalrocks = 0; - for(int x = 0; x < Vars.world.width(); x ++){ - for(int y = 0; y < Vars.world.height(); y ++){ - Tile tile = Vars.world.tile(x, y); + for(int x = 0; x < world.width(); x ++){ + for(int y = 0; y < world.height(); y ++){ + Tile tile = world.tile(x, y); if(tile.breakable()){ if(tile.block() instanceof Rock){ @@ -264,9 +269,9 @@ public class Save13 extends SaveFileVersion { stream.writeInt(totalrocks); //write all rocks - for(int x = 0; x < Vars.world.width(); x ++) { - for (int y = 0; y < Vars.world.height(); y++) { - Tile tile = Vars.world.tile(x, y); + for(int x = 0; x < world.width(); x ++) { + for (int y = 0; y < world.height(); y++) { + Tile tile = world.tile(x, y); if (tile.block() instanceof Rock) { stream.writeInt(tile.packedPosition()); @@ -277,13 +282,13 @@ public class Save13 extends SaveFileVersion { //write all blocks stream.writeInt(totalblocks); - for(int x = 0; x < Vars.world.width(); x ++){ - for(int y = 0; y < Vars.world.height(); y ++){ - Tile tile = Vars.world.tile(x, y); + for(int x = 0; x < world.width(); x ++){ + for(int y = 0; y < world.height(); y ++){ + Tile tile = world.tile(x, y); if(tile.breakable() && !(tile.block() instanceof Rock)){ - stream.writeInt(x + y*Vars.world.width()); //tile pos + stream.writeInt(x + y*world.width()); //tile pos stream.writeInt(tile.block().id); //block ID if(tile.block() instanceof BlockPart) stream.writeByte(tile.link); diff --git a/core/src/io/anuke/mindustry/io/versions/Save14.java b/core/src/io/anuke/mindustry/io/versions/Save14.java index f87a6a0083..9908d23a8f 100644 --- a/core/src/io/anuke/mindustry/io/versions/Save14.java +++ b/core/src/io/anuke/mindustry/io/versions/Save14.java @@ -25,7 +25,7 @@ import java.io.DataOutputStream; import java.io.IOException; import java.util.Arrays; -import static io.anuke.mindustry.Vars.android; +import static io.anuke.mindustry.Vars.*; public class Save14 extends SaveFileVersion{ @@ -66,36 +66,36 @@ public class Save14 extends SaveFileVersion{ Vars.player.x = playerx; Vars.player.y = playery; Vars.player.health = playerhealth; - Vars.control.setMode(GameMode.values()[mode]); + state.mode = GameMode.values()[mode]; Core.camera.position.set(playerx, playery, 0); //weapons - Vars.control.getWeapons().clear(); - Vars.control.getWeapons().add(Weapon.blaster); + control.upgrades().getWeapons().clear(); + control.upgrades().getWeapons().add(Weapon.blaster); Vars.player.weaponLeft = Vars.player.weaponRight = Weapon.blaster; int weapons = stream.readByte(); for(int i = 0; i < weapons; i ++){ - Vars.control.addWeapon((Weapon) Upgrade.getByID(stream.readByte())); + control.upgrades().addWeapon((Weapon) Upgrade.getByID(stream.readByte())); } - Vars.ui.hudfrag.updateWeapons(); + ui.hudfrag.updateWeapons(); //inventory int totalItems = stream.readByte(); - Arrays.fill(Vars.control.getItems(), 0); + Arrays.fill(state.inventory.getItems(), 0); for(int i = 0; i < totalItems; i ++){ Item item = Item.getByID(stream.readByte()); int amount = stream.readInt(); - Vars.control.getItems()[item.id] = amount; + state.inventory.getItems()[item.id] = amount; } - Vars.ui.hudfrag.updateItems(); + ui.hudfrag.updateItems(); //enemies @@ -120,14 +120,16 @@ public class Save14 extends SaveFileVersion{ enemy.x = x; enemy.y = y; enemy.tier = tier; - enemy.add(Vars.control.enemyGroup); + enemy.add(enemyGroup); enemiesToUpdate.add(enemy); }catch (Exception e){ throw new RuntimeException(e); } } - Vars.control.setWaveData(enemies, wave, wavetime); + state.enemies = enemies; + state.wave = wave; + state.wavetime = wavetime; if(!android) Vars.player.add(); @@ -136,8 +138,8 @@ public class Save14 extends SaveFileVersion{ int seed = stream.readInt(); - Vars.world.loadMap(Vars.world.maps().getMap(mapid), seed); - Vars.renderer.clearTiles(); + world.loadMap(world.maps().getMap(mapid), seed); + renderer.clearTiles(); for(Enemy enemy : enemiesToUpdate){ enemy.node = -2; @@ -145,20 +147,20 @@ public class Save14 extends SaveFileVersion{ int rocks = stream.readInt(); - for(int x = 0; x < Vars.world.width(); x ++){ - for(int y = 0; y < Vars.world.height(); y ++){ - Tile tile = Vars.world.tile(x, y); + for(int x = 0; x < world.width(); x ++){ + for(int y = 0; y < world.height(); y ++){ + Tile tile = world.tile(x, y); //remove breakables like rocks if(tile.breakable()){ - Vars.world.tile(x, y).setBlock(Blocks.air); + world.tile(x, y).setBlock(Blocks.air); } } } for(int i = 0; i < rocks; i ++){ int pos = stream.readInt(); - Tile tile = Vars.world.tile(pos % Vars.world.width(), pos / Vars.world.width()); + Tile tile = world.tile(pos % world.width(), pos / world.width()); if(tile == null) continue; Block result = WorldGenerator.rocks.get(tile.floor()); if(result != null) tile.setBlock(result); @@ -170,7 +172,7 @@ public class Save14 extends SaveFileVersion{ int pos = stream.readInt(); int blockid = stream.readInt(); - Tile tile = Vars.world.tile(pos % Vars.world.width(), pos / Vars.world.width()); + Tile tile = world.tile(pos % world.width(), pos / world.width()); tile.setBlock(map.get(blockid)); if(blockid == Blocks.blockpart.id){ @@ -203,11 +205,11 @@ public class Save14 extends SaveFileVersion{ stream.writeLong(TimeUtils.millis()); //last saved //--GENERAL STATE-- - stream.writeByte(Vars.control.getMode().ordinal()); //gamemode - stream.writeByte(Vars.world.getMap().id); //map ID + stream.writeByte(state.mode.ordinal()); //gamemode + stream.writeByte(world.getMap().id); //map ID - stream.writeInt(Vars.control.getWave()); //wave - stream.writeFloat(Vars.control.getWaveCountdown()); //wave countdown + stream.writeInt(state.wave); //wave + stream.writeFloat(state.wavetime); //wave countdown //--BLOCK HEADER-- @@ -224,20 +226,20 @@ public class Save14 extends SaveFileVersion{ stream.writeInt(Vars.player.health); //player health - stream.writeByte(Vars.control.getWeapons().size - 1); //amount of weapons + stream.writeByte(control.upgrades().getWeapons().size - 1); //amount of weapons //start at 1, because the first weapon is always the starter - ignore that - for(int i = 1; i < Vars.control.getWeapons().size; i ++){ - stream.writeByte(Vars.control.getWeapons().get(i).id); //weapon ordinal + for(int i = 1; i < control.upgrades().getWeapons().size; i ++){ + stream.writeByte(control.upgrades().getWeapons().get(i).id); //weapon ordinal } //--INVENTORY-- - int l = Vars.control.getItems().length; + int l = state.inventory.getItems().length; int itemsize = 0; for(int i = 0; i < l; i ++){ - if(Vars.control.getItems()[i] > 0){ + if(state.inventory.getItems()[i] > 0){ itemsize ++; } } @@ -245,15 +247,15 @@ public class Save14 extends SaveFileVersion{ stream.writeByte(itemsize); //amount of items for(int i = 0; i < l; i ++){ - if(Vars.control.getItems()[i] > 0){ + if(state.inventory.getItems()[i] > 0){ stream.writeByte(i); //item ID - stream.writeInt(Vars.control.getItems()[i]); //item amount + stream.writeInt(state.inventory.getItems()[i]); //item amount } } //--ENEMIES-- - Array enemies = Vars.control.enemyGroup.all(); + Array enemies = enemyGroup.all(); stream.writeInt(enemies.size); //enemy amount @@ -270,14 +272,14 @@ public class Save14 extends SaveFileVersion{ //--MAP DATA-- //seed - stream.writeInt(Vars.world.getSeed()); + stream.writeInt(world.getSeed()); int totalblocks = 0; int totalrocks = 0; - for(int x = 0; x < Vars.world.width(); x ++){ - for(int y = 0; y < Vars.world.height(); y ++){ - Tile tile = Vars.world.tile(x, y); + for(int x = 0; x < world.width(); x ++){ + for(int y = 0; y < world.height(); y ++){ + Tile tile = world.tile(x, y); if(tile.breakable()){ if(tile.block() instanceof Rock){ @@ -293,9 +295,9 @@ public class Save14 extends SaveFileVersion{ stream.writeInt(totalrocks); //write all rocks - for(int x = 0; x < Vars.world.width(); x ++) { - for (int y = 0; y < Vars.world.height(); y++) { - Tile tile = Vars.world.tile(x, y); + for(int x = 0; x < world.width(); x ++) { + for (int y = 0; y < world.height(); y++) { + Tile tile = world.tile(x, y); if (tile.block() instanceof Rock) { stream.writeInt(tile.packedPosition()); @@ -306,13 +308,13 @@ public class Save14 extends SaveFileVersion{ //write all blocks stream.writeInt(totalblocks); - for(int x = 0; x < Vars.world.width(); x ++){ - for(int y = 0; y < Vars.world.height(); y ++){ - Tile tile = Vars.world.tile(x, y); + for(int x = 0; x < world.width(); x ++){ + for(int y = 0; y < world.height(); y ++){ + Tile tile = world.tile(x, y); if(tile.breakable() && !(tile.block() instanceof Rock)){ - stream.writeInt(x + y*Vars.world.width()); //tile pos + stream.writeInt(x + y*world.width()); //tile pos stream.writeInt(tile.block().id); //block ID if(tile.block() instanceof BlockPart) stream.writeByte(tile.link); diff --git a/core/src/io/anuke/mindustry/io/versions/Save15.java b/core/src/io/anuke/mindustry/io/versions/Save15.java index 2a4474cade..19a90995fa 100644 --- a/core/src/io/anuke/mindustry/io/versions/Save15.java +++ b/core/src/io/anuke/mindustry/io/versions/Save15.java @@ -3,7 +3,6 @@ package io.anuke.mindustry.io.versions; import com.badlogic.gdx.utils.Array; import com.badlogic.gdx.utils.IntMap; import com.badlogic.gdx.utils.TimeUtils; -import io.anuke.mindustry.Vars; import io.anuke.mindustry.entities.enemies.Enemy; import io.anuke.mindustry.entities.enemies.EnemyType; import io.anuke.mindustry.game.Difficulty; @@ -26,7 +25,7 @@ import java.io.DataOutputStream; import java.io.IOException; import java.util.Arrays; -import static io.anuke.mindustry.Vars.android; +import static io.anuke.mindustry.Vars.*; public class Save15 extends SaveFileVersion { @@ -47,7 +46,7 @@ public class Save15 extends SaveFileVersion { float wavetime = stream.readFloat(); byte difficulty = stream.readByte(); - Vars.control.setDifficulty(Difficulty.values()[difficulty]); + state.difficulty = Difficulty.values()[difficulty]; //block header @@ -67,39 +66,44 @@ public class Save15 extends SaveFileVersion { int playerhealth = stream.readInt(); - Vars.player.x = playerx; - Vars.player.y = playery; - Vars.player.health = playerhealth; - Vars.control.setMode(GameMode.values()[mode]); - Core.camera.position.set(playerx, playery, 0); + if(!headless) { + player.x = playerx; + player.y = playery; + player.health = playerhealth; + state.mode = GameMode.values()[mode]; + Core.camera.position.set(playerx, playery, 0); - //weapons + //weapons - Vars.control.getWeapons().clear(); - Vars.control.getWeapons().add(Weapon.blaster); - Vars.player.weaponLeft = Vars.player.weaponRight = Weapon.blaster; + control.upgrades().getWeapons().clear(); + control.upgrades().getWeapons().add(Weapon.blaster); + player.weaponLeft = player.weaponRight = Weapon.blaster; - int weapons = stream.readByte(); + int weapons = stream.readByte(); - for(int i = 0; i < weapons; i ++){ - Vars.control.addWeapon((Weapon) Upgrade.getByID(stream.readByte())); + for (int i = 0; i < weapons; i++) { + control.upgrades().addWeapon((Weapon) Upgrade.getByID(stream.readByte())); + } + + ui.hudfrag.updateWeapons(); + }else{ + byte b = stream.readByte(); + for(int i = 0; i < b; i ++) stream.readByte(); } - Vars.ui.hudfrag.updateWeapons(); - //inventory int totalItems = stream.readByte(); - Arrays.fill(Vars.control.getItems(), 0); + Arrays.fill(state.inventory.getItems(), 0); for(int i = 0; i < totalItems; i ++){ Item item = Item.getByID(stream.readByte()); int amount = stream.readInt(); - Vars.control.getItems()[item.id] = amount; + state.inventory.getItems()[item.id] = amount; } - Vars.ui.hudfrag.updateItems(); + if(!headless) ui.hudfrag.updateItems(); //enemies @@ -124,24 +128,26 @@ public class Save15 extends SaveFileVersion { enemy.x = x; enemy.y = y; enemy.tier = tier; - enemy.add(Vars.control.enemyGroup); + enemy.add(enemyGroup); enemiesToUpdate.add(enemy); }catch (Exception e){ throw new RuntimeException(e); } } - Vars.control.setWaveData(enemies, wave, wavetime); + state.enemies = enemies; + state.wave = wave; + state.wavetime = wavetime; - if(!android) - Vars.player.add(); + if(!android && !headless) + player.add(); //map int seed = stream.readInt(); - Vars.world.loadMap(Vars.world.maps().getMap(mapid), seed); - Vars.renderer.clearTiles(); + world.loadMap(world.maps().getMap(mapid), seed); + if(!headless) renderer.clearTiles(); for(Enemy enemy : enemiesToUpdate){ enemy.node = -2; @@ -149,20 +155,20 @@ public class Save15 extends SaveFileVersion { int rocks = stream.readInt(); - for(int x = 0; x < Vars.world.width(); x ++){ - for(int y = 0; y < Vars.world.height(); y ++){ - Tile tile = Vars.world.tile(x, y); + for(int x = 0; x < world.width(); x ++){ + for(int y = 0; y < world.height(); y ++){ + Tile tile = world.tile(x, y); //remove breakables like rocks if(tile.breakable()){ - Vars.world.tile(x, y).setBlock(Blocks.air); + world.tile(x, y).setBlock(Blocks.air); } } } for(int i = 0; i < rocks; i ++){ int pos = stream.readInt(); - Tile tile = Vars.world.tile(pos % Vars.world.width(), pos / Vars.world.width()); + Tile tile = world.tile(pos % world.width(), pos / world.width()); if(tile == null) continue; Block result = WorldGenerator.rocks.get(tile.floor()); if(result != null) tile.setBlock(result); @@ -174,7 +180,7 @@ public class Save15 extends SaveFileVersion { int pos = stream.readInt(); int blockid = stream.readInt(); - Tile tile = Vars.world.tile(pos % Vars.world.width(), pos / Vars.world.width()); + Tile tile = world.tile(pos % world.width(), pos / world.width()); tile.setBlock(map.get(blockid)); if(blockid == Blocks.blockpart.id){ @@ -207,12 +213,12 @@ public class Save15 extends SaveFileVersion { stream.writeLong(TimeUtils.millis()); //last saved //--GENERAL STATE-- - stream.writeByte(Vars.control.getMode().ordinal()); //gamemode - stream.writeByte(Vars.world.getMap().id); //map ID + stream.writeByte(state.mode.ordinal()); //gamemode + stream.writeByte(world.getMap().id); //map ID - stream.writeInt(Vars.control.getWave()); //wave - stream.writeFloat(Vars.control.getWaveCountdown()); //wave countdown - stream.writeByte(Vars.control.getDifficulty().ordinal()); + stream.writeInt(state.wave); //wave + stream.writeFloat(state.wavetime); //wave countdown + stream.writeByte(state.difficulty.ordinal()); //--BLOCK HEADER-- @@ -224,25 +230,32 @@ public class Save15 extends SaveFileVersion { stream.writeShort(block.id); } - stream.writeFloat(Vars.player.x); //player x/y - stream.writeFloat(Vars.player.y); + if(!headless) { + stream.writeFloat(player.x); //player x/y + stream.writeFloat(player.y); - stream.writeInt(Vars.player.health); //player health + stream.writeInt(player.health); //player health - stream.writeByte(Vars.control.getWeapons().size - 1); //amount of weapons + stream.writeByte(control.upgrades().getWeapons().size - 1); //amount of weapons - //start at 1, because the first weapon is always the starter - ignore that - for(int i = 1; i < Vars.control.getWeapons().size; i ++){ - stream.writeByte(Vars.control.getWeapons().get(i).id); //weapon ordinal + //start at 1, because the first weapon is always the starter - ignore that + for (int i = 1; i < control.upgrades().getWeapons().size; i++) { + stream.writeByte(control.upgrades().getWeapons().get(i).id); //weapon ordinal + } + }else{ + stream.writeFloat(0); + stream.writeFloat(0); + stream.writeInt(0); + stream.writeByte(0); } //--INVENTORY-- - int l = Vars.control.getItems().length; + int l = state.inventory.getItems().length; int itemsize = 0; for(int i = 0; i < l; i ++){ - if(Vars.control.getItems()[i] > 0){ + if(state.inventory.getItems()[i] > 0){ itemsize ++; } } @@ -250,15 +263,15 @@ public class Save15 extends SaveFileVersion { stream.writeByte(itemsize); //amount of items for(int i = 0; i < l; i ++){ - if(Vars.control.getItems()[i] > 0){ + if(state.inventory.getItems()[i] > 0){ stream.writeByte(i); //item ID - stream.writeInt(Vars.control.getItems()[i]); //item amount + stream.writeInt(state.inventory.getItems()[i]); //item amount } } //--ENEMIES-- - Array enemies = Vars.control.enemyGroup.all(); + Array enemies = enemyGroup.all(); stream.writeInt(enemies.size); //enemy amount @@ -275,14 +288,14 @@ public class Save15 extends SaveFileVersion { //--MAP DATA-- //seed - stream.writeInt(Vars.world.getSeed()); + stream.writeInt(world.getSeed()); int totalblocks = 0; int totalrocks = 0; - for(int x = 0; x < Vars.world.width(); x ++){ - for(int y = 0; y < Vars.world.height(); y ++){ - Tile tile = Vars.world.tile(x, y); + for(int x = 0; x < world.width(); x ++){ + for(int y = 0; y < world.height(); y ++){ + Tile tile = world.tile(x, y); if(tile.breakable()){ if(tile.block() instanceof Rock){ @@ -298,9 +311,9 @@ public class Save15 extends SaveFileVersion { stream.writeInt(totalrocks); //write all rocks - for(int x = 0; x < Vars.world.width(); x ++) { - for (int y = 0; y < Vars.world.height(); y++) { - Tile tile = Vars.world.tile(x, y); + for(int x = 0; x < world.width(); x ++) { + for (int y = 0; y < world.height(); y++) { + Tile tile = world.tile(x, y); if (tile.block() instanceof Rock) { stream.writeInt(tile.packedPosition()); @@ -311,13 +324,13 @@ public class Save15 extends SaveFileVersion { //write all blocks stream.writeInt(totalblocks); - for(int x = 0; x < Vars.world.width(); x ++){ - for(int y = 0; y < Vars.world.height(); y ++){ - Tile tile = Vars.world.tile(x, y); + for(int x = 0; x < world.width(); x ++){ + for(int y = 0; y < world.height(); y ++){ + Tile tile = world.tile(x, y); if(tile.breakable() && !(tile.block() instanceof Rock)){ - stream.writeInt(x + y*Vars.world.width()); //tile pos + stream.writeInt(x + y*world.width()); //tile pos stream.writeInt(tile.block().id); //block ID if(tile.block() instanceof BlockPart) stream.writeByte(tile.link); diff --git a/core/src/io/anuke/mindustry/mapeditor/DrawOperation.java b/core/src/io/anuke/mindustry/mapeditor/DrawOperation.java index aa66e65858..5884250cd5 100755 --- a/core/src/io/anuke/mindustry/mapeditor/DrawOperation.java +++ b/core/src/io/anuke/mindustry/mapeditor/DrawOperation.java @@ -34,7 +34,7 @@ public class DrawOperation implements Disposable{ } public void disposeFrom(){ - from.dispose(); + if(from != null) from.dispose(); } } diff --git a/core/src/io/anuke/mindustry/mapeditor/EditorTool.java b/core/src/io/anuke/mindustry/mapeditor/EditorTool.java index 1b3aeddb14..561a9abf42 100644 --- a/core/src/io/anuke/mindustry/mapeditor/EditorTool.java +++ b/core/src/io/anuke/mindustry/mapeditor/EditorTool.java @@ -3,7 +3,7 @@ package io.anuke.mindustry.mapeditor; import com.badlogic.gdx.graphics.Pixmap; import com.badlogic.gdx.math.GridPoint2; import com.badlogic.gdx.utils.IntSet; -import io.anuke.mindustry.Vars; +import static io.anuke.mindustry.Vars.*; import io.anuke.mindustry.world.Block; import io.anuke.mindustry.world.ColorMapper; import io.anuke.mindustry.world.ColorMapper.BlockPair; @@ -17,7 +17,7 @@ public enum EditorTool{ if(pair == null) return; Block block = pair.dominant(); editor.setDrawBlock(block); - Vars.ui.editor.updateSelectedBlock(); + ui.editor.updateSelectedBlock(); } }, pencil{ diff --git a/core/src/io/anuke/mindustry/mapeditor/MapEditorDialog.java b/core/src/io/anuke/mindustry/mapeditor/MapEditorDialog.java index 4a7bb352be..029fc79a67 100644 --- a/core/src/io/anuke/mindustry/mapeditor/MapEditorDialog.java +++ b/core/src/io/anuke/mindustry/mapeditor/MapEditorDialog.java @@ -4,8 +4,7 @@ import com.badlogic.gdx.files.FileHandle; import com.badlogic.gdx.graphics.Color; import com.badlogic.gdx.graphics.Pixmap; import com.badlogic.gdx.graphics.Texture; -import io.anuke.mindustry.Mindustry; -import io.anuke.mindustry.Vars; +import io.anuke.mindustry.io.Platform; import io.anuke.mindustry.ui.dialogs.FileChooser; import io.anuke.mindustry.world.Block; import io.anuke.mindustry.world.ColorMapper; @@ -13,10 +12,9 @@ import io.anuke.mindustry.world.ColorMapper.BlockPair; import io.anuke.mindustry.world.Map; import io.anuke.mindustry.world.blocks.Blocks; import io.anuke.mindustry.world.blocks.SpecialBlocks; -import io.anuke.ucore.UCore; import io.anuke.ucore.core.Core; -import io.anuke.ucore.graphics.Draw; import io.anuke.ucore.core.Timers; +import io.anuke.ucore.graphics.Draw; import io.anuke.ucore.graphics.Pixmaps; import io.anuke.ucore.scene.builders.build; import io.anuke.ucore.scene.builders.imagebutton; @@ -25,10 +23,13 @@ import io.anuke.ucore.scene.builders.table; import io.anuke.ucore.scene.ui.*; import io.anuke.ucore.scene.ui.layout.Table; import io.anuke.ucore.util.Bundles; +import io.anuke.ucore.util.Log; import io.anuke.ucore.util.Strings; import java.util.Arrays; +import static io.anuke.mindustry.Vars.*; + public class MapEditorDialog extends Dialog{ private MapEditor editor; private MapView view; @@ -43,14 +44,14 @@ public class MapEditorDialog extends Dialog{ public MapEditorDialog(){ super("$text.mapeditor", "dialog"); - if(Vars.gwt) return; + if(gwt) return; editor = new MapEditor(); dialog = new MapGenerateDialog(editor); view = new MapView(editor); openFile = new FileChooser("$text.loadimage", FileChooser.pngFilter, true, file -> { - Vars.ui.loadfrag.show(); + ui.loadfrag.show(); Timers.run(3f, () -> { try{ Pixmap pixmap = new Pixmap(file); @@ -58,13 +59,13 @@ public class MapEditorDialog extends Dialog{ editor.setPixmap(pixmap); view.clearStack(); }else{ - Vars.ui.showError(Bundles.format("text.editor.badsize", Arrays.toString(MapEditor.validMapSizes))); + ui.showError(Bundles.format("text.editor.badsize", Arrays.toString(MapEditor.validMapSizes))); } }catch (Exception e){ - Vars.ui.showError(Bundles.format("text.editor.errorimageload", Strings.parseException(e, false))); - UCore.error(e); + ui.showError(Bundles.format("text.editor.errorimageload", Strings.parseException(e, false))); + Log.err(e); } - Vars.ui.loadfrag.hide(); + ui.loadfrag.hide(); }); }); @@ -73,21 +74,21 @@ public class MapEditorDialog extends Dialog{ file = file.parent().child(file.nameWithoutExtension() + ".png"); } FileHandle result = file; - Vars.ui.loadfrag.show(); + ui.loadfrag.show(); Timers.run(3f, () -> { try{ Pixmaps.write(editor.pixmap(), result); }catch (Exception e){ - Vars.ui.showError(Bundles.format("text.editor.errorimagesave", Strings.parseException(e, false))); - if(!Vars.android) UCore.error(e); + ui.showError(Bundles.format("text.editor.errorimagesave", Strings.parseException(e, false))); + if(!android) Log.err(e); } - Vars.ui.loadfrag.hide(); + ui.loadfrag.hide(); }); }); loadDialog = new MapLoadDialog(map -> { saveDialog.setFieldText(map.name); - Vars.ui.loadfrag.show(); + ui.loadfrag.show(); Timers.run(3f, () -> { Map copy = new Map(); @@ -95,8 +96,9 @@ public class MapEditorDialog extends Dialog{ copy.id = -1; copy.pixmap = Pixmaps.copy(map.pixmap); copy.texture = new Texture(copy.pixmap); + copy.oreGen = map.oreGen; editor.beginEdit(copy); - Vars.ui.loadfrag.hide(); + ui.loadfrag.hide(); view.clearStack(); }); }); @@ -104,28 +106,28 @@ public class MapEditorDialog extends Dialog{ resizeDialog = new MapResizeDialog(editor, (x, y) -> { Pixmap pix = editor.pixmap(); if(!(pix.getWidth() == x && pix.getHeight() == y)){ - Vars.ui.loadfrag.show(); + ui.loadfrag.show(); Timers.run(10f, ()->{ editor.resize(x, y); view.clearStack(); - Vars.ui.loadfrag.hide(); + ui.loadfrag.hide(); }); } }); saveDialog = new MapSaveDialog(name -> { - Vars.ui.loadfrag.show(); + ui.loadfrag.show(); if(verifyMap()){ saved = true; editor.getMap().name = name; Timers.run(10f, () -> { - Vars.world.maps().saveAndReload(editor.getMap(), editor.pixmap()); + world.maps().saveAndReload(editor.getMap(), editor.pixmap()); loadDialog.rebuild(); - Vars.ui.loadfrag.hide(); + ui.loadfrag.hide(); view.clearStack(); }); }else{ - Vars.ui.loadfrag.hide(); + ui.loadfrag.hide(); } }); @@ -145,11 +147,11 @@ public class MapEditorDialog extends Dialog{ view.clearStack(); Timers.runTask(3f, () -> { - Mindustry.platforms.updateRPC(); + Platform.instance.updateRPC(); }); }); - hidden(() -> Mindustry.platforms.updateRPC()); + hidden(() -> Platform.instance.updateRPC()); } public MapView getView() { @@ -220,7 +222,7 @@ public class MapEditorDialog extends Dialog{ new imagebutton("icon-back", isize, () -> { if(!saved){ - Vars.ui.showConfirm("$text.confirm", "$text.editor.unsaved", + ui.showConfirm("$text.confirm", "$text.editor.unsaved", MapEditorDialog.this::hide); }else{ hide(); @@ -276,8 +278,16 @@ public class MapEditorDialog extends Dialog{ new label(() -> Bundles.format("text.editor.brushsize", MapEditor.brushSizes[(int)slider.getValue()])).left(); row(); add(slider).growX().padTop(4f); - }}.growX().end(); + }}.growX().padBottom(-6).end(); + row(); + + new table("button"){{ + get().addCheck("$text.oregen", b -> { + editor.getMap().oreGen = b; + }).update(c -> c.setChecked(editor.getMap().oreGen)).padTop(3).padBottom(3); + }}.growX().padBottom(-6).end(); + row(); addBlockSelection(get()); @@ -317,15 +327,15 @@ public class MapEditorDialog extends Dialog{ } if(playerSpawns == 0){ - Vars.ui.showError("$text.editor.noplayerspawn"); + ui.showError("$text.editor.noplayerspawn"); return false; }else if(playerSpawns > 1){ - Vars.ui.showError("$text.editor.manyplayerspawns"); + ui.showError("$text.editor.manyplayerspawns"); return false; } if(enemySpawns > MapEditor.maxSpawnpoints){ - Vars.ui.showError(Bundles.format("text.editor.manyenemyspawns", MapEditor.maxSpawnpoints)); + ui.showError(Bundles.format("text.editor.manyenemyspawns", MapEditor.maxSpawnpoints)); return false; } @@ -361,7 +371,7 @@ public class MapEditorDialog extends Dialog{ Table extra = new Table("button"); extra.labelWrap(() -> editor.getDrawBlock().formalName).width(180f).center(); - table.add(extra).growX(); + table.add(extra).padBottom(-6).growX(); table.row(); table.add(pane).growY().fillX(); } diff --git a/core/src/io/anuke/mindustry/mapeditor/MapGenerateDialog.java b/core/src/io/anuke/mindustry/mapeditor/MapGenerateDialog.java index 330f70b7ee..ee6535aafe 100644 --- a/core/src/io/anuke/mindustry/mapeditor/MapGenerateDialog.java +++ b/core/src/io/anuke/mindustry/mapeditor/MapGenerateDialog.java @@ -5,7 +5,7 @@ import com.badlogic.gdx.graphics.g2d.TextureRegion; import com.badlogic.gdx.utils.Align; import com.badlogic.gdx.utils.Scaling; -import io.anuke.mindustry.Vars; +import static io.anuke.mindustry.Vars.*; import io.anuke.mindustry.mapeditor.MapFilter.GenPref; import io.anuke.mindustry.ui.BorderImage; import io.anuke.mindustry.ui.dialogs.FloatingDialog; @@ -71,14 +71,14 @@ public class MapGenerateDialog extends FloatingDialog{ }); buttons().addButton("$text.update", this::apply); buttons().addButton("$text.apply", () ->{ - Vars.ui.loadfrag.show(); + ui.loadfrag.show(); Timers.run(3f, () ->{ Pixmap copy = Pixmaps.copy(editor.pixmap()); editor.applyFilter(); - Vars.ui.editor.getView().push(copy, Pixmaps.copy(editor.pixmap())); - Vars.ui.loadfrag.hide(); - Vars.ui.editor.resetSaved(); + ui.editor.getView().push(copy, Pixmaps.copy(editor.pixmap())); + ui.loadfrag.hide(); + ui.editor.resetSaved(); hide(); }); }); diff --git a/core/src/io/anuke/mindustry/mapeditor/MapLoadDialog.java b/core/src/io/anuke/mindustry/mapeditor/MapLoadDialog.java index 9e8ab29403..b4f2e7197f 100644 --- a/core/src/io/anuke/mindustry/mapeditor/MapLoadDialog.java +++ b/core/src/io/anuke/mindustry/mapeditor/MapLoadDialog.java @@ -1,6 +1,6 @@ package io.anuke.mindustry.mapeditor; -import io.anuke.mindustry.Vars; +import static io.anuke.mindustry.Vars.*; import io.anuke.mindustry.ui.BorderImage; import io.anuke.mindustry.ui.dialogs.FloatingDialog; import io.anuke.mindustry.world.Map; @@ -11,7 +11,7 @@ import io.anuke.ucore.scene.ui.TextButton; import io.anuke.ucore.scene.ui.layout.Table; public class MapLoadDialog extends FloatingDialog{ - private Map selected = Vars.world.maps().getMap(0); + private Map selected = world.maps().getMap(0); public MapLoadDialog(Consumer loader) { super("$text.editor.loadmap"); @@ -35,7 +35,7 @@ public class MapLoadDialog extends FloatingDialog{ public void rebuild(){ content().clear(); - selected = Vars.world.maps().getMap(0); + selected = world.maps().getMap(0); ButtonGroup group = new ButtonGroup<>(); @@ -50,7 +50,7 @@ public class MapLoadDialog extends FloatingDialog{ ScrollPane pane = new ScrollPane(table, "horizontal"); pane.setFadeScrollBars(false); - for (Map map : Vars.world.maps().list()) { + for (Map map : world.maps().list()) { if (!map.visible) continue; TextButton button = new TextButton(map.localized(), "toggle"); diff --git a/core/src/io/anuke/mindustry/mapeditor/MapSaveDialog.java b/core/src/io/anuke/mindustry/mapeditor/MapSaveDialog.java index 28c2267276..967917e5d7 100644 --- a/core/src/io/anuke/mindustry/mapeditor/MapSaveDialog.java +++ b/core/src/io/anuke/mindustry/mapeditor/MapSaveDialog.java @@ -1,7 +1,7 @@ package io.anuke.mindustry.mapeditor; -import io.anuke.mindustry.Mindustry; -import io.anuke.mindustry.Vars; +import static io.anuke.mindustry.Vars.*; +import io.anuke.mindustry.io.Platform; import io.anuke.mindustry.ui.dialogs.FloatingDialog; import io.anuke.mindustry.world.Map; import io.anuke.ucore.function.Consumer; @@ -15,12 +15,12 @@ public class MapSaveDialog extends FloatingDialog{ super("$text.editor.savemap"); field = new TextField(); - Mindustry.platforms.addDialog(field); + Platform.instance.addDialog(field); shown(() -> { content().clear(); content().label(() ->{ - Map map = Vars.world.maps().getMap(field.getText()); + Map map = world.maps().getMap(field.getText()); if(map != null){ if(map.custom){ return "$text.editor.overwrite"; @@ -58,7 +58,7 @@ public class MapSaveDialog extends FloatingDialog{ if(field.getText().isEmpty()){ return true; } - Map map = Vars.world.maps().getMap(field.getText()); + Map map = world.maps().getMap(field.getText()); return map != null && !map.custom; } } diff --git a/core/src/io/anuke/mindustry/mapeditor/MapView.java b/core/src/io/anuke/mindustry/mapeditor/MapView.java index abccb3f188..14e065d2d0 100644 --- a/core/src/io/anuke/mindustry/mapeditor/MapView.java +++ b/core/src/io/anuke/mindustry/mapeditor/MapView.java @@ -11,7 +11,7 @@ import com.badlogic.gdx.math.GridPoint2; import com.badlogic.gdx.math.Vector2; import com.badlogic.gdx.scenes.scene2d.utils.ScissorStack; import com.badlogic.gdx.utils.Array; -import io.anuke.mindustry.Vars; +import static io.anuke.mindustry.Vars.*; import io.anuke.mindustry.ui.GridImage; import io.anuke.mindustry.world.ColorMapper; import io.anuke.ucore.core.Core; @@ -116,7 +116,7 @@ public class MapView extends Element implements GestureListener{ if(tool.edit){ updated = true; - Vars.ui.editor.resetSaved(); + ui.editor.resetSaved(); } op = new DrawOperation(editor.pixmap()); @@ -132,7 +132,7 @@ public class MapView extends Element implements GestureListener{ GridPoint2 p = project(x, y); if(tool == EditorTool.line){ - Vars.ui.editor.resetSaved(); + ui.editor.resetSaved(); Array points = br.line(startx, starty, p.x, p.y); for(GridPoint2 point : points){ editor.draw(point.x, point.y); @@ -155,7 +155,7 @@ public class MapView extends Element implements GestureListener{ GridPoint2 p = project(x, y); if(drawing && tool == EditorTool.pencil){ - Vars.ui.editor.resetSaved(); + ui.editor.resetSaved(); Array points = br.line(lastx, lasty, p.x, p.y); for(GridPoint2 point : points){ editor.draw(point.x, point.y); @@ -256,8 +256,8 @@ public class MapView extends Element implements GestureListener{ private boolean active(){ return Core.scene.getKeyboardFocus() != null - && Core.scene.getKeyboardFocus().isDescendantOf(Vars.ui.editor) - && Vars.ui.editor.isShown() && tool == EditorTool.zoom && + && Core.scene.getKeyboardFocus().isDescendantOf(ui.editor) + && ui.editor.isShown() && tool == EditorTool.zoom && Core.scene.hit(Graphics.mouse().x, Graphics.mouse().y, true) == this; } 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 03fffd1aeb..f3b384c388 100644 --- a/core/src/io/anuke/mindustry/net/Net.java +++ b/core/src/io/anuke/mindustry/net/Net.java @@ -4,25 +4,27 @@ import com.badlogic.gdx.Gdx; import com.badlogic.gdx.utils.Array; import com.badlogic.gdx.utils.IntMap; import com.badlogic.gdx.utils.ObjectMap; -import io.anuke.mindustry.Mindustry; +import com.badlogic.gdx.utils.reflect.ClassReflection; import io.anuke.mindustry.net.Packet.ImportantPacket; import io.anuke.mindustry.net.Packets.KickReason; import io.anuke.mindustry.net.Streamable.StreamBegin; import io.anuke.mindustry.net.Streamable.StreamBuilder; import io.anuke.mindustry.net.Streamable.StreamChunk; -import io.anuke.ucore.UCore; -import io.anuke.ucore.core.Timers; import io.anuke.ucore.function.BiConsumer; import io.anuke.ucore.function.Consumer; +import io.anuke.ucore.util.Log; import java.io.IOException; +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; private static boolean clientLoaded; + private static ObjectMap, Consumer> listeners = new ObjectMap<>(); private static ObjectMap, Consumer> clientListeners = new ObjectMap<>(); private static ObjectMap, BiConsumer> serverListeners = new ObjectMap<>(); private static ClientProvider clientProvider; @@ -30,6 +32,15 @@ public class Net{ private static IntMap streams = new IntMap<>(); + /**Display a network error.*/ + public static void showError(String text){ + if(!headless){ + ui.showError(text); + }else{ + Log.err(text); + } + } + /**Sets the client loaded status, or whether it will recieve normal packets from the server.*/ public static void setClientLoaded(boolean loaded){ clientLoaded = loaded; @@ -40,8 +51,6 @@ public class Net{ clientProvider.connect(ip, port); active = true; server = false; - - Timers.runTask(60f, Mindustry.platforms::updateRPC); } /**Host a server at an address*/ @@ -49,8 +58,6 @@ public class Net{ serverProvider.host(port); active = true; server = true; - - Timers.runTask(60f, Mindustry.platforms::updateRPC); } /**Closes the server.*/ @@ -85,9 +92,9 @@ public class Net{ /**Send an object to all connected clients, or to the server if this is a client.*/ public static void send(Object object, SendMode mode){ if(server){ - serverProvider.send(object, mode); + if(serverProvider != null) serverProvider.send(object, mode); }else { - clientProvider.send(object, mode); + if(clientProvider != null) clientProvider.send(object, mode); } } @@ -115,9 +122,14 @@ public class Net{ public static void setServerProvider(ServerProvider provider){ Net.serverProvider = provider; } - - /**Registers a client listener for when an object is recieved.*/ + + /**Registers a common listener for when an object is recieved. Fired on both client and serve.r*/ public static void handle(Class type, Consumer listener){ + listeners.put(type, listener); + } + + /**Registers a client listener for when an object is recieved.*/ + public static void handleClient(Class type, Consumer listener){ clientListeners.put(type, listener); } @@ -128,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)); @@ -142,11 +156,13 @@ public class Net{ streams.remove(builder.id); handleClientReceived(builder.build()); } - }else if(clientListeners.get(object.getClass()) != null){ + }else if(clientListeners.get(object.getClass()) != null || + listeners.get(object.getClass()) != null){ if(clientLoaded || object instanceof ImportantPacket){ - clientListeners.get(object.getClass()).accept(object); + if(clientListeners.get(object.getClass()) != null) clientListeners.get(object.getClass()).accept(object); + if(listeners.get(object.getClass()) != null) listeners.get(object.getClass()).accept(object); }else{ - UCore.log("Recieved " + object, "but ignoring data, as client is not loaded."); + Log.info("Recieved {0}, but ignoring data, as client is not loaded.", ClassReflection.getSimpleName(object.getClass())); } }else{ Gdx.app.error("Mindustry::Net", "Unhandled packet type: '" + object.getClass() + "'!"); @@ -155,8 +171,11 @@ public class Net{ /**Call to handle a packet being recieved for the server.*/ public static void handleServerReceived(int connection, Object object){ - if(serverListeners.get(object.getClass()) != null){ - serverListeners.get(object.getClass()).accept(connection, 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); }else{ Gdx.app.error("Mindustry::Net", "Unhandled packet type: '" + object.getClass() + "'!"); } @@ -184,12 +203,12 @@ public class Net{ /**Whether this is a server or not.*/ public static boolean server(){ - return server; + return server && active; } /**Whether this is a client or not.*/ public static boolean client(){ - return !server; + return !server && active; } public static void dispose(){ diff --git a/core/src/io/anuke/mindustry/net/NetEvents.java b/core/src/io/anuke/mindustry/net/NetEvents.java new file mode 100644 index 0000000000..cc70b52eae --- /dev/null +++ b/core/src/io/anuke/mindustry/net/NetEvents.java @@ -0,0 +1,134 @@ +package io.anuke.mindustry.net; + +import io.anuke.mindustry.Vars; +import io.anuke.mindustry.core.GameState.State; +import io.anuke.mindustry.entities.BulletType; +import io.anuke.mindustry.entities.TileEntity; +import io.anuke.mindustry.entities.enemies.Enemy; +import io.anuke.mindustry.net.Net.SendMode; +import io.anuke.mindustry.net.Packets.*; +import io.anuke.mindustry.resource.Weapon; +import io.anuke.mindustry.world.Block; +import io.anuke.mindustry.world.Tile; +import io.anuke.ucore.entities.Entity; + +import static io.anuke.mindustry.Vars.*; + +public class NetEvents { + + public static void handleFriendlyFireChange(boolean enabled){ + FriendlyFireChangePacket packet = new FriendlyFireChangePacket(); + packet.enabled = enabled; + + netCommon.sendMessage(enabled ? "[accent]Friendly fire enabled." : "[accent]Friendly fire disabled."); + + Net.send(packet, SendMode.tcp); + } + + public static void handleGameOver(){ + Net.send(new GameOverPacket(), SendMode.tcp); + state.gameOver = true; + state.set(State.menu); + } + + public static void handleBullet(BulletType type, Entity owner, float x, float y, float angle, short damage){ + BulletPacket packet = new BulletPacket(); + packet.x = x; + packet.y = y; + packet.angle = angle; + packet.damage = damage; + packet.owner = owner.id; + packet.type = type.id; + Net.send(packet, SendMode.udp); + } + + public static void handleEnemyDeath(Enemy enemy){ + EnemyDeathPacket packet = new EnemyDeathPacket(); + packet.id = enemy.id; + state.gameOver = true; + Net.send(packet, SendMode.tcp); + } + + public static void handleBlockDestroyed(TileEntity entity){ + BlockDestroyPacket packet = new BlockDestroyPacket(); + packet.position = entity.tile.packedPosition(); + Net.send(packet, SendMode.tcp); + } + + public static void handleBlockDamaged(TileEntity entity){ + BlockUpdatePacket packet = new BlockUpdatePacket(); + packet.health = (int)entity.health; + packet.position = entity.tile.packedPosition(); + Net.send(packet, SendMode.udp); + } + + public static void handlePlayerDeath(){ + PlayerDeathPacket packet = new PlayerDeathPacket(); + packet.id = Vars.player.id; + Net.send(packet, SendMode.tcp); + } + + public static void handleBlockConfig(Tile tile, byte data){ + BlockConfigPacket packet = new BlockConfigPacket(); + packet.data = data; + packet.position = tile.packedPosition(); + Net.send(packet, SendMode.tcp); + } + + public static void handleBlockTap(Tile tile){ + BlockTapPacket packet = new BlockTapPacket(); + packet.position = tile.packedPosition(); + Net.send(packet, SendMode.tcp); + } + + public static void handleWeaponSwitch(){ + WeaponSwitchPacket packet = new WeaponSwitchPacket(); + packet.left = Vars.player.weaponLeft.id; + packet.right = Vars.player.weaponRight.id; + packet.playerid = Vars.player.id; + Net.send(packet, SendMode.tcp); + } + + public static void handleUpgrade(Weapon weapon){ + UpgradePacket packet = new UpgradePacket(); + packet.id = weapon.id; + Net.send(packet, SendMode.tcp); + } + + public static void handleSendMessage(String message){ + ChatPacket packet = new ChatPacket(); + packet.text = message; + packet.name = Vars.player.name; + packet.id = Vars.player.id; + Net.send(packet, SendMode.tcp); + + ui.chatfrag.addMessage(packet.text, netCommon.colorizeName(Vars.player.id, Vars.player.name)); + } + + public static void handleShoot(Weapon weapon, float x, float y, float angle){ + ShootPacket packet = new ShootPacket(); + packet.weaponid = weapon.id; + packet.x = x; + packet.y = y; + packet.rotation = angle; + packet.playerid = Vars.player.id; + Net.send(packet, SendMode.udp); + } + + public static void handlePlace(int x, int y, Block block, int rotation){ + PlacePacket packet = new PlacePacket(); + packet.x = (short)x; + packet.y = (short)y; + packet.rotation = (byte)rotation; + packet.playerid = Vars.player.id; + packet.block = block.id; + Net.send(packet, SendMode.tcp); + } + + public static void handleBreak(int x, int y){ + BreakPacket packet = new BreakPacket(); + packet.x = (short)x; + packet.y = (short)y; + Net.send(packet, SendMode.tcp); + } +} diff --git a/core/src/io/anuke/mindustry/net/NetworkIO.java b/core/src/io/anuke/mindustry/net/NetworkIO.java index d6af000781..a8bae0b5e1 100644 --- a/core/src/io/anuke/mindustry/net/NetworkIO.java +++ b/core/src/io/anuke/mindustry/net/NetworkIO.java @@ -4,14 +4,10 @@ import com.badlogic.gdx.graphics.Pixmap; import com.badlogic.gdx.graphics.Pixmap.Format; import com.badlogic.gdx.utils.ByteArray; import com.badlogic.gdx.utils.TimeUtils; -import io.anuke.mindustry.Vars; import io.anuke.mindustry.game.GameMode; import io.anuke.mindustry.resource.Upgrade; import io.anuke.mindustry.resource.Weapon; -import io.anuke.mindustry.world.Block; -import io.anuke.mindustry.world.ColorMapper; -import io.anuke.mindustry.world.Tile; -import io.anuke.mindustry.world.WorldGenerator; +import io.anuke.mindustry.world.*; import io.anuke.mindustry.world.blocks.Blocks; import io.anuke.mindustry.world.blocks.types.BlockPart; import io.anuke.mindustry.world.blocks.types.Rock; @@ -20,10 +16,14 @@ import io.anuke.ucore.entities.Entities; import java.io.*; +import static io.anuke.mindustry.Vars.*; + public class NetworkIO { - public static void writeMap(Pixmap map, OutputStream os){ + public static void writeMap(Map map, OutputStream os){ try(DataOutputStream stream = new DataOutputStream(os)){ + stream.writeBoolean(map.oreGen); + stream.writeShort(map.getWidth()); stream.writeShort(map.getHeight()); @@ -32,7 +32,7 @@ public class NetworkIO { int pos = 0; while(pos < cap){ - int color = map.getPixel(pos % width, pos / width); + int color = map.pixmap.getPixel(pos % width, pos / width); byte id = ColorMapper.getColorID(color); int length = 1; @@ -43,7 +43,7 @@ public class NetworkIO { pos ++; - int next = map.getPixel(pos % width, pos / width); + int next = map.pixmap.getPixel(pos % width, pos / width); if(next != color){ pos --; break; @@ -52,7 +52,7 @@ public class NetworkIO { } } - if(id == -1) id = 0; + if(id == -1) id = 2; stream.writeByte((byte)(length > 127 ? length - 256 : length)); stream.writeByte(id); @@ -63,8 +63,10 @@ public class NetworkIO { } } - public static Pixmap loadMap(InputStream is){ + public static Map loadMap(InputStream is){ try(DataInputStream stream = new DataInputStream(is)){ + boolean ores = stream.readBoolean(); + short width = stream.readShort(); short height = stream.readShort(); Pixmap pixmap = new Pixmap(width, height, Format.RGBA8888); @@ -82,8 +84,15 @@ public class NetworkIO { } } + Map map = new Map(); + map.oreGen = ores; + map.custom = true; + map.pixmap = pixmap; + map.visible = false; + map.name = "network map"; + map.id = -1; - return pixmap; + return map; }catch (IOException e){ throw new RuntimeException(e); } @@ -97,20 +106,20 @@ public class NetworkIO { stream.writeLong(TimeUtils.millis()); //timestamp //--GENERAL STATE-- - stream.writeByte(Vars.control.getMode().ordinal()); //gamemode - stream.writeByte(Vars.world.getMap().custom ? -1 : Vars.world.getMap().id); //map ID + stream.writeByte(state.mode.ordinal()); //gamemode + stream.writeByte(world.getMap().custom ? -1 : world.getMap().id); //map ID - stream.writeInt(Vars.control.getWave()); //wave - stream.writeFloat(Vars.control.getWaveCountdown()); //wave countdown - stream.writeInt(Vars.control.enemyGroup.amount()); //enemy amount + stream.writeInt(state.wave); //wave + stream.writeFloat(state.wavetime); //wave countdown + stream.writeInt(state.enemies); //enemy amount - stream.writeBoolean(Vars.control.isFriendlyFire()); //friendly fire state + stream.writeBoolean(state.friendlyFire); //friendly fire state stream.writeInt(playerID); //player remap ID //--INVENTORY-- - for(int i = 0; i < Vars.control.getItems().length; i ++){ //items - stream.writeInt(Vars.control.getItems()[i]); + for(int i = 0; i < state.inventory.getItems().length; i ++){ //items + stream.writeInt(state.inventory.getItems()[i]); } stream.writeByte(upgrades.size); //upgrade data @@ -122,14 +131,14 @@ public class NetworkIO { //--MAP DATA-- //seed - stream.writeInt(Vars.world.getSeed()); + stream.writeInt(world.getSeed()); int totalblocks = 0; int totalrocks = 0; - for(int x = 0; x < Vars.world.width(); x ++){ - for(int y = 0; y < Vars.world.height(); y ++){ - Tile tile = Vars.world.tile(x, y); + for(int x = 0; x < world.width(); x ++){ + for(int y = 0; y < world.height(); y ++){ + Tile tile = world.tile(x, y); if(tile.breakable()){ if(tile.block() instanceof Rock){ @@ -145,9 +154,9 @@ public class NetworkIO { stream.writeInt(totalrocks); //write all rocks - for(int x = 0; x < Vars.world.width(); x ++) { - for (int y = 0; y < Vars.world.height(); y++) { - Tile tile = Vars.world.tile(x, y); + for(int x = 0; x < world.width(); x ++) { + for (int y = 0; y < world.height(); y++) { + Tile tile = world.tile(x, y); if (tile.block() instanceof Rock) { stream.writeInt(tile.packedPosition()); @@ -158,13 +167,13 @@ public class NetworkIO { //tile amount stream.writeInt(totalblocks); - for(int x = 0; x < Vars.world.width(); x ++){ - for(int y = 0; y < Vars.world.height(); y ++){ - Tile tile = Vars.world.tile(x, y); + for(int x = 0; x < world.width(); x ++){ + for(int y = 0; y < world.height(); y ++){ + Tile tile = world.tile(x, y); if(tile.breakable() && !(tile.block() instanceof Rock)){ - stream.writeInt(x + y*Vars.world.width()); //tile pos + stream.writeInt(x + y*world.width()); //tile pos //TODO will break if block number gets over BYTE_MAX stream.writeByte(tile.block().id); //block ID @@ -227,51 +236,53 @@ public class NetworkIO { int enemies = stream.readInt(); boolean friendlyfire = stream.readBoolean(); - Vars.control.setWaveData(enemies, wave, wavetime); - Vars.control.setMode(GameMode.values()[mode]); - Vars.control.setFriendlyFire(friendlyfire); + state.enemies = enemies; + state.wave = wave; + state.wavetime = wavetime; + state.mode = GameMode.values()[mode]; + state.friendlyFire = friendlyfire; int pid = stream.readInt(); //inventory - for(int i = 0; i < Vars.control.getItems().length; i ++){ - Vars.control.getItems()[i] = stream.readInt(); + for(int i = 0; i < state.inventory.getItems().length; i ++){ + state.inventory.getItems()[i] = stream.readInt(); } - Vars.ui.hudfrag.updateItems(); + ui.hudfrag.updateItems(); - Vars.control.getWeapons().clear(); - Vars.control.getWeapons().add(Weapon.blaster); + control.upgrades().getWeapons().clear(); + control.upgrades().getWeapons().add(Weapon.blaster); byte weapons = stream.readByte(); for(int i = 0; i < weapons; i ++){ - Vars.control.getWeapons().add((Weapon) Upgrade.getByID(stream.readByte())); + control.upgrades().getWeapons().add((Weapon) Upgrade.getByID(stream.readByte())); } - Vars.player.weaponLeft = Vars.player.weaponRight = Vars.control.getWeapons().peek(); - Vars.ui.hudfrag.updateWeapons(); + player.weaponLeft = player.weaponRight = control.upgrades().getWeapons().peek(); + ui.hudfrag.updateWeapons(); Entities.clear(); - Vars.player.id = pid; - Vars.player.add(); + player.id = pid; + player.add(); //map int seed = stream.readInt(); - Vars.world.loadMap(Vars.world.maps().getMap(mapid), seed); - Vars.renderer.clearTiles(); + world.loadMap(world.maps().getMap(mapid), seed); + renderer.clearTiles(); - Vars.player.set(Vars.control.getCore().worldx(), Vars.control.getCore().worldy()); + player.set(world.getSpawnX(), world.getSpawnY()); - for(int x = 0; x < Vars.world.width(); x ++){ - for(int y = 0; y < Vars.world.height(); y ++){ - Tile tile = Vars.world.tile(x, y); + for(int x = 0; x < world.width(); x ++){ + for(int y = 0; y < world.height(); y ++){ + Tile tile = world.tile(x, y); //remove breakables like rocks if(tile.breakable()){ - Vars.world.tile(x, y).setBlock(Blocks.air); + world.tile(x, y).setBlock(Blocks.air); } } } @@ -280,7 +291,7 @@ public class NetworkIO { for(int i = 0; i < rocks; i ++){ int pos = stream.readInt(); - Tile tile = Vars.world.tile(pos % Vars.world.width(), pos / Vars.world.width()); + Tile tile = world.tile(pos % world.width(), pos / world.width()); Block result = WorldGenerator.rocks.get(tile.floor()); if(result != null) tile.setBlock(result); } @@ -291,7 +302,7 @@ public class NetworkIO { int pos = stream.readInt(); byte blockid = stream.readByte(); - Tile tile = Vars.world.tile(pos % Vars.world.width(), pos / Vars.world.width()); + Tile tile = world.tile(pos % world.width(), pos / world.width()); tile.setBlock(Block.getByID(blockid)); if(tile.block() == Blocks.blockpart){ 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/resource/Weapon.java b/core/src/io/anuke/mindustry/resource/Weapon.java index 8e56bd070b..271ad6a300 100644 --- a/core/src/io/anuke/mindustry/resource/Weapon.java +++ b/core/src/io/anuke/mindustry/resource/Weapon.java @@ -6,6 +6,7 @@ import io.anuke.mindustry.entities.BulletType; import io.anuke.mindustry.entities.Player; import io.anuke.mindustry.graphics.Fx; import io.anuke.mindustry.net.Net; +import io.anuke.mindustry.net.NetEvents; import io.anuke.ucore.core.Effects; import io.anuke.ucore.core.Effects.Effect; import io.anuke.ucore.core.Timers; @@ -112,7 +113,7 @@ public class Weapon extends Upgrade{ shootInternal(p, x, y, angle); if(Net.active() && p == Vars.player){ - Vars.netClient.handleShoot(this, x, y, angle); + NetEvents.handleShoot(this, x, y, angle); } } diff --git a/core/src/io/anuke/mindustry/ui/dialogs/DiscordDialog.java b/core/src/io/anuke/mindustry/ui/dialogs/DiscordDialog.java index 95984d86ae..c94c3e1ae6 100644 --- a/core/src/io/anuke/mindustry/ui/dialogs/DiscordDialog.java +++ b/core/src/io/anuke/mindustry/ui/dialogs/DiscordDialog.java @@ -1,9 +1,10 @@ package io.anuke.mindustry.ui.dialogs; import com.badlogic.gdx.Gdx; -import io.anuke.mindustry.Vars; import io.anuke.ucore.scene.ui.Dialog; +import static io.anuke.mindustry.Vars.discordURL; + public class DiscordDialog extends Dialog { public DiscordDialog(){ @@ -11,9 +12,9 @@ public class DiscordDialog extends Dialog { content().margin(12f); content().add("$text.discord"); content().row(); - content().add("[orange]"+ Vars.discordURL); + content().add("[orange]"+ discordURL); buttons().defaults().size(200f, 50); - buttons().addButton("$text.openlink", () -> Gdx.net.openURI(Vars.discordURL)); + buttons().addButton("$text.openlink", () -> Gdx.net.openURI(discordURL)); buttons().addButton("$text.back", this::hide); } } diff --git a/core/src/io/anuke/mindustry/ui/dialogs/FileChooser.java b/core/src/io/anuke/mindustry/ui/dialogs/FileChooser.java index acd0d97b3f..eda9d315ad 100644 --- a/core/src/io/anuke/mindustry/ui/dialogs/FileChooser.java +++ b/core/src/io/anuke/mindustry/ui/dialogs/FileChooser.java @@ -6,7 +6,7 @@ import com.badlogic.gdx.graphics.g2d.GlyphLayout; import com.badlogic.gdx.utils.Align; import com.badlogic.gdx.utils.Array; import com.badlogic.gdx.utils.Pools; -import io.anuke.mindustry.Mindustry; +import io.anuke.mindustry.io.Platform; import io.anuke.ucore.core.Core; import io.anuke.ucore.core.Timers; import io.anuke.ucore.function.Consumer; @@ -49,7 +49,7 @@ public class FileChooser extends FloatingDialog { filefield = new TextField(); filefield.setOnlyFontChars(false); - if(!open) Mindustry.platforms.addDialog(filefield); + if(!open) Platform.instance.addDialog(filefield); filefield.setDisabled(open); ok = new TextButton(open ? "$text.load" : "$text.save"); @@ -251,7 +251,7 @@ public class FileChooser extends FloatingDialog { @Override public Dialog show(){ - Mindustry.platforms.requestWritePerms(); + Platform.instance.requestWritePerms(); Timers.runTask(2f, () -> { content().clear(); setupWidgets(); @@ -316,8 +316,8 @@ public class FileChooser extends FloatingDialog { } } - public static interface FileHandleFilter{ - public boolean accept(FileHandle file); + public interface FileHandleFilter{ + boolean accept(FileHandle file); } public static Predicate pngFilter = file -> file.extension().equalsIgnoreCase("png"); diff --git a/core/src/io/anuke/mindustry/ui/dialogs/HostDialog.java b/core/src/io/anuke/mindustry/ui/dialogs/HostDialog.java index 9fba52ad60..d49f6a8300 100644 --- a/core/src/io/anuke/mindustry/ui/dialogs/HostDialog.java +++ b/core/src/io/anuke/mindustry/ui/dialogs/HostDialog.java @@ -9,6 +9,8 @@ import io.anuke.ucore.util.Strings; import java.io.IOException; +import static io.anuke.mindustry.Vars.ui; + //TODO add port specification public class HostDialog extends FloatingDialog{ float w = 300; @@ -25,21 +27,21 @@ public class HostDialog extends FloatingDialog{ Vars.player.name = text; Settings.put("name", text); Settings.save(); - Vars.ui.listfrag.rebuild(); + ui.listfrag.rebuild(); }).grow().pad(8); }).width(w).height(70f).pad(4); content().row(); content().addButton("$text.host", () -> { - Vars.ui.loadfrag.show("$text.hosting"); + ui.loadfrag.show("$text.hosting"); Timers.runTask(5f, () -> { try{ Net.host(Vars.port); }catch (IOException e){ - Vars.ui.showError(Bundles.format("text.server.error", Strings.parseException(e, false))); + ui.showError(Bundles.format("text.server.error", Strings.parseException(e, false))); } - Vars.ui.loadfrag.hide(); + ui.loadfrag.hide(); hide(); }); }).width(w).height(70f); @@ -49,12 +51,12 @@ public class HostDialog extends FloatingDialog{ showTextInput("$text.hostserver", "$text.server.port", Vars.port + "", new DigitsOnlyFilter(), text -> { int result = Strings.parseInt(text); if(result == Integer.MIN_VALUE || result >= 65535){ - Vars.ui.showError("$text.server.invalidport"); + ui.showError("$text.server.invalidport"); }else{ try{ Net.host(result); }catch (IOException e){ - Vars.ui.showError(Bundles.format("text.server.error", Strings.parseException(e, false))); + ui.showError(Bundles.format("text.server.error", Strings.parseException(e, false))); } } }); diff --git a/core/src/io/anuke/mindustry/ui/dialogs/JoinDialog.java b/core/src/io/anuke/mindustry/ui/dialogs/JoinDialog.java index 7e6b59c576..196d05e231 100644 --- a/core/src/io/anuke/mindustry/ui/dialogs/JoinDialog.java +++ b/core/src/io/anuke/mindustry/ui/dialogs/JoinDialog.java @@ -1,11 +1,10 @@ package io.anuke.mindustry.ui.dialogs; import com.badlogic.gdx.utils.Array; -import io.anuke.mindustry.Mindustry; import io.anuke.mindustry.Vars; +import io.anuke.mindustry.io.Platform; import io.anuke.mindustry.net.Host; import io.anuke.mindustry.net.Net; -import io.anuke.ucore.UCore; import io.anuke.ucore.core.Settings; import io.anuke.ucore.core.Timers; import io.anuke.ucore.scene.style.Drawable; @@ -14,8 +13,11 @@ import io.anuke.ucore.scene.ui.ScrollPane; import io.anuke.ucore.scene.ui.TextButton; import io.anuke.ucore.scene.ui.layout.Table; import io.anuke.ucore.util.Bundles; +import io.anuke.ucore.util.Log; import io.anuke.ucore.util.Strings; +import static io.anuke.mindustry.Vars.ui; + public class JoinDialog extends FloatingDialog { Array servers = new Array<>(); Dialog add; @@ -35,7 +37,7 @@ public class JoinDialog extends FloatingDialog { add = new FloatingDialog("$text.joingame.title"); add.content().add("$text.joingame.ip").padRight(5f).left(); - Mindustry.platforms.addDialog(add.content().addField(Settings.getString("ip"), text ->{ + Platform.instance.addDialog(add.content().addField(Settings.getString("ip"), text ->{ Settings.putString("ip", text); Settings.save(); }).size(340f, 54f).get(), 100); @@ -100,7 +102,7 @@ public class JoinDialog extends FloatingDialog { }).margin(3f).padTop(6f).top().right(); inner.addImageButton("icon-trash-16", "empty", 16*2, () -> { - Vars.ui.showConfirm("$text.confirm", "$text.server.delete", () -> { + ui.showConfirm("$text.confirm", "$text.server.delete", () -> { servers.removeValue(server, true); saveServers(); setupRemote(); @@ -207,7 +209,7 @@ public class JoinDialog extends FloatingDialog { } void connect(String ip, int port){ - Vars.ui.loadfrag.show("$text.connecting"); + ui.loadfrag.show("$text.connecting"); Timers.runTask(2f, () -> { try{ @@ -233,10 +235,10 @@ public class JoinDialog extends FloatingDialog { }else{ error = Strings.parseException(e, false); } - Vars.ui.showError(Bundles.format("text.connectfail", error)); - Vars.ui.loadfrag.hide(); + ui.showError(Bundles.format("text.connectfail", error)); + ui.loadfrag.hide(); - UCore.error(e); + Log.err(e); } }); } diff --git a/core/src/io/anuke/mindustry/ui/dialogs/LanguageDialog.java b/core/src/io/anuke/mindustry/ui/dialogs/LanguageDialog.java index e2e3918fbe..27f5eca753 100644 --- a/core/src/io/anuke/mindustry/ui/dialogs/LanguageDialog.java +++ b/core/src/io/anuke/mindustry/ui/dialogs/LanguageDialog.java @@ -1,16 +1,17 @@ package io.anuke.mindustry.ui.dialogs; -import io.anuke.mindustry.Mindustry; -import io.anuke.mindustry.Vars; -import io.anuke.ucore.UCore; +import io.anuke.mindustry.io.Platform; import io.anuke.ucore.core.Settings; import io.anuke.ucore.scene.ui.ButtonGroup; import io.anuke.ucore.scene.ui.ScrollPane; import io.anuke.ucore.scene.ui.TextButton; import io.anuke.ucore.scene.ui.layout.Table; +import io.anuke.ucore.util.Log; import java.util.Locale; +import static io.anuke.mindustry.Vars.ui; + public class LanguageDialog extends FloatingDialog{ private Locale[] locales = {Locale.ENGLISH, new Locale("fr", "FR"), new Locale("es", "LA"), new Locale("pt", "BR"), new Locale("ko"), new Locale("in", "ID")}; @@ -30,17 +31,17 @@ public class LanguageDialog extends FloatingDialog{ ButtonGroup group = new ButtonGroup<>(); for(Locale loc : locales){ - TextButton button = new TextButton(Mindustry.platforms.getLocaleName(loc), "toggle"); - button.setChecked(Vars.ui.getLocale().equals(loc)); + TextButton button = new TextButton(Platform.instance.getLocaleName(loc), "toggle"); + button.setChecked(ui.getLocale().equals(loc)); button.clicked(() -> { - if(Vars.ui.getLocale().equals(loc)) return; + if(ui.getLocale().equals(loc)) return; Settings.putString("locale", loc.toString()); Settings.save(); - UCore.log("Setting locale: " + loc.toString()); - Vars.ui.showInfo("$text.language.restart"); + Log.info("Setting locale: {0}", loc.toString()); + ui.showInfo("$text.language.restart"); }); langs.add(button).group(group).update(t -> { - t.setChecked(loc.equals(Vars.ui.getLocale())); + t.setChecked(loc.equals(ui.getLocale())); }).size(400f, 60f).row(); } diff --git a/core/src/io/anuke/mindustry/ui/dialogs/LevelDialog.java b/core/src/io/anuke/mindustry/ui/dialogs/LevelDialog.java index f219129e1f..67aa616e1b 100644 --- a/core/src/io/anuke/mindustry/ui/dialogs/LevelDialog.java +++ b/core/src/io/anuke/mindustry/ui/dialogs/LevelDialog.java @@ -1,7 +1,6 @@ package io.anuke.mindustry.ui.dialogs; import com.badlogic.gdx.graphics.g2d.TextureRegion; -import io.anuke.mindustry.Vars; import io.anuke.mindustry.game.Difficulty; import io.anuke.mindustry.game.GameMode; import io.anuke.mindustry.world.Map; @@ -19,8 +18,10 @@ import io.anuke.ucore.util.Bundles; import io.anuke.ucore.util.Mathf; import io.anuke.ucore.util.Tmp; +import static io.anuke.mindustry.Vars.*; + public class LevelDialog extends FloatingDialog{ - private Map selectedMap = Vars.world.maps().getMap(0); + private Map selectedMap = world.maps().getMap(0); private TextureRegion region = new TextureRegion(); private ScrollPane pane; @@ -50,7 +51,7 @@ public class LevelDialog extends FloatingDialog{ for(GameMode mode : GameMode.values()){ TextButton b = Elements.newButton("$mode."+mode.name()+".name", "toggle", ()->{ - Vars.control.setMode(mode); + state.mode = mode; }); group.add(b); selmode.add(b).size(130f, 54f); @@ -69,27 +70,27 @@ public class LevelDialog extends FloatingDialog{ sdif.defaults().height(s+4); sdif.addImageButton("icon-arrow-left", 10*3, () -> { - Vars.control.setDifficulty(ds[Mathf.mod(Vars.control.getDifficulty().ordinal() - 1, ds.length)]); + state.difficulty = (ds[Mathf.mod(state.difficulty.ordinal() - 1, ds.length)]); }).width(s); sdif.addButton("", () -> { }).update(t -> { - t.setText(Vars.control.getDifficulty().toString()); + t.setText(state.difficulty.toString()); t.setTouchable(Touchable.disabled); }).width(180f); sdif.addImageButton("icon-arrow-right", 10*3, () -> { - Vars.control.setDifficulty(ds[Mathf.mod(Vars.control.getDifficulty().ordinal() + 1, ds.length)]); + state.difficulty = (ds[Mathf.mod(state.difficulty.ordinal() + 1, ds.length)]); }).width(s); content().add(sdif); content().row(); int i = 0; - for(Map map : Vars.world.maps().list()){ + for(Map map : world.maps().list()){ - if(!map.visible && !Vars.debug) continue; + if(!map.visible && !debug) continue; if(i % maxwidth == 0){ maps.row(); @@ -122,8 +123,8 @@ public class LevelDialog extends FloatingDialog{ image.row(); delete[0] = image.addButton("Delete", () -> { Timers.run(1f, () -> { - Vars.ui.showConfirm("$text.level.delete.title", Bundles.format("text.level.delete", Bundles.get("map."+map.name+".name", map.name)), () -> { - Vars.world.maps().removeMap(map); + ui.showConfirm("$text.level.delete.title", Bundles.format("text.level.delete", Bundles.get("map."+map.name+".name", map.name)), () -> { + world.maps().removeMap(map); reload(); Core.scene.setScrollFocus(pane); }); @@ -142,7 +143,7 @@ public class LevelDialog extends FloatingDialog{ selectedMap = map; hide(); - Vars.control.playMap(selectedMap); + control.playMap(selectedMap); } }); image.getImageCell().size(images); diff --git a/core/src/io/anuke/mindustry/ui/dialogs/LoadDialog.java b/core/src/io/anuke/mindustry/ui/dialogs/LoadDialog.java index cf60e0de5d..0fd9fa53d7 100644 --- a/core/src/io/anuke/mindustry/ui/dialogs/LoadDialog.java +++ b/core/src/io/anuke/mindustry/ui/dialogs/LoadDialog.java @@ -1,22 +1,22 @@ package io.anuke.mindustry.ui.dialogs; import com.badlogic.gdx.utils.Array; -import io.anuke.mindustry.Vars; -import io.anuke.mindustry.core.GameState; import io.anuke.mindustry.core.GameState.State; import io.anuke.mindustry.io.SaveIO; import io.anuke.mindustry.io.Saves.SaveSlot; -import io.anuke.ucore.UCore; import io.anuke.ucore.core.Core; import io.anuke.ucore.core.Timers; import io.anuke.ucore.scene.ui.ScrollPane; import io.anuke.ucore.scene.ui.TextButton; import io.anuke.ucore.scene.ui.layout.Table; import io.anuke.ucore.util.Bundles; +import io.anuke.ucore.util.Log; import io.anuke.ucore.util.Strings; import java.io.IOException; +import static io.anuke.mindustry.Vars.*; + public class LoadDialog extends FloatingDialog{ ScrollPane pane; Table slots; @@ -49,7 +49,7 @@ public class LoadDialog extends FloatingDialog{ Timers.runTask(2f, () -> Core.scene.setScrollFocus(pane)); - Array array = Vars.control.getSaves().getSaveSlots(); + Array array = control.getSaves().getSaveSlots(); for(SaveSlot slot : array){ @@ -68,27 +68,27 @@ public class LoadDialog extends FloatingDialog{ }).checked(slot.isAutosave()).right(); t.addImageButton("icon-trash", "empty", 14*3, () -> { - Vars.ui.showConfirm("$text.confirm", "$text.save.delete.confirm", () -> { + ui.showConfirm("$text.confirm", "$text.save.delete.confirm", () -> { slot.delete(); setup(); }); }).size(14*3).right(); t.addImageButton("icon-pencil-small", "empty", 14*3, () -> { - Vars.ui.showTextInput("$text.save.rename", "$text.save.rename.text", slot.getName(), text -> { + ui.showTextInput("$text.save.rename", "$text.save.rename.text", slot.getName(), text -> { slot.setName(text); setup(); }); }).size(14*3).right(); - if(!Vars.gwt) { + if(!gwt) { t.addImageButton("icon-save", "empty", 14 * 3, () -> { new FileChooser("$text.save.export", false, file -> { try { slot.exportFile(file); setup(); } catch (IOException e) { - Vars.ui.showError(Bundles.format("text.save.export.fail", Strings.parseException(e, false))); + ui.showError(Bundles.format("text.save.export.fail", Strings.parseException(e, false))); } }).show(); }).size(14 * 3).right(); @@ -123,7 +123,7 @@ public class LoadDialog extends FloatingDialog{ } public void addSetup(){ - if(Vars.control.getSaves().getSaveSlots().size == 0) { + if(control.getSaves().getSaveSlots().size == 0) { slots.row(); slots.addButton("$text.save.none", "clear", () -> { @@ -132,19 +132,19 @@ public class LoadDialog extends FloatingDialog{ slots.row(); - if(Vars.gwt) return; + if(gwt) return; slots.addImageTextButton("$text.save.import", "icon-add", "clear", 14*3, () -> { new FileChooser("$text.save.import", f -> f.extension().equals("mins"), true, file -> { if(SaveIO.isSaveValid(file)){ try{ - Vars.control.getSaves().importSave(file); + control.getSaves().importSave(file); setup(); }catch (IOException e){ - Vars.ui.showError(Bundles.format("text.save.import.fail", Strings.parseException(e, false))); + ui.showError(Bundles.format("text.save.import.fail", Strings.parseException(e, false))); } }else{ - Vars.ui.showError("$text.save.import.invalid"); + ui.showError("$text.save.import.invalid"); } }).show(); }).fillX().margin(10f).minWidth(300f).height(70f).pad(4f).padRight(-4); @@ -153,21 +153,21 @@ public class LoadDialog extends FloatingDialog{ public void modifyButton(TextButton button, SaveSlot slot){ button.clicked(() -> { if(!button.childrenPressed()){ - Vars.ui.loadfrag.show(); + ui.loadfrag.show(); Timers.runTask(3f, () -> { - Vars.ui.loadfrag.hide(); + ui.loadfrag.hide(); hide(); try{ slot.load(); - GameState.set(State.playing); - Vars.ui.paused.hide(); + state.set(State.playing); + ui.paused.hide(); }catch(Exception e){ - UCore.error(e); - Vars.ui.paused.hide(); - GameState.set(State.menu); - Vars.control.reset(); - Vars.ui.showError("$text.save.corrupted"); + Log.err(e); + ui.paused.hide(); + state.set(State.menu); + logic.reset(); + ui.showError("$text.save.corrupted"); } }); } diff --git a/core/src/io/anuke/mindustry/ui/dialogs/PausedDialog.java b/core/src/io/anuke/mindustry/ui/dialogs/PausedDialog.java index 589ab0d6c9..2aeda7122e 100644 --- a/core/src/io/anuke/mindustry/ui/dialogs/PausedDialog.java +++ b/core/src/io/anuke/mindustry/ui/dialogs/PausedDialog.java @@ -1,8 +1,6 @@ package io.anuke.mindustry.ui.dialogs; import com.badlogic.gdx.utils.reflect.ClassReflection; -import io.anuke.mindustry.Vars; -import io.anuke.mindustry.core.GameState; import io.anuke.mindustry.core.GameState.State; import io.anuke.mindustry.net.Net; import io.anuke.mindustry.ui.PressGroup; @@ -13,7 +11,7 @@ import io.anuke.ucore.scene.builders.imagebutton; import io.anuke.ucore.scene.ui.ImageButton; import io.anuke.ucore.util.Bundles; -import static io.anuke.mindustry.Vars.ui; +import static io.anuke.mindustry.Vars.*; public class PausedDialog extends FloatingDialog{ private SaveDialog save = new SaveDialog(); @@ -27,23 +25,23 @@ public class PausedDialog extends FloatingDialog{ void setup(){ update(() -> { - if(GameState.is(State.menu) && isShown()){ + if(state.is(State.menu) && isShown()){ hide(); } }); shown(() -> { - wasPaused = GameState.is(State.paused); - if(!Net.active()) GameState.set(State.paused); + wasPaused = state.is(State.paused); + if(!Net.active()) state.set(State.paused); }); - if(!Vars.android){ + if(!android){ content().defaults().width(220).height(50); content().addButton("$text.back", () -> { hide(); - if((!wasPaused || Net.active()) && !GameState.is(State.menu)) - GameState.set(State.playing); + if((!wasPaused || Net.active()) && !state.is(State.menu)) + state.set(State.playing); }); content().row(); @@ -52,7 +50,7 @@ public class PausedDialog extends FloatingDialog{ content().row(); content().addButton("$text.savegame", () -> { save.show(); - }).disabled(b -> Vars.world.getMap().id == -1); + }).disabled(b -> world.getMap().id == -1); content().row(); content().addButton("$text.loadgame", () -> { @@ -61,7 +59,7 @@ public class PausedDialog extends FloatingDialog{ content().row(); - if(!Vars.gwt) { + if(!gwt) { content().addButton("$text.hostserver", () -> { ui.host.show(); }).disabled(b -> Net.active()); @@ -71,7 +69,7 @@ public class PausedDialog extends FloatingDialog{ content().addButton("$text.quit", () -> { ui.showConfirm("$text.confirm", "$text.quit.confirm", () -> { - if(Net.active() && Net.client()) Vars.netClient.disconnectQuietly(); + if(Net.client()) netClient.disconnectQuietly(); runExitSave(); hide(); }); @@ -87,15 +85,15 @@ public class PausedDialog extends FloatingDialog{ new imagebutton("icon-play-2", isize, () -> { hide(); - if(!wasPaused && !GameState.is(State.menu)) - GameState.set(State.playing); + if(!wasPaused && !state.is(State.menu)) + state.set(State.playing); }).text("$text.back").padTop(4f); new imagebutton("icon-tools", isize, ui.settings::show).text("$text.settings").padTop(4f); imagebutton sa = new imagebutton("icon-save", isize, save::show); sa.text("$text.save").padTop(4f); - sa.cell.disabled(b -> Vars.world.getMap().id == -1); + sa.cell.disabled(b -> world.getMap().id == -1); content().row(); @@ -110,8 +108,8 @@ public class PausedDialog extends FloatingDialog{ ho.cell.disabled(b -> Net.active()); new imagebutton("icon-quit", isize, () -> { - Vars.ui.showConfirm("$text.confirm", "$text.quit.confirm", () -> { - if(Net.active() && Net.client()) Vars.netClient.disconnectQuietly(); + ui.showConfirm("$text.confirm", "$text.quit.confirm", () -> { + if(Net.client()) netClient.disconnectQuietly(); runExitSave(); hide(); }); @@ -128,24 +126,24 @@ public class PausedDialog extends FloatingDialog{ } private void runExitSave(){ - if(Vars.control.getSaves().getCurrent() == null || - !Vars.control.getSaves().getCurrent().isAutosave()){ - GameState.set(State.menu); - Vars.control.getTutorial().reset(); + if(control.getSaves().getCurrent() == null || + !control.getSaves().getCurrent().isAutosave()){ + state.set(State.menu); + control.tutorial().reset(); return; } - Vars.ui.loadfrag.show("$text.saveload"); + ui.loadfrag.show("$text.saveload"); Timers.runTask(5f, () -> { - Vars.ui.loadfrag.hide(); + ui.loadfrag.hide(); try{ - Vars.control.getSaves().getCurrent().save(); + control.getSaves().getCurrent().save(); }catch(Throwable e){ e = (e.getCause() == null ? e : e.getCause()); - Vars.ui.showError("[orange]"+ Bundles.get("text.savefail")+"\n[white]" + ClassReflection.getSimpleName(e.getClass()) + ": " + e.getMessage() + "\n" + "at " + e.getStackTrace()[0].getFileName() + ":" + e.getStackTrace()[0].getLineNumber()); + ui.showError("[orange]"+ Bundles.get("text.savefail")+"\n[white]" + ClassReflection.getSimpleName(e.getClass()) + ": " + e.getMessage() + "\n" + "at " + e.getStackTrace()[0].getFileName() + ":" + e.getStackTrace()[0].getLineNumber()); } - GameState.set(State.menu); + state.set(State.menu); }); } } diff --git a/core/src/io/anuke/mindustry/ui/dialogs/RestartDialog.java b/core/src/io/anuke/mindustry/ui/dialogs/RestartDialog.java index 6ec166071c..855f53d6ff 100644 --- a/core/src/io/anuke/mindustry/ui/dialogs/RestartDialog.java +++ b/core/src/io/anuke/mindustry/ui/dialogs/RestartDialog.java @@ -1,10 +1,9 @@ package io.anuke.mindustry.ui.dialogs; -import io.anuke.mindustry.core.GameState; import io.anuke.mindustry.core.GameState.State; import io.anuke.ucore.scene.ui.Dialog; -import static io.anuke.mindustry.Vars.control; +import static io.anuke.mindustry.Vars.*; public class RestartDialog extends Dialog { @@ -18,14 +17,14 @@ public class RestartDialog extends Dialog { content().row(); } content().add("$text.lasted").pad(12).get(); - content().add("[accent]" + control.getWave()); + content().add("[accent]" + state.wave); pack(); }); getButtonTable().addButton("$text.menu", ()-> { hide(); - GameState.set(State.menu); - control.reset(); + state.set(State.menu); + logic.reset(); }).size(130f, 60f); } } diff --git a/core/src/io/anuke/mindustry/ui/dialogs/SaveDialog.java b/core/src/io/anuke/mindustry/ui/dialogs/SaveDialog.java index 419530db3b..082d7751f6 100644 --- a/core/src/io/anuke/mindustry/ui/dialogs/SaveDialog.java +++ b/core/src/io/anuke/mindustry/ui/dialogs/SaveDialog.java @@ -1,35 +1,35 @@ package io.anuke.mindustry.ui.dialogs; import com.badlogic.gdx.utils.reflect.ClassReflection; -import io.anuke.mindustry.Vars; -import io.anuke.mindustry.core.GameState; import io.anuke.mindustry.core.GameState.State; import io.anuke.mindustry.io.Saves.SaveSlot; import io.anuke.ucore.core.Timers; import io.anuke.ucore.scene.ui.TextButton; import io.anuke.ucore.util.Bundles; +import static io.anuke.mindustry.Vars.*; + public class SaveDialog extends LoadDialog{ public SaveDialog() { super("$text.savegame"); update(() -> { - if(GameState.is(State.menu) && isShown()){ + if(state.is(State.menu) && isShown()){ hide(); } }); } public void addSetup(){ - if(!Vars.control.getSaves().canAddSave()){ + if(!control.getSaves().canAddSave()){ return; } slots.row(); slots.addImageTextButton("$text.save.new", "icon-add", "clear", 14*3, () -> - Vars.ui.showTextInput("$text.save", "$text.save.newslot", "", text -> { - Vars.control.getSaves().addSave(text); + ui.showTextInput("$text.save", "$text.save.newslot", "", text -> { + control.getSaves().addSave(text); setup(); }) ).fillX().margin(10f).minWidth(300f).height(70f).pad(4f).padRight(-4); @@ -40,23 +40,23 @@ public class SaveDialog extends LoadDialog{ button.clicked(() -> { if(button.childrenPressed()) return; - Vars.ui.showConfirm("$text.overwrite", "$text.save.overwrite", () -> save(slot)); + ui.showConfirm("$text.overwrite", "$text.save.overwrite", () -> save(slot)); }); } void save(SaveSlot slot){ - Vars.ui.loadfrag.show("$text.saveload"); + ui.loadfrag.show("$text.saveload"); Timers.runTask(5f, () -> { hide(); - Vars.ui.loadfrag.hide(); + ui.loadfrag.hide(); try{ slot.save(); }catch(Throwable e){ e = (e.getCause() == null ? e : e.getCause()); - Vars.ui.showError("[orange]"+Bundles.get("text.savefail")+"\n[white]" + ClassReflection.getSimpleName(e.getClass()) + ": " + e.getMessage() + "\n" + "at " + e.getStackTrace()[0].getFileName() + ":" + e.getStackTrace()[0].getLineNumber()); + ui.showError("[orange]"+Bundles.get("text.savefail")+"\n[white]" + ClassReflection.getSimpleName(e.getClass()) + ": " + e.getMessage() + "\n" + "at " + e.getStackTrace()[0].getFileName() + ":" + e.getStackTrace()[0].getLineNumber()); } }); } diff --git a/core/src/io/anuke/mindustry/ui/dialogs/SettingsMenuDialog.java b/core/src/io/anuke/mindustry/ui/dialogs/SettingsMenuDialog.java index 5adff6d807..82809c2032 100644 --- a/core/src/io/anuke/mindustry/ui/dialogs/SettingsMenuDialog.java +++ b/core/src/io/anuke/mindustry/ui/dialogs/SettingsMenuDialog.java @@ -5,7 +5,6 @@ import com.badlogic.gdx.Input.Keys; import com.badlogic.gdx.graphics.Colors; import com.badlogic.gdx.utils.Align; import io.anuke.mindustry.Vars; -import io.anuke.mindustry.core.GameState; import io.anuke.mindustry.core.GameState.State; import io.anuke.mindustry.net.Net; import io.anuke.ucore.core.Core; @@ -18,7 +17,7 @@ import io.anuke.ucore.scene.ui.layout.Table; import io.anuke.ucore.util.Bundles; import io.anuke.ucore.util.Mathf; -import static io.anuke.mindustry.Vars.renderer; +import static io.anuke.mindustry.Vars.*; public class SettingsMenuDialog extends SettingsDialog{ public SettingsTable graphics; @@ -33,20 +32,20 @@ public class SettingsMenuDialog extends SettingsDialog{ setStyle(Core.skin.get("dialog", WindowStyle.class)); hidden(()->{ - if(!GameState.is(State.menu)){ + if(!state.is(State.menu)){ if(!wasPaused || Net.active()) - GameState.set(State.playing); + state.set(State.playing); } }); shown(()->{ - if(!GameState.is(State.menu)){ - wasPaused = GameState.is(State.paused); + if(!state.is(State.menu)){ + wasPaused = state.is(State.paused); if(menu.getScene() != null){ wasPaused = ((PausedDialog)menu).wasPaused; } - if(!Net.active()) GameState.set(State.paused); - Vars.ui.paused.hide(); + if(!Net.active()) state.set(State.paused); + ui.paused.hide(); } }); @@ -83,10 +82,10 @@ public class SettingsMenuDialog extends SettingsDialog{ menu.addButton("$text.settings.sound", () -> visible(2)); if(!Vars.android) { menu.row(); - menu.addButton("$text.settings.controls", Vars.ui.controls::show); + menu.addButton("$text.settings.controls", ui.controls::show); } menu.row(); - menu.addButton("$text.settings.language", Vars.ui.language::show); + menu.addButton("$text.settings.language", ui.language::show); prefs.clearChildren(); prefs.add(menu); diff --git a/core/src/io/anuke/mindustry/ui/fragments/BackgroundFragment.java b/core/src/io/anuke/mindustry/ui/fragments/BackgroundFragment.java index b90dd5fc4b..94306dd868 100644 --- a/core/src/io/anuke/mindustry/ui/fragments/BackgroundFragment.java +++ b/core/src/io/anuke/mindustry/ui/fragments/BackgroundFragment.java @@ -1,12 +1,13 @@ package io.anuke.mindustry.ui.fragments; import com.badlogic.gdx.graphics.g2d.TextureRegion; -import io.anuke.mindustry.core.GameState; import io.anuke.mindustry.core.GameState.State; import io.anuke.ucore.core.Core; import io.anuke.ucore.graphics.Draw; import io.anuke.ucore.scene.ui.layout.Unit; +import static io.anuke.mindustry.Vars.state; + public class BackgroundFragment implements Fragment { @Override @@ -29,6 +30,6 @@ public class BackgroundFragment implements Fragment { Draw.color(); Core.batch.draw(logo, w/2 - logow/2, h - logoh + 15, logow, logoh); - }).visible(() -> GameState.is(State.menu)).grow(); + }).visible(() -> state.is(State.menu)).grow(); } } diff --git a/core/src/io/anuke/mindustry/ui/fragments/BlocksFragment.java b/core/src/io/anuke/mindustry/ui/fragments/BlocksFragment.java index 4b205e3abb..dae54a1dc6 100644 --- a/core/src/io/anuke/mindustry/ui/fragments/BlocksFragment.java +++ b/core/src/io/anuke/mindustry/ui/fragments/BlocksFragment.java @@ -5,8 +5,6 @@ import com.badlogic.gdx.graphics.Colors; import com.badlogic.gdx.graphics.g2d.TextureRegion; import com.badlogic.gdx.math.Interpolation; import com.badlogic.gdx.utils.Array; -import io.anuke.mindustry.Vars; -import io.anuke.mindustry.core.GameState; import io.anuke.mindustry.core.GameState.State; import io.anuke.mindustry.input.InputHandler; import io.anuke.mindustry.resource.*; @@ -23,8 +21,7 @@ import io.anuke.ucore.util.Bundles; import io.anuke.ucore.util.Mathf; import io.anuke.ucore.util.Strings; -import static io.anuke.mindustry.Vars.control; -import static io.anuke.mindustry.Vars.fontscale; +import static io.anuke.mindustry.Vars.*; public class BlocksFragment implements Fragment{ private Table desctable, itemtable, blocks, weapons; @@ -33,18 +30,18 @@ public class BlocksFragment implements Fragment{ private boolean shown = true; public void build(){ - InputHandler input = control.getInput(); + InputHandler input = control.input(); new table(){{ abottom(); aright(); - visible(() -> !GameState.is(State.menu) && shown); + visible(() -> !state.is(State.menu) && shown); blocks = new table(){{ itemtable = new Table("button"); - itemtable.setVisible(() -> input.recipe == null && !Vars.control.getMode().infiniteResources); + itemtable.setVisible(() -> input.recipe == null && !state.mode.infiniteResources); desctable = new Table("button"); desctable.setVisible(() -> input.recipe != null); @@ -121,8 +118,8 @@ public class BlocksFragment implements Fragment{ image.getImageCell().size(size); image.update(() -> { - boolean canPlace = !control.getTutorial().active() || control.getTutorial().canPlace(); - boolean has = (control.hasItems(r.requirements)) && canPlace; + boolean canPlace = !control.tutorial().active() || control.tutorial().canPlace(); + boolean has = (state.inventory.hasItems(r.requirements)) && canPlace; image.setChecked(input.recipe == r); image.setTouchable(canPlace ? Touchable.enabled : Touchable.disabled); image.getImage().setColor(has ? Color.WHITE : Hue.lightness(0.33f)); @@ -152,11 +149,11 @@ public class BlocksFragment implements Fragment{ row(); - if(!Vars.android) { + if(!android) { weapons = new table("button").margin(0).fillX().end().get(); } - visible(() -> !GameState.is(State.menu) && shown); + visible(() -> !state.is(State.menu) && shown); }}.end().get(); }}.end(); @@ -165,21 +162,21 @@ public class BlocksFragment implements Fragment{ } public void updateWeapons(){ - if(Vars.android) return; + if(android) return; weapons.clearChildren(); weapons.left(); ButtonGroup group = new ButtonGroup<>(); - for(int i = 0; i < Vars.control.getWeapons().size; i ++){ - Weapon weapon = Vars.control.getWeapons().get(i); + for(int i = 0; i < control.upgrades().getWeapons().size; i ++){ + Weapon weapon = control.upgrades().getWeapons().get(i); weapons.addImageButton(weapon.name, "toggle", 8*3, () -> { - Vars.player.weaponLeft = Vars.player.weaponRight = weapon; + player.weaponLeft = player.weaponRight = weapon; }).left().size(40f, 45f).padRight(-1).group(group); } - int idx = Vars.control.getWeapons().indexOf(Vars.player.weaponLeft, true); + int idx = control.upgrades().getWeapons().indexOf(player.weaponLeft, true); if(idx != -1) group.getButtons().get(idx).setChecked(true); @@ -197,7 +194,7 @@ public class BlocksFragment implements Fragment{ } void updateRecipe(){ - Recipe recipe = Vars.control.getInput().recipe; + Recipe recipe = control.input().recipe; desctable.clear(); desctable.setTouchable(Touchable.enabled); @@ -228,8 +225,8 @@ public class BlocksFragment implements Fragment{ Label desclabel = new Label(recipe.result.fullDescription); desclabel.setWrap(true); - boolean wasPaused = GameState.is(State.paused); - GameState.set(State.paused); + boolean wasPaused = state.is(State.paused); + state.set(State.paused); FloatingDialog d = new FloatingDialog("$text.blocks.blockinfo"); Table table = new Table(); @@ -264,7 +261,7 @@ public class BlocksFragment implements Fragment{ } d.buttons().addButton("$text.ok", ()->{ - if(!wasPaused) GameState.set(State.playing); + if(!wasPaused) state.set(State.playing); d.hide(); }).size(110, 50).pad(10f); @@ -286,7 +283,7 @@ public class BlocksFragment implements Fragment{ Label reqlabel = new Label(""); reqlabel.update(()->{ - int current = control.getAmount(stack.item); + int current = state.inventory.getAmount(stack.item); String text = Mathf.clamp(current, 0, stack.amount) + "/" + stack.amount; reqlabel.setColor(current < stack.amount ? Colors.get("missingitems") : Color.WHITE); @@ -311,12 +308,12 @@ public class BlocksFragment implements Fragment{ itemtable.clear(); itemtable.left(); - if(control.getMode().infiniteResources){ + if(state.mode.infiniteResources){ return; } - for(int i = 0; i < control.getItems().length; i ++){ - int amount = control.getItems()[i]; + for(int i = 0; i < state.inventory.getItems().length; i ++){ + int amount = state.inventory.getItems()[i]; if(amount == 0) continue; String formatted = amount > 99999999 ? "inf" : format(amount); Image image = new Image(Draw.hasRegion("icon-" + Item.getByID(i).name) ? diff --git a/core/src/io/anuke/mindustry/ui/fragments/ChatFragment.java b/core/src/io/anuke/mindustry/ui/fragments/ChatFragment.java index 029797b088..e9aab42c13 100644 --- a/core/src/io/anuke/mindustry/ui/fragments/ChatFragment.java +++ b/core/src/io/anuke/mindustry/ui/fragments/ChatFragment.java @@ -6,11 +6,11 @@ import com.badlogic.gdx.graphics.g2d.BitmapFont; import com.badlogic.gdx.graphics.g2d.GlyphLayout; import com.badlogic.gdx.utils.Align; import com.badlogic.gdx.utils.Array; -import io.anuke.mindustry.Mindustry; import io.anuke.mindustry.Vars; -import io.anuke.mindustry.core.GameState; import io.anuke.mindustry.core.GameState.State; +import io.anuke.mindustry.io.Platform; import io.anuke.mindustry.net.Net; +import io.anuke.mindustry.net.NetEvents; import io.anuke.ucore.core.Core; import io.anuke.ucore.core.Inputs; import io.anuke.ucore.core.Timers; @@ -21,6 +21,7 @@ import io.anuke.ucore.scene.ui.TextField; import io.anuke.ucore.scene.ui.layout.Table; import io.anuke.ucore.scene.ui.layout.Unit; +import static io.anuke.mindustry.Vars.state; import static io.anuke.ucore.core.Core.scene; import static io.anuke.ucore.core.Core.skin; @@ -45,7 +46,7 @@ public class ChatFragment extends Table implements Fragment{ setFillParent(true); font = Core.skin.getFont("default-font"); - setVisible(() -> !GameState.is(State.menu) && Net.active()); + setVisible(() -> !state.is(State.menu) && Net.active()); //TODO put it in input? update(() -> { @@ -57,7 +58,7 @@ public class ChatFragment extends Table implements Fragment{ toggle(); } - if(GameState.is(State.menu) && messages.size > 0){ + if(state.is(State.menu) && messages.size > 0){ messages.clear(); } }); @@ -81,7 +82,7 @@ public class ChatFragment extends Table implements Fragment{ chatfield.getStyle().fontColor = Color.WHITE; chatfield.getStyle().font = skin.getFont("default-font-chat"); chatfield.setStyle(chatfield.getStyle()); - Mindustry.platforms.addDialog(chatfield, maxLength); + Platform.instance.addDialog(chatfield, maxLength); bottom().left().marginBottom(offsety).marginLeft(offsetx*2).add(fieldlabel).padBottom(4f); @@ -105,10 +106,6 @@ public class ChatFragment extends Table implements Fragment{ if(chatOpen) batch.draw(skin.getRegion("white"), offsetx, chatfield.getY(), chatfield.getWidth() + 15f, chatfield.getHeight()-1); - //font.getData().down = Unit.dp.scl(-21.5f); - //font.getData().lineHeight = 22f; - //chatfield.getStyle().font.getData().setScale(Vars.fontscale); - super.draw(batch, alpha); float spacing = chatspace; @@ -151,7 +148,7 @@ public class ChatFragment extends Table implements Fragment{ if(message.replaceAll(" ", "").isEmpty()) return; - Vars.netClient.handleSendMessage(message); + NetEvents.handleSendMessage(message); } public void toggle(){ @@ -181,6 +178,10 @@ public class ChatFragment extends Table implements Fragment{ return chatOpen; } + public int getMessagesSize(){ + return messages.size; + } + public void addMessage(String message, String sender){ messages.insert(0, new ChatMessage(message, sender)); 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..54710b1b76 --- /dev/null +++ b/core/src/io/anuke/mindustry/ui/fragments/DebugFragment.java @@ -0,0 +1,127 @@ +package io.anuke.mindustry.ui.fragments; + +import com.badlogic.gdx.Gdx; +import com.badlogic.gdx.files.FileHandle; +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{ + FileHandle file = Gdx.files.local("packet-dump.txt"); + file.writeString("--INFO--\n", false); + file.writeString(debugInfo(), true); + file.writeString("--LOG--\n\n", true); + file.writeString(log.toString(), true); + }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(), + "chat.open: " + ui.chatfrag.chatOpen(), + "chat.messages: " + ui.chatfrag.getMessagesSize(), + "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 d4d5465c2c..4f46d6bbf8 100644 --- a/core/src/io/anuke/mindustry/ui/fragments/HudFragment.java +++ b/core/src/io/anuke/mindustry/ui/fragments/HudFragment.java @@ -3,13 +3,10 @@ package io.anuke.mindustry.ui.fragments; import com.badlogic.gdx.Gdx; import com.badlogic.gdx.graphics.Color; import com.badlogic.gdx.math.Interpolation; -import io.anuke.mindustry.Vars; -import io.anuke.mindustry.core.GameState; 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; @@ -28,7 +25,7 @@ public class HudFragment implements Fragment{ private Table wavetable; private boolean shown = true; private BlocksFragment blockfrag = new BlocksFragment(); - + public void build(){ //menu at top left @@ -66,17 +63,17 @@ public class HudFragment implements Fragment{ }).get(); new imagebutton("icon-pause", isize, () -> { - if (Net.active() && Vars.android) { + if (Net.active() && android) { ui.listfrag.visible = !ui.listfrag.visible; } else { - GameState.set(GameState.is(State.paused) ? State.playing : State.paused); + state.set(state.is(State.paused) ? State.playing : State.paused); } }).update(i -> { - if (Net.active() && Vars.android) { + if (Net.active() && android) { i.getStyle().imageUp = Core.skin.getDrawable("icon-players"); } else { i.setDisabled(Net.active()); - i.getStyle().imageUp = Core.skin.getDrawable(GameState.is(State.paused) ? "icon-play" : "icon-pause"); + i.getStyle().imageUp = Core.skin.getDrawable(state.is(State.paused) ? "icon-play" : "icon-pause"); } }).get(); @@ -92,10 +89,10 @@ public class HudFragment implements Fragment{ row(); - visible(() -> !GameState.is(State.menu)); + visible(() -> !state.is(State.menu)); Label fps = new Label(() -> (Settings.getBool("fps") ? (Gdx.graphics.getFramesPerSecond() + " FPS") + - (Net.active() && !Vars.gwt && !Net.server() ? " / Ping: " + Net.getPing() : "") : "")); + (Net.client() && !gwt ? " / Ping: " + Net.getPing() : "") : "")); row(); add(fps).size(-1); @@ -110,124 +107,96 @@ public class HudFragment implements Fragment{ }).visible(() -> Net.active() && android).top().left().size(58f).get(); }}.end(); - + //tutorial ui table new table(){{ - control.getTutorial().buildUI(this); - - visible(()->control.getTutorial().active()); + control.tutorial().buildUI(this); + + visible(() -> control.tutorial().active()); }}.end(); - + //paused table new table(){{ - visible(()->GameState.is(State.paused) && !Net.active()); + visible(() -> state.is(State.paused) && !Net.active()); atop(); - + new table("pane"){{ new label("[orange]< "+ Bundles.get("text.paused") + " >").scale(0.75f).pad(6); }}.end(); }}.end(); - + //respawn background table new table("white"){{ respawntable = get(); respawntable.setColor(Color.CLEAR); update(t -> { - if(GameState.is(State.menu)){ + if(state.is(State.menu)){ respawntable.setColor(Color.CLEAR); } }); }}.end(); - + //respawn table new table(){{ new table("pane"){{ - + new label(()->"[orange]"+Bundles.get("text.respawn")+" " + (int)(control.getRespawnTime()/60)).scale(0.75f).pad(10); - - visible(()->control.getRespawnTime() > 0 && !GameState.is(State.menu)); - + + visible(()->control.getRespawnTime() > 0 && !state.is(State.menu)); + }}.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: " + Vars.control.tileGroup.amount()).left(); - row(); - new label(() -> "[purple]enemies: " + Vars.control.enemyGroup.amount()).left(); - row(); - new label(() -> "[orange]noclip: " + Vars.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(() -> !GameState.is(State.menu) && Vars.control.getSaves().isSaving()); + visible(() -> !state.is(State.menu) && control.getSaves().isSaving()); new label("$text.saveload"); }}.end(); - if(Vars.debugNet) { - new table() {{ - new label(() -> "players: " + Vars.control.playerGroup.amount()); - row(); - new label(() -> "" + Vars.control.playerGroup.all()); - }}.end(); - } - blockfrag.build(); } private String getEnemiesRemaining() { - if(control.getEnemiesRemaining() == 1) { - return Bundles.format("text.enemies.single", control.getEnemiesRemaining()); - } else return Bundles.format("text.enemies", control.getEnemiesRemaining()); + if(state.enemies == 1) { + return Bundles.format("text.enemies.single", state.enemies); + } else return Bundles.format("text.enemies", state.enemies); } - + private void addWaveTable(){ float uheight = 66f; - + wavetable = new table("button"){{ aleft(); new table(){{ aleft(); - new label(() -> Bundles.format("text.wave", control.getWave())).scale(fontscale*1.5f).left().padLeft(-6); + new label(() -> Bundles.format("text.wave", state.wave)).scale(fontscale*1.5f).left().padLeft(-6); row(); - - new label(()-> control.getEnemiesRemaining() > 0 ? + + new label(()-> state.enemies > 0 ? getEnemiesRemaining() : - (control.getTutorial().active() || Vars.control.getMode().toggleWaves) ? "$text.waiting" - : Bundles.format("text.wave.waiting", (int) (control.getWaveCountdown() / 60f))) + (control.tutorial().active() || state.mode.toggleWaves) ? "$text.waiting" + : Bundles.format("text.wave.waiting", (int) (state.wavetime / 60f))) .minWidth(126).padLeft(-6).padRight(-12).left(); margin(10f); get().marginLeft(6); }}.left().end(); - + playButton(uheight); }}.height(uheight).fillX().expandX().end().get(); wavetable.getParent().getParent().swapActor(wavetable.getParent(), menu.getParent()); } - + private void playButton(float uheight){ new imagebutton("icon-play", 30f, () -> { - Vars.control.runWave(); + logic.runWave(); }).height(uheight).fillX().right().padTop(-8f).padBottom(-12f).padRight(-36).width(40f).update(l->{ - boolean vis = Vars.control.getEnemiesRemaining() <= 0 && (Net.server() || !Net.active()); - boolean paused = GameState.is(State.paused) || !vis; + boolean vis = state.enemies <= 0 && (Net.server() || !Net.active()); + boolean paused = state.is(State.paused) || !vis; l.setVisible(vis); l.getStyle().imageUp = Core.skin.getDrawable(vis ? "icon-play" : "clear"); diff --git a/core/src/io/anuke/mindustry/ui/fragments/MenuFragment.java b/core/src/io/anuke/mindustry/ui/fragments/MenuFragment.java index a8953b436e..378b88470d 100644 --- a/core/src/io/anuke/mindustry/ui/fragments/MenuFragment.java +++ b/core/src/io/anuke/mindustry/ui/fragments/MenuFragment.java @@ -1,10 +1,9 @@ package io.anuke.mindustry.ui.fragments; import com.badlogic.gdx.Gdx; -import io.anuke.mindustry.Mindustry; import io.anuke.mindustry.Vars; -import io.anuke.mindustry.core.GameState; import io.anuke.mindustry.core.GameState.State; +import io.anuke.mindustry.io.Platform; import io.anuke.mindustry.ui.MenuButton; import io.anuke.mindustry.ui.PressGroup; import io.anuke.ucore.scene.builders.imagebutton; @@ -28,7 +27,7 @@ public class MenuFragment implements Fragment{ add(new MenuButton("$text.play", group, ui.levels::show)); row(); - if(Mindustry.platforms.canJoinGame()) { + if(Platform.instance.canJoinGame()) { add(new MenuButton("$text.joingame", group, ui.join::show)); row(); } @@ -53,7 +52,7 @@ public class MenuFragment implements Fragment{ get().margin(16); }}.end(); - visible(()-> GameState.is(State.menu)); + visible(() -> state.is(State.menu)); }}.end(); }else{ new table(){{ @@ -77,9 +76,9 @@ public class MenuFragment implements Fragment{ new imagebutton("icon-info", isize, ui.about::show).text("$text.about.button").padTop(4f); - new imagebutton("icon-donate", isize, Mindustry.platforms::openDonations).text("$text.donate").padTop(4f); + new imagebutton("icon-donate", isize, Platform.instance::openDonations).text("$text.donate").padTop(4f); - visible(()->GameState.is(State.menu)); + visible(() -> state.is(State.menu)); }}.end(); }}.end(); } @@ -87,12 +86,12 @@ public class MenuFragment implements Fragment{ //extra icons in top right new table(){{ atop().aright(); - if(Mindustry.hasDiscord){ + if(Platform.instance.hasDiscord()){ new imagebutton("icon-discord", 30f, ui.discord::show).margin(14); } if(!Vars.android) { new imagebutton("icon-info", 30f, ui.about::show).margin(14); } - }}.end().visible(()->GameState.is(State.menu)); + }}.end().visible(()->state.is(State.menu)); } } diff --git a/core/src/io/anuke/mindustry/ui/fragments/PlacementFragment.java b/core/src/io/anuke/mindustry/ui/fragments/PlacementFragment.java index a438643841..0498428c9f 100644 --- a/core/src/io/anuke/mindustry/ui/fragments/PlacementFragment.java +++ b/core/src/io/anuke/mindustry/ui/fragments/PlacementFragment.java @@ -3,8 +3,6 @@ package io.anuke.mindustry.ui.fragments; import com.badlogic.gdx.graphics.Color; import com.badlogic.gdx.math.Interpolation; import com.badlogic.gdx.utils.Align; -import io.anuke.mindustry.Vars; -import io.anuke.mindustry.core.GameState; import io.anuke.mindustry.core.GameState.State; import io.anuke.mindustry.input.InputHandler; import io.anuke.mindustry.input.PlaceMode; @@ -22,7 +20,7 @@ import io.anuke.ucore.scene.ui.layout.Unit; import io.anuke.ucore.util.Bundles; import io.anuke.ucore.util.Mathf; -import static io.anuke.mindustry.Vars.control; +import static io.anuke.mindustry.Vars.*; public class PlacementFragment implements Fragment{ boolean shown = false, placing = false; @@ -30,15 +28,15 @@ public class PlacementFragment implements Fragment{ Label modelabel; public void build(){ - if(!Vars.android) return; + if(!android) return; - InputHandler input = control.getInput(); + InputHandler input = control.input(); float s = 50f; float translation = Unit.dp.scl(54f); new table(){{ - visible(() -> !GameState.is(State.menu)); + visible(() -> !state.is(State.menu)); abottom(); aleft(); @@ -130,7 +128,7 @@ public class PlacementFragment implements Fragment{ defaults().padBottom(-5.5f); new imagebutton("icon-" + mode.name(), "toggle", 10 * 3, () -> { - control.getInput().resetCursor(); + control.input().resetCursor(); input.breakMode = mode; input.lastBreakMode = mode; if (!mode.both){ @@ -174,7 +172,7 @@ public class PlacementFragment implements Fragment{ if (!mode.shown || mode.delete) continue; new imagebutton("icon-" + mode.name(), "toggle", 10 * 3, () -> { - control.getInput().resetCursor(); + control.input().resetCursor(); input.placeMode = mode; input.lastPlaceMode = mode; modeText(Bundles.format("text.mode.place", mode.toString())); diff --git a/core/src/io/anuke/mindustry/ui/fragments/PlayerListFragment.java b/core/src/io/anuke/mindustry/ui/fragments/PlayerListFragment.java index 4ef8ea0a25..f0d4f7e1da 100644 --- a/core/src/io/anuke/mindustry/ui/fragments/PlayerListFragment.java +++ b/core/src/io/anuke/mindustry/ui/fragments/PlayerListFragment.java @@ -1,20 +1,21 @@ package io.anuke.mindustry.ui.fragments; -import io.anuke.mindustry.Vars; -import io.anuke.mindustry.core.GameState; 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.net.Packets.KickReason; import io.anuke.mindustry.ui.BorderImage; -import io.anuke.ucore.graphics.Draw; import io.anuke.ucore.core.Inputs; +import io.anuke.ucore.graphics.Draw; 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.Bundles; +import static io.anuke.mindustry.Vars.*; + public class PlayerListFragment implements Fragment{ public boolean visible = false; Table content = new Table(); @@ -25,8 +26,8 @@ public class PlayerListFragment implements Fragment{ new table(){{ new table("pane"){{ margin(14f); - new label(() -> Bundles.format(Vars.control.playerGroup.amount() == 1 ? "text.players.single" : - "text.players", Vars.control.playerGroup.amount())); + new label(() -> Bundles.format(playerGroup.size() == 1 ? "text.players.single" : + "text.players", playerGroup.size())); row(); content.marginRight(13f).marginLeft(13f); ScrollPane pane = new ScrollPane(content, "clear"); @@ -37,21 +38,22 @@ public class PlayerListFragment implements Fragment{ new table("pane"){{ margin(12f); get().addCheck("$text.server.friendlyfire", b -> { - Vars.control.setFriendlyFire(b); - }).growX().update(i -> i.setChecked(Vars.control.isFriendlyFire())).disabled(b -> Net.client()); + state.friendlyFire = b; + NetEvents.handleFriendlyFireChange(b); + }).growX().update(i -> i.setChecked(state.friendlyFire)).disabled(b -> Net.client()); }}.pad(10f).growX().end(); }}.end(); update(t -> { - if(!Vars.android){ + if(!android){ visible = Inputs.keyDown("player_list"); } - if(!(Net.active() && !GameState.is(State.menu))){ + if(!(Net.active() && !state.is(State.menu))){ visible = false; } - if(Vars.control.playerGroup.amount() != last){ + if(playerGroup.size() != last){ rebuild(); - last = Vars.control.playerGroup.amount(); + last = playerGroup.size(); } }); @@ -66,7 +68,7 @@ public class PlayerListFragment implements Fragment{ float h = 60f; - for(Player player : Vars.control.playerGroup.all()){ + for(Player player : playerGroup.all()){ Table button = new Table("button"); button.left(); button.margin(5).marginBottom(10); diff --git a/core/src/io/anuke/mindustry/ui/fragments/ToolFragment.java b/core/src/io/anuke/mindustry/ui/fragments/ToolFragment.java index 552a999f9c..0b31f54ed6 100644 --- a/core/src/io/anuke/mindustry/ui/fragments/ToolFragment.java +++ b/core/src/io/anuke/mindustry/ui/fragments/ToolFragment.java @@ -3,8 +3,7 @@ package io.anuke.mindustry.ui.fragments; import com.badlogic.gdx.Gdx; import com.badlogic.gdx.math.Vector2; import com.badlogic.gdx.utils.Align; -import io.anuke.mindustry.Vars; -import io.anuke.mindustry.core.GameState; +import static io.anuke.mindustry.Vars.*; import io.anuke.mindustry.core.GameState.State; import io.anuke.mindustry.input.InputHandler; import io.anuke.mindustry.input.PlaceMode; @@ -20,7 +19,7 @@ public class ToolFragment implements Fragment{ public boolean confirming; public void build(){ - InputHandler input = control.getInput(); + InputHandler input = control.input(); float isize = 14*3; @@ -44,25 +43,25 @@ public class ToolFragment implements Fragment{ input.placeMode.released(px, py, px2, py2); confirming = false; }else{ - input.placeMode.tapped(control.getInput().getBlockX(), control.getInput().getBlockY()); + input.placeMode.tapped(control.input().getBlockX(), control.input().getBlockY()); } }); Core.scene.add(tools); tools.setVisible(() -> - !GameState.is(State.menu) && android && ((input.recipe != null && control.hasItems(input.recipe.requirements) && + !state.is(State.menu) && android && ((input.recipe != null && state.inventory.hasItems(input.recipe.requirements) && input.placeMode == PlaceMode.cursor) || confirming) ); tools.update(() -> { if(confirming){ - Vector2 v = Graphics.screen((px + px2)/2f * Vars.tilesize, Math.min(py, py2) * Vars.tilesize - Vars.tilesize*1.5f); + Vector2 v = Graphics.screen((px + px2)/2f * tilesize, Math.min(py, py2) * tilesize - tilesize*1.5f); tools.setPosition(v.x, v.y, Align.top); }else{ - tools.setPosition(control.getInput().getCursorX(), - Gdx.graphics.getHeight() - control.getInput().getCursorY() - 15*Core.cameraScale, Align.top); + tools.setPosition(control.input().getCursorX(), + Gdx.graphics.getHeight() - control.input().getCursorY() - 15*Core.cameraScale, Align.top); } if(input.placeMode != PlaceMode.areaDelete){ diff --git a/core/src/io/anuke/mindustry/world/Block.java b/core/src/io/anuke/mindustry/world/Block.java index 893622b187..ee6d92dcbd 100644 --- a/core/src/io/anuke/mindustry/world/Block.java +++ b/core/src/io/anuke/mindustry/world/Block.java @@ -4,21 +4,24 @@ import com.badlogic.gdx.graphics.g2d.TextureRegion; import com.badlogic.gdx.math.Vector2; import com.badlogic.gdx.utils.Array; import com.badlogic.gdx.utils.ObjectMap; -import io.anuke.mindustry.Vars; -import io.anuke.mindustry.core.GameState; import io.anuke.mindustry.core.GameState.State; import io.anuke.mindustry.entities.TileEntity; import io.anuke.mindustry.graphics.Fx; +import io.anuke.mindustry.net.NetEvents; import io.anuke.mindustry.resource.Item; import io.anuke.mindustry.resource.ItemStack; import io.anuke.mindustry.resource.Liquid; -import io.anuke.ucore.graphics.Draw; import io.anuke.ucore.core.Effects; import io.anuke.ucore.core.Effects.Effect; +import io.anuke.ucore.graphics.Draw; import io.anuke.ucore.scene.ui.layout.Table; import io.anuke.ucore.util.Bundles; import io.anuke.ucore.util.Mathf; import io.anuke.ucore.util.Tmp; + +import static io.anuke.mindustry.Vars.state; +import static io.anuke.mindustry.Vars.tilesize; + public class Block{ private static int lastid; private static Array blocks = new Array<>(); @@ -104,7 +107,6 @@ public class Block{ public void drawLayer2(Tile tile){} public void drawSelect(Tile tile){} public void drawPlace(int x, int y, int rotation, boolean valid){} - public void postInit(){} public void placed(Tile tile){} public void tapped(Tile tile){} @@ -112,7 +114,7 @@ public class Block{ public void configure(Tile tile, byte data){} public void setConfigure(Tile tile, byte data){ - Vars.netClient.handleBlockConfig(tile, data); + NetEvents.handleBlockConfig(tile, data); } public boolean isConfigurable(Tile tile){ @@ -128,10 +130,6 @@ public class Block{ return name; } - public void onReset(){ - - } - public boolean isSolidFor(Tile tile){ return false; } @@ -249,7 +247,7 @@ public class Block{ } //update the tile entity through the draw method, only if it's an entity without updating - if(destructible && !update && !GameState.is(State.paused)){ + if(destructible && !update && !state.is(State.paused)){ tile.entity.update(); } } @@ -265,7 +263,7 @@ public class Block{ /**Offset for placing and drawing multiblocks.*/ public Vector2 getPlaceOffset(){ - return Tmp.v3.set(((width + 1) % 2) * Vars.tilesize/2, ((height + 1) % 2) * Vars.tilesize/2); + return Tmp.v3.set(((width + 1) % 2) * tilesize/2, ((height + 1) % 2) * tilesize/2); } public boolean isMultiblock(){ diff --git a/core/src/io/anuke/mindustry/world/Tile.java b/core/src/io/anuke/mindustry/world/Tile.java index 1bf628b514..2bdca83a92 100644 --- a/core/src/io/anuke/mindustry/world/Tile.java +++ b/core/src/io/anuke/mindustry/world/Tile.java @@ -2,13 +2,13 @@ package io.anuke.mindustry.world; import com.badlogic.gdx.math.Vector2; import com.badlogic.gdx.utils.Array; -import io.anuke.mindustry.Vars; import io.anuke.mindustry.entities.TileEntity; import io.anuke.mindustry.world.blocks.Blocks; import io.anuke.ucore.util.Bits; import io.anuke.ucore.util.Mathf; import static io.anuke.mindustry.Vars.tilesize; +import static io.anuke.mindustry.Vars.world; public class Tile{ @@ -37,7 +37,7 @@ public class Tile{ } public int packedPosition(){ - return x + y * Vars.world.width(); + return x + y * world.width(); } private void iSetFloor(Block floor){ @@ -77,7 +77,7 @@ public class Tile{ float dst = Vector2.dst(dx, dy, 0, 0); if(dst > rad || (dx == 0 && dy == 0)) continue; - Tile other = Vars.world.tile(x + dx, y + dy); + Tile other = world.tile(x + dx, y + dy); if(other != null && other.entity != null){ other.entity.damage((int)(amount * Mathf.lerp(1f-dst/rad, 1f, falloff))); } @@ -86,7 +86,7 @@ public class Tile{ } public int id(){ - return x + y * Vars.world.width(); + return x + y * world.width(); } public float worldx(){ @@ -211,7 +211,7 @@ public class Tile{ int offsety = -(block.height-1)/2; for(int dx = 0; dx < block.width; dx ++){ for(int dy = 0; dy < block.height; dy ++){ - Tile other = Vars.world.tile(x + dx + offsetx, y + dy + offsety); + Tile other = world.tile(x + dx + offsetx, y + dy + offsety); tmpArray.add(other); } } @@ -226,23 +226,23 @@ public class Tile{ }else{ byte dx = Bits.getLeftByte(link); byte dy = Bits.getRightByte(link); - return Vars.world.tile(x - (dx - 8), y - (dy - 8)); + return world.tile(x - (dx - 8), y - (dy - 8)); } } public Tile[] getNearby(){ - return Vars.world.getNearby(x, y); + return world.getNearby(x, y); } public Tile[] getNearby(Tile[] copy){ - return Vars.world.getNearby(x, y, copy); + return world.getNearby(x, y, copy); } public void updateOcclusion(){ occluded = false; for(int dx = -1; dx <= 1; dx ++){ for(int dy = -1; dy <= 1; dy ++){ - Tile tile = Vars.world.tile(x + dx, y + dy); + Tile tile = world.tile(x + dx, y + dy); if(tile != null && tile.solid()){ occluded = true; break; diff --git a/core/src/io/anuke/mindustry/world/WorldGenerator.java b/core/src/io/anuke/mindustry/world/WorldGenerator.java index 2140c46d4c..a38a80a164 100644 --- a/core/src/io/anuke/mindustry/world/WorldGenerator.java +++ b/core/src/io/anuke/mindustry/world/WorldGenerator.java @@ -2,13 +2,13 @@ package io.anuke.mindustry.world; import com.badlogic.gdx.graphics.Color; import com.badlogic.gdx.graphics.Pixmap; +import com.badlogic.gdx.utils.Array; import com.badlogic.gdx.utils.IntMap; import com.badlogic.gdx.utils.ObjectMap; import io.anuke.mindustry.Vars; -import io.anuke.mindustry.core.GameState; -import io.anuke.mindustry.core.GameState.State; import io.anuke.mindustry.entities.enemies.Enemy; import io.anuke.mindustry.entities.enemies.EnemyTypes; +import io.anuke.mindustry.game.SpawnPoint; import io.anuke.mindustry.world.ColorMapper.BlockPair; import io.anuke.mindustry.world.blocks.Blocks; import io.anuke.mindustry.world.blocks.SpecialBlocks; @@ -16,6 +16,9 @@ import io.anuke.ucore.graphics.Hue; import io.anuke.ucore.noise.Noise; import io.anuke.ucore.util.Mathf; +import static io.anuke.mindustry.Vars.tilesize; +import static io.anuke.mindustry.Vars.world; + public class WorldGenerator { public static final ObjectMap rocks = new ObjectMap(){{ put(Blocks.stone, Blocks.rock); @@ -24,11 +27,11 @@ public class WorldGenerator { put(Blocks.blackstone, Blocks.blackrock); }}; - /**Returns world size.*/ - public static void generate(Pixmap pixmap, Tile[][] tiles){ - boolean hasenemies = true, hascore = false; - - Noise.setSeed(Vars.world.getSeed()); + /**Returns the core (starting) block. Should fill spawns with the correct spawnpoints.*/ + public static Tile generate(Pixmap pixmap, Tile[][] tiles, Array spawns){ + Noise.setSeed(world.getSeed()); + + Tile core = null; for(int x = 0; x < pixmap.getWidth(); x ++){ for(int y = 0; y < pixmap.getHeight(); y ++){ @@ -45,19 +48,17 @@ public class WorldGenerator { if(block == SpecialBlocks.playerSpawn){ block = Blocks.air; - Vars.control.setCore(Vars.world.tile(x, y)); - hascore = true; + core = world.tile(x, y); }else if(block == SpecialBlocks.enemySpawn){ block = Blocks.air; - Vars.control.addSpawnPoint(Vars.world.tile(x, y)); - hasenemies = true; + spawns.add(new SpawnPoint(tiles[x][y])); } if(block == Blocks.air && Mathf.chance(0.025) && rocks.containsKey(floor)){ block = rocks.get(floor); } - if(Vars.world.getMap().oreGen && (floor == Blocks.stone || floor == Blocks.grass || floor == Blocks.blackstone || + if(world.getMap().oreGen && (floor == Blocks.stone || floor == Blocks.grass || floor == Blocks.blackstone || floor == Blocks.snow || floor == Blocks.sand)){ if(Noise.nnoise(x, y, 8, 1) > 0.21){ floor = Blocks.iron; @@ -77,7 +78,7 @@ public class WorldGenerator { } if(color == Hue.rgb(Color.PURPLE)){ - if(!Vars.android) new Enemy(EnemyTypes.target).set(x * Vars.tilesize, y * Vars.tilesize).add(); + if(!Vars.android) new Enemy(EnemyTypes.target).set(x * tilesize, y * tilesize).add(); floor = Blocks.stone; } @@ -91,16 +92,8 @@ public class WorldGenerator { tiles[x][y].updateOcclusion(); } } - - if(!hascore){ - GameState.set(State.menu); - Vars.ui.showError("[orange]Invalid map:[] this map has no core!"); - } - - if(!hasenemies){ - GameState.set(State.menu); - Vars.ui.showError("[orange]Invalid map:[] this map has no enemy spawnpoints!"); - } + + return core; } private static IntMap map(Object...objects){ diff --git a/core/src/io/anuke/mindustry/world/blocks/WeaponBlocks.java b/core/src/io/anuke/mindustry/world/blocks/WeaponBlocks.java index 4361571f87..81b4c70523 100644 --- a/core/src/io/anuke/mindustry/world/blocks/WeaponBlocks.java +++ b/core/src/io/anuke/mindustry/world/blocks/WeaponBlocks.java @@ -1,7 +1,6 @@ package io.anuke.mindustry.world.blocks; import com.badlogic.gdx.graphics.Color; -import io.anuke.mindustry.Vars; import io.anuke.mindustry.entities.BulletType; import io.anuke.mindustry.entities.effect.TeslaOrb; import io.anuke.mindustry.graphics.Fx; @@ -138,8 +137,7 @@ public class WeaponBlocks{ TurretEntity entity = tile.entity(); Angles.translation(entity.rotation, 4); - new TeslaOrb(tile.worldx() + Angles.x(), tile.worldy() + Angles.y(), - range, (int)(9*Vars.multiplier)).add(); + new TeslaOrb(tile.worldx() + Angles.x(), tile.worldy() + Angles.y(), range, 9).add(); } }, diff --git a/core/src/io/anuke/mindustry/world/blocks/types/Floor.java b/core/src/io/anuke/mindustry/world/blocks/types/Floor.java index 9f01fa59aa..ad4b083305 100644 --- a/core/src/io/anuke/mindustry/world/blocks/types/Floor.java +++ b/core/src/io/anuke/mindustry/world/blocks/types/Floor.java @@ -3,7 +3,7 @@ package io.anuke.mindustry.world.blocks.types; import com.badlogic.gdx.graphics.g2d.TextureRegion; import com.badlogic.gdx.math.MathUtils; -import io.anuke.mindustry.Vars; +import static io.anuke.mindustry.Vars.*; import io.anuke.mindustry.world.Block; import io.anuke.mindustry.world.Tile; import io.anuke.ucore.graphics.Draw; @@ -31,7 +31,7 @@ public class Floor extends Block{ if(dx == 0 && dy == 0) continue; - Tile other = Vars.world.tile(tile.x+dx, tile.y+dy); + Tile other = world.tile(tile.x+dx, tile.y+dy); if(other == null) continue; diff --git a/core/src/io/anuke/mindustry/world/blocks/types/LiquidBlock.java b/core/src/io/anuke/mindustry/world/blocks/types/LiquidBlock.java index 04a87dcdbe..aeadf037c1 100644 --- a/core/src/io/anuke/mindustry/world/blocks/types/LiquidBlock.java +++ b/core/src/io/anuke/mindustry/world/blocks/types/LiquidBlock.java @@ -1,11 +1,6 @@ package io.anuke.mindustry.world.blocks.types; -import java.io.DataInputStream; -import java.io.DataOutputStream; -import java.io.IOException; - import com.badlogic.gdx.utils.Array; - import io.anuke.mindustry.entities.TileEntity; import io.anuke.mindustry.resource.Liquid; import io.anuke.mindustry.world.Block; @@ -13,6 +8,10 @@ import io.anuke.mindustry.world.Tile; import io.anuke.ucore.graphics.Draw; import io.anuke.ucore.util.Mathf; +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; + public class LiquidBlock extends Block implements LiquidAcceptor{ protected final int timerFlow = timers++; @@ -57,7 +56,7 @@ public class LiquidBlock extends Block implements LiquidAcceptor{ public void update(Tile tile){ LiquidEntity entity = tile.entity(); - if(entity.liquidAmount > 0.01f && entity.timer.get(timerFlow, 3)){ + if(entity.liquidAmount > 0.01f && entity.timer.get(timerFlow, 1)){ tryMoveLiquid(tile, tile.getNearby()[tile.getRotation()]); } diff --git a/core/src/io/anuke/mindustry/world/blocks/types/PowerBlock.java b/core/src/io/anuke/mindustry/world/blocks/types/PowerBlock.java index 558cde9c3a..e5d77a10c4 100644 --- a/core/src/io/anuke/mindustry/world/blocks/types/PowerBlock.java +++ b/core/src/io/anuke/mindustry/world/blocks/types/PowerBlock.java @@ -2,7 +2,6 @@ package io.anuke.mindustry.world.blocks.types; import com.badlogic.gdx.graphics.Color; import com.badlogic.gdx.utils.Array; -import io.anuke.mindustry.Vars; import io.anuke.mindustry.entities.TileEntity; import io.anuke.mindustry.world.Block; import io.anuke.mindustry.world.Tile; @@ -12,6 +11,9 @@ import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; +import static io.anuke.mindustry.Vars.renderer; +import static io.anuke.mindustry.Vars.tilesize; + public abstract class PowerBlock extends Block implements PowerAcceptor{ public float powerCapacity = 10f; public float voltage = 0.001f; @@ -32,12 +34,12 @@ public abstract class PowerBlock extends Block implements PowerAcceptor{ public void drawSelect(Tile tile){ PowerEntity entity = tile.entity(); - float fract = (float)entity.power / powerCapacity; + float fract = entity.power / powerCapacity; if(fract > 0) fract = Mathf.clamp(fract + 0.2f, 0.24f, 1f); - Vars.renderer.drawBar(Color.YELLOW, tile.drawx(), - tile.drawy() + Vars.tilesize * height/2f + 2, fract); + renderer.drawBar(Color.YELLOW, tile.drawx(), + tile.drawy() + tilesize * height/2f + 2, fract); } /**Tries adding all the power with no remainder, returns success.*/ diff --git a/core/src/io/anuke/mindustry/world/blocks/types/defense/CoreBlock.java b/core/src/io/anuke/mindustry/world/blocks/types/defense/CoreBlock.java index 5216e7a517..4fb54a0eed 100644 --- a/core/src/io/anuke/mindustry/world/blocks/types/defense/CoreBlock.java +++ b/core/src/io/anuke/mindustry/world/blocks/types/defense/CoreBlock.java @@ -1,10 +1,12 @@ package io.anuke.mindustry.world.blocks.types.defense; -import io.anuke.mindustry.Vars; import io.anuke.mindustry.resource.Item; import io.anuke.mindustry.world.Block; import io.anuke.mindustry.world.Tile; +import static io.anuke.mindustry.Vars.debug; +import static io.anuke.mindustry.Vars.state; + public class CoreBlock extends Block { public CoreBlock(String name) { @@ -19,12 +21,12 @@ public class CoreBlock extends Block { @Override public int handleDamage(Tile tile, int amount){ - return Vars.debug ? 0 : amount; + return debug ? 0 : amount; } @Override public void handleItem(Item item, Tile tile, Tile source){ - Vars.control.addItem(item, 1); + state.inventory.addItem(item, 1); } @Override 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 4d370c8240..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 @@ -1,7 +1,6 @@ package io.anuke.mindustry.world.blocks.types.defense; import com.badlogic.gdx.math.Rectangle; -import io.anuke.mindustry.Vars; import io.anuke.mindustry.entities.TileEntity; import io.anuke.mindustry.graphics.Fx; import io.anuke.mindustry.world.Block; @@ -18,8 +17,7 @@ import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; -import static io.anuke.mindustry.Vars.player; -import static io.anuke.mindustry.Vars.tilesize; +import static io.anuke.mindustry.Vars.*; public class Door extends Wall{ protected Effect openfx = Fx.dooropen; @@ -67,19 +65,23 @@ public class Door extends Wall{ boolean anyEntities(Tile tile){ int x = tile.x, y = tile.y; Block type = tile.block(); - Tmp.r2.setSize(type.width * Vars.tilesize, type.height * Vars.tilesize); + Tmp.r2.setSize(type.width * tilesize, type.height * tilesize); Tmp.r2.setCenter(tile.drawx(), tile.drawy()); - for(SolidEntity e : Entities.getNearby(Vars.control.enemyGroup, x * tilesize, y * tilesize, tilesize * 2f)){ + for(SolidEntity e : Entities.getNearby(enemyGroup, x * tilesize, y * tilesize, tilesize * 2f)){ Rectangle rect = e.hitbox.getRect(e.x, e.y); if(Tmp.r2.overlaps(rect)){ 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/PowerTurret.java b/core/src/io/anuke/mindustry/world/blocks/types/defense/PowerTurret.java index 213fbff4f9..6b6bd1a6af 100644 --- a/core/src/io/anuke/mindustry/world/blocks/types/defense/PowerTurret.java +++ b/core/src/io/anuke/mindustry/world/blocks/types/defense/PowerTurret.java @@ -2,7 +2,7 @@ package io.anuke.mindustry.world.blocks.types.defense; import com.badlogic.gdx.graphics.Color; import com.badlogic.gdx.utils.Array; -import io.anuke.mindustry.Vars; +import static io.anuke.mindustry.Vars.*; import io.anuke.mindustry.entities.TileEntity; import io.anuke.mindustry.resource.Item; import io.anuke.mindustry.world.Tile; @@ -48,7 +48,7 @@ public class PowerTurret extends Turret implements PowerAcceptor{ if(fract > 0) fract = Mathf.clamp(fract, 0.24f, 1f); - Vars.renderer.drawBar(Color.YELLOW, tile.drawx(), tile.drawy() + 6, fract); + renderer.drawBar(Color.YELLOW, tile.drawx(), tile.drawy() + 6, fract); } @Override diff --git a/core/src/io/anuke/mindustry/world/blocks/types/defense/RepairTurret.java b/core/src/io/anuke/mindustry/world/blocks/types/defense/RepairTurret.java index fa968b6290..b726454101 100644 --- a/core/src/io/anuke/mindustry/world/blocks/types/defense/RepairTurret.java +++ b/core/src/io/anuke/mindustry/world/blocks/types/defense/RepairTurret.java @@ -3,7 +3,6 @@ package io.anuke.mindustry.world.blocks.types.defense; import com.badlogic.gdx.graphics.Color; import com.badlogic.gdx.math.MathUtils; import com.badlogic.gdx.utils.Array; -import io.anuke.mindustry.Vars; import io.anuke.mindustry.world.Layer; import io.anuke.mindustry.world.Tile; import io.anuke.ucore.core.Timers; @@ -14,6 +13,8 @@ import io.anuke.ucore.util.Angles; import io.anuke.ucore.util.Mathf; import io.anuke.ucore.util.Strings; +import static io.anuke.mindustry.Vars.world; + public class RepairTurret extends PowerTurret{ protected float repairFrac = 1f / 135f; @@ -45,7 +46,7 @@ public class RepairTurret extends PowerTurret{ } if(entity.timer.get(timerTarget, targetInterval)){ - entity.blockTarget = Vars.world.findTileTarget(tile.worldx(), tile.worldy(), tile, range, true); + entity.blockTarget = world.findTileTarget(tile.worldx(), tile.worldy(), tile, range, true); } if(entity.blockTarget != null){ 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 4fef525c4c..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 @@ -1,7 +1,6 @@ package io.anuke.mindustry.world.blocks.types.defense; import com.badlogic.gdx.utils.Array; - import io.anuke.mindustry.Vars; import io.anuke.mindustry.entities.TileEntity; import io.anuke.mindustry.entities.effect.Shield; @@ -14,6 +13,9 @@ 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{ public float shieldRadius = 40f; public float powerDrain = 0.005f; @@ -75,7 +77,7 @@ public class ShieldBlock extends PowerBlock{ bullet.remove(); Effects.effect(bullet.damage > 5 ? Fx.shieldhit : Fx.laserhit, bullet); - Vars.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/defense/ShieldedWallBlock.java b/core/src/io/anuke/mindustry/world/blocks/types/defense/ShieldedWallBlock.java index eb652f9cd7..a8d8b0c63e 100644 --- a/core/src/io/anuke/mindustry/world/blocks/types/defense/ShieldedWallBlock.java +++ b/core/src/io/anuke/mindustry/world/blocks/types/defense/ShieldedWallBlock.java @@ -2,14 +2,16 @@ package io.anuke.mindustry.world.blocks.types.defense; import com.badlogic.gdx.graphics.Color; import com.badlogic.gdx.utils.Array; -import io.anuke.mindustry.Vars; +import static io.anuke.mindustry.Vars.*; import io.anuke.mindustry.entities.TileEntity; import io.anuke.mindustry.world.Tile; import io.anuke.mindustry.world.blocks.types.PowerBlock; -import io.anuke.ucore.graphics.Draw; import io.anuke.ucore.core.Timers; +import io.anuke.ucore.graphics.Draw; import io.anuke.ucore.util.Strings; +import static io.anuke.mindustry.Vars.renderer; + public class ShieldedWallBlock extends PowerBlock{ static final float hitTime = 18f; static final Color hitColor = Color.SKY.cpy().mul(1.2f); @@ -54,12 +56,12 @@ public class ShieldedWallBlock extends PowerBlock{ ShieldedWallEntity entity = tile.entity(); if(entity.power > powerPerDamage){ - Vars.renderer.addShield(() -> Draw.rect("blank", tile.worldx(), tile.worldy(), Vars.tilesize, Vars.tilesize)); + renderer.addShield(() -> Draw.rect("blank", tile.worldx(), tile.worldy(), tilesize, tilesize)); } Draw.color(hitColor); Draw.alpha(entity.hit / hitTime * 0.9f); - Draw.rect("blank", tile.worldx(), tile.worldy(), Vars.tilesize, Vars.tilesize); + Draw.rect("blank", tile.worldx(), tile.worldy(), tilesize, tilesize); Draw.reset(); entity.hit -= Timers.delta(); diff --git a/core/src/io/anuke/mindustry/world/blocks/types/defense/Turret.java b/core/src/io/anuke/mindustry/world/blocks/types/defense/Turret.java index 66a16112e2..b073f9e32c 100644 --- a/core/src/io/anuke/mindustry/world/blocks/types/defense/Turret.java +++ b/core/src/io/anuke/mindustry/world/blocks/types/defense/Turret.java @@ -2,7 +2,6 @@ package io.anuke.mindustry.world.blocks.types.defense; import com.badlogic.gdx.graphics.Color; import com.badlogic.gdx.utils.Array; -import io.anuke.mindustry.Vars; import io.anuke.mindustry.entities.Bullet; import io.anuke.mindustry.entities.BulletType; import io.anuke.mindustry.entities.TileEntity; @@ -26,6 +25,8 @@ import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; +import static io.anuke.mindustry.Vars.*; + public class Turret extends Block{ static final int targetInterval = 15; static boolean drawDebug = false; @@ -90,7 +91,7 @@ public class Turret extends Block{ Draw.rect(name(), tile.drawx(), tile.drawy(), entity.rotation - 90); - if(Vars.debug && drawDebug){ + if(debug && drawDebug){ drawTargeting(tile); } } @@ -107,14 +108,14 @@ public class Turret extends Block{ if(fract > 0) fract = Mathf.clamp(fract, 0.24f, 1f); - Vars.renderer.drawBar(Color.GREEN, tile.drawx(), 2 + tile.drawy() + height/2f*Vars.tilesize, fract); + renderer.drawBar(Color.GREEN, tile.drawx(), 2 + tile.drawy() + height/2f * tilesize, fract); } @Override public void drawPlace(int x, int y, int rotation, boolean valid){ Draw.color(Color.PURPLE); Lines.stroke(1f); - Lines.dashCircle(x*Vars.tilesize, y*Vars.tilesize, range); + Lines.dashCircle(x * tilesize, y * tilesize, range); } @Override @@ -134,10 +135,10 @@ public class Turret extends Block{ if(entity.target != null && entity.target.isDead()) entity.target = null; - if(hasAmmo(tile) || (Vars.debug && Vars.infiniteAmmo)){ + if(hasAmmo(tile) || (debug && infiniteAmmo)){ if(entity.timer.get(timerTarget, targetInterval)){ - entity.target = (Enemy)Entities.getClosest(Vars.control.enemyGroup, + entity.target = (Enemy)Entities.getClosest(enemyGroup, tile.worldx(), tile.worldy(), range, e-> e instanceof Enemy && !((Enemy)e).isDead()); } @@ -151,8 +152,7 @@ public class Turret extends Block{ } entity.rotation = Mathf.slerp(entity.rotation, targetRot, rotatespeed*Timers.delta()); - - float reload = Vars.multiplier*this.reload; + if(Angles.angleDist(entity.rotation, targetRot) < shootCone && entity.timer.get(timerReload, reload)){ if(shootsound != null && entity.timer.get(timerSound, soundReload)) Effects.sound(shootsound, entity); shoot(tile); @@ -214,17 +214,15 @@ public class Turret extends Block{ protected void shoot(Tile tile){ TurretEntity entity = tile.entity(); - - - - Angles.translation(entity.rotation, width * Vars.tilesize / 2f); + + Angles.translation(entity.rotation, width * tilesize / 2f); for(int i = 0; i < shots; i ++){ if(Mathf.zero(shotDelayScale)){ bullet(tile, entity.rotation + Mathf.range(inaccuracy)); }else{ Timers.run(i * shotDelayScale, ()->{ - Angles.translation(entity.rotation, width * Vars.tilesize / 2f); + Angles.translation(entity.rotation, width * tilesize / 2f); bullet(tile, entity.rotation + Mathf.range(inaccuracy)); }); } @@ -243,7 +241,6 @@ public class Turret extends Block{ protected void bullet(Tile tile, float angle){ Bullet out = new Bullet(bullet, tile.entity, tile.drawx() + Angles.x(), tile.drawy() + Angles.y(), angle).add(); - out.damage = (int)(bullet.damage*Vars.multiplier); } public static class TurretEntity extends TileEntity{ diff --git a/core/src/io/anuke/mindustry/world/blocks/types/distribution/Conveyor.java b/core/src/io/anuke/mindustry/world/blocks/types/distribution/Conveyor.java index 19dcfd8ddf..c33e1e98ed 100644 --- a/core/src/io/anuke/mindustry/world/blocks/types/distribution/Conveyor.java +++ b/core/src/io/anuke/mindustry/world/blocks/types/distribution/Conveyor.java @@ -1,14 +1,14 @@ package io.anuke.mindustry.world.blocks.types.distribution; import com.badlogic.gdx.utils.Array; -import com.badlogic.gdx.utils.IntArray; +import com.badlogic.gdx.utils.LongArray; import io.anuke.mindustry.entities.TileEntity; import io.anuke.mindustry.resource.Item; import io.anuke.mindustry.world.Block; import io.anuke.mindustry.world.Layer; import io.anuke.mindustry.world.Tile; -import io.anuke.ucore.graphics.Draw; import io.anuke.ucore.core.Timers; +import io.anuke.ucore.graphics.Draw; import io.anuke.ucore.util.Bits; import io.anuke.ucore.util.Mathf; import io.anuke.ucore.util.Strings; @@ -26,7 +26,7 @@ import static io.anuke.mindustry.Vars.tilesize; public class Conveyor extends Block{ private static ItemPos pos1 = new ItemPos(); private static ItemPos pos2 = new ItemPos(); - private static IntArray removals = new IntArray(); + private static LongArray removals = new LongArray(); private static final float itemSpace = 0.135f; private static final float offsetScl = 128f*3f; private static final float itemSize = 4f; @@ -96,7 +96,7 @@ public class Conveyor extends Block{ float shift = entity.elapsed * speed; for(int i = 0; i < entity.convey.size; i ++){ - int value = entity.convey.get(i); + long value = entity.convey.get(i); ItemPos pos = pos1.set(value); if(pos.item == null){ @@ -105,10 +105,12 @@ public class Conveyor extends Block{ } boolean canmove = i == entity.convey.size - 1 || - !(pos2.set(entity.convey.get(i + 1)).y - pos.y < itemSpace * Timers.delta()); - + !(pos2.set(entity.convey.get(i + 1)).y - pos.y < itemSpace); + + float minmove = 1f / (Short.MAX_VALUE - 2); + if(canmove){ - pos.y += Math.max(speed * Timers.delta() + shift, 1f/252f); //TODO fix precision issues when at high FPS? + pos.y += Math.max(speed * Timers.delta() + shift, minmove); //TODO fix precision issues when at high FPS? pos.x = Mathf.lerpDelta(pos.x, 0, 0.06f); }else{ pos.x = Mathf.lerpDelta(pos.x, pos.seed/offsetScl, 0.1f); @@ -157,7 +159,7 @@ public class Conveyor extends Block{ float y = (ang == -1 || ang == 3) ? 1 : (ang == 1 || ang == -3) ? -1 : 0; ConveyorEntity entity = tile.entity(); - int result = ItemPos.packItem(item, y*0.9f, pos, (byte)Mathf.random(255)); + long result = ItemPos.packItem(item, y*0.9f, pos, (byte)Mathf.random(255)); boolean inserted = false; for(int i = 0; i < entity.convey.size; i ++){ @@ -183,7 +185,7 @@ public class Conveyor extends Block{ * Size is 4 bytes, or one int. */ public static class ConveyorEntity extends TileEntity{ - IntArray convey = new IntArray(); + LongArray convey = new LongArray(); float minitem = 1, elapsed; @Override @@ -191,7 +193,7 @@ public class Conveyor extends Block{ stream.writeInt(convey.size); for(int i = 0; i < convey.size; i ++){ - stream.writeInt(convey.get(i)); + stream.writeInt(pos1.toInt(convey.get(i))); } } @@ -202,7 +204,7 @@ public class Conveyor extends Block{ convey.ensureCapacity(amount); for(int i = 0; i < amount; i ++){ - convey.add(stream.readInt()); + convey.add(pos1.getValue(stream.readInt())); } sort(convey.items, convey.size); @@ -215,11 +217,11 @@ public class Conveyor extends Block{ } } - private static void sort(int[] elements, int length){ - List wrapper = new AbstractList() { + private static void sort(long[] elements, int length){ + List wrapper = new AbstractList() { @Override - public Integer get(int index) { + public Long get(int index) { return elements[index]; } @@ -229,8 +231,8 @@ public class Conveyor extends Block{ } @Override - public Integer set(int index, Integer element) { - int v = elements[index]; + public Long set(int index, Long element) { + long v = elements[index]; elements[index] = element; return v; } @@ -239,7 +241,7 @@ public class Conveyor extends Block{ Collections.sort(wrapper, Conveyor::compareItems); } - private static int compareItems(Integer a, Integer b){ + private static int compareItems(Long a, Long b){ pos1.set(a); pos2.set(b); return Float.compare(pos1.y, pos2.y); @@ -266,20 +268,50 @@ public class Conveyor extends Block{ seed = values[3]; return this; } + + ItemPos set(long lvalue){ + short[] values = Bits.getShorts(lvalue); + + if(values[0] >= Item.getAllItems().size || values[0] < 0) + item = null; + else + item = Item.getAllItems().get(values[0]); + + x = values[1] / (float)Short.MAX_VALUE; + y = ((float)values[2]) / Short.MAX_VALUE + 1f; + seed = (byte)values[3]; + return this; + } - int pack(){ + long pack(){ return packItem(item, x, y, seed); } - static int packItem(Item item, float x, float y, byte seed){ + static long packItem(Item item, float x, float y, byte seed){ + short[] shorts = Bits.getShorts(0); + shorts[0] = (short)item.id; + shorts[1] = (short)(x*Short.MAX_VALUE); + shorts[2] = (short)((y - 1f)*Short.MAX_VALUE); + shorts[3] = seed; + return Bits.packLong(shorts); + } + + static int packItemInt(Item item, float x, float y, byte seed){ byte[] bytes = Bits.getBytes(0); bytes[0] = (byte)item.id; bytes[1] = (byte)(x*127); bytes[2] = (byte)(y*255-128); bytes[3] = seed; - //UCore.log("Packing item: ", item, x, y, seed, "\n", Arrays.toString(bytes)); - //UCore.log(Arrays.toString(Bits.getBytes(Bits.packInt(bytes)))); return Bits.packInt(bytes); } + + int toInt(long value){ + set(value); + return packItemInt(item, x, y, seed); + } + + long getValue(int value){ + return set(value).pack(); + } } } diff --git a/core/src/io/anuke/mindustry/world/blocks/types/distribution/LiquidRouter.java b/core/src/io/anuke/mindustry/world/blocks/types/distribution/LiquidRouter.java index bae37634b3..2c3b617b93 100644 --- a/core/src/io/anuke/mindustry/world/blocks/types/distribution/LiquidRouter.java +++ b/core/src/io/anuke/mindustry/world/blocks/types/distribution/LiquidRouter.java @@ -5,19 +5,19 @@ import io.anuke.mindustry.world.Tile; import io.anuke.ucore.graphics.Draw; public class LiquidRouter extends Conduit{ - protected final int timerDump = timers++; public LiquidRouter(String name) { super(name); rotate = false; solid = true; + flowfactor = 2f; } @Override public void update(Tile tile){ LiquidEntity entity = tile.entity(); - if(entity.timer.get(timerDump, 2) && entity.liquidAmount > 0){ + if(entity.liquidAmount > 0){ if(tile.getExtra() != tile.getRotation()){ tryMoveLiquid(tile, tile.getNearby()[tile.getRotation()]); } diff --git a/core/src/io/anuke/mindustry/world/blocks/types/distribution/PowerBooster.java b/core/src/io/anuke/mindustry/world/blocks/types/distribution/PowerBooster.java index bad80d4a2d..2e5d056716 100644 --- a/core/src/io/anuke/mindustry/world/blocks/types/distribution/PowerBooster.java +++ b/core/src/io/anuke/mindustry/world/blocks/types/distribution/PowerBooster.java @@ -4,7 +4,7 @@ import com.badlogic.gdx.graphics.Color; import com.badlogic.gdx.math.Vector2; import com.badlogic.gdx.utils.Array; -import io.anuke.mindustry.Vars; +import static io.anuke.mindustry.Vars.*; import io.anuke.mindustry.world.Tile; import io.anuke.mindustry.world.blocks.types.PowerAcceptor; import io.anuke.mindustry.world.blocks.types.production.Generator; @@ -29,7 +29,7 @@ public class PowerBooster extends Generator{ super.drawSelect(tile); Draw.color(Color.YELLOW); - Lines.dashCircle(tile.worldx(), tile.worldy(), powerRange * Vars.tilesize); + Lines.dashCircle(tile.worldx(), tile.worldy(), powerRange * tilesize); Draw.reset(); } @@ -37,7 +37,7 @@ public class PowerBooster extends Generator{ public void drawPlace(int x, int y, int rotation, boolean valid){ Draw.color(Color.PURPLE); Lines.stroke(1f); - Lines.dashCircle(x * Vars.tilesize, y * Vars.tilesize, powerRange * Vars.tilesize); + Lines.dashCircle(x * tilesize, y * tilesize, powerRange * tilesize); Draw.reset(); } @@ -82,7 +82,7 @@ public class PowerBooster extends Generator{ } if(Vector2.dst(x, y, 0, 0) < powerRange){ - Tile dest = Vars.world.tile(tile.x + x, tile.y + y); + Tile dest = world.tile(tile.x + x, tile.y + y); if(dest != null && dest.block() instanceof PowerAcceptor && ((PowerAcceptor) dest.block()).acceptsPower(dest)){ if(i == 1){ PowerAcceptor block = (PowerAcceptor) dest.block(); diff --git a/core/src/io/anuke/mindustry/world/blocks/types/distribution/Router.java b/core/src/io/anuke/mindustry/world/blocks/types/distribution/Router.java index 6d42db8391..919d1e7b0c 100644 --- a/core/src/io/anuke/mindustry/world/blocks/types/distribution/Router.java +++ b/core/src/io/anuke/mindustry/world/blocks/types/distribution/Router.java @@ -3,7 +3,7 @@ package io.anuke.mindustry.world.blocks.types.distribution; import com.badlogic.gdx.graphics.Color; import com.badlogic.gdx.utils.Array; -import io.anuke.mindustry.Vars; +import static io.anuke.mindustry.Vars.*; import io.anuke.mindustry.resource.Item; import io.anuke.mindustry.world.Block; import io.anuke.mindustry.world.Tile; @@ -62,7 +62,7 @@ public class Router extends Block{ float fract = (float)tile.entity.totalItems()/capacity; - Vars.renderer.drawBar(Color.GREEN, tile.worldx(), tile.worldy() + 6, fract); + renderer.drawBar(Color.GREEN, tile.worldx(), tile.worldy() + 6, fract); } } diff --git a/core/src/io/anuke/mindustry/world/blocks/types/distribution/TunnelConveyor.java b/core/src/io/anuke/mindustry/world/blocks/types/distribution/TunnelConveyor.java index 0b525e9946..1e196d2c93 100644 --- a/core/src/io/anuke/mindustry/world/blocks/types/distribution/TunnelConveyor.java +++ b/core/src/io/anuke/mindustry/world/blocks/types/distribution/TunnelConveyor.java @@ -3,8 +3,8 @@ package io.anuke.mindustry.world.blocks.types.distribution; import io.anuke.mindustry.resource.Item; import io.anuke.mindustry.world.Block; import io.anuke.mindustry.world.Tile; -import io.anuke.ucore.UCore; import io.anuke.ucore.core.Timers; +import io.anuke.ucore.util.Log; public class TunnelConveyor extends Block{ protected int maxdist = 3; @@ -32,10 +32,11 @@ public class TunnelConveyor extends Block{ Timers.run(25, () -> { if(to.block() != before) return; + //TODO fix try { to.block().handleItem(item, to, tunnel); }catch (NullPointerException e){ - UCore.error(e); + Log.err(e); } }); } 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 ed03365e10..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,24 +4,23 @@ 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 io.anuke.mindustry.Vars; -import io.anuke.mindustry.core.GameState; import io.anuke.mindustry.core.GameState.State; import io.anuke.mindustry.graphics.Fx; import io.anuke.mindustry.world.Layer; import io.anuke.mindustry.world.Tile; import io.anuke.mindustry.world.blocks.types.PowerAcceptor; import io.anuke.mindustry.world.blocks.types.PowerBlock; -import io.anuke.ucore.graphics.Draw; import io.anuke.ucore.core.Effects; import io.anuke.ucore.core.Settings; import io.anuke.ucore.core.Timers; +import io.anuke.ucore.graphics.Draw; import io.anuke.ucore.graphics.Hue; import io.anuke.ucore.graphics.Lines; import io.anuke.ucore.graphics.Shapes; import io.anuke.ucore.util.*; +import static io.anuke.mindustry.Vars.*; + public class Generator extends PowerBlock{ public static final int powerTime = 2; public static boolean drawRangeOverlay = false; @@ -66,14 +65,14 @@ public class Generator extends PowerBlock{ for(int i = 0; i < laserDirections; i++){ int dir = Mathf.mod(i + rotation - laserDirections / 2, 4); float lx = Geometry.d4[dir].x, ly = Geometry.d4[dir].y; - float dx = lx * laserRange * Vars.tilesize; - float dy = ly * laserRange * Vars.tilesize; + float dx = lx * laserRange * tilesize; + float dy = ly * laserRange * tilesize; Lines.dashLine( - tile.worldx() + lx * Vars.tilesize / 2, - tile.worldy() + ly * Vars.tilesize / 2, - tile.worldx() + dx - lx * Vars.tilesize, - tile.worldy() + dy - ly * Vars.tilesize, 9); + tile.worldx() + lx * tilesize / 2, + tile.worldy() + ly * tilesize / 2, + tile.worldx() + dx - lx * tilesize, + tile.worldy() + dy - ly * tilesize, 9); } Draw.reset(); @@ -90,13 +89,13 @@ public class Generator extends PowerBlock{ for(int i = 0; i < laserDirections; i++){ int dir = Mathf.mod(i + rotation - laserDirections / 2, 4); float lx = Geometry.d4[dir].x, ly = Geometry.d4[dir].y; - float dx = lx * laserRange * Vars.tilesize; - float dy = ly * laserRange * Vars.tilesize; + float dx = lx * laserRange * tilesize; + float dy = ly * laserRange * tilesize; Lines.dashLine( - x * Vars.tilesize + lx * Vars.tilesize / 2, - y * Vars.tilesize + ly * Vars.tilesize / 2, - x * Vars.tilesize + dx - lx * Vars.tilesize, - y * Vars.tilesize + dy - ly * Vars.tilesize, 9); + x * tilesize + lx * tilesize / 2, + y * tilesize + ly * tilesize / 2, + x * tilesize + dx - lx * tilesize, + y * tilesize + dy - ly * tilesize, 9); } Draw.reset(); @@ -177,20 +176,22 @@ public class Generator extends PowerBlock{ if(target != null){ boolean interfering = isInterfering(target, rotation); - Tmp.v1.set(Angles.translation(rotation * 90, target.block().width * Vars.tilesize / 2 + 2f + (interfering ? Vector2.dst(tile.worldx(), tile.worldy(), target.worldx(), target.worldy()) / 2f - Vars.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 * Vars.tilesize / 2 + 2f); + Angles.translation(rotation * 90, width * tilesize / 2 + 2f); if(!interfering){ Draw.tint(Hue.mix(Color.GRAY, Color.WHITE, 0.904f + Mathf.sin(Timers.time(), 1.7f, 0.06f))); }else{ Draw.tint(Hue.mix(Color.SCARLET, Color.WHITE, 0.902f + Mathf.sin(Timers.time(), 1.7f, 0.08f))); - if(GameState.is(State.playing) && Mathf.chance(Timers.delta() * 0.033)){ + + if(state.is(State.playing) && Mathf.chance(Timers.delta() * 0.033)){ Effects.effect(Fx.laserspark, target.worldx() - Tmp.v1.x, target.worldy() - Tmp.v1.y); } } - float r = interfering ? 0.8f : 0f; + float r = interfering ? 0f : 0f; int relative = tile.relativeTo(target.x, target.y); @@ -200,8 +201,8 @@ public class Generator extends PowerBlock{ target.worldy() - Tmp.v1.y + Mathf.range(r), 0.7f); }else{ Draw.rect("laserfull", - tile.worldx() + Geometry.d4[relative].x * width * Vars.tilesize / 2f, - tile.worldy() + Geometry.d4[relative].y * width * Vars.tilesize / 2f); + tile.worldx() + Geometry.d4[relative].x * width * tilesize / 2f, + tile.worldy() + Geometry.d4[relative].y * width * tilesize / 2f); } Draw.color(); @@ -230,7 +231,7 @@ public class Generator extends PowerBlock{ int i = 0; for(i = 1; i < laserRange; i++){ - Tile other = Vars.world.tile(tile.x + i * point.x, tile.y + i * point.y); + Tile other = world.tile(tile.x + i * point.x, tile.y + i * point.y); if(other != null && other.block() instanceof PowerAcceptor){ Tile linked = other.getLinked(); diff --git a/core/src/io/anuke/mindustry/world/blocks/types/production/ItemPowerGenerator.java b/core/src/io/anuke/mindustry/world/blocks/types/production/ItemPowerGenerator.java index cc9dc0c3e9..a73b7555f2 100644 --- a/core/src/io/anuke/mindustry/world/blocks/types/production/ItemPowerGenerator.java +++ b/core/src/io/anuke/mindustry/world/blocks/types/production/ItemPowerGenerator.java @@ -3,7 +3,7 @@ package io.anuke.mindustry.world.blocks.types.production; import com.badlogic.gdx.graphics.Color; import com.badlogic.gdx.utils.Array; -import io.anuke.mindustry.Vars; +import static io.anuke.mindustry.Vars.*; import io.anuke.mindustry.entities.TileEntity; import io.anuke.mindustry.graphics.Fx; import io.anuke.mindustry.resource.Item; @@ -60,7 +60,7 @@ public class ItemPowerGenerator extends Generator{ TileEntity entity = tile.entity; //TODO maybe don't draw it due to clutter - Vars.renderer.drawBar(Color.GREEN, tile.worldx(), tile.worldy() + 10, (float)entity.getItem(generateItem) / itemCapacity); + renderer.drawBar(Color.GREEN, tile.worldx(), tile.worldy() + 10, (float)entity.getItem(generateItem) / itemCapacity); } @Override diff --git a/core/src/io/anuke/mindustry/world/blocks/types/production/LiquidCrafter.java b/core/src/io/anuke/mindustry/world/blocks/types/production/LiquidCrafter.java index 4fe4464599..c1c6320ac1 100644 --- a/core/src/io/anuke/mindustry/world/blocks/types/production/LiquidCrafter.java +++ b/core/src/io/anuke/mindustry/world/blocks/types/production/LiquidCrafter.java @@ -2,7 +2,7 @@ package io.anuke.mindustry.world.blocks.types.production; import com.badlogic.gdx.graphics.Color; import com.badlogic.gdx.utils.Array; -import io.anuke.mindustry.Vars; +import static io.anuke.mindustry.Vars.*; import io.anuke.mindustry.entities.TileEntity; import io.anuke.mindustry.graphics.Fx; import io.anuke.mindustry.resource.Item; @@ -85,7 +85,7 @@ public class LiquidCrafter extends LiquidBlock{ float fract = (float)tile.entity.getItem(input) / itemCapacity; - Vars.renderer.drawBar(Color.GREEN, tile.worldx(), tile.worldy() + 6, fract); + renderer.drawBar(Color.GREEN, tile.worldx(), tile.worldy() + 6, fract); } @Override diff --git a/core/src/io/anuke/mindustry/world/blocks/types/production/NuclearReactor.java b/core/src/io/anuke/mindustry/world/blocks/types/production/NuclearReactor.java index 2ad3dfcd7b..ff002ee84f 100644 --- a/core/src/io/anuke/mindustry/world/blocks/types/production/NuclearReactor.java +++ b/core/src/io/anuke/mindustry/world/blocks/types/production/NuclearReactor.java @@ -2,7 +2,6 @@ package io.anuke.mindustry.world.blocks.types.production; import com.badlogic.gdx.graphics.Color; import com.badlogic.gdx.utils.Array; -import io.anuke.mindustry.Vars; import io.anuke.mindustry.entities.TileEntity; import io.anuke.mindustry.entities.effect.DamageArea; import io.anuke.mindustry.graphics.Fx; @@ -20,6 +19,8 @@ import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; +import static io.anuke.mindustry.Vars.*; + public class NuclearReactor extends LiquidPowerGenerator{ protected final int timerFuel = timers++; @@ -65,7 +66,7 @@ public class NuclearReactor extends LiquidPowerGenerator{ float fullness = (float)fuel / itemCapacity; if(fuel > 0){ - entity.heat += fullness * heating; + entity.heat += fullness * heating * Timers.delta(); entity.power += powerMultiplier * fullness * Timers.delta(); entity.power = Mathf.clamp(entity.power, 0f, powerCapacity); if(entity.timer.get(timerFuel, fuelUseTime)){ @@ -82,14 +83,14 @@ public class NuclearReactor extends LiquidPowerGenerator{ if(entity.heat > smokeThreshold){ float smoke = 1.0f + (entity.heat - smokeThreshold) / (1f - smokeThreshold); //ranges from 1.0 to 2.0 if(Mathf.chance(smoke / 20.0 * Timers.delta())){ - Effects.effect(Fx.reactorsmoke, tile.worldx() + Mathf.range(width * Vars.tilesize / 2f), - tile.worldy() + Mathf.random(height * Vars.tilesize / 2f)); + Effects.effect(Fx.reactorsmoke, tile.worldx() + Mathf.range(width * tilesize / 2f), + tile.worldy() + Mathf.random(height * tilesize / 2f)); } } if(entity.heat >= 1f){ onDestroyed(tile); - Vars.world.removeBlock(tile); + world.removeBlock(tile); }else{ distributeLaserPower(tile); @@ -129,7 +130,7 @@ public class NuclearReactor extends LiquidPowerGenerator{ }); } - DamageArea.damageEntities(tile.worldx(), tile.worldy(), explosionRadius * Vars.tilesize, explosionDamage * 4); + DamageArea.damageEntities(tile.worldx(), tile.worldy(), explosionRadius * tilesize, explosionDamage * 4); for(int i = 0; i < 20; i ++){ @@ -153,16 +154,16 @@ public class NuclearReactor extends LiquidPowerGenerator{ NuclearReactorEntity entity = tile.entity(); - Vars.renderer.drawBar(Color.GREEN, tile.drawx(), tile.drawy() + 6 + - height*Vars.tilesize/2f, (float)entity.getItem(generateItem) / itemCapacity); + renderer.drawBar(Color.GREEN, tile.drawx(), tile.drawy() + 6 + + height*tilesize/2f, (float)entity.getItem(generateItem) / itemCapacity); Draw.reset(); float fract = entity.heat; if(fract > 0) fract = Mathf.clamp(fract + 0.2f, 0.24f, 1f); - Vars.renderer.drawBar(Color.ORANGE, tile.drawx(), - tile.drawy() + Vars.tilesize * height/2f + 10, fract); + renderer.drawBar(Color.ORANGE, tile.drawx(), + tile.drawy() + tilesize * height/2f + 10, fract); } @Override @@ -177,7 +178,7 @@ public class NuclearReactor extends LiquidPowerGenerator{ NuclearReactorEntity entity = tile.entity(); Draw.color(coolColor, hotColor, entity.heat); - Draw.rect("white", tile.drawx(), tile.drawy(), width * Vars.tilesize, height * Vars.tilesize); + Draw.rect("white", tile.drawx(), tile.drawy(), width * tilesize, height * tilesize); if(entity.heat > flashThreshold){ float flash = 1f + ((entity.heat - flashThreshold) / (1f - flashThreshold)) * 5.4f; diff --git a/core/src/io/anuke/mindustry/world/blocks/types/production/Pump.java b/core/src/io/anuke/mindustry/world/blocks/types/production/Pump.java index 29ccdb488e..4391e4c02e 100644 --- a/core/src/io/anuke/mindustry/world/blocks/types/production/Pump.java +++ b/core/src/io/anuke/mindustry/world/blocks/types/production/Pump.java @@ -73,12 +73,12 @@ public class Pump extends LiquidBlock{ LiquidEntity entity = tile.entity(); if(tile.floor().liquidDrop != null){ - float maxPump = Math.min(liquidCapacity - entity.liquidAmount, pumpAmount); + float maxPump = Math.min(liquidCapacity - entity.liquidAmount, pumpAmount * Timers.delta()); entity.liquid = tile.floor().liquidDrop; entity.liquidAmount += maxPump; } - if(entity.timer.get(timerDump, 2)){ + if(entity.timer.get(timerDump, 1)){ tryDumpLiquid(tile); } } diff --git a/core/src/io/anuke/mindustry/world/blocks/types/production/Smelter.java b/core/src/io/anuke/mindustry/world/blocks/types/production/Smelter.java index ebfb6f234f..f86410843f 100644 --- a/core/src/io/anuke/mindustry/world/blocks/types/production/Smelter.java +++ b/core/src/io/anuke/mindustry/world/blocks/types/production/Smelter.java @@ -2,7 +2,7 @@ package io.anuke.mindustry.world.blocks.types.production; import com.badlogic.gdx.graphics.Color; import com.badlogic.gdx.utils.Array; -import io.anuke.mindustry.Vars; +import static io.anuke.mindustry.Vars.*; import io.anuke.mindustry.entities.TileEntity; import io.anuke.mindustry.graphics.Fx; import io.anuke.mindustry.resource.Item; @@ -125,7 +125,7 @@ public class Smelter extends Block{ for(int i = 0; i < inputs.length; i ++){ float fract = ((float)tile.entity.getItem(inputs[i]))/capacity; - Vars.renderer.drawBar(Color.GREEN, tile.worldx(), tile.worldy() + 6 + i*4, fract); + renderer.drawBar(Color.GREEN, tile.worldx(), tile.worldy() + 6 + i*4, fract); } } diff --git a/core/src/io/anuke/mindustry/world/blocks/types/production/WeaponFactory.java b/core/src/io/anuke/mindustry/world/blocks/types/production/WeaponFactory.java index 94abe9afc5..2125e2b913 100644 --- a/core/src/io/anuke/mindustry/world/blocks/types/production/WeaponFactory.java +++ b/core/src/io/anuke/mindustry/world/blocks/types/production/WeaponFactory.java @@ -2,21 +2,22 @@ package io.anuke.mindustry.world.blocks.types.production; import io.anuke.mindustry.Vars; import io.anuke.mindustry.net.Net; +import io.anuke.mindustry.net.NetEvents; import io.anuke.mindustry.resource.ItemStack; import io.anuke.mindustry.resource.Upgrade; import io.anuke.mindustry.resource.UpgradeRecipes; import io.anuke.mindustry.resource.Weapon; import io.anuke.mindustry.world.Block; import io.anuke.mindustry.world.Tile; -import io.anuke.ucore.graphics.Draw; import io.anuke.ucore.core.Effects; import io.anuke.ucore.function.Listenable; +import io.anuke.ucore.graphics.Draw; import io.anuke.ucore.scene.style.TextureRegionDrawable; import io.anuke.ucore.scene.ui.ImageButton; import io.anuke.ucore.scene.ui.Tooltip; import io.anuke.ucore.scene.ui.layout.Table; -import static io.anuke.mindustry.Vars.control; +import static io.anuke.mindustry.Vars.*; public class WeaponFactory extends Block{ @@ -58,10 +59,10 @@ public class WeaponFactory extends Block{ tiptable.row(); tiptable.add(reqtable).left(); - if(!control.hasWeapon(weapon)){ + if(!control.upgrades().hasWeapon(weapon)){ for(ItemStack s : requirements){ - int amount = Math.min(control.getAmount(s.item), s.amount); + int amount = Math.min(state.inventory.getAmount(s.item), s.amount); reqtable.addImage(Draw.region("icon-" + s.item.name)).padRight(3).size(8*2); reqtable.add( (amount >= s.amount ? "" : "[RED]") @@ -75,7 +76,7 @@ public class WeaponFactory extends Block{ tiptable.row(); tiptable.add("[gray]" + description).left(); tiptable.row(); - if(control.hasWeapon(weapon)){ + if(control.upgrades().hasWeapon(weapon)){ tiptable.add("$text.purchased").padTop(4).left(); } tiptable.margin(8f); @@ -88,18 +89,18 @@ public class WeaponFactory extends Block{ tip.setInstant(true); ImageButton button = content.addImageButton("white", 8*4, () -> { - control.removeItems(requirements); - control.addWeapon(weapon); - Vars.ui.hudfrag.updateWeapons(); + state.inventory.removeItems(requirements); + control.upgrades().addWeapon(weapon); + ui.hudfrag.updateWeapons(); run.listen(); Effects.sound("purchase"); - if(Net.active() && Net.client()){ - Vars.netClient.handleUpgrade(weapon); + if(Net.client()){ + NetEvents.handleUpgrade(weapon); } }).size(49f, 54f).padBottom(-5).get(); - button.setDisabled(() -> control.hasWeapon(weapon) || !control.hasItems(requirements)); + button.setDisabled(() -> control.upgrades().hasWeapon(weapon) || !state.inventory.hasItems(requirements)); button.getStyle().imageUp = new TextureRegionDrawable(Draw.region(weapon.name)); button.addListener(tip); diff --git a/desktop/src/io/anuke/mindustry/desktop/CrashHandler.java b/desktop/src/io/anuke/mindustry/desktop/CrashHandler.java new file mode 100644 index 0000000000..ed1d06582f --- /dev/null +++ b/desktop/src/io/anuke/mindustry/desktop/CrashHandler.java @@ -0,0 +1,53 @@ +package io.anuke.mindustry.desktop; + +import io.anuke.mindustry.net.Net; +import io.anuke.ucore.util.Strings; + +import javax.swing.*; +import java.io.File; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.text.SimpleDateFormat; +import java.util.Date; + +public class CrashHandler { + + public static void handle(Throwable e){ + //TODO send full error report to server via HTTP + e.printStackTrace(); + + //attempt to close connections, if applicable + try{ + Net.dispose(); + }catch (Throwable p){ + p.printStackTrace(); + } + + //don't create crash logs for me (anuke), as it's expected + if(System.getProperty("user.name").equals("anuke")) return; + + //parse exception + String result = Strings.parseException(e, true); + boolean failed = false; + + String filename = ""; + + //try to write it + try{ + filename = "crash-report-" + new SimpleDateFormat("dd-MM-yy h.mm.ss").format(new Date()) + ".txt"; + Files.write(Paths.get(filename), result.getBytes()); + }catch (Throwable i){ + i.printStackTrace(); + failed = true; + } + + try{ + JOptionPane.showMessageDialog(null, "An error has occured: \n" + result + "\n\n" + + (!failed ? "A crash report has been written to " + new File(filename).getAbsolutePath() + ".\nPlease send this file to the developer!" + : "Failed to generate crash report.\nPlease send an image of this crash log to the developer!")); + }catch (Throwable i){ + i.printStackTrace(); + //what now? + } + } +} diff --git a/desktop/src/io/anuke/mindustry/desktop/DesktopLauncher.java b/desktop/src/io/anuke/mindustry/desktop/DesktopLauncher.java index 7cacd221cf..4751731a93 100644 --- a/desktop/src/io/anuke/mindustry/desktop/DesktopLauncher.java +++ b/desktop/src/io/anuke/mindustry/desktop/DesktopLauncher.java @@ -1,31 +1,12 @@ package io.anuke.mindustry.desktop; -import club.minnced.discord.rpc.DiscordEventHandlers; -import club.minnced.discord.rpc.DiscordRPC; -import club.minnced.discord.rpc.DiscordRichPresence; import com.badlogic.gdx.backends.lwjgl3.Lwjgl3Application; import com.badlogic.gdx.backends.lwjgl3.Lwjgl3ApplicationConfiguration; -import com.badlogic.gdx.utils.Array; import io.anuke.kryonet.KryoClient; import io.anuke.kryonet.KryoServer; import io.anuke.mindustry.Mindustry; -import io.anuke.mindustry.Vars; -import io.anuke.mindustry.core.GameState; -import io.anuke.mindustry.core.GameState.State; -import io.anuke.mindustry.io.PlatformFunction; +import io.anuke.mindustry.io.Platform; import io.anuke.mindustry.net.Net; -import io.anuke.ucore.util.Strings; - -import javax.swing.*; -import java.io.File; -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Paths; -import java.text.DateFormat; -import java.text.NumberFormat; -import java.text.SimpleDateFormat; -import java.util.Date; -import java.util.Locale; public class DesktopLauncher { @@ -37,114 +18,15 @@ public class DesktopLauncher { config.setWindowedMode(960, 540); config.setWindowIcon("sprites/icon.png"); - DiscordRPC lib = DiscordRPC.INSTANCE; - String applicationId = "398246104468291591"; - DiscordEventHandlers handlers = new DiscordEventHandlers(); - handlers.joinGame = secret -> { + Platform.instance = new DesktopPlatform(); - }; - - handlers.joinRequest = request -> { - //TODO actual text, implementation of discord join dialog, possibly move it to Dialogs - Vars.ui.showConfirmListen("$text.join.discord.title", "$text.join.discord", b -> { - if(b){ - lib.Discord_Respond(request.userId, DiscordRPC.DISCORD_REPLY_YES); - }else{ - lib.Discord_Respond(request.userId, DiscordRPC.DISCORD_REPLY_NO); - } - }); - }; - - lib.Discord_Initialize(applicationId, handlers, true, ""); - - Mindustry.platforms = new PlatformFunction(){ - DateFormat format = SimpleDateFormat.getDateTimeInstance(); - - @Override - public String format(Date date){ - return format.format(date); - } - - @Override - public String format(int number){ - return NumberFormat.getIntegerInstance().format(number); - } - - @Override - public void showError(String text){ - JOptionPane.showMessageDialog(null, text); - } - - @Override - public String getLocaleName(Locale locale){ - return locale.getDisplayName(locale); - } - - @Override - public void updateRPC() { - DiscordRichPresence presence = new DiscordRichPresence(); - - if(!GameState.is(State.menu)){ - presence.state = Strings.capitalize(Vars.control.getMode().name()) + ", Solo"; - presence.details = Strings.capitalize(Vars.world.getMap().name) + " | Wave " + Vars.control.getWave(); - presence.largeImageText = "Wave " + Vars.control.getWave(); - if(Net.active() ){ - presence.partyMax = 16; - presence.partySize = Vars.control.playerGroup.amount(); - presence.state = Strings.capitalize(Vars.control.getMode().name()); - } - }else{ - if(Vars.ui.editor != null && Vars.ui.editor.isShown()){ - presence.state = "In Editor"; - }else { - presence.state = "In Menu"; - } - } - - presence.largeImageKey = "logo"; - - lib.Discord_UpdatePresence(presence); - } - - @Override - public void onGameExit() { - lib.Discord_Shutdown(); - } - }; - - Mindustry.args = Array.with(arg); - - //Net.setClientProvider(new JavaWebsocketClient()); Net.setClientProvider(new KryoClient()); Net.setServerProvider(new KryoServer()); try { new Lwjgl3Application(new Mindustry(), config); - }catch (Exception e){ - e.printStackTrace(); - - //attempt to close connections - try{ Net.dispose(); }catch (Exception p){} - - //don't create crash logs for me (anuke), as it's expected - if(System.getProperty("user.name").equals("anuke")) return; - - String result = Strings.parseException(e, true); - boolean failed = false; - - String filename = ""; - - try{ - filename = "crash-report-" + new SimpleDateFormat("dd-MM-yy h.mm.ss").format(new Date()) + ".txt"; - Files.write(Paths.get(filename), result.getBytes()); - }catch (IOException i){ - i.printStackTrace(); - failed = true; - } - - JOptionPane.showMessageDialog(null, "An error has occured: \n" + result + "\n\n" + - (!failed ? "A crash report has been written to " + new File(filename).getAbsolutePath() + ".\nPlease send this file to the developer!" - : "Failed to generate crash report.\nPlease send an image of this crash log to the developer!")); + }catch (Throwable e){ + CrashHandler.handle(e); } } } diff --git a/desktop/src/io/anuke/mindustry/desktop/DesktopPlatform.java b/desktop/src/io/anuke/mindustry/desktop/DesktopPlatform.java new file mode 100644 index 0000000000..8bdb6597e2 --- /dev/null +++ b/desktop/src/io/anuke/mindustry/desktop/DesktopPlatform.java @@ -0,0 +1,83 @@ +package io.anuke.mindustry.desktop; + +import club.minnced.discord.rpc.DiscordEventHandlers; +import club.minnced.discord.rpc.DiscordRPC; +import club.minnced.discord.rpc.DiscordRichPresence; +import static io.anuke.mindustry.Vars.*; +import io.anuke.mindustry.core.GameState.State; +import io.anuke.mindustry.io.Platform; +import io.anuke.mindustry.net.Net; +import io.anuke.ucore.util.Strings; + +import javax.swing.*; +import java.text.DateFormat; +import java.text.NumberFormat; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.Locale; + +import static io.anuke.mindustry.Vars.state; +import static io.anuke.mindustry.Vars.world; + +public class DesktopPlatform extends Platform { + DateFormat format = SimpleDateFormat.getDateTimeInstance(); + DiscordRPC lib = DiscordRPC.INSTANCE; + + public DesktopPlatform(){ + String applicationId = "398246104468291591"; + DiscordEventHandlers handlers = new DiscordEventHandlers(); + + lib.Discord_Initialize(applicationId, handlers, true, ""); + } + + @Override + public String format(Date date){ + return format.format(date); + } + + @Override + public String format(int number){ + return NumberFormat.getIntegerInstance().format(number); + } + + @Override + public void showError(String text){ + JOptionPane.showMessageDialog(null, text); + } + + @Override + public String getLocaleName(Locale locale){ + return locale.getDisplayName(locale); + } + + @Override + public void updateRPC() { + DiscordRichPresence presence = new DiscordRichPresence(); + + if(!state.is(State.menu)){ + presence.state = Strings.capitalize(state.mode.name()) + ", Solo"; + presence.details = Strings.capitalize(world.getMap().name) + " | Wave " + state.wave; + presence.largeImageText = "Wave " + state.wave; + if(Net.active() ){ + presence.partyMax = 16; + presence.partySize = Net.getConnections().size; + presence.state = Strings.capitalize(state.mode.name()); + } + }else{ + if(ui.editor != null && ui.editor.isShown()){ + presence.state = "In Editor"; + }else { + presence.state = "In Menu"; + } + } + + presence.largeImageKey = "logo"; + + lib.Discord_UpdatePresence(presence); + } + + @Override + public void onGameExit() { + lib.Discord_Shutdown(); + } +} diff --git a/html/src/io/anuke/mindustry/client/HtmlLauncher.java b/html/src/io/anuke/mindustry/client/HtmlLauncher.java index 250b869a47..e504d0c2db 100644 --- a/html/src/io/anuke/mindustry/client/HtmlLauncher.java +++ b/html/src/io/anuke/mindustry/client/HtmlLauncher.java @@ -15,7 +15,7 @@ import com.google.gwt.i18n.client.NumberFormat; import com.google.gwt.i18n.shared.DateTimeFormat; import com.google.gwt.user.client.ui.*; import io.anuke.mindustry.Mindustry; -import io.anuke.mindustry.io.PlatformFunction; +import io.anuke.mindustry.io.Platform; import io.anuke.mindustry.net.Net; import java.util.Date; @@ -94,7 +94,7 @@ public class HtmlLauncher extends GwtApplication { Net.setClientProvider(new WebsocketClient()); - Mindustry.platforms = new PlatformFunction(){ + Platform.instance = new Platform(){ DateTimeFormat format = DateTimeFormat.getFormat("EEE, dd MMM yyyy HH:mm:ss"); @Override diff --git a/html/src/io/anuke/mindustry/client/WebsocketClient.java b/html/src/io/anuke/mindustry/client/WebsocketClient.java index 9e4e2013df..7118e45c5f 100644 --- a/html/src/io/anuke/mindustry/client/WebsocketClient.java +++ b/html/src/io/anuke/mindustry/client/WebsocketClient.java @@ -6,8 +6,7 @@ import com.badlogic.gdx.utils.reflect.ClassReflection; import com.badlogic.gdx.utils.reflect.ReflectionException; import com.sksamuel.gwt.websockets.Websocket; import com.sksamuel.gwt.websockets.WebsocketListener; -import io.anuke.mindustry.Mindustry; -import io.anuke.mindustry.Vars; +import io.anuke.mindustry.io.Platform; import io.anuke.mindustry.net.Host; import io.anuke.mindustry.net.Net; import io.anuke.mindustry.net.Net.ClientProvider; @@ -23,13 +22,15 @@ import io.anuke.ucore.util.Strings; import java.io.IOException; import java.nio.ByteBuffer; +import static io.anuke.mindustry.Vars.*; + public class WebsocketClient implements ClientProvider { Websocket socket; ByteBuffer buffer = ByteBuffer.allocate(1024); @Override public void connect(String ip, int port){ - socket = new Websocket("ws://" + ip + ":" + Vars.webPort); + socket = new Websocket("ws://" + ip + ":" + webPort); socket.addListener(new WebsocketListener() { public void onMessage(byte[] bytes) { try { @@ -103,10 +104,10 @@ public class WebsocketClient implements ClientProvider { @Override public void pingHost(String address, int port, Consumer valid, Consumer failed) { - if(!Mindustry.platforms.canJoinGame()) { + if(!Platform.instance.canJoinGame()) { failed.accept(new IOException()); }else { - Websocket socket = new Websocket("ws://" + address + ":" + Vars.webPort); + Websocket socket = new Websocket("ws://" + address + ":" + webPort); final boolean[] accepted = {false}; socket.addListener(new WebsocketListener() { @Override diff --git a/kryonet/src/io/anuke/kryonet/JavaWebsocketClient.java b/kryonet/src/io/anuke/kryonet/JavaWebsocketClient.java index eb4693c1b4..cafb859967 100644 --- a/kryonet/src/io/anuke/kryonet/JavaWebsocketClient.java +++ b/kryonet/src/io/anuke/kryonet/JavaWebsocketClient.java @@ -12,8 +12,8 @@ import io.anuke.mindustry.net.Packet; import io.anuke.mindustry.net.Packets.Connect; import io.anuke.mindustry.net.Packets.Disconnect; import io.anuke.mindustry.net.Registrator; -import io.anuke.ucore.UCore; import io.anuke.ucore.function.Consumer; +import io.anuke.ucore.util.Log; import org.java_websocket.client.WebSocketClient; import org.java_websocket.drafts.Draft_6455; import org.java_websocket.handshake.ServerHandshake; @@ -32,7 +32,7 @@ public class JavaWebsocketClient implements ClientProvider { public void connect(String ip, int port) throws IOException { try { URI i = new URI("ws://" + ip + ":" + Vars.webPort); - UCore.log("Connecting: " + i); + Log.info("Connecting: {0}", i); socket = new WebSocketClient(i, new Draft_6455(), null, 5000) { Thread thread; @@ -47,14 +47,13 @@ public class JavaWebsocketClient implements ClientProvider { @Override public void onOpen(ServerHandshake handshakedata) { - UCore.log("Connected!"); + Log.info("Connected!"); Connect connect = new Connect(); Net.handleClientReceived(connect); } @Override public void onMessage(String message) { - if(debug) UCore.log("Got message: " + message); try { byte[] bytes = Base64Coder.decode(message); ByteBuffer buffer = ByteBuffer.wrap(bytes); @@ -63,7 +62,6 @@ public class JavaWebsocketClient implements ClientProvider { //this is a framework message... do nothing yet? } else { Class type = Registrator.getByID(id); - if(debug) UCore.log("Got class ID: " + type); Packet packet = (Packet) ClassReflection.newInstance(type); packet.read(buffer); Net.handleClientReceived(packet); @@ -76,7 +74,6 @@ public class JavaWebsocketClient implements ClientProvider { @Override public void onClose(int code, String reason, boolean remote) { - if(debug) UCore.log("Closed."); Disconnect disconnect = new Disconnect(); Net.handleClientReceived(disconnect); } @@ -105,7 +102,6 @@ public class JavaWebsocketClient implements ClientProvider { byte[] out = new byte[pos]; buffer.get(out); String string = new String(Base64Coder.encode(out)); - if(debug) UCore.log("Sending string: " + string); socket.send(string); } diff --git a/kryonet/src/io/anuke/kryonet/KryoClient.java b/kryonet/src/io/anuke/kryonet/KryoClient.java index cfc77ecc8c..52cddac4e2 100644 --- a/kryonet/src/io/anuke/kryonet/KryoClient.java +++ b/kryonet/src/io/anuke/kryonet/KryoClient.java @@ -6,14 +6,12 @@ import com.badlogic.gdx.utils.ObjectMap; import com.badlogic.gdx.utils.ObjectSet; import com.esotericsoftware.kryonet.*; import com.esotericsoftware.kryonet.Listener.LagListener; -import io.anuke.mindustry.Vars; import io.anuke.mindustry.net.Host; import io.anuke.mindustry.net.Net; import io.anuke.mindustry.net.Net.ClientProvider; 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.UCore; import io.anuke.ucore.function.Consumer; import java.io.IOException; @@ -21,8 +19,12 @@ import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress; import java.nio.ByteBuffer; +import java.nio.channels.ClosedSelectorException; import java.util.List; +import static io.anuke.mindustry.Vars.netClient; +import static io.anuke.mindustry.Vars.port; + public class KryoClient implements ClientProvider{ Client client; ObjectMap addresses = new ObjectMap<>(); @@ -40,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); - UCore.log("Host data found: " + buffer.capacity() + " bytes."); } @Override @@ -78,8 +79,8 @@ public class KryoClient implements ClientProvider{ Net.handleClientReceived(object); }catch (Exception e){ if(e instanceof KryoNetException && e.getMessage() != null && e.getMessage().toLowerCase().contains("incorrect")) { - Vars.ui.showError("$text.server.mismatch"); - Vars.netClient.disconnectQuietly(); + Net.showError("$text.server.mismatch"); + netClient.disconnectQuietly(); }else{ throw new RuntimeException(e); } @@ -105,7 +106,7 @@ public class KryoClient implements ClientProvider{ try{ client.run(); }catch (Exception e){ - handleException(e); + if(!(e instanceof ClosedSelectorException)) handleException(e); } }, "Kryonet Client"); updateThread.setDaemon(true); @@ -143,7 +144,7 @@ public class KryoClient implements ClientProvider{ runAsync(() -> { try { DatagramSocket socket = new DatagramSocket(); - socket.send(new DatagramPacket(new byte[]{-2, 1}, 2, InetAddress.getByName(address), Vars.port)); + socket.send(new DatagramPacket(new byte[]{-2, 1}, 2, InetAddress.getByName(address), port)); socket.setSoTimeout(2000); @@ -171,7 +172,7 @@ public class KryoClient implements ClientProvider{ public void discover(Consumer> callback){ runAsync(() -> { addresses.clear(); - List list = client.discoverHosts(Vars.port, 3000); + List list = client.discoverHosts(port, 3000); ObjectSet hostnames = new ObjectSet<>(); Array result = new Array<>(); @@ -206,7 +207,7 @@ public class KryoClient implements ClientProvider{ private void handleException(Exception e){ e.printStackTrace(); if(e instanceof KryoNetException){ - Gdx.app.postRunnable(() -> Vars.ui.showError("$text.server.mismatch")); + Gdx.app.postRunnable(() -> Net.showError("$text.server.mismatch")); }else{ //TODO better exception handling. disconnect(); diff --git a/kryonet/src/io/anuke/kryonet/KryoRegistrator.java b/kryonet/src/io/anuke/kryonet/KryoRegistrator.java index 757bd07fde..a407b91ff0 100644 --- a/kryonet/src/io/anuke/kryonet/KryoRegistrator.java +++ b/kryonet/src/io/anuke/kryonet/KryoRegistrator.java @@ -1,27 +1,57 @@ package io.anuke.kryonet; -import com.esotericsoftware.kryo.Kryo; +import com.esotericsoftware.minlog.Log; +import com.esotericsoftware.minlog.Log.Logger; import io.anuke.mindustry.Vars; import io.anuke.mindustry.net.Host; -import io.anuke.mindustry.net.Net; +import io.anuke.ucore.util.ColorCodes; +import java.io.PrintWriter; +import java.io.StringWriter; import java.net.InetAddress; import java.nio.ByteBuffer; +import static io.anuke.mindustry.Vars.headless; +import static io.anuke.mindustry.Vars.playerGroup; + public class KryoRegistrator { public static boolean fakeLag = false; public static final int fakeLagAmount = 500; - public static void register(Kryo kryo){ - //TODO register stuff? - //Log.set(Log.LEVEL_DEBUG); + static{ + Log.setLogger(new Logger(){ + public void log (int level, String category, String message, Throwable ex) { + StringBuilder builder = new StringBuilder(256); + + if(headless) + builder.append(ColorCodes.BLUE); + + builder.append("Net: "); + + builder.append(message); + + if (ex != null) { + StringWriter writer = new StringWriter(256); + ex.printStackTrace(new PrintWriter(writer)); + builder.append('\n'); + builder.append(writer.toString().trim()); + } + + if(headless) + builder.append(ColorCodes.RESET); + + io.anuke.ucore.util.Log.info("&b" + builder.toString()); + } + }); } public static ByteBuffer writeServerData(){ - ByteBuffer buffer = ByteBuffer.allocate(1 + Vars.player.name.length() + 4); - buffer.put((byte)Vars.player.name.length()); - buffer.put(Vars.player.name.getBytes()); - buffer.putInt(Net.getConnections().size + 1); + String host = headless ? "Server" : Vars.player.name; + + ByteBuffer buffer = ByteBuffer.allocate(1 + host.getBytes().length + 4); + buffer.put((byte)host.getBytes().length); + buffer.put(host.getBytes()); + buffer.putInt(playerGroup.size()); return buffer; } diff --git a/kryonet/src/io/anuke/kryonet/KryoServer.java b/kryonet/src/io/anuke/kryonet/KryoServer.java index ff705d8763..4f6543449c 100644 --- a/kryonet/src/io/anuke/kryonet/KryoServer.java +++ b/kryonet/src/io/anuke/kryonet/KryoServer.java @@ -23,6 +23,7 @@ import io.anuke.mindustry.net.Streamable; import io.anuke.mindustry.net.Streamable.StreamBegin; import io.anuke.mindustry.net.Streamable.StreamChunk; import io.anuke.ucore.UCore; +import io.anuke.ucore.util.Log; import org.java_websocket.WebSocket; import org.java_websocket.exceptions.WebsocketNotConnectedException; import org.java_websocket.handshake.ClientHandshake; @@ -32,7 +33,7 @@ import java.io.IOException; import java.net.BindException; import java.net.InetSocketAddress; import java.nio.ByteBuffer; -import java.util.Arrays; +import java.nio.channels.ClosedSelectorException; import java.util.concurrent.CopyOnWriteArrayList; public class KryoServer implements ServerProvider { @@ -50,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(); - UCore.log("Replying to discover request with buffer of size " + buffer.capacity()); buffer.position(0); datagramChannel.send(buffer, fromAddress); return true; @@ -67,7 +67,6 @@ public class KryoServer implements ServerProvider { c.addressTCP = connection.getRemoteAddressTCP().toString(); connections.add(kn); - UCore.log("Adding connection #" + kn.id + " to list."); Gdx.app.postRunnable(() -> Net.handleServerReceived(kn.id, c)); } @@ -136,7 +135,7 @@ public class KryoServer implements ServerProvider { try{ server.run(); }catch (Exception e){ - handleException(e); + if(!(e instanceof ClosedSelectorException)) handleException(e); } }, "Kryonet Server"); thread.setDaemon(true); @@ -152,7 +151,7 @@ public class KryoServer implements ServerProvider { Thread thread = new Thread(() ->{ try { server.close(); - UCore.log("Killing web server..."); + Log.info("Killing web server..."); try { if (webServer != null) webServer.stop(1); //please die, right now }catch(Exception e){ @@ -164,7 +163,7 @@ public class KryoServer implements ServerProvider { worker.interrupt(); } } - UCore.log("Killed web server."); + Log.info("Killed web server."); }catch (Exception e){ Gdx.app.postRunnable(() -> {throw new RuntimeException(e);}); } @@ -260,7 +259,7 @@ public class KryoServer implements ServerProvider { } try { - UCore.log("Disposing web server..."); + Log.info("Disposing web server..."); if(webServer != null) webServer.stop(1); //kill them all @@ -269,7 +268,7 @@ public class KryoServer implements ServerProvider { thread.interrupt(); } } - UCore.log("Killed web server."); + Log.info("Killed web server."); }catch (Exception e){ e.printStackTrace(); } @@ -334,14 +333,14 @@ public class KryoServer implements ServerProvider { try { synchronized (buffer) { buffer.position(0); - if(debug) UCore.log("Sending object with ID " + Registrator.getID(object.getClass())); + if(debug) Log.info("Sending object with ID {0}", Registrator.getID(object.getClass())); serializer.write(buffer, object); int pos = buffer.position(); buffer.position(0); byte[] out = new byte[pos]; buffer.get(out); String string = new String(Base64Coder.encode(out)); - if(debug) UCore.log("Sending string: " + string); + if(debug) Log.info("Sending string: {0}", string); socket.send(string); } }catch (WebsocketNotConnectedException e){ @@ -360,7 +359,7 @@ public class KryoServer implements ServerProvider { } }catch (Exception e){ e.printStackTrace(); - UCore.log("Disconnecting invalid client!"); + Log.info("Disconnecting invalid client!"); connection.close(); } } @@ -387,7 +386,7 @@ public class KryoServer implements ServerProvider { public void onOpen(WebSocket conn, ClientHandshake handshake) { Connect connect = new Connect(); connect.addressTCP = conn.getRemoteSocketAddress().toString(); - UCore.log("Websocket connection recieved: " + connect.addressTCP); + Log.info("Websocket connection recieved: {0}", connect.addressTCP); KryoConnection kn = new KryoConnection(lastconnection ++, connect.addressTCP, conn); connections.add(kn); } @@ -412,36 +411,33 @@ public class KryoServer implements ServerProvider { conn.send("---" + connections.size() + "|" + Vars.player.name); connections.remove(k); }else { - if (debug) UCore.log("Got message: " + message); byte[] out = Base64Coder.decode(message); - if (debug) UCore.log("Decoded: " + Arrays.toString(out)); ByteBuffer buffer = ByteBuffer.wrap(out); Object o = serializer.read(buffer); Net.handleServerReceived(k.id, o); } }catch (Exception e){ - UCore.log("Error reading message!"); - e.printStackTrace(); + Log.err(e); } } @Override public void onError(WebSocket conn, Exception ex) { - UCore.log("WS error:"); + Log.info("WS error:"); ex.printStackTrace(); if(ex instanceof BindException){ Net.closeServer(); - Vars.ui.showError("$text.server.addressinuse"); + Net.showError("$text.server.addressinuse"); }else if(ex.getMessage().equals("Permission denied")){ Net.closeServer(); - Vars.ui.showError("Permission denied."); + Net.showError("Permission denied."); } } @Override public void onStart() { - UCore.log("Web server started."); + Log.info("Web server started."); } } diff --git a/server/build.gradle b/server/build.gradle new file mode 100644 index 0000000000..3dde2b0bc3 --- /dev/null +++ b/server/build.gradle @@ -0,0 +1,40 @@ +apply plugin: "java" + +sourceCompatibility = 1.8 +sourceSets.main.java.srcDirs = [ "src/" ] + +project.ext.mainClassName = "io.anuke.mindustry.server.ServerLauncher" +project.ext.assetsDir = new File("../core/assets"); + +task run(dependsOn: classes, type: JavaExec) { + main = project.mainClassName + classpath = sourceSets.main.runtimeClasspath + standardInput = System.in + workingDir = project.assetsDir + ignoreExitValue = true + if (project.hasProperty("appArgs")) { + args Eval.me(appArgs) + } +} + +task debug(dependsOn: classes, type: JavaExec) { + main = project.mainClassName + classpath = sourceSets.main.runtimeClasspath + standardInput = System.in + workingDir = project.assetsDir + ignoreExitValue = true + debug = true +} + +task dist(type: Jar) { + from files(sourceSets.main.output.classesDir) + from files(sourceSets.main.output.resourcesDir) + from {configurations.compile.collect {zipTree(it)}} + from files(project.assetsDir); + + manifest { + attributes 'Main-Class': project.mainClassName + } +} + +dist.dependsOn classes diff --git a/server/src/io/anuke/mindustry/server/ServerLauncher.java b/server/src/io/anuke/mindustry/server/ServerLauncher.java new file mode 100644 index 0000000000..dc2c95b5b6 --- /dev/null +++ b/server/src/io/anuke/mindustry/server/ServerLauncher.java @@ -0,0 +1,57 @@ +package io.anuke.mindustry.server; + +import com.badlogic.gdx.backends.headless.HeadlessApplication; +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; + +import java.lang.reflect.Method; + +public class ServerLauncher{ + + public static void main(String[] args) throws Exception{ + + Net.setClientProvider(new KryoClient()); + Net.setServerProvider(new KryoServer()); + + HeadlessApplication app = new HeadlessApplication(new MindustryServer()){ + @Override + public boolean executeRunnables() { + try { + return super.executeRunnables(); + }catch(Throwable e) { + Log.err(e); + System.exit(-1); + return false; + } + } + }; + + Method method = app.getClass().getDeclaredMethod("mainLoop"); + method.setAccessible(true); + + //kill default libGDX thread + for(Thread thread : Thread.getAllStackTraces().keySet()){ + if(thread.getName().equals("\"HeadlessApplication\"")){ + thread.interrupt(); + } + } + + //replace it with my own + Thread mainLoopThread = new Thread("HeadlessApplication") { + @Override + public void run () { + try { + method.invoke(app); + } catch (Throwable t) { + t.printStackTrace(); + System.exit(-1); + } + } + }; + mainLoopThread.start(); + + } +} \ No newline at end of file diff --git a/settings.gradle b/settings.gradle index b0219d0817..420a1f02eb 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,4 +1,4 @@ -include 'desktop', 'html', 'core', 'android', 'kryonet' +include 'desktop', 'html', 'core', 'android', 'kryonet', 'server' if(System.properties["release"] == null || System.properties["release"].equals("false")){ if (new File(settingsDir, '../uCore').exists()) {