zones(){
+ return getBy(ContentType.zone);
+ }
+
/**
* Registers sync IDs for all types of sync entities.
* Do not register units here!
@@ -280,7 +244,5 @@ public class ContentLoader{
TypeTrait.registerType(Lightning.class, Lightning::new);
}
- private class ImpendingDoomException extends RuntimeException{
- public ImpendingDoomException(String s){ super(s); }
- }
+ private class ImpendingDoomException extends RuntimeException{ ImpendingDoomException(String s){ super(s); }}
}
diff --git a/core/src/io/anuke/mindustry/core/Control.java b/core/src/io/anuke/mindustry/core/Control.java
index ae61933103..b1f7c806a1 100644
--- a/core/src/io/anuke/mindustry/core/Control.java
+++ b/core/src/io/anuke/mindustry/core/Control.java
@@ -1,35 +1,40 @@
package io.anuke.mindustry.core;
-import com.badlogic.gdx.Gdx;
-import com.badlogic.gdx.graphics.Color;
+import io.anuke.arc.ApplicationListener;
+import io.anuke.arc.Core;
+import io.anuke.arc.Events;
+import io.anuke.arc.graphics.Color;
+import io.anuke.arc.graphics.g2d.Draw;
+import io.anuke.arc.graphics.g2d.TextureAtlas;
+import io.anuke.arc.input.KeyCode;
+import io.anuke.arc.scene.ui.TextField;
+import io.anuke.arc.util.Interval;
+import io.anuke.arc.util.Strings;
+import io.anuke.arc.util.Time;
import io.anuke.mindustry.content.Mechs;
import io.anuke.mindustry.core.GameState.State;
-import io.anuke.mindustry.entities.Player;
-import io.anuke.mindustry.entities.TileEntity;
+import io.anuke.mindustry.entities.Effects;
+import io.anuke.mindustry.entities.EntityQuery;
+import io.anuke.mindustry.entities.type.Player;
import io.anuke.mindustry.game.Content;
import io.anuke.mindustry.game.EventType.*;
+import io.anuke.mindustry.game.GlobalData;
+import io.anuke.mindustry.game.Rules;
import io.anuke.mindustry.game.Saves;
-import io.anuke.mindustry.game.Unlocks;
import io.anuke.mindustry.gen.Call;
-import io.anuke.mindustry.input.DefaultKeybinds;
+import io.anuke.mindustry.input.Binding;
import io.anuke.mindustry.input.DesktopInput;
import io.anuke.mindustry.input.InputHandler;
import io.anuke.mindustry.input.MobileInput;
import io.anuke.mindustry.maps.Map;
import io.anuke.mindustry.net.Net;
-import io.anuke.mindustry.type.ItemStack;
-import io.anuke.mindustry.type.Recipe;
+import io.anuke.mindustry.type.Item;
import io.anuke.mindustry.ui.dialogs.FloatingDialog;
-import io.anuke.ucore.core.*;
-import io.anuke.ucore.entities.EntityQuery;
-import io.anuke.ucore.modules.Module;
-import io.anuke.ucore.util.Atlas;
-import io.anuke.ucore.util.Bundles;
-import io.anuke.ucore.util.Strings;
-import io.anuke.ucore.util.Timer;
+import io.anuke.mindustry.world.Tile;
import java.io.IOException;
+import static io.anuke.arc.Core.scene;
import static io.anuke.mindustry.Vars.*;
/**
@@ -38,36 +43,36 @@ import static io.anuke.mindustry.Vars.*;
* Should not handle any logic-critical state.
* This class is not created in the headless server.
*/
-public class Control extends Module{
+public class Control implements ApplicationListener{
public final Saves saves;
- public final Unlocks unlocks;
- private Timer timerRPC = new Timer(), timerUnlock = new Timer();
+ private Interval timer = new Interval(2);
private boolean hiscore = false;
private boolean wasPaused = false;
private InputHandler[] inputs = {};
- private Throwable error;
public Control(){
saves = new Saves();
- unlocks = new Unlocks();
+ data = new GlobalData();
- Inputs.useControllers(true);
-
- Gdx.input.setCatchBackKey(true);
+ Core.input.setCatch(KeyCode.BACK, true);
Effects.setShakeFalloff(10000f);
content.initialize(Content::init);
- Core.atlas = new Atlas("sprites.atlas");
- Core.atlas.setErrorRegion("error");
+ Core.atlas = new TextureAtlas("sprites/sprites.atlas");
+ Draw.scl = 1f / Core.atlas.find("scale_marker").getWidth();
content.initialize(Content::load);
- unlocks.load();
+ if(Core.atlas.getTextures().size != 1){
+ throw new IllegalStateException("Atlas must be exactly one texture. " +
+ "If more textures are used, the map editor will not display them correctly.");
+ }
- DefaultKeybinds.load();
+ data.load();
- Settings.defaultList(
+ Core.settings.setAppName(appName);
+ Core.settings.defaults(
"ip", "localhost",
"color-0", Color.rgba8888(playerColors[8]),
"color-1", Color.rgba8888(playerColors[11]),
@@ -77,15 +82,13 @@ public class Control extends Module{
"lastBuild", 0
);
- KeyBinds.load();
-
addPlayer(0);
saves.load();
Events.on(StateChangeEvent.class, event -> {
if((event.from == State.playing && event.to == State.menu) || (event.from == State.menu && event.to != State.menu)){
- Timers.runTask(5f, Platform.instance::updateRPC);
+ Time.runTask(5f, Platform.instance::updateRPC);
}
});
@@ -97,9 +100,9 @@ public class Control extends Module{
state.set(State.playing);
});
- Events.on(WorldLoadGraphicsEvent.class, event -> {
+ Events.on(WorldLoadEvent.class, event -> {
if(mobile){
- Gdx.app.postRunnable(() -> Core.camera.position.set(players[0].x, players[0].y, 0));
+ Core.app.post(() -> Core.camera.position.set(players[0]));
}
});
@@ -113,46 +116,61 @@ public class Control extends Module{
saves.resetSave();
});
- Events.on(WaveEvent.class, event -> {
-
- int last = Settings.getInt("hiscore" + world.getMap().name, 0);
-
- if(state.wave > last && !state.mode.infiniteResources && !state.mode.disableWaveTimer && world.getSector() == null){
- Settings.putInt("hiscore" + world.getMap().name, state.wave);
- Settings.save();
- hiscore = true;
- }
-
- Platform.instance.updateRPC();
- });
+ //todo high scores for custom maps, as well as other statistics
Events.on(GameOverEvent.class, event -> {
- //delete saves for game-over sectors
- if(world.getSector() != null && world.getSector().hasSave()){
- world.getSector().getSave().delete();
- }
-
- threads.runGraphics(() -> {
- Effects.shake(5, 6, Core.camera.position.x, Core.camera.position.y);
- //the restart dialog can show info for any number of scenarios
- Call.onGameOver(event.winner);
- });
- });
-
- //autohost for pvp sectors
- Events.on(WorldLoadEvent.class, event -> {
- if(state.mode.isPvp && !Net.active()){
- try{
- Net.host(port);
- players[0].isAdmin = true;
- }catch(IOException e){
- ui.showError(Bundles.format("text.server.error", Strings.parseException(e, false)));
- threads.runDelay(() -> state.set(State.menu));
+ state.stats.wavesLasted = state.wave;
+ Effects.shake(5, 6, Core.camera.position.x, Core.camera.position.y);
+ //the restart dialog can show info for any number of scenarios
+ Call.onGameOver(event.winner);
+ if(state.rules.zone != -1){
+ //remove zone save on game over
+ if(saves.getZoneSlot() != null){
+ saves.getZoneSlot().delete();
}
}
});
- Events.on(WorldLoadEvent.class, event -> threads.runGraphics(() -> Events.fire(new WorldLoadGraphicsEvent())));
+ //autohost for pvp sectors
+ Events.on(WorldLoadEvent.class, event -> {
+ if(state.rules.pvp && !Net.active()){
+ try{
+ Net.host(port);
+ players[0].isAdmin = true;
+ }catch(IOException e){
+ ui.showError(Core.bundle.format("server.error", Strings.parseException(e, false)));
+ Core.app.post(() -> state.set(State.menu));
+ }
+ }
+ });
+
+ Events.on(UnlockEvent.class, e -> ui.hudfrag.showUnlock(e.content));
+
+ Events.on(BlockBuildEndEvent.class, e -> {
+ if(e.team == players[0].getTeam()){
+ if(e.breaking){
+ state.stats.buildingsDeconstructed++;
+ }else{
+ state.stats.buildingsBuilt ++;
+ }
+ }
+ });
+
+ Events.on(BlockDestroyEvent.class, e -> {
+ if(e.tile.getTeam() == players[0].getTeam()){
+ state.stats.buildingsDestroyed ++;
+ }
+ });
+
+ Events.on(UnitDestroyEvent.class, e -> {
+ if(e.unit.getTeam() != players[0].getTeam()){
+ state.stats.enemyUnitsDestroyed ++;
+ }
+ });
+
+ Events.on(ZoneCompleteEvent.class, e -> {
+ ui.hudfrag.showToast(Core.bundle.get("zone.complete"));
+ });
}
public void addPlayer(int index){
@@ -171,9 +189,9 @@ public class Control extends Module{
Player setTo = (index == 0 ? null : players[0]);
Player player = new Player();
- player.name = Settings.getString("name");
+ player.name = Core.settings.getString("name");
player.mech = mobile ? Mechs.starterMobile : Mechs.starterDesktop;
- player.color.set(Settings.getInt("color-" + index));
+ player.color.set(Core.settings.getInt("color-" + index));
player.isLocal = true;
player.playerIndex = index;
player.isMobile = mobile;
@@ -196,7 +214,7 @@ public class Control extends Module{
}
inputs[index] = input;
- Inputs.addProcessor(input);
+ Core.input.addProcessor(input);
}
public void removePlayer(){
@@ -212,17 +230,14 @@ public class Control extends Module{
System.arraycopy(oldi, 0, inputs, 0, inputs.length);
}
- public void setError(Throwable error){
- this.error = error;
- }
-
public InputHandler input(int index){
return inputs[index];
}
- public void playMap(Map map){
- ui.loadLogic(() -> {
+ public void playMap(Map map, Rules rules){
+ ui.loadAnd(() -> {
logic.reset();
+ state.rules = rules;
world.loadMap(map);
logic.play();
});
@@ -232,35 +247,8 @@ public class Control extends Module{
return hiscore;
}
- private void checkUnlockableBlocks(){
- TileEntity entity = players[0].getClosestCore();
-
- if(entity == null) return;
-
- entity.items.forEach((item, amount) -> unlocks.unlockContent(item));
-
- if(players[0].inventory.hasItem()){
- unlocks.unlockContent(players[0].inventory.getItem().item);
- }
-
- outer:
- for(int i = 0; i < content.recipes().size; i ++){
- Recipe recipe = content.recipes().get(i);
- if(!recipe.isHidden() && recipe.requirements != null){
- for(ItemStack stack : recipe.requirements){
- if(!entity.items.has(stack.item, Math.min((int) (stack.amount * unlockResourceScaling), 2000))) continue outer;
- }
-
- if(unlocks.unlockContent(recipe)){
- ui.hudfrag.showUnlock(recipe);
- }
- }
- }
- }
-
@Override
public void dispose(){
- Platform.instance.onGameExit();
content.dispose();
Net.dispose();
ui.editor.dispose();
@@ -287,16 +275,16 @@ public class Control extends Module{
Platform.instance.updateRPC();
- if(!Settings.getBool("4.0-warning-2", false)){
+ if(!Core.settings.getBool("4.0-warning-2", false)){
- Timers.run(5f, () -> {
- FloatingDialog dialog = new FloatingDialog("[accent]WARNING![]");
- dialog.buttons().addButton("$text.ok", () -> {
+ Time.run(5f, () -> {
+ FloatingDialog dialog = new FloatingDialog("WARNING!");
+ dialog.buttons.addButton("$ok", () -> {
dialog.hide();
- Settings.putBool("4.0-warning-2", true);
- Settings.save();
+ Core.settings.put("4.0-warning-2", true);
+ Core.settings.save();
}).size(100f, 60f);
- dialog.content().add("Reminder: The beta version you are about to play is very unstable, and is [accent]not representative of the final 4.0 release.[]\n\n " +
+ dialog.cont.add("Reminder: The alpha version you are about to play is very unstable, and is [accent]not representative of the final 4.0 release.[]\n\n " +
"\nThere is currently[scarlet] no sound implemented[]; this is intentional.\n" +
"All current art and UI is temporary, and will be re-drawn before release. " +
"\n\n[accent]Saves and maps may be corrupted without warning between updates.").wrap().width(400f);
@@ -305,65 +293,59 @@ public class Control extends Module{
}
}
- /** Called from main logic thread.*/
- public void runUpdateLogic(){
- if(!state.is(State.menu)){
- renderer.minimap.updateUnitArray();
- }
- }
-
@Override
public void update(){
- if(error != null){
- throw new RuntimeException(error);
- }
-
saves.update();
for(InputHandler inputHandler : inputs){
inputHandler.updateController();
}
+ //autosave global data every second if it's modified
+ if(timer.get(1, 60)){
+ data.checkSave();
+ }
+
if(!state.is(State.menu)){
for(InputHandler input : inputs){
input.update();
}
- //auto-update rpc every 5 seconds
- if(timerRPC.get(60 * 5)){
- Platform.instance.updateRPC();
- }
-
- //check unlocks every 2 seconds
- if(!state.mode.infiniteResources && timerUnlock.get(120)){
- checkUnlockableBlocks();
-
- //save if the unlocks changed
- if(unlocks.isDirty()){
- unlocks.save();
+ if(world.isZone()){
+ for(Tile tile : state.teams.get(players[0].getTeam()).cores){
+ for(Item item : content.items()){
+ if(tile.entity.items.has(item)){
+ data.unlockContent(item);
+ }
+ }
}
}
- if(Inputs.keyTap("pause") && !ui.restart.isShown() && (state.is(State.paused) || state.is(State.playing))){
+ //auto-update rpc every 5 seconds
+ if(timer.get(0, 60 * 5)){
+ Platform.instance.updateRPC();
+ }
+
+ if(Core.input.keyTap(Binding.pause) && !ui.restart.isShown() && (state.is(State.paused) || state.is(State.playing))){
state.set(state.is(State.playing) ? State.paused : State.playing);
}
- if(Inputs.keyTap("menu") && !ui.restart.isShown()){
+ if(Core.input.keyTap(Binding.menu) && !ui.restart.isShown()){
if(ui.chatfrag.chatOpen()){
ui.chatfrag.hide();
- }else if(!ui.paused.isShown() && !ui.hasDialog()){
+ }else if(!ui.paused.isShown() && !scene.hasDialog()){
ui.paused.show();
state.set(State.paused);
}
}
- if(!mobile && Inputs.keyTap("screenshot") && !ui.chatfrag.chatOpen()){
+ if(!mobile && Core.input.keyTap(Binding.screenshot) && !(scene.getKeyboardFocus() instanceof TextField) && !ui.chatfrag.chatOpen()){
renderer.takeMapScreenshot();
}
}else{
if(!state.isPaused()){
- Timers.update();
+ Time.update();
}
}
}
diff --git a/core/src/io/anuke/mindustry/core/GameState.java b/core/src/io/anuke/mindustry/core/GameState.java
index 96a36fad8a..fd521bf2c0 100644
--- a/core/src/io/anuke/mindustry/core/GameState.java
+++ b/core/src/io/anuke/mindustry/core/GameState.java
@@ -1,11 +1,11 @@
package io.anuke.mindustry.core;
-import io.anuke.mindustry.game.Difficulty;
+import io.anuke.arc.Events;
import io.anuke.mindustry.game.EventType.StateChangeEvent;
-import io.anuke.mindustry.game.GameMode;
+import io.anuke.mindustry.game.Rules;
+import io.anuke.mindustry.game.Stats;
import io.anuke.mindustry.game.Teams;
import io.anuke.mindustry.net.Net;
-import io.anuke.ucore.core.Events;
import static io.anuke.mindustry.Vars.unitGroups;
import static io.anuke.mindustry.Vars.waveTeam;
@@ -16,11 +16,11 @@ public class GameState{
/**Wave countdown in ticks.*/
public float wavetime;
/**Whether the game is in game over state.*/
- public boolean gameOver = false;
- /**The current game mode.*/
- public GameMode mode = GameMode.waves;
- /**The current difficulty for wave modes.*/
- public Difficulty difficulty = Difficulty.normal;
+ public boolean gameOver = false, launched = false;
+ /**The current game rules.*/
+ public Rules rules = new Rules();
+ /**Statistics for this save/game. Displayed after game over.*/
+ public Stats stats = new Stats();
/**Team data. Gets reset every new game.*/
public Teams teams = new Teams();
/**Number of enemies in the game; only used clientside in servers.*/
@@ -38,7 +38,7 @@ public class GameState{
}
public boolean isPaused(){
- return is(State.paused) && !Net.active();
+ return (is(State.paused) && !Net.active()) || gameOver;
}
public boolean is(State astate){
diff --git a/core/src/io/anuke/mindustry/core/Logic.java b/core/src/io/anuke/mindustry/core/Logic.java
index 5f7035cb7e..28a4e44461 100644
--- a/core/src/io/anuke/mindustry/core/Logic.java
+++ b/core/src/io/anuke/mindustry/core/Logic.java
@@ -1,27 +1,23 @@
package io.anuke.mindustry.core;
-import com.badlogic.gdx.utils.Array;
import io.anuke.annotations.Annotations.Loc;
import io.anuke.annotations.Annotations.Remote;
-import io.anuke.mindustry.Vars;
+import io.anuke.arc.ApplicationListener;
+import io.anuke.arc.Events;
+import io.anuke.arc.collection.ObjectSet.ObjectSetIterator;
+import io.anuke.mindustry.entities.Effects;
+import io.anuke.mindustry.entities.Entities;
+import io.anuke.mindustry.entities.EntityGroup;
+import io.anuke.mindustry.entities.EntityQuery;
+import io.anuke.arc.util.Time;
+import io.anuke.mindustry.content.Fx;
import io.anuke.mindustry.core.GameState.State;
-import io.anuke.mindustry.entities.TileEntity;
+import io.anuke.mindustry.entities.type.TileEntity;
import io.anuke.mindustry.game.EventType.*;
-import io.anuke.mindustry.game.GameMode;
-import io.anuke.mindustry.game.Team;
-import io.anuke.mindustry.game.Teams;
-import io.anuke.mindustry.game.UnlockableContent;
-import io.anuke.mindustry.gen.Call;
+import io.anuke.mindustry.game.*;
import io.anuke.mindustry.net.Net;
-import io.anuke.mindustry.type.ItemStack;
-import io.anuke.mindustry.type.Recipe;
+import io.anuke.mindustry.type.Item;
import io.anuke.mindustry.world.Tile;
-import io.anuke.ucore.core.Events;
-import io.anuke.ucore.core.Timers;
-import io.anuke.ucore.entities.Entities;
-import io.anuke.ucore.entities.EntityGroup;
-import io.anuke.ucore.entities.EntityQuery;
-import io.anuke.ucore.modules.Module;
import static io.anuke.mindustry.Vars.*;
@@ -33,12 +29,12 @@ import static io.anuke.mindustry.Vars.*;
*
* This class should not call any outside methods to change state of modules, but instead fire events.
*/
-public class Logic extends Module{
+public class Logic implements ApplicationListener{
public Logic(){
- Events.on(TileChangeEvent.class, event -> {
- if(event.tile.getTeam() == defaultTeam && Recipe.getByResult(event.tile.block()) != null){
- handleContent(Recipe.getByResult(event.tile.block()));
+ Events.on(WaveEvent.class, event -> {
+ if(world.isZone()){
+ data.updateWaveScore(world.getZone(), state.wave);
}
});
}
@@ -54,38 +50,28 @@ public class Logic extends Module{
/**Handles the event of content being used by either the player or some block.*/
public void handleContent(UnlockableContent content){
- if(world.getSector() != null){
- world.getSector().currentMission().onContentUsed(content);
- }
-
if(!headless){
- control.unlocks.unlockContent(content);
+ data.unlockContent(content);
}
}
public void play(){
state.set(State.playing);
- state.wavetime = wavespace * state.difficulty.timeScaling * 2;
-
- for(Tile tile : state.teams.get(defaultTeam).cores){
- if(world.getSector() != null){
- Array items = world.getSector().startingItems;
- for(ItemStack stack : items){
- tile.entity.items.add(stack.item, stack.amount);
- }
- }
- }
+ state.wavetime = state.rules.waveSpacing * 2; //grace period of 2x wave time before game starts
Events.fire(new PlayEvent());
}
public void reset(){
state.wave = 1;
- state.wavetime = wavespace * state.difficulty.timeScaling;
- state.gameOver = false;
+ state.wavetime = state.rules.waveSpacing;
+ state.gameOver = state.launched = false;
state.teams = new Teams();
+ state.rules = new Rules();
+ state.rules.spawns = Waves.getDefaultSpawns();
+ state.stats = new Stats();
- Timers.clear();
+ Time.clear();
Entities.clear();
TileEntity.sleepingEntities = 0;
@@ -95,16 +81,16 @@ public class Logic extends Module{
public void runWave(){
world.spawner.spawnEnemies();
state.wave++;
- state.wavetime = wavespace * state.difficulty.timeScaling;
+ state.wavetime = state.rules.waveSpacing;
Events.fire(new WaveEvent());
}
private void checkGameOver(){
- if(!state.mode.isPvp && state.teams.get(defaultTeam).cores.size == 0 && !state.gameOver){
+ if(!state.rules.pvp && state.teams.get(defaultTeam).cores.size == 0 && !state.gameOver){
state.gameOver = true;
Events.fire(new GameOverEvent(waveTeam));
- }else if(state.mode.isPvp){
+ }else if(state.rules.pvp){
Team alive = null;
for(Team team : Team.all){
@@ -123,74 +109,50 @@ public class Logic extends Module{
}
}
- private void updateSectors(){
- if(world.getSector() == null || state.gameOver) return;
+ @Remote(called = Loc.both)
+ public static void launchZone(){
+ Effects.effect(Fx.launchFull, 0, 0);
- world.getSector().currentMission().update();
-
- //check unlocked sectors
- while(!world.getSector().complete && world.getSector().currentMission().isComplete()){
- Call.onMissionFinish(world.getSector().completedMissions);
+ for(Tile tile : new ObjectSetIterator<>(state.teams.get(defaultTeam).cores)){
+ Effects.effect(Fx.launch, tile);
}
- //check if all assigned missions are complete
- if(!world.getSector().complete && world.getSector().completedMissions >= world.getSector().missions.size){
- Call.onSectorComplete();
- }
+ Time.runTask(30f, () -> {
+ for(Tile tile : new ObjectSetIterator<>(state.teams.get(defaultTeam).cores)){
+ for(Item item : content.items()){
+ data.addItem(item, tile.entity.items.get(item) / playerGroup.size());
+ }
+ world.removeBlock(tile);
+ }
+ state.launched = true;
+ });
}
@Remote(called = Loc.both)
public static void onGameOver(Team winner){
- threads.runGraphics(() -> ui.restart.show(winner));
+ ui.restart.show(winner);
netClient.setQuiet();
}
- @Remote(called = Loc.server)
- public static void onMissionFinish(int index){
- world.getSector().missions.get(index).onComplete();
- world.getSector().completedMissions = index + 1;
-
- state.mode = world.getSector().currentMission().getMode();
- world.getSector().currentMission().onBegin();
- world.sectors.save();
- }
-
- @Remote(called = Loc.server)
- public static void onSectorComplete(){
- state.mode = GameMode.victory;
-
- world.sectors.completeSector(world.getSector().x, world.getSector().y);
- world.sectors.save();
-
- if(!headless && !Net.client()){
- ui.missions.show(world.getSector());
- }
-
- Events.fire(new SectorCompleteEvent());
- }
-
@Override
public void update(){
- if(Vars.control != null){
- control.runUpdateLogic();
- }
-
if(!state.is(State.menu)){
if(!state.isPaused()){
- Timers.update();
+ Time.update();
- if(!state.mode.disableWaveTimer && !state.mode.disableWaves && !state.gameOver){
- state.wavetime -= Timers.delta();
+ if(state.rules.waves && state.rules.waveTimer && !state.gameOver){
+ state.wavetime = Math.max(state.wavetime - Time.delta(), 0);
}
- if(!Net.client() && state.wavetime <= 0 && !state.mode.disableWaves){
+ if(!Net.client() && state.wavetime <= 0 && state.rules.waves){
runWave();
}
- if(!Entities.defaultGroup().isEmpty())
- throw new RuntimeException("Do not add anything to the default group!");
+ if(!Entities.defaultGroup().isEmpty()){
+ throw new IllegalArgumentException("Do not add anything to the default group!");
+ }
if(!headless){
Entities.update(effectGroup);
@@ -226,7 +188,6 @@ public class Logic extends Module{
}
if(!Net.client() && !world.isInvalidMap()){
- updateSectors();
checkGameOver();
}
}
diff --git a/core/src/io/anuke/mindustry/core/NetClient.java b/core/src/io/anuke/mindustry/core/NetClient.java
index bf124f9be2..3a47eee4ff 100644
--- a/core/src/io/anuke/mindustry/core/NetClient.java
+++ b/core/src/io/anuke/mindustry/core/NetClient.java
@@ -1,17 +1,23 @@
package io.anuke.mindustry.core;
-import com.badlogic.gdx.Gdx;
-import com.badlogic.gdx.graphics.Color;
-import com.badlogic.gdx.utils.Base64Coder;
-import com.badlogic.gdx.utils.IntSet;
-import com.badlogic.gdx.utils.TimeUtils;
import io.anuke.annotations.Annotations.Loc;
import io.anuke.annotations.Annotations.PacketPriority;
import io.anuke.annotations.Annotations.Remote;
import io.anuke.annotations.Annotations.Variant;
+import io.anuke.arc.ApplicationListener;
+import io.anuke.arc.Core;
+import io.anuke.arc.collection.IntSet;
+import io.anuke.mindustry.entities.Entities;
+import io.anuke.mindustry.entities.EntityGroup;
+import io.anuke.arc.graphics.Color;
+import io.anuke.arc.util.Interval;
+import io.anuke.arc.util.Log;
+import io.anuke.arc.util.Time;
+import io.anuke.arc.util.io.ReusableByteArrayInputStream;
+import io.anuke.arc.util.serialization.Base64Coder;
import io.anuke.mindustry.Vars;
import io.anuke.mindustry.core.GameState.State;
-import io.anuke.mindustry.entities.Player;
+import io.anuke.mindustry.entities.type.Player;
import io.anuke.mindustry.entities.traits.BuilderTrait.BuildRequest;
import io.anuke.mindustry.entities.traits.SyncTrait;
import io.anuke.mindustry.entities.traits.TypeTrait;
@@ -25,16 +31,6 @@ import io.anuke.mindustry.net.Packets.*;
import io.anuke.mindustry.net.ValidateException;
import io.anuke.mindustry.world.Tile;
import io.anuke.mindustry.world.modules.ItemModule;
-import io.anuke.ucore.core.Core;
-import io.anuke.ucore.core.Settings;
-import io.anuke.ucore.core.Timers;
-import io.anuke.ucore.entities.Entities;
-import io.anuke.ucore.entities.EntityGroup;
-import io.anuke.ucore.io.ReusableByteArrayInputStream;
-import io.anuke.ucore.modules.Module;
-import io.anuke.ucore.util.Log;
-import io.anuke.ucore.util.Mathf;
-import io.anuke.ucore.util.Timer;
import java.io.DataInputStream;
import java.io.IOException;
@@ -43,12 +39,12 @@ import java.util.zip.InflaterInputStream;
import static io.anuke.mindustry.Vars.*;
-public class NetClient extends Module{
+public class NetClient implements ApplicationListener{
private final static float dataTimeout = 60 * 18;
private final static float playerSyncTime = 2;
public final static float viewScale = 2f;
- private Timer timer = new Timer(5);
+ private Interval timer = new Interval(5);
/**Whether the client is currently connecting.*/
private boolean connecting = false;
/**If true, no message will be shown on disconnect.*/
@@ -58,16 +54,6 @@ public class NetClient extends Module{
/**Last sent client snapshot ID.*/
private int lastSent;
- /**Last snapshot ID recieved.*/
- private int lastSnapshotBaseID = -1;
-
- /**Current snapshot that is being built from chinks.*/
- private byte[] currentSnapshot;
- /**Counter of how many chunks have been recieved.*/
- private int recievedChunkCounter;
- /**ID of snapshot that is currently being constructed.*/
- private int currentSnapshotID = -1;
-
/**List of entities that were removed, and need not be added while syncing.*/
private IntSet removed = new IntSet();
/**Byte stream for reading in snapshots.*/
@@ -84,7 +70,7 @@ public class NetClient extends Module{
reset();
ui.loadfrag.hide();
- ui.loadfrag.show("$text.connecting.data");
+ ui.loadfrag.show("$connecting.data");
ui.loadfrag.setButton(() -> {
ui.loadfrag.hide();
@@ -102,7 +88,7 @@ public class NetClient extends Module{
c.uuid = Platform.instance.getUUID();
if(c.uuid == null){
- ui.showError("$text.invalidid");
+ ui.showError("$invalidid");
ui.loadfrag.hide();
disconnectQuietly();
return;
@@ -114,11 +100,11 @@ public class NetClient extends Module{
Net.handleClient(Disconnect.class, packet -> {
if(quiet) return;
- Timers.runTask(3f, ui.loadfrag::hide);
+ Time.runTask(3f, ui.loadfrag::hide);
state.set(State.menu);
- ui.showError("$text.disconnect");
+ ui.showError("$disconnect");
connecting = false;
Platform.instance.updateRPC();
@@ -168,21 +154,19 @@ public class NetClient extends Module{
netClient.disconnectQuietly();
state.set(State.menu);
- threads.runGraphics(() -> {
- if(!reason.quiet){
- if(reason.extraText() != null){
- ui.showText(reason.toString(), reason.extraText());
- }else{
- ui.showText("$text.disconnect", reason.toString());
- }
+ if(!reason.quiet){
+ if(reason.extraText() != null){
+ ui.showText(reason.toString(), reason.extraText());
+ }else{
+ ui.showText("$disconnect", reason.toString());
}
- ui.loadfrag.hide();
- });
+ }
+ ui.loadfrag.hide();
}
@Remote(variants = Variant.both)
public static void onInfoMessage(String message){
- threads.runGraphics(() -> ui.showText("", message));
+ ui.showText("", message);
}
@Remote(variants = Variant.both)
@@ -193,15 +177,13 @@ public class NetClient extends Module{
ui.chatfrag.clearMessages();
Net.setClientLoaded(false);
- threads.runGraphics(() -> {
- ui.loadfrag.show("$text.connecting.data");
+ ui.loadfrag.show("$connecting.data");
- ui.loadfrag.setButton(() -> {
- ui.loadfrag.hide();
- netClient.connecting = false;
- netClient.quiet = true;
- Net.disconnect();
- });
+ ui.loadfrag.setButton(() -> {
+ ui.loadfrag.hide();
+ netClient.connecting = false;
+ netClient.quiet = true;
+ Net.disconnect();
});
}
@@ -217,97 +199,11 @@ public class NetClient extends Module{
}
@Remote(variants = Variant.one, priority = PacketPriority.low, unreliable = true)
- public static void onSnapshot(byte[] chunk, int snapshotID, short chunkID, int totalLength, int uncompressedLength){
- int totalChunks = Mathf.ceil((float) totalLength / NetServer.maxSnapshotSize);
-
- if(NetServer.debugSnapshots)
- Log.info("Recieved snapshot: len {0} ID {1} chunkID {2} / "+totalChunks+" totalLength {3} bclient-base {4}", chunk.length, snapshotID, chunkID, totalLength, netClient.lastSnapshotBaseID);
-
- //skip snapshot IDs that have already been recieved OR snapshots that are too far in front
- if(snapshotID < netClient.lastSnapshotBaseID){
- if(NetServer.debugSnapshots) Log.info("//SKIP SNAPSHOT");
- return;
- }
-
+ public static void onEntitySnapshot(byte groupID, short amount, short dataLen, byte[] data){
try{
- byte[] snapshot;
-
- //total length exceeds that needed to hold one snapshot, therefore, it is split into chunks
- if(totalLength > NetServer.maxSnapshotSize){
- //total amount of chunks to recieve
-
- //reset status when a new snapshot sending begins
- if(netClient.currentSnapshotID != snapshotID || netClient.currentSnapshot == null){
- netClient.currentSnapshotID = snapshotID;
- netClient.currentSnapshot = new byte[totalLength];
- netClient.recievedChunkCounter = 0;
- }
-
- netClient.recievedChunkCounter++; //update recieved status
- //copy the recieved bytes into the holding array
- System.arraycopy(chunk, 0, netClient.currentSnapshot, chunkID * NetServer.maxSnapshotSize,
- Math.min(NetServer.maxSnapshotSize, totalLength - chunkID * NetServer.maxSnapshotSize));
-
- //when all chunks have been recieved, begin
- if(netClient.recievedChunkCounter >= totalChunks && netClient.currentSnapshot != null){
- snapshot = netClient.currentSnapshot;
- }else{
- return;
- }
- }else{
- snapshot = chunk;
- }
-
- if(NetServer.debugSnapshots)
- Log.info("Finished recieving snapshot ID {0} length {1}", snapshotID, chunk.length);
-
- byte[] result = Net.decompressSnapshot(snapshot, uncompressedLength);
- int length = result.length;
-
- netClient.lastSnapshotBaseID = snapshotID;
-
- //set stream bytes to begin snapshot reading
- netClient.byteStream.setBytes(result, 0, length);
-
- //get data input for reading from the stream
+ netClient.byteStream.setBytes(Net.decompressSnapshot(data, dataLen));
DataInputStream input = netClient.dataStream;
- netClient.readSnapshot(input);
-
- //confirm that snapshot has been recieved
- netClient.lastSnapshotBaseID = snapshotID;
- }catch(Exception e){
- throw new RuntimeException(e);
- }
- }
-
- public void readSnapshot(DataInputStream input) throws IOException{
-
- //read wave info
- state.wavetime = input.readFloat();
- state.wave = input.readInt();
- state.enemies = input.readInt();
-
- byte cores = input.readByte();
- for(int i = 0; i < cores; i++){
- int pos = input.readInt();
- Tile tile = world.tile(pos);
- if(tile != null && tile.entity != null){
- tile.entity.items.read(input);
- }else{
- new ItemModule().read(input);
- }
- }
-
- long timestamp = input.readLong();
-
- byte totalGroups = input.readByte();
- //for each group...
- for(int i = 0; i < totalGroups; i++){
- //read group info
- byte groupID = input.readByte();
- short amount = input.readShort();
-
EntityGroup group = Entities.getGroup(groupID);
//go through each entity
@@ -328,13 +224,41 @@ public class NetClient extends Module{
}
//read the entity
- entity.read(input, timestamp);
+ entity.read(input);
if(add){
entity.add();
netClient.addRemovedEntity(entity.getID());
}
}
+ }catch(IOException e){
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Remote(variants = Variant.one, priority = PacketPriority.low, unreliable = true)
+ public static void onStateSnapshot(float waveTime, int wave, int enemies, short coreDataLen, byte[] coreData){
+ try{
+ state.wavetime = waveTime;
+ state.wave = wave;
+ state.enemies = enemies;
+
+ netClient.byteStream.setBytes(Net.decompressSnapshot(coreData, coreDataLen));
+ DataInputStream input = netClient.dataStream;
+
+ byte cores = input.readByte();
+ for(int i = 0; i < cores; i++){
+ int pos = input.readInt();
+ Tile tile = world.tile(pos);
+ if(tile != null && tile.entity != null){
+ tile.entity.items.read(input);
+ }else{
+ new ItemModule().read(input);
+ }
+ }
+
+ }catch(IOException e){
+ throw new RuntimeException(e);
}
}
@@ -347,12 +271,12 @@ public class NetClient extends Module{
}else if(!connecting){
Net.disconnect();
}else{ //...must be connecting
- timeoutTime += Timers.delta();
+ timeoutTime += Time.delta();
if(timeoutTime > dataTimeout){
Log.err("Failed to load data!");
ui.loadfrag.hide();
quiet = true;
- ui.showError("$text.disconnect.data");
+ ui.showError("$disconnect.data");
Net.disconnect();
timeoutTime = 0f;
}
@@ -369,8 +293,8 @@ public class NetClient extends Module{
ui.loadfrag.hide();
ui.join.hide();
Net.setClientLoaded(true);
- Gdx.app.postRunnable(Call::connectConfirm);
- Timers.runTask(40f, Platform.instance::updateRPC);
+ Core.app.post(Call::connectConfirm);
+ Time.runTask(40f, Platform.instance::updateRPC);
}
private void reset(){
@@ -380,9 +304,6 @@ public class NetClient extends Module{
connecting = true;
quiet = false;
lastSent = 0;
- currentSnapshot = null;
- currentSnapshotID = -1;
- lastSnapshotBaseID = -1;
Entities.clear();
ui.chatfrag.clearMessages();
@@ -416,19 +337,21 @@ public class NetClient extends Module{
Player player = players[0];
BuildRequest[] requests;
+ //limit to 10 to prevent buffer overflows
+ int usedRequests = Math.min(player.getPlaceQueue().size, 10);
- requests = new BuildRequest[player.getPlaceQueue().size];
- for(int i = 0; i < requests.length; i++){
+ requests = new BuildRequest[usedRequests];
+ for(int i = 0; i < usedRequests; i++){
requests[i] = player.getPlaceQueue().get(i);
}
- Call.onClientShapshot(lastSent++, TimeUtils.millis(), player.x, player.y,
+ Call.onClientShapshot(lastSent++, player.x, player.y,
player.pointerX, player.pointerY, player.rotation, player.baseRotation,
- player.getVelocity().x, player.getVelocity().y,
+ player.velocity().x, player.velocity().y,
player.getMineTile(),
player.isBoosting, player.isShooting, requests,
Core.camera.position.x, Core.camera.position.y,
- Core.camera.viewportWidth * Core.camera.zoom * viewScale, Core.camera.viewportHeight * Core.camera.zoom * viewScale);
+ Core.camera.width * viewScale, Core.camera.height * viewScale);
}
if(timer.get(1, 60)){
@@ -437,14 +360,14 @@ public class NetClient extends Module{
}
String getUsid(String ip){
- if(Settings.getString("usid-" + ip, null) != null){
- return Settings.getString("usid-" + ip, null);
+ if(Core.settings.getString("usid-" + ip, null) != null){
+ return Core.settings.getString("usid-" + ip, null);
}else{
byte[] bytes = new byte[8];
new Random().nextBytes(bytes);
String result = new String(Base64Coder.encode(bytes));
- Settings.putString("usid-" + ip, result);
- Settings.save();
+ Core.settings.put("usid-" + ip, result);
+ Core.settings.save();
return result;
}
}
diff --git a/core/src/io/anuke/mindustry/core/NetServer.java b/core/src/io/anuke/mindustry/core/NetServer.java
index a88ea19301..7e0cdbef72 100644
--- a/core/src/io/anuke/mindustry/core/NetServer.java
+++ b/core/src/io/anuke/mindustry/core/NetServer.java
@@ -1,19 +1,30 @@
package io.anuke.mindustry.core;
-import com.badlogic.gdx.graphics.Color;
-import com.badlogic.gdx.graphics.Colors;
-import com.badlogic.gdx.math.Rectangle;
-import com.badlogic.gdx.math.Vector2;
-import com.badlogic.gdx.utils.Array;
-import com.badlogic.gdx.utils.IntMap;
-import com.badlogic.gdx.utils.ObjectSet;
-import com.badlogic.gdx.utils.TimeUtils;
import io.anuke.annotations.Annotations.Loc;
import io.anuke.annotations.Annotations.Remote;
+import io.anuke.arc.ApplicationListener;
+import io.anuke.arc.Events;
+import io.anuke.arc.collection.Array;
+import io.anuke.arc.collection.IntMap;
+import io.anuke.arc.collection.ObjectSet;
+import io.anuke.mindustry.entities.Entities;
+import io.anuke.mindustry.entities.EntityGroup;
+import io.anuke.mindustry.entities.EntityQuery;
+import io.anuke.mindustry.entities.traits.Entity;
+import io.anuke.arc.graphics.Color;
+import io.anuke.arc.graphics.Colors;
+import io.anuke.arc.math.Mathf;
+import io.anuke.arc.math.geom.Rectangle;
+import io.anuke.arc.math.geom.Vector2;
+import io.anuke.arc.util.Log;
+import io.anuke.arc.util.Structs;
+import io.anuke.arc.util.Time;
+import io.anuke.arc.util.io.ByteBufferOutput;
+import io.anuke.arc.util.io.CountableByteArrayOutputStream;
import io.anuke.mindustry.content.Mechs;
-import io.anuke.mindustry.content.blocks.Blocks;
+import io.anuke.mindustry.content.Blocks;
import io.anuke.mindustry.core.GameState.State;
-import io.anuke.mindustry.entities.Player;
+import io.anuke.mindustry.entities.type.Player;
import io.anuke.mindustry.entities.traits.BuilderTrait.BuildRequest;
import io.anuke.mindustry.entities.traits.SyncTrait;
import io.anuke.mindustry.game.EventType.WorldLoadEvent;
@@ -21,35 +32,25 @@ import io.anuke.mindustry.game.Team;
import io.anuke.mindustry.game.Version;
import io.anuke.mindustry.gen.Call;
import io.anuke.mindustry.gen.RemoteReadServer;
-import io.anuke.mindustry.net.*;
+import io.anuke.mindustry.net.Administration;
import io.anuke.mindustry.net.Administration.PlayerInfo;
+import io.anuke.mindustry.net.Net;
+import io.anuke.mindustry.net.NetConnection;
+import io.anuke.mindustry.net.NetworkIO;
import io.anuke.mindustry.net.Packets.*;
import io.anuke.mindustry.world.Tile;
-import io.anuke.ucore.core.Events;
-import io.anuke.ucore.core.Timers;
-import io.anuke.ucore.entities.Entities;
-import io.anuke.ucore.entities.EntityGroup;
-import io.anuke.ucore.entities.EntityQuery;
-import io.anuke.ucore.entities.trait.Entity;
-import io.anuke.ucore.io.ByteBufferOutput;
-import io.anuke.ucore.io.CountableByteArrayOutputStream;
-import io.anuke.ucore.modules.Module;
-import io.anuke.ucore.util.Structs;
-import io.anuke.ucore.util.Log;
-import io.anuke.ucore.util.Mathf;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
-import java.util.Arrays;
import java.util.zip.DeflaterOutputStream;
import static io.anuke.mindustry.Vars.*;
-public class NetServer extends Module{
- public final static int maxSnapshotSize = 2047;
+public class NetServer implements ApplicationListener{
+ public final static int maxSnapshotSize = 430;
public final static boolean debugSnapshots = false;
public final static float maxSnapshotDelay = 200;
@@ -122,7 +123,7 @@ public class NetServer extends Module{
return;
}
- if(TimeUtils.millis() - info.lastKicked < kickDuration){
+ if(Time.millis() - info.lastKicked < kickDuration){
kick(id, KickReason.recentKick);
return;
}
@@ -155,7 +156,7 @@ public class NetServer extends Module{
return;
}
- Log.info("Recieved connect packet for player '{0}' / UUID {1} / IP {2}", packet.name, uuid, connection.address);
+ Log.debug("Recieved connect packet for player '{0}' / UUID {1} / IP {2}", packet.name, uuid, connection.address);
String ip = Net.getConnection(id).address;
@@ -192,7 +193,8 @@ public class NetServer extends Module{
return;
}
- if(state.mode.isPvp){
+ //playing in pvp mode automatically assigns players to teams
+ if(state.rules.pvp){
//find team with minimum amount of players and auto-assign player to that.
Team min = Structs.findMin(Team.all, team -> {
if(state.teams.isActive(team)){
@@ -224,45 +226,6 @@ public class NetServer extends Module{
});
}
- /** Sends a raw byte[] snapshot to a client, splitting up into chunks when needed.*/
- private static void sendSplitSnapshot(int userid, byte[] bytes, int snapshotID, int uncompressedLength){
- if(bytes.length < maxSnapshotSize){
- scheduleSnapshot(() -> Call.onSnapshot(userid, bytes, snapshotID, (short) 0, bytes.length, uncompressedLength));
- }else{
- int remaining = bytes.length;
- int offset = 0;
- int chunkid = 0;
- while(remaining > 0){
- int used = Math.min(remaining, maxSnapshotSize);
- byte[] toSend;
- //re-use sent byte arrays when possible
- if(used == maxSnapshotSize && !debugSnapshots){
- toSend = reusableSnapArray;
- System.arraycopy(bytes, offset, toSend, 0, Math.min(offset + maxSnapshotSize, bytes.length) - offset);
- }else{
- toSend = Arrays.copyOfRange(bytes, offset, Math.min(offset + maxSnapshotSize, bytes.length));
- }
-
- short fchunk = (short)chunkid;
- scheduleSnapshot(() -> Call.onSnapshot(userid, toSend, snapshotID, fchunk, bytes.length, uncompressedLength));
-
- remaining -= used;
- offset += used;
- chunkid++;
- }
- }
- }
-
- private static void scheduleSnapshot(Runnable r){
- if(debugSnapshots){
- if(!Mathf.chance(snapshotDropchance)){
- Timers.run(maxSnapshotDelay / 1000f * 60f, r);
- }
- }else{
- r.run();
- }
- }
-
public void sendWorldData(Player player, int clientID){
ByteArrayOutputStream stream = new ByteArrayOutputStream();
DeflaterOutputStream def = new DeflaterOutputStream(stream);
@@ -271,7 +234,7 @@ public class NetServer extends Module{
data.stream = new ByteArrayInputStream(stream.toByteArray());
Net.sendStream(clientID, data);
- Log.info("Packed {0} compressed bytes of world data.", stream.size());
+ Log.debug("Packed {0} compressed bytes of world data.", stream.size());
}
public static void onDisconnect(Player player){
@@ -296,7 +259,7 @@ public class NetServer extends Module{
@Remote(targets = Loc.client, unreliable = true)
public static void onClientShapshot(
Player player,
- int snapshotID, long sent,
+ int snapshotID,
float x, float y,
float pointerX, float pointerY,
float rotation, float baseRotation,
@@ -309,16 +272,16 @@ public class NetServer extends Module{
NetConnection connection = player.con;
if(connection == null || snapshotID < connection.lastRecievedClientSnapshot) return;
- boolean verifyPosition = !player.isDead() && netServer.admins.getStrict() && headless && player.getCarrier() == null;
+ boolean verifyPosition = !player.isDead() && netServer.admins.getStrict() && headless;
- if(connection.lastRecievedClientTime == 0) connection.lastRecievedClientTime = TimeUtils.millis() - 16;
+ if(connection.lastRecievedClientTime == 0) connection.lastRecievedClientTime = Time.millis() - 16;
connection.viewX = viewX;
connection.viewY = viewY;
connection.viewWidth = viewWidth;
connection.viewHeight = viewHeight;
- long elapsed = TimeUtils.timeSinceMillis(connection.lastRecievedClientTime);
+ long elapsed = Time.timeSinceMillis(connection.lastRecievedClientTime);
float maxSpeed = boosting && !player.mech.flying ? player.mech.boostSpeed : player.mech.speed;
float maxMove = elapsed / 1000f * 60f * Math.min(compound(maxSpeed, player.mech.drag) * 1.25f, player.mech.maxSpeed * 1.1f);
@@ -333,7 +296,7 @@ public class NetServer extends Module{
//auto-skip done requests
if(req.breaking && world.tile(req.x, req.y).block() == Blocks.air){
continue;
- }else if(!req.breaking && world.tile(req.x, req.y).block() == req.recipe.result && (!req.recipe.result.rotate || world.tile(req.x, req.y).getRotation() == req.rotation)){
+ }else if(!req.breaking && world.tile(req.x, req.y).block() == req.block && (!req.block.rotate || world.tile(req.x, req.y).getRotation() == req.rotation)){
continue;
}
player.getPlaceQueue().addLast(req);
@@ -357,7 +320,7 @@ public class NetServer extends Module{
player.y = prevy;
newx = x;
newy = y;
- }else if(Vector2.dst(x, y, newx, newy) > correctDist){
+ }else if(Mathf.dst(x, y, newx, newy) > correctDist){
Call.onPositionSet(player.con.id, newx, newy); //teleport and correct position when necessary
}
@@ -366,24 +329,24 @@ public class NetServer extends Module{
player.y = prevy;
//set interpolator target to *new* position so it moves toward it
- player.getInterpolator().read(player.x, player.y, newx, newy, sent, rotation, baseRotation);
- player.getVelocity().set(xVelocity, yVelocity); //only for visual calculation purposes, doesn't actually update the player
+ player.getInterpolator().read(player.x, player.y, newx, newy, rotation, baseRotation);
+ player.velocity().set(xVelocity, yVelocity); //only for visual calculation purposes, doesn't actually update the player
connection.lastRecievedClientSnapshot = snapshotID;
- connection.lastRecievedClientTime = TimeUtils.millis();
+ connection.lastRecievedClientTime = Time.millis();
}
@Remote(targets = Loc.client, called = Loc.server)
public static void onAdminRequest(Player player, Player other, AdminAction action){
if(!player.isAdmin){
- Log.err("ACCESS DENIED: Player {0} / {1} attempted to perform admin action without proper security access.",
+ Log.warn("ACCESS DENIED: Player {0} / {1} attempted to perform admin action without proper security access.",
player.name, player.con.address);
return;
}
if(other == null || ((other.isAdmin && !player.isLocal) && other != player)){
- Log.err("{0} attempted to perform admin action on nonexistant or admin player.", player.name);
+ Log.warn("{0} attempted to perform admin action on nonexistant or admin player.", player.name);
return;
}
@@ -420,7 +383,7 @@ public class NetServer extends Module{
}
public boolean isWaitingForPlayers(){
- if(state.mode.isPvp){
+ if(state.rules.pvp){
int used = 0;
for(Team t : Team.all){
if(playerGroup.count(p -> p.getTeam() == t) > 0){
@@ -436,8 +399,8 @@ public class NetServer extends Module{
if(!headless && !closing && Net.server() && state.is(State.menu)){
closing = true;
- threads.runGraphics(() -> ui.loadfrag.show("$text.server.closing"));
- Timers.runTask(5f, () -> {
+ ui.loadfrag.show("$server.closing");
+ Time.runTask(5f, () -> {
Net.closeServer();
ui.loadfrag.hide();
closing = false;
@@ -469,45 +432,34 @@ public class NetServer extends Module{
if(player != null && (reason == KickReason.kick || reason == KickReason.banned) && player.uuid != null){
PlayerInfo info = admins.getInfo(player.uuid);
info.timesKicked++;
- info.lastKicked = TimeUtils.millis();
+ info.lastKicked = Time.millis();
}
Call.onKick(connection, reason);
- Timers.runTask(2f, con::close);
+ Time.runTask(2f, con::close);
admins.save();
}
- public void writeSnapshot(Player player, DataOutputStream dataStream) throws IOException{
- viewport.setSize(player.con.viewWidth, player.con.viewHeight).setCenter(player.con.viewX, player.con.viewY);
-
- //write wave datas
- dataStream.writeFloat(state.wavetime);
- dataStream.writeInt(state.wave);
- dataStream.writeInt(state.enemies());
-
+ public void writeSnapshot(Player player) throws IOException{
+ syncStream.reset();
ObjectSet cores = state.teams.get(player.getTeam()).cores;
dataStream.writeByte(cores.size);
- //write all core inventory data
for(Tile tile : cores){
dataStream.writeInt(tile.pos());
tile.entity.items.write(dataStream);
}
- //write timestamp
- dataStream.writeLong(TimeUtils.millis());
+ dataStream.close();
+ byte[] stateBytes = syncStream.toByteArray();
- int totalGroups = 0;
+ //write basic state data.
+ Call.onStateSnapshot(player.con.id, state.wavetime, state.wave, state.enemies, (short)stateBytes.length, Net.compressSnapshot(stateBytes));
- for(EntityGroup> group : Entities.getAllGroups()){
- if(!group.isEmpty() && (group.all().get(0) instanceof SyncTrait)) totalGroups++;
- }
-
- //write total amount of serializable groups
- dataStream.writeByte(totalGroups);
+ viewport.setSize(player.con.viewWidth, player.con.viewHeight).setCenter(player.con.viewX, player.con.viewY);
//check for syncable groups
for(EntityGroup> group : Entities.getAllGroups()){
@@ -535,15 +487,32 @@ public class NetServer extends Module{
}
}
- //write group ID + group size
- dataStream.writeByte(group.getID());
- dataStream.writeShort(returnArray.size);
+ syncStream.reset();
+
+ int sent = 0;
for(Entity entity : returnArray){
//write all entities now
dataStream.writeInt(entity.getID()); //write id
dataStream.writeByte(((SyncTrait) entity).getTypeID()); //write type ID
((SyncTrait) entity).write(dataStream); //write entity
+
+ sent ++;
+
+ if(syncStream.position() > maxSnapshotSize){
+ dataStream.close();
+ byte[] syncBytes = syncStream.toByteArray();
+ Call.onEntitySnapshot(player.con.id, (byte)group.getID(), (short)sent, (short)syncBytes.length, Net.compressSnapshot(syncBytes));
+ sent = 0;
+ syncStream.reset();
+ }
+ }
+
+ if(sent > 0){
+ dataStream.close();
+
+ byte[] syncBytes = syncStream.toByteArray();
+ Call.onEntitySnapshot(player.con.id, (byte)group.getID(), (short)sent, (short)syncBytes.length, Net.compressSnapshot(syncBytes));
}
}
}
@@ -617,21 +586,7 @@ public class NetServer extends Module{
if(!player.timer.get(Player.timerSync, serverSyncTime) || !connection.hasConnected) continue;
- //reset stream to begin writing
- Timers.mark();
- syncStream.reset();
-
- writeSnapshot(player, dataStream);
-
- dataStream.close();
-
- byte[] bytes = syncStream.toByteArray();
- int uncompressed = bytes.length;
- bytes = Net.compressSnapshot(bytes);
- int snapid = connection.lastSentSnapshotID ++;
-
- if(debugSnapshots) Log.info("Sent snapshot: {0} bytes.", bytes.length);
- sendSplitSnapshot(connection.id, bytes, snapid, uncompressed);
+ writeSnapshot(player);
}
}catch(IOException e){
diff --git a/core/src/io/anuke/mindustry/core/Platform.java b/core/src/io/anuke/mindustry/core/Platform.java
index 0064c066c3..999c57fa7f 100644
--- a/core/src/io/anuke/mindustry/core/Platform.java
+++ b/core/src/io/anuke/mindustry/core/Platform.java
@@ -1,15 +1,11 @@
package io.anuke.mindustry.core;
-import com.badlogic.gdx.Gdx;
-import com.badlogic.gdx.Input.Keys;
-import com.badlogic.gdx.files.FileHandle;
-import com.badlogic.gdx.utils.Base64Coder;
-import io.anuke.ucore.core.Core;
-import io.anuke.ucore.core.Settings;
-import io.anuke.ucore.core.Timers;
-import io.anuke.ucore.function.Consumer;
-import io.anuke.ucore.scene.ui.Dialog;
-import io.anuke.ucore.scene.ui.TextField;
+import io.anuke.arc.Core;
+import io.anuke.arc.Input.TextInput;
+import io.anuke.arc.files.FileHandle;
+import io.anuke.arc.function.Consumer;
+import io.anuke.arc.scene.ui.TextField;
+import io.anuke.arc.util.serialization.Base64Coder;
import java.util.Random;
@@ -28,46 +24,20 @@ public abstract class Platform {
if(!mobile) return; //this is mobile only, desktop doesn't need dialogs
field.tapped(() -> {
- Dialog dialog = new Dialog("", "dialog");
- dialog.setFillParent(true);
- dialog.content().top();
- dialog.content().defaults().height(65f);
-
- TextField[] use = {null};
-
- dialog.content().addImageButton("icon-copy", "clear", 16*3, () -> use[0].copy())
- .visible(() -> !use[0].getSelection().isEmpty()).width(65f);
-
- dialog.content().addImageButton("icon-paste", "clear", 16*3, () ->
- use[0].paste(Gdx.app.getClipboard().getContents(), false))
- .visible(() -> Gdx.app.getClipboard() != null && Gdx.app.getClipboard().getContents() != null && !Gdx.app.getClipboard().getContents().isEmpty()).width(65f);
-
- TextField to = dialog.content().addField(field.getText(), t-> {}).pad(15).width(250f).get();
- to.setMaxLength(maxLength);
- to.keyDown(Keys.ENTER, () -> dialog.content().find("okb").fireClick());
-
- use[0] = to;
-
- dialog.content().addButton("$text.ok", () -> {
+ TextInput input = new TextInput();
+ input.text = field.getText();
+ input.maxLength = maxLength;
+ input.accepted = text -> {
field.clearText();
- field.appendText(to.getText());
+ field.appendText(text);
field.change();
- dialog.hide();
- Gdx.input.setOnscreenKeyboardVisible(false);
- }).width(90f).name("okb");
-
- dialog.show();
- Timers.runTask(1f, () -> {
- to.setCursorPosition(to.getText().length());
- Core.scene.setKeyboardFocus(to);
- Gdx.input.setOnscreenKeyboardVisible(true);
- });
+ Core.input.setOnscreenKeyboardVisible(false);
+ };
+ Core.input.getTextInput(input);
});
}
/**Update discord RPC.*/
public void updateRPC(){}
- /**Called when the game is exited.*/
- public void onGameExit(){}
/**Open donation dialog. Currently android only.*/
public void openDonations(){}
/**Whether donating is supported.*/
@@ -76,13 +46,13 @@ public abstract class Platform {
}
/**Must be a base64 string 8 bytes in length.*/
public String getUUID(){
- String uuid = Settings.getString("uuid", "");
+ String uuid = Core.settings.getString("uuid", "");
if(uuid.isEmpty()){
byte[] result = new byte[8];
new Random().nextBytes(result);
uuid = new String(Base64Coder.encode(result));
- Settings.putString("uuid", uuid);
- Settings.save();
+ Core.settings.put("uuid", uuid);
+ Core.settings.save();
return uuid;
}
return uuid;
diff --git a/core/src/io/anuke/mindustry/core/Renderer.java b/core/src/io/anuke/mindustry/core/Renderer.java
index df097fc0f9..cb33334a45 100644
--- a/core/src/io/anuke/mindustry/core/Renderer.java
+++ b/core/src/io/anuke/mindustry/core/Renderer.java
@@ -1,85 +1,80 @@
package io.anuke.mindustry.core;
-import com.badlogic.gdx.Gdx;
-import com.badlogic.gdx.files.FileHandle;
-import com.badlogic.gdx.graphics.Color;
-import com.badlogic.gdx.graphics.Pixmap;
-import com.badlogic.gdx.graphics.PixmapIO;
-import com.badlogic.gdx.graphics.g2d.SpriteBatch;
-import com.badlogic.gdx.math.Rectangle;
-import com.badlogic.gdx.math.Vector2;
-import com.badlogic.gdx.utils.BufferUtils;
-import com.badlogic.gdx.utils.ScreenUtils;
-import com.badlogic.gdx.utils.TimeUtils;
-import io.anuke.mindustry.content.fx.Fx;
+import io.anuke.arc.ApplicationListener;
+import io.anuke.arc.Core;
+import io.anuke.arc.function.Consumer;
+import io.anuke.arc.function.Predicate;
+import io.anuke.arc.graphics.Camera;
+import io.anuke.arc.graphics.Color;
+import io.anuke.arc.graphics.g2d.Draw;
+import io.anuke.arc.graphics.g2d.Lines;
+import io.anuke.arc.graphics.g2d.SpriteBatch;
+import io.anuke.arc.graphics.glutils.FrameBuffer;
+import io.anuke.arc.math.Mathf;
+import io.anuke.arc.math.geom.Rectangle;
+import io.anuke.arc.math.geom.Vector2;
+import io.anuke.arc.util.ScreenRecorder;
+import io.anuke.arc.util.Time;
+import io.anuke.arc.util.pooling.Pools;
+import io.anuke.mindustry.content.Fx;
import io.anuke.mindustry.core.GameState.State;
-import io.anuke.mindustry.entities.Player;
-import io.anuke.mindustry.entities.TileEntity;
-import io.anuke.mindustry.entities.Unit;
+import io.anuke.mindustry.entities.Effects;
+import io.anuke.mindustry.entities.EntityDraw;
+import io.anuke.mindustry.entities.EntityGroup;
import io.anuke.mindustry.entities.effect.GroundEffectEntity;
import io.anuke.mindustry.entities.effect.GroundEffectEntity.GroundEffect;
+import io.anuke.mindustry.entities.impl.EffectEntity;
import io.anuke.mindustry.entities.traits.BelowLiquidTrait;
-import io.anuke.mindustry.entities.units.BaseUnit;
+import io.anuke.mindustry.entities.traits.DrawTrait;
+import io.anuke.mindustry.entities.traits.Entity;
+import io.anuke.mindustry.entities.type.BaseUnit;
+import io.anuke.mindustry.entities.type.Player;
+import io.anuke.mindustry.entities.type.TileEntity;
+import io.anuke.mindustry.entities.type.Unit;
import io.anuke.mindustry.game.Team;
import io.anuke.mindustry.graphics.*;
import io.anuke.mindustry.world.blocks.defense.ForceProjector.ShieldEntity;
-import io.anuke.ucore.core.Core;
-import io.anuke.ucore.core.Effects;
-import io.anuke.ucore.core.Graphics;
-import io.anuke.ucore.core.Settings;
-import io.anuke.ucore.entities.EntityDraw;
-import io.anuke.ucore.entities.EntityGroup;
-import io.anuke.ucore.entities.impl.EffectEntity;
-import io.anuke.ucore.entities.trait.DrawTrait;
-import io.anuke.ucore.entities.trait.Entity;
-import io.anuke.ucore.function.Consumer;
-import io.anuke.ucore.function.Predicate;
-import io.anuke.ucore.graphics.Draw;
-import io.anuke.ucore.graphics.Lines;
-import io.anuke.ucore.graphics.Surface;
-import io.anuke.ucore.modules.RendererModule;
-import io.anuke.ucore.scene.utils.Cursors;
-import io.anuke.ucore.util.Bundles;
-import io.anuke.ucore.util.Mathf;
-import io.anuke.ucore.util.Pooling;
-import io.anuke.ucore.util.Translator;
+import static io.anuke.arc.Core.*;
import static io.anuke.mindustry.Vars.*;
-import static io.anuke.ucore.core.Core.batch;
-import static io.anuke.ucore.core.Core.camera;
-public class Renderer extends RendererModule{
- public final Surface effectSurface;
+public class Renderer implements ApplicationListener{
public final BlockRenderer blocks = new BlockRenderer();
public final MinimapRenderer minimap = new MinimapRenderer();
public final OverlayRenderer overlays = new OverlayRenderer();
- public final FogRenderer fog = new FogRenderer();
- private int targetscale = baseCameraScale;
+ private FrameBuffer shieldBuffer = new FrameBuffer(2, 2);
+ private Color clearColor;
+ private float targetscale = io.anuke.arc.scene.ui.layout.Unit.dp.scl(4);
+ private float camerascale = targetscale;
private Rectangle rect = new Rectangle(), rect2 = new Rectangle();
- private Vector2 avgPosition = new Translator();
+ private Vector2 avgPosition = new Vector2();
+ private float shakeIntensity, shaketime;
public Renderer(){
- Core.batch = new SpriteBatch(4096);
-
+ batch = new SpriteBatch(4096);
+ camera = new Camera();
Lines.setCircleVertices(14);
-
Shaders.init();
- Core.cameraScale = baseCameraScale;
+ Effects.setScreenShakeProvider((intensity, duration) -> {
+ shakeIntensity = Math.max(intensity, shakeIntensity);
+ shaketime = Math.max(shaketime, duration);
+ });
+
Effects.setEffectProvider((effect, color, x, y, rotation, data) -> {
if(effect == Fx.none) return;
- if(Settings.getBool("effects")){
- Rectangle view = rect.setSize(camera.viewportWidth, camera.viewportHeight)
+ if(Core.settings.getBool("effects")){
+ Rectangle view = rect.setSize(camera.width, camera.height)
.setCenter(camera.position.x, camera.position.y);
Rectangle pos = rect2.setSize(effect.size).setCenter(x, y);
if(view.overlaps(pos)){
if(!(effect instanceof GroundEffect)){
- EffectEntity entity = Pooling.obtain(EffectEntity.class, EffectEntity::new);
+ EffectEntity entity = Pools.obtain(EffectEntity.class, EffectEntity::new);
entity.effect = effect;
- entity.color = color;
+ entity.color.set(color);
entity.rotation = rotation;
entity.data = data;
entity.id++;
@@ -87,11 +82,11 @@ public class Renderer extends RendererModule{
if(data instanceof Entity){
entity.setParent((Entity) data);
}
- threads.runGraphics(() -> effectGroup.add(entity));
+ effectGroup.add(entity);
}else{
- GroundEffectEntity entity = Pooling.obtain(GroundEffectEntity.class, GroundEffectEntity::new);
+ GroundEffectEntity entity = Pools.obtain(GroundEffectEntity.class, GroundEffectEntity::new);
entity.effect = effect;
- entity.color = color;
+ entity.color.set(color);
entity.rotation = rotation;
entity.id++;
entity.data = data;
@@ -99,30 +94,13 @@ public class Renderer extends RendererModule{
if(data instanceof Entity){
entity.setParent((Entity) data);
}
- threads.runGraphics(() -> groundEffectGroup.add(entity));
+ groundEffectGroup.add(entity);
}
}
}
});
- Cursors.cursorScaling = 3;
- Cursors.outlineColor = Color.valueOf("444444");
-
- Cursors.arrow = Cursors.loadCursor("cursor");
- Cursors.hand = Cursors.loadCursor("hand");
- Cursors.ibeam = Cursors.loadCursor("ibar");
- Cursors.restoreCursor();
- Cursors.loadCustom("drill");
- Cursors.loadCustom("unload");
-
clearColor = new Color(0f, 0f, 0f, 1f);
-
- effectSurface = Graphics.createSurface(Core.cameraScale);
- pixelSurface = Graphics.createSurface(Core.cameraScale);
- }
-
- @Override
- public void init(){
}
@Override
@@ -130,113 +108,80 @@ public class Renderer extends RendererModule{
//TODO hack, find source of this bug
Color.WHITE.set(1f, 1f, 1f, 1f);
- if(Core.cameraScale != targetscale){
- float targetzoom = (float) Core.cameraScale / targetscale;
- camera.zoom = Mathf.lerpDelta(camera.zoom, targetzoom, 0.2f);
-
- if(Mathf.in(camera.zoom, targetzoom, 0.005f)){
- camera.zoom = 1f;
- Graphics.setCameraScale(targetscale);
- for(Player player : players){
- control.input(player.playerIndex).resetCursor();
- }
- }
- }else{
- camera.zoom = Mathf.lerpDelta(camera.zoom, 1f, 0.2f);
- }
+ camerascale = Mathf.lerpDelta(camerascale, targetscale, 0.1f);
+ camera.width = graphics.getWidth() / camerascale;
+ camera.height = graphics.getHeight() / camerascale;
if(state.is(State.menu)){
- Graphics.clear(Color.BLACK);
+ graphics.clear(Color.BLACK);
}else{
Vector2 position = averagePosition();
if(players[0].isDead()){
TileEntity core = players[0].getClosestCore();
- if(core != null && players[0].spawner == Unit.noSpawner){
- smoothCamera(core.x, core.y, 0.08f);
+ if(core != null && players[0].spawner == null){
+ camera.position.lerpDelta(core.x, core.y, 0.08f);
}else{
- smoothCamera(position.x + 0.0001f, position.y + 0.0001f, 0.08f);
+ camera.position.lerpDelta(position, 0.08f);
}
}else if(!mobile){
- setCamera(position.x + 0.0001f, position.y + 0.0001f);
+ camera.position.lerpDelta(position, 0.08f);
}
- camera.position.x = Mathf.clamp(camera.position.x, -tilesize / 2f, world.width() * tilesize - tilesize / 2f);
- camera.position.y = Mathf.clamp(camera.position.y, -tilesize / 2f, world.height() * tilesize - tilesize / 2f);
- float prex = camera.position.x, prey = camera.position.y;
updateShake(0.75f);
- float deltax = camera.position.x - prex, deltay = camera.position.y - prey;
- float lastx = camera.position.x, lasty = camera.position.y;
-
- if(snapCamera){
- camera.position.set((int) camera.position.x, (int) camera.position.y, 0);
- }
-
- if(Gdx.graphics.getHeight() / Core.cameraScale % 2 == 1){
- camera.position.add(0, -0.5f, 0);
- }
-
- if(Gdx.graphics.getWidth() / Core.cameraScale % 2 == 1){
- camera.position.add(-0.5f, 0, 0);
- }
-
draw();
-
- camera.position.set(lastx - deltax, lasty - deltay, 0);
}
if(!ui.chatfrag.chatOpen()){
- renderer.record(); //this only does something if GdxGifRecorder is on the class path, which it usually isn't
+ ScreenRecorder.record(); //this only does something if CoreGifRecorder is on the class path, which it usually isn't
+ }
+ }
+
+ void updateShake(float scale){
+ if(shaketime > 0){
+ float intensity = shakeIntensity * (settings.getInt("screenshake", 4) / 4f) * scale;
+ camera.position.add(Mathf.range(intensity), Mathf.range(intensity));
+ shakeIntensity -= 0.25f * Time.delta();
+ shaketime -= Time.delta();
+ shakeIntensity = Mathf.clamp(shakeIntensity, 0f, 100f);
+ }else{
+ shakeIntensity = 0f;
}
}
- @Override
public void draw(){
camera.update();
- if(Float.isNaN(Core.camera.position.x) || Float.isNaN(Core.camera.position.y)){
- Core.camera.position.x = players[0].x;
- Core.camera.position.y = players[0].y;
+
+ if(Float.isNaN(camera.position.x) || Float.isNaN(camera.position.y)){
+ camera.position.x = players[0].x;
+ camera.position.y = players[0].y;
}
- Graphics.clear(clearColor);
+ graphics.clear(clearColor);
- batch.setProjectionMatrix(camera.combined);
+ Draw.proj(camera.projection());
- Graphics.surface(pixelSurface, false);
-
- Graphics.clear(clearColor);
-
- blocks.drawFloor();
+ blocks.floor.drawFloor();
drawAndInterpolate(groundEffectGroup, e -> e instanceof BelowLiquidTrait);
drawAndInterpolate(puddleGroup);
drawAndInterpolate(groundEffectGroup, e -> !(e instanceof BelowLiquidTrait));
blocks.processBlocks();
+
blocks.drawShadows();
- for(Team team : Team.all){
- if(blocks.isTeamShown(team)){
- boolean outline = team != players[0].getTeam() && team != Team.none;
- if(outline){
- Shaders.outline.color.set(team.color);
- Shaders.outline.color.a = 0.8f;
- Graphics.beginShaders(Shaders.outline);
- }
+ blocks.floor.beginDraw();
+ blocks.floor.drawLayer(CacheLayer.walls);
+ blocks.floor.endDraw();
- blocks.drawTeamBlocks(Layer.block, team);
+ blocks.drawBlocks(Layer.block);
+ blocks.drawFog();
- if(outline){
- Graphics.endShaders();
- }
- }
- }
- blocks.skipLayer(Layer.block);
-
- Graphics.shader(Shaders.blockbuild, false);
+ Draw.shader(Shaders.blockbuild, true);
blocks.drawBlocks(Layer.placement);
- Graphics.shader();
+ Draw.shader();
blocks.drawBlocks(Layer.overlay);
@@ -255,39 +200,38 @@ public class Renderer extends RendererModule{
overlays.drawBottom();
drawAndInterpolate(playerGroup, p -> true, Player::drawBuildRequests);
- Graphics.beginShaders(Shaders.shield);
- EntityDraw.draw(shieldGroup);
- EntityDraw.drawWith(shieldGroup, shield -> true, shield -> ((ShieldEntity)shield).drawOver());
- Draw.color(Palette.accent);
- Graphics.endShaders();
- Draw.color();
+ if(EntityDraw.countInBounds(shieldGroup) > 0){
+ if(graphics.getWidth() >= 2 && graphics.getHeight() >= 2 && (shieldBuffer.getWidth() != graphics.getWidth() || shieldBuffer.getHeight() != graphics.getHeight())){
+ shieldBuffer.resize(graphics.getWidth(), graphics.getHeight());
+ }
+
+ Draw.flush();
+ shieldBuffer.begin();
+ graphics.clear(Color.CLEAR);
+ EntityDraw.draw(shieldGroup);
+ EntityDraw.drawWith(shieldGroup, shield -> true, shield -> ((ShieldEntity)shield).drawOver());
+ Draw.flush();
+ shieldBuffer.end();
+ Draw.shader(Shaders.shield);
+ Draw.color(Pal.accent);
+ Draw.rect(Draw.wrap(shieldBuffer.getTexture()), camera.position.x, camera.position.y, camera.width, -camera.height);
+ Draw.color();
+ Draw.shader();
+ }
overlays.drawTop();
- if(showFog){
- Graphics.surface();
- }else{
- Graphics.flushSurface();
- }
-
- batch.end();
-
- if(showFog){
- fog.draw();
- }
-
- Graphics.beginCam();
EntityDraw.setClip(false);
drawAndInterpolate(playerGroup, p -> !p.isDead() && !p.isLocal, Player::drawName);
EntityDraw.setClip(true);
- Graphics.end();
+
Draw.color();
+ Draw.flush();
}
private void drawFlyerShadows(){
- Graphics.surface(effectSurface, true, false);
-
float trnsX = -12, trnsY = -13;
+ Draw.color(0, 0, 0, 0.15f);
for(EntityGroup extends BaseUnit> group : unitGroups){
if(!group.isEmpty()){
@@ -299,8 +243,6 @@ public class Renderer extends RendererModule{
drawAndInterpolate(playerGroup, unit -> unit.isFlying() && !unit.isDead(), player -> player.drawShadow(trnsX, trnsY));
}
- Draw.color(0, 0, 0, 0.15f);
- Graphics.flushSurface();
Draw.color();
}
@@ -312,18 +254,18 @@ public class Renderer extends RendererModule{
playerGroup.count(p -> p.isFlying() == flying && p.getTeam() == team) == 0 && flying) continue;
drawAndInterpolate(unitGroups[team.ordinal()], u -> u.isFlying() == flying && !u.isDead(), Unit::drawUnder);
- drawAndInterpolate(playerGroup, p -> p.isFlying() == flying && p.getTeam() == team, Unit::drawUnder);
+ drawAndInterpolate(playerGroup, p -> p.isFlying() == flying && p.getTeam() == team && !p.isDead(), Unit::drawUnder);
Shaders.outline.color.set(team.color);
Shaders.mix.color.set(Color.WHITE);
- Graphics.beginShaders(Shaders.outline);
- Graphics.shader(Shaders.mix, true);
+ //Graphics.beginShaders(Shaders.outline);
+ Draw.shader(Shaders.mix, true);
drawAndInterpolate(unitGroups[team.ordinal()], u -> u.isFlying() == flying && !u.isDead(), Unit::drawAll);
drawAndInterpolate(playerGroup, p -> p.isFlying() == flying && p.getTeam() == team, Unit::drawAll);
- Graphics.shader();
+ Draw.shader();
blocks.drawTeamBlocks(Layer.turret, team);
- Graphics.endShaders();
+ //Graphics.endShaders();
drawAndInterpolate(unitGroups[team.ordinal()], u -> u.isFlying() == flying && !u.isDead(), Unit::drawOver);
drawAndInterpolate(playerGroup, p -> p.isFlying() == flying && p.getTeam() == team, Unit::drawOver);
@@ -342,20 +284,8 @@ public class Renderer extends RendererModule{
EntityDraw.drawWith(group, toDraw, drawer);
}
- @Override
- public void resize(int width, int height){
- float lastX = camera.position.x, lastY = camera.position.y;
- super.resize(width, height);
- for(Player player : players){
- control.input(player.playerIndex).resetCursor();
- }
- camera.update();
- camera.position.set(lastX, lastY, 0f);
- }
-
- @Override
- public void dispose(){
- fog.dispose();
+ public float cameraScale(){
+ return camerascale;
}
public Vector2 averagePosition(){
@@ -367,43 +297,35 @@ public class Renderer extends RendererModule{
return avgPosition;
}
- public void setCameraScale(int amount){
- targetscale = amount;
+ public void scaleCamera(float amount){
+ targetscale += amount;
clampScale();
- //scale up all surfaces in preparation for the zoom
- for(Surface surface : Graphics.getSurfaces()){
- surface.setScale(targetscale);
- }
- }
-
- public void scaleCamera(int amount){
- setCameraScale(targetscale + amount);
}
public void clampScale(){
- float s = io.anuke.ucore.scene.ui.layout.Unit.dp.scl(1f);
- targetscale = Mathf.clamp(targetscale, Math.round(s * 2), Math.round(s * 5));
+ float s = io.anuke.arc.scene.ui.layout.Unit.dp.scl(1f);
+ targetscale = Mathf.clamp(targetscale, s * 2.5f, Math.round(s * 7));
}
public void takeMapScreenshot(){
- float vpW = Core.camera.viewportWidth, vpH = Core.camera.viewportHeight;
+ //TODO fix/implement
+ /*
+ float vpW = camera.width, vpH = camera.height;
int w = world.width()*tilesize, h = world.height()*tilesize;
int pw = pixelSurface.width(), ph = pixelSurface.height();
- showFog = false;
disableUI = true;
pixelSurface.setSize(w, h, true);
Graphics.getEffectSurface().setSize(w, h, true);
- Core.camera.viewportWidth = w;
- Core.camera.viewportHeight = h;
- Core.camera.position.x = w/2f + tilesize/2f;
- Core.camera.position.y = h/2f + tilesize/2f;
+ camera.width = w;
+ camera.height = h;
+ camera.position.x = w/2f + tilesize/2f;
+ camera.position.y = h/2f + tilesize/2f;
draw();
- showFog = true;
disableUI = false;
- Core.camera.viewportWidth = vpW;
- Core.camera.viewportHeight = vpH;
+ camera.width = vpW;
+ camera.height = vpH;
pixelSurface.getBuffer().begin();
byte[] lines = ScreenUtils.getFrameBufferPixels(0, 0, w, h, true);
@@ -415,14 +337,14 @@ public class Renderer extends RendererModule{
Pixmap fullPixmap = new Pixmap(w, h, Pixmap.Format.RGBA8888);
BufferUtils.copy(lines, 0, fullPixmap.getPixels(), lines.length);
- FileHandle file = screenshotDirectory.child("screenshot-" + TimeUtils.millis() + ".png");
+ FileHandle file = screenshotDirectory.child("screenshot-" + Time.millis() + ".png");
PixmapIO.writePNG(file, fullPixmap);
fullPixmap.dispose();
pixelSurface.setSize(pw, ph, false);
Graphics.getEffectSurface().setSize(pw, ph, false);
- ui.showInfoFade(Bundles.format("text.screenshot", file.toString()));
+ ui.showInfoFade(Core.bundle.format("screenshot", file.toString()));*/
}
}
diff --git a/core/src/io/anuke/mindustry/core/ThreadHandler.java b/core/src/io/anuke/mindustry/core/ThreadHandler.java
deleted file mode 100644
index 700b816a92..0000000000
--- a/core/src/io/anuke/mindustry/core/ThreadHandler.java
+++ /dev/null
@@ -1,54 +0,0 @@
-package io.anuke.mindustry.core;
-
-import com.badlogic.gdx.Gdx;
-import com.badlogic.gdx.utils.TimeUtils;
-import io.anuke.ucore.core.Settings;
-import io.anuke.ucore.core.Timers;
-
-public class ThreadHandler{
- private long lastFrameTime;
-
- public ThreadHandler(){
- Timers.setDeltaProvider(() -> {
- float result = Gdx.graphics.getDeltaTime() * 60f;
- return Float.isNaN(result) || Float.isInfinite(result) ? 1f : Math.min(result, 60f / 10f);
- });
- }
-
- public void run(Runnable r){
- r.run();
- }
-
- public void runGraphics(Runnable r){
- r.run();
- }
-
- public void runDelay(Runnable r){
- Gdx.app.postRunnable(r);
- }
-
- public long getFrameID(){
- return Gdx.graphics.getFrameId();
- }
-
- public void handleBeginRender(){
- lastFrameTime = TimeUtils.millis();
- }
-
- public void handleEndRender(){
- int fpsCap = Settings.getInt("fpscap", 125);
-
- if(fpsCap <= 120){
- long target = 1000/fpsCap;
- long elapsed = TimeUtils.timeSinceMillis(lastFrameTime);
- if(elapsed < target){
- try{
- Thread.sleep(target - elapsed);
- }catch(InterruptedException e){
- e.printStackTrace();
- }
- }
- }
- }
-
-}
diff --git a/core/src/io/anuke/mindustry/core/UI.java b/core/src/io/anuke/mindustry/core/UI.java
index 27e8fd3569..85cf266f77 100644
--- a/core/src/io/anuke/mindustry/core/UI.java
+++ b/core/src/io/anuke/mindustry/core/UI.java
@@ -1,51 +1,54 @@
package io.anuke.mindustry.core;
-import com.badlogic.gdx.Gdx;
-import com.badlogic.gdx.Input.Keys;
-import com.badlogic.gdx.graphics.Color;
-import com.badlogic.gdx.graphics.Colors;
-import com.badlogic.gdx.graphics.g2d.BitmapFont;
-import com.badlogic.gdx.graphics.g2d.freetype.FreeTypeFontGenerator;
-import com.badlogic.gdx.graphics.g2d.freetype.FreeTypeFontGenerator.FreeTypeFontParameter;
-import com.badlogic.gdx.math.Interpolation;
-import com.badlogic.gdx.utils.Align;
+import io.anuke.arc.ApplicationListener;
+import io.anuke.arc.Core;
+import io.anuke.arc.Events;
+import io.anuke.arc.Graphics.Cursor;
+import io.anuke.arc.Graphics.Cursor.SystemCursor;
+import io.anuke.arc.freetype.FreeTypeFontGenerator;
+import io.anuke.arc.freetype.FreeTypeFontGenerator.FreeTypeFontParameter;
+import io.anuke.arc.function.Consumer;
+import io.anuke.arc.graphics.Color;
+import io.anuke.arc.graphics.Colors;
+import io.anuke.arc.graphics.g2d.BitmapFont;
+import io.anuke.arc.input.KeyCode;
+import io.anuke.arc.math.Interpolation;
+import io.anuke.arc.scene.Group;
+import io.anuke.arc.scene.Scene;
+import io.anuke.arc.scene.Skin;
+import io.anuke.arc.scene.actions.Actions;
+import io.anuke.arc.scene.ui.Dialog;
+import io.anuke.arc.scene.ui.TextField;
+import io.anuke.arc.scene.ui.TextField.TextFieldFilter;
+import io.anuke.arc.scene.ui.TooltipManager;
+import io.anuke.arc.scene.ui.layout.Table;
+import io.anuke.arc.scene.ui.layout.Unit;
+import io.anuke.arc.util.Align;
+import io.anuke.arc.util.Strings;
+import io.anuke.arc.util.Time;
import io.anuke.mindustry.editor.MapEditorDialog;
import io.anuke.mindustry.game.EventType.ResizeEvent;
-import io.anuke.mindustry.graphics.Palette;
-import io.anuke.mindustry.input.InputHandler;
+import io.anuke.mindustry.graphics.Pal;
import io.anuke.mindustry.ui.dialogs.*;
import io.anuke.mindustry.ui.fragments.*;
-import io.anuke.ucore.core.*;
-import io.anuke.ucore.function.Consumer;
-import io.anuke.ucore.graphics.Draw;
-import io.anuke.ucore.modules.SceneModule;
-import io.anuke.ucore.scene.Group;
-import io.anuke.ucore.scene.Skin;
-import io.anuke.ucore.scene.actions.Actions;
-import io.anuke.ucore.scene.ui.Dialog;
-import io.anuke.ucore.scene.ui.TextField;
-import io.anuke.ucore.scene.ui.TextField.TextFieldFilter;
-import io.anuke.ucore.scene.ui.TooltipManager;
-import io.anuke.ucore.scene.ui.layout.Table;
-import io.anuke.ucore.scene.ui.layout.Unit;
-import io.anuke.ucore.util.Strings;
-import static io.anuke.mindustry.Vars.*;
-import static io.anuke.ucore.scene.actions.Actions.*;
+import static io.anuke.arc.scene.actions.Actions.*;
+import static io.anuke.mindustry.Vars.control;
+import static io.anuke.mindustry.Vars.disableUI;
-public class UI extends SceneModule{
+public class UI implements ApplicationListener{
private FreeTypeFontGenerator generator;
- public final MenuFragment menufrag = new MenuFragment();
- public final HudFragment hudfrag = new HudFragment();
- public final ChatFragment chatfrag = new ChatFragment();
- public final PlayerListFragment listfrag = new PlayerListFragment();
- public final BackgroundFragment backfrag = new BackgroundFragment();
- public final LoadingFragment loadfrag = new LoadingFragment();
+ public MenuFragment menufrag;
+ public HudFragment hudfrag;
+ public ChatFragment chatfrag;
+ public PlayerListFragment listfrag;
+ public BackgroundFragment backfrag;
+ public LoadingFragment loadfrag;
public AboutDialog about;
- public RestartDialog restart;
- public CustomGameDialog levels;
+ public GameOverDialog restart;
+ public CustomGameDialog custom;
public MapsDialog maps;
public LoadDialog load;
public DiscordDialog discord;
@@ -61,16 +64,29 @@ public class UI extends SceneModule{
public TraceDialog traces;
public ChangelogDialog changelog;
public LocalPlayerDialog localplayers;
- public UnlocksDialog unlocks;
+ public DatabaseDialog database;
public ContentInfoDialog content;
- public SectorsDialog sectors;
- public MissionDialog missions;
+ public DeployDialog deploy;
+ public TechTreeDialog tech;
+
+ public Cursor drillCursor, unloadCursor;
public UI(){
+ Skin skin = new Skin(Core.atlas);
+ generateFonts(skin);
+ skin.load(Core.files.internal("sprites/uiskin.json"));
+
+ for(BitmapFont font : skin.getAll(BitmapFont.class).values()){
+ font.setUseIntegerPositions(true);
+ }
+
+ Core.scene = new Scene(skin);
+ Core.input.addProcessor(Core.scene);
+
Dialog.setShowAction(() -> sequence(
alpha(0f),
originCenter(),
- moveToAligned(Gdx.graphics.getWidth() / 2f, Gdx.graphics.getHeight() / 2f, Align.center),
+ moveToAligned(Core.graphics.getWidth() / 2f, Core.graphics.getHeight() / 2f, Align.center),
scaleTo(0.0f, 1f),
parallel(
scaleTo(1f, 1f, 0.1f, Interpolation.fade),
@@ -87,16 +103,31 @@ public class UI extends SceneModule{
TooltipManager.getInstance().animations = false;
- Settings.setErrorHandler(() -> Timers.run(1f, () -> showError("[crimson]Failed to access local storage.\nSettings will not be saved.")));
+ Core.settings.setErrorHandler(e -> {
+ e.printStackTrace();
+ Core.app.post(() -> showError("Failed to access local storage.\nSettings will not be saved."));
+ });
- Dialog.closePadR = -1;
- Dialog.closePadT = 5;
+ Colors.put("accent", Pal.accent);
- Colors.put("accent", Palette.accent);
+ loadCursors();
+ }
+
+ void loadCursors(){
+ int cursorScaling = 3;
+ Color outlineColor = Color.valueOf("444444");
+
+ drillCursor = Core.graphics.newCursor("drill", cursorScaling, outlineColor);
+ unloadCursor = Core.graphics.newCursor("unload", cursorScaling, outlineColor);
+ SystemCursor.arrow.set(Core.graphics.newCursor("cursor", cursorScaling, outlineColor));
+ SystemCursor.hand.set(Core.graphics.newCursor("hand", cursorScaling, outlineColor));
+ SystemCursor.ibeam.set(Core.graphics.newCursor("ibeam", cursorScaling, outlineColor));
+
+ Core.graphics.restoreCursor();
}
- void generateFonts(){
- generator = new FreeTypeFontGenerator(Gdx.files.internal("fonts/pixel.ttf"));
+ void generateFonts(Skin skin){
+ generator = new FreeTypeFontGenerator(Core.files.internal("fonts/pixel.ttf"));
FreeTypeFontParameter param = new FreeTypeFontParameter();
param.size = (int)(14*2 * Math.max(Unit.dp.scl(1f), 0.5f));
param.shadowColor = Color.DARK_GRAY;
@@ -109,55 +140,32 @@ public class UI extends SceneModule{
skin.getFont("default-font").setOwnsTexture(false);
}
- @Override
- protected void loadSkin(){
- skin = new Skin(Core.atlas);
- generateFonts();
- skin.load(Gdx.files.internal("ui/uiskin.json"));
-
- for(BitmapFont font : skin.getAll(BitmapFont.class).values()){
- font.setUseIntegerPositions(true);
- //font.getData().setScale(Vars.fontScale);
- }
- }
-
@Override
public void update(){
if(disableUI) return;
- if(Graphics.drawing()) Graphics.end();
-
- act();
-
- Graphics.begin();
-
- for(int i = 0; i < players.length; i++){
- InputHandler input = control.input(i);
-
- if(input.isCursorVisible()){
- Draw.color();
-
- float scl = Unit.dp.scl(3f);
-
- Draw.rect("controller-cursor", input.getMouseX(), Gdx.graphics.getHeight() - input.getMouseY(), 16 * scl, 16 * scl);
- }
- }
-
- Graphics.end();
- Draw.color();
+ Core.scene.act();
+ Core.scene.draw();
}
@Override
public void init(){
+ menufrag = new MenuFragment();
+ hudfrag = new HudFragment();
+ chatfrag = new ChatFragment();
+ listfrag = new PlayerListFragment();
+ backfrag = new BackgroundFragment();
+ loadfrag = new LoadingFragment();
+
editor = new MapEditorDialog();
controls = new ControlsDialog();
- restart = new RestartDialog();
+ restart = new GameOverDialog();
join = new JoinDialog();
discord = new DiscordDialog();
load = new LoadDialog();
- levels = new CustomGameDialog();
+ custom = new CustomGameDialog();
language = new LanguageDialog();
- unlocks = new UnlocksDialog();
+ database = new DatabaseDialog();
settings = new SettingsMenuDialog();
host = new HostDialog();
paused = new PausedDialog();
@@ -169,13 +177,13 @@ public class UI extends SceneModule{
maps = new MapsDialog();
localplayers = new LocalPlayerDialog();
content = new ContentInfoDialog();
- sectors = new SectorsDialog();
- missions = new MissionDialog();
+ deploy = new DeployDialog();
+ tech = new TechTreeDialog();
- Group group = Core.scene.getRoot();
+ Group group = Core.scene.root;
backfrag.build(group);
- control.input(0).getFrag().build(Core.scene.getRoot());
+ control.input(0).getFrag().build(group);
hudfrag.build(group);
menufrag.build(group);
chatfrag.container().build(group);
@@ -185,55 +193,40 @@ public class UI extends SceneModule{
@Override
public void resize(int width, int height){
- super.resize(width, height);
-
+ Core.scene.resize(width, height);
Events.fire(new ResizeEvent());
}
@Override
public void dispose(){
- super.dispose();
generator.dispose();
}
- public void loadGraphics(Runnable call){
- loadGraphics("$text.loading", call);
+ public void loadAnd(Runnable call){
+ loadAnd("$loading", call);
}
- public void loadGraphics(String text, Runnable call){
+ public void loadAnd(String text, Runnable call){
loadfrag.show(text);
- Timers.runTask(7f, () -> {
+ Time.runTask(7f, () -> {
call.run();
loadfrag.hide();
});
}
- public void loadLogic(Runnable call){
- loadLogic("$text.loading", call);
- }
-
- public void loadLogic(String text, Runnable call){
- loadfrag.show(text);
- Timers.runTask(7f, () ->
- threads.run(() -> {
- call.run();
- threads.runGraphics(loadfrag::hide);
- }));
- }
-
- public void showTextInput(String title, String text, String def, TextFieldFilter filter, Consumer confirmed){
- new Dialog(title, "dialog"){{
- content().margin(30).add(text).padRight(6f);
- TextField field = content().addField(def, t -> {
+ public void showTextInput(String titleText, String text, String def, TextFieldFilter filter, Consumer confirmed){
+ new Dialog(titleText, "dialog"){{
+ cont.margin(30).add(text).padRight(6f);
+ TextField field = cont.addField(def, t -> {
}).size(170f, 50f).get();
field.setTextFieldFilter((f, c) -> field.getText().length() < 12 && filter.acceptChar(f, c));
Platform.instance.addDialog(field);
- buttons().defaults().size(120, 54).pad(4);
- buttons().addButton("$text.ok", () -> {
+ buttons.defaults().size(120, 54).pad(4);
+ buttons.addButton("$ok", () -> {
confirmed.accept(field.getText());
hide();
}).disabled(b -> field.getText().isEmpty());
- buttons().addButton("$text.cancel", this::hide);
+ buttons.addButton("$cancel", this::hide);
}}.show();
}
@@ -245,23 +238,23 @@ public class UI extends SceneModule{
Table table = new Table();
table.setFillParent(true);
table.actions(Actions.fadeOut(7f, Interpolation.fade), Actions.removeActor());
- table.top().add(info).padTop(8);
+ table.top().add(info).padTop(10);
Core.scene.add(table);
}
public void showInfo(String info){
new Dialog("", "dialog"){{
- getCell(content()).growX();
- content().margin(15).add(info).width(400f).wrap().get().setAlignment(Align.center, Align.center);
- buttons().addButton("$text.ok", this::hide).size(90, 50).pad(4);
+ getCell(cont).growX();
+ cont.margin(15).add(info).width(400f).wrap().get().setAlignment(Align.center, Align.center);
+ buttons.addButton("$ok", this::hide).size(90, 50).pad(4);
}}.show();
}
public void showInfo(String info, Runnable clicked){
new Dialog("", "dialog"){{
- getCell(content()).growX();
- content().margin(15).add(info).width(400f).wrap().get().setAlignment(Align.center, Align.center);
- buttons().addButton("$text.ok", () -> {
+ getCell(cont).growX();
+ cont.margin(15).add(info).width(400f).wrap().get().setAlignment(Align.center, Align.center);
+ buttons.addButton("$ok", () -> {
clicked.run();
hide();
}).size(90, 50).pad(4);
@@ -269,31 +262,31 @@ public class UI extends SceneModule{
}
public void showError(String text){
- new Dialog("$text.error.title", "dialog"){{
- content().margin(15).add(text).width(400f).wrap().get().setAlignment(Align.center, Align.center);
- buttons().addButton("$text.ok", this::hide).size(90, 50).pad(4);
+ new Dialog("$error.title", "dialog"){{
+ cont.margin(15).add(text).width(400f).wrap().get().setAlignment(Align.center, Align.center);
+ buttons.addButton("$ok", this::hide).size(90, 50).pad(4);
}}.show();
}
- public void showText(String title, String text){
- new Dialog(title, "dialog"){{
- content().margin(15).add(text).width(400f).wrap().get().setAlignment(Align.center, Align.center);
- buttons().addButton("$text.ok", this::hide).size(90, 50).pad(4);
+ public void showText(String titleText, String text){
+ new Dialog(titleText, "dialog"){{
+ cont.margin(15).add(text).width(400f).wrap().get().setAlignment(Align.center, Align.center);
+ buttons.addButton("$ok", this::hide).size(90, 50).pad(4);
}}.show();
}
public void showConfirm(String title, String text, Runnable confirmed){
FloatingDialog dialog = new FloatingDialog(title);
- dialog.content().add(text).width(400f).wrap().pad(4f).get().setAlignment(Align.center, Align.center);
- dialog.buttons().defaults().size(200f, 54f).pad(2f);
+ dialog.cont.add(text).width(500f).wrap().pad(4f).get().setAlignment(Align.center, Align.center);
+ dialog.buttons.defaults().size(200f, 54f).pad(2f);
dialog.setFillParent(false);
- dialog.buttons().addButton("$text.cancel", dialog::hide);
- dialog.buttons().addButton("$text.ok", () -> {
+ dialog.buttons.addButton("$cancel", dialog::hide);
+ dialog.buttons.addButton("$ok", () -> {
dialog.hide();
confirmed.run();
});
- dialog.keyDown(Keys.ESCAPE, dialog::hide);
- dialog.keyDown(Keys.BACK, dialog::hide);
+ dialog.keyDown(KeyCode.ESCAPE, dialog::hide);
+ dialog.keyDown(KeyCode.BACK, dialog::hide);
dialog.show();
}
diff --git a/core/src/io/anuke/mindustry/core/World.java b/core/src/io/anuke/mindustry/core/World.java
index 58dedd6e2a..48572dc653 100644
--- a/core/src/io/anuke/mindustry/core/World.java
+++ b/core/src/io/anuke/mindustry/core/World.java
@@ -1,55 +1,56 @@
package io.anuke.mindustry.core;
-import com.badlogic.gdx.math.GridPoint2;
-import com.badlogic.gdx.utils.Array;
-import com.badlogic.gdx.utils.ObjectMap;
+import io.anuke.arc.ApplicationListener;
+import io.anuke.arc.Core;
+import io.anuke.arc.Events;
+import io.anuke.arc.collection.Array;
+import io.anuke.arc.collection.IntArray;
+import io.anuke.mindustry.entities.EntityQuery;
+import io.anuke.arc.math.Mathf;
+import io.anuke.arc.math.geom.Geometry;
+import io.anuke.arc.math.geom.Point2;
+import io.anuke.arc.util.Log;
+import io.anuke.arc.util.Structs;
+import io.anuke.arc.util.Tmp;
import io.anuke.mindustry.ai.BlockIndexer;
import io.anuke.mindustry.ai.Pathfinder;
import io.anuke.mindustry.ai.WaveSpawner;
-import io.anuke.mindustry.content.blocks.Blocks;
+import io.anuke.mindustry.content.Blocks;
import io.anuke.mindustry.core.GameState.State;
import io.anuke.mindustry.game.EventType.TileChangeEvent;
import io.anuke.mindustry.game.EventType.WorldLoadEvent;
import io.anuke.mindustry.game.Team;
import io.anuke.mindustry.io.MapIO;
-import io.anuke.mindustry.maps.*;
-import io.anuke.mindustry.maps.generation.WorldGenerator;
+import io.anuke.mindustry.maps.Map;
+import io.anuke.mindustry.maps.MapTileData;
+import io.anuke.mindustry.maps.MapTileData.TileDataMarker;
+import io.anuke.mindustry.maps.Maps;
+import io.anuke.mindustry.maps.generators.Generator;
+import io.anuke.mindustry.type.ContentType;
+import io.anuke.mindustry.type.ItemStack;
+import io.anuke.mindustry.type.Zone;
import io.anuke.mindustry.world.Block;
import io.anuke.mindustry.world.Pos;
import io.anuke.mindustry.world.Tile;
-import io.anuke.mindustry.world.blocks.OreBlock;
-import io.anuke.ucore.core.Events;
-import io.anuke.ucore.core.Timers;
-import io.anuke.ucore.entities.EntityQuery;
-import io.anuke.ucore.modules.Module;
-import io.anuke.ucore.util.*;
import static io.anuke.mindustry.Vars.*;
-public class World extends Module{
+public class World implements ApplicationListener{
public final Maps maps = new Maps();
- public final Sectors sectors = new Sectors();
- public final WorldGenerator generator = new WorldGenerator();
public final BlockIndexer indexer = new BlockIndexer();
public final WaveSpawner spawner = new WaveSpawner();
public final Pathfinder pathfinder = new Pathfinder();
private Map currentMap;
- private Sector currentSector;
private Tile[][] tiles;
- private Array tempTiles = new ThreadArray<>();
+ private Array tempTiles = new Array<>();
private boolean generating, invalidMap;
public World(){
maps.load();
}
- @Override
- public void init(){
- sectors.load();
- }
-
@Override
public void dispose(){
maps.dispose();
@@ -84,14 +85,6 @@ public class World extends Module{
return currentMap;
}
- public Sector getSector(){
- return currentSector;
- }
-
- public void setSector(Sector currentSector){
- this.currentSector = currentSector;
- }
-
public void setMap(Map map){
this.currentMap = map;
}
@@ -121,11 +114,11 @@ public class World extends Module{
}
public Tile tileWorld(float x, float y){
- return tile(Mathf.scl2(x, tilesize), Mathf.scl2(y, tilesize));
+ return tile(Math.round(x / tilesize), Math.round(y / tilesize));
}
public int toTile(float coord){
- return Mathf.scl2(coord, tilesize);
+ return Math.round(coord / tilesize);
}
public Tile[][] getTiles(){
@@ -184,17 +177,15 @@ public class World extends Module{
Tile tile = tiles[x][y];
tile.updateOcclusion();
- if(tile.floor() instanceof OreBlock && tile.hasCliffs()){
- tile.setFloor(((OreBlock) tile.floor()).base);
- }
-
if(tile.entity != null){
tile.entity.updateProximity();
}
}
}
- EntityQuery.resizeTree(0, 0, tiles.length * tilesize, tiles[0].length * tilesize);
+ addDarkness(tiles);
+
+ EntityQuery.resizeTree(-finalWorldBounds, -finalWorldBounds, tiles.length * tilesize + finalWorldBounds, tiles[0].length * tilesize + finalWorldBounds);
generating = false;
Events.fire(new WorldLoadEvent());
@@ -204,34 +195,42 @@ public class World extends Module{
return generating;
}
- /**Loads up a sector map. This does not call play(), but calls reset().*/
- public void loadSector(Sector sector){
- currentSector = sector;
- state.difficulty = sectors.getDifficulty(sector);
- state.mode = sector.currentMission().getMode();
- Timers.mark();
- Timers.mark();
+ public boolean isZone(){
+ return getZone() != null;
+ }
- logic.reset();
+ public Zone getZone(){
+ return content.getByID(ContentType.zone, state.rules.zone);
+ }
+ public void playZone(Zone zone){
+ ui.loadAnd(() -> {
+ logic.reset();
+ state.rules = zone.rules.get();
+ state.rules.zone = zone.id;
+ loadGenerator(zone.generator);
+ for(Tile core : state.teams.get(defaultTeam).cores){
+ for(ItemStack stack : zone.startingItems){
+ core.entity.items.add(stack.item, stack.amount);
+ }
+ }
+ state.set(State.playing);
+ control.saves.zoneSave();
+ logic.play();
+ });
+ }
+
+ public void loadGenerator(Generator generator){
beginMapLoad();
- int width = sectorSize, height = sectorSize;
-
- Tile[][] tiles = createTiles(width, height);
-
- Map map = new Map("Sector " + sector.x + ", " + sector.y, new MapMeta(0, new ObjectMap<>(), width, height, null), true, () -> null);
- setMap(map);
-
- EntityQuery.resizeTree(0, 0, width * tilesize, height * tilesize);
-
- generator.generateMap(tiles, sector);
+ createTiles(generator.width, generator.height);
+ generator.generate(tiles);
+ prepareTiles(tiles);
endMapLoad();
}
public void loadMap(Map map){
- currentSector = null;
beginMapLoad();
this.currentMap = map;
@@ -239,15 +238,13 @@ public class World extends Module{
createTiles(width, height);
- EntityQuery.resizeTree(0, 0, width * tilesize, height * tilesize);
-
try{
- generator.loadTileData(tiles, MapIO.readTileData(map, true), map.meta.hasOreGen(), Mathf.random(99999));
- } catch(Exception e){
+ loadTileData(tiles, MapIO.readTileData(map, true));
+ }catch(Exception e){
Log.err(e);
if(!headless){
- ui.showError("$text.map.invalid");
- threads.runDelay(() -> state.set(State.menu));
+ ui.showError("$map.invalid");
+ Core.app.post(() -> state.set(State.menu));
invalidMap = true;
}
generating = false;
@@ -260,9 +257,9 @@ public class World extends Module{
if(!headless){
if(state.teams.get(players[0].getTeam()).cores.size == 0){
- ui.showError("$text.map.nospawn");
+ ui.showError("$map.nospawn");
invalidMap = true;
- }else if(state.mode.isPvp){
+ }else if(state.rules.pvp){ //pvp maps need two cores to be valid
invalidMap = true;
for(Team team : Team.all){
if(state.teams.get(team).cores.size != 0 && team != players[0].getTeam()){
@@ -270,20 +267,17 @@ public class World extends Module{
}
}
if(invalidMap){
- ui.showError("$text.map.nospawn.pvp");
+ ui.showError("$map.nospawn.pvp");
}
}
- }else{
- invalidMap = false;
}
- if(invalidMap) threads.runDelay(() -> state.set(State.menu));
-
+ if(invalidMap) Core.app.post(() -> state.set(State.menu));
}
public void notifyChanged(Tile tile){
if(!generating){
- threads.runDelay(() -> Events.fire(new TileChangeEvent(tile)));
+ Core.app.post(() -> Events.fire(new TileChangeEvent(tile)));
}
}
@@ -334,9 +328,9 @@ public class World extends Module{
/**
* 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));
+ public Point2 raycastWorld(float x, float y, float x2, float y2){
+ return raycast(Math.round(x / tilesize), Math.round(y / tilesize),
+ Math.round(x2 / tilesize), Math.round(y2 / tilesize));
}
/**
@@ -344,7 +338,7 @@ public class World extends Module{
*
* @return null if no collisions found, block position otherwise.
*/
- public GridPoint2 raycast(int x0f, int y0f, int x1, int y1){
+ public Point2 raycast(int x0f, int y0f, int x1, int y1){
int x0 = x0f;
int y0 = y0f;
int dx = Math.abs(x1 - x0);
@@ -409,6 +403,126 @@ public class World extends Module{
}
}
+ /**Loads raw map tile data into a Tile[][] array, setting up multiblocks, cliffs and ores. */
+ void loadTileData(Tile[][] tiles, MapTileData data){
+ data.position(0, 0);
+ TileDataMarker marker = data.newDataMarker();
+
+ for(int y = 0; y < data.height(); y++){
+ for(int x = 0; x < data.width(); x++){
+ data.read(marker);
+
+ tiles[x][y] = new Tile(x, y, marker.floor, marker.wall == Blocks.part.id ? 0 : marker.wall, marker.rotation, marker.team);
+ }
+ }
+
+ prepareTiles(tiles);
+ }
+
+ public void addDarkness(Tile[][] tiles){
+
+ byte[][] dark = new byte[tiles.length][tiles[0].length];
+ byte[][] writeBuffer = new byte[tiles.length][tiles[0].length];
+
+ byte darkIterations = 4;
+ for(int x = 0; x < tiles.length; x++){
+ for(int y = 0; y < tiles[0].length; y++){
+ Tile tile = tiles[x][y];
+ if(tile.block().solid && !tile.block().synthetic() && tile.block().fillsTile){
+ dark[x][y] = darkIterations;
+ }
+ }
+ }
+
+ for(int i = 0; i < darkIterations; i++){
+ for(int x = 0; x < tiles.length; x++){
+ for(int y = 0; y < tiles[0].length; y++){
+ boolean min = false;
+ for(Point2 point : Geometry.d4){
+ int newX = x + point.x, newY = y + point.y;
+ if(Structs.inBounds(newX, newY, tiles) && dark[newX][newY] < dark[x][y]){
+ min = true;
+ break;
+ }
+ }
+ writeBuffer[x][y] = (byte)Math.max(0, dark[x][y] - Mathf.num(min));
+ }
+ }
+
+ for(int x = 0; x < tiles.length; x++){
+ for(int y = 0; y < tiles[0].length; y++){
+ dark[x][y] = writeBuffer[x][y];
+ }
+ }
+ }
+
+ for(int x = 0; x < tiles.length; x++){
+ for(int y = 0; y < tiles[0].length; y++){
+ Tile tile = tiles[x][y];
+ if(tile.block().solid && !tile.block().synthetic()){
+ tiles[x][y].setRotation(dark[x][y]);
+ }
+ }
+ }
+ }
+
+ /**'Prepares' a tile array by:
+ * - setting up multiblocks
+ * - updating occlusion
+ * Usually used before placing structures on a tile array.*/
+ public void prepareTiles(Tile[][] tiles){
+
+ //find multiblocks
+ IntArray multiblocks = new IntArray();
+
+ for(int x = 0; x < tiles.length; x++){
+ for(int y = 0; y < tiles[0].length; y++){
+ Tile tile = tiles[x][y];
+
+ if(tile.block().isMultiblock()){
+ multiblocks.add(tile.pos());
+ }
+ }
+ }
+
+ //place multiblocks now
+ for(int i = 0; i < multiblocks.size; i++){
+ int pos = multiblocks.get(i);
+
+ int x = Pos.x(pos);
+ int y = Pos.y(pos);
+
+ Block result = tiles[x][y].block();
+ Team team = tiles[x][y].getTeam();
+
+ int offsetx = -(result.size - 1) / 2;
+ int offsety = -(result.size - 1) / 2;
+
+ for(int dx = 0; dx < result.size; dx++){
+ for(int dy = 0; dy < result.size; 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));
+ toplace.setTeam(team);
+ }
+ }
+ }
+ }
+ }
+
+ //update cliffs, occlusion data
+ for(int x = 0; x < tiles.length; x++){
+ for(int y = 0; y < tiles[0].length; y++){
+ Tile tile = tiles[x][y];
+
+ tile.updateOcclusion();
+ }
+ }
+ }
+
public interface Raycaster{
boolean accept(int x, int y);
}
diff --git a/core/src/io/anuke/mindustry/editor/DrawOperation.java b/core/src/io/anuke/mindustry/editor/DrawOperation.java
index d2b434e21f..b6b7d13f76 100755
--- a/core/src/io/anuke/mindustry/editor/DrawOperation.java
+++ b/core/src/io/anuke/mindustry/editor/DrawOperation.java
@@ -1,10 +1,10 @@
package io.anuke.mindustry.editor;
-import com.badlogic.gdx.utils.Array;
-import com.badlogic.gdx.utils.IntSet;
+import io.anuke.arc.collection.Array;
+import io.anuke.arc.collection.IntSet;
+import io.anuke.arc.util.Pack;
import io.anuke.mindustry.maps.MapTileData;
import io.anuke.mindustry.maps.MapTileData.TileDataMarker;
-import io.anuke.ucore.util.Bits;
public class DrawOperation{
/**
@@ -29,7 +29,7 @@ public class DrawOperation{
}
public boolean checkDuplicate(short x, short y){
- int i = Bits.packInt(x, y);
+ int i = Pack.shortInt(x, y);
if(checks.contains(i)) return true;
checks.add(i);
diff --git a/core/src/io/anuke/mindustry/editor/EditorTool.java b/core/src/io/anuke/mindustry/editor/EditorTool.java
index 6eca7e8fd4..3ec34b21da 100644
--- a/core/src/io/anuke/mindustry/editor/EditorTool.java
+++ b/core/src/io/anuke/mindustry/editor/EditorTool.java
@@ -1,15 +1,17 @@
package io.anuke.mindustry.editor;
-import com.badlogic.gdx.utils.IntArray;
-import io.anuke.mindustry.content.blocks.Blocks;
+import io.anuke.arc.Core;
+import io.anuke.arc.collection.IntArray;
+import io.anuke.arc.function.IntPositionConsumer;
+import io.anuke.arc.input.KeyCode;
+import io.anuke.arc.util.Pack;
+import io.anuke.arc.util.Structs;
+import io.anuke.mindustry.content.Blocks;
import io.anuke.mindustry.maps.MapTileData;
import io.anuke.mindustry.maps.MapTileData.DataPosition;
import io.anuke.mindustry.maps.MapTileData.TileDataMarker;
import io.anuke.mindustry.world.Block;
import io.anuke.mindustry.world.blocks.Floor;
-import io.anuke.ucore.function.IntPositionConsumer;
-import io.anuke.ucore.util.Structs;
-import io.anuke.ucore.util.Bits;
import static io.anuke.mindustry.Vars.content;
import static io.anuke.mindustry.Vars.ui;
@@ -24,8 +26,8 @@ public enum EditorTool{
byte link = editor.getMap().read(x, y, DataPosition.link);
if(link != 0){
- x -= (Bits.getLeftByte(link) - 8);
- y -= (Bits.getRightByte(link) - 8);
+ x -= (Pack.leftByte(link) - 8);
+ y -= (Pack.rightByte(link) - 8);
bf = editor.getMap().read(x, y, DataPosition.floor);
bw = editor.getMap().read(x, y, DataPosition.wall);
}
@@ -43,7 +45,7 @@ public enum EditorTool{
@Override
public void touched(MapEditor editor, int x, int y){
- editor.draw(x, y);
+ editor.draw(x, y, isPaint());
}
},
eraser{
@@ -54,10 +56,10 @@ public enum EditorTool{
@Override
public void touched(MapEditor editor, int x, int y){
- editor.draw(x, y, Blocks.air);
+ editor.draw(x, y, isPaint(), Blocks.air);
}
},
- elevation{
+ spray{
{
edit = true;
draggable = true;
@@ -65,7 +67,7 @@ public enum EditorTool{
@Override
public void touched(MapEditor editor, int x, int y){
- editor.elevate(x, y);
+ editor.draw(x, y, isPaint(), editor.getDrawBlock(), 0.012);
}
},
line{
@@ -99,9 +101,8 @@ public enum EditorTool{
byte bf = data.read(x, y, DataPosition.floor);
byte bw = data.read(x, y, DataPosition.wall);
- be = data.read(x, y, DataPosition.elevation);
boolean synth = editor.getDrawBlock().synthetic();
- byte brt = Bits.packByte((byte) editor.getDrawRotation(), (byte) editor.getDrawTeam().ordinal());
+ byte brt = Pack.byteByte((byte) editor.getDrawRotation(), (byte) editor.getDrawTeam().ordinal());
dest = floor ? bf : bw;
byte draw = editor.getDrawBlock().id;
@@ -113,13 +114,6 @@ public enum EditorTool{
width = editor.getMap().width();
int height = editor.getMap().height();
- int x1;
- boolean spanAbove, spanBelow;
-
- stack.clear();
-
- stack.add(asi(x, y));
-
IntPositionConsumer writer = (px, py) -> {
TileDataMarker prev = editor.getPrev(px, py, false);
@@ -136,32 +130,49 @@ public enum EditorTool{
editor.onWrite(px, py, prev);
};
- while(stack.size > 0){
- int popped = stack.pop();
- x = popped % width;
- y = popped / width;
-
- x1 = x;
- while(x1 >= 0 && eq(x1, y)) x1--;
- x1++;
- spanAbove = spanBelow = false;
- while(x1 < width && eq(x1, y)){
- writer.accept(x1, y);
-
- if(!spanAbove && y > 0 && eq(x1, y - 1)){
- stack.add(asi(x1, y - 1));
- spanAbove = true;
- }else if(spanAbove && y > 0 && eq(x1, y - 1)){
- spanAbove = false;
+ if(isAlt()){
+ for(int cx = 0; cx < width; cx++){
+ for(int cy = 0; cy < height; cy++){
+ if(eq(cx, cy)){
+ writer.accept(cx, cy);
+ }
}
+ }
+ }else{
+ int x1;
+ boolean spanAbove, spanBelow;
- if(!spanBelow && y < height - 1 && eq(x1, y + 1)){
- stack.add(asi(x1, y + 1));
- spanBelow = true;
- }else if(spanBelow && y < height - 1 && eq(x1, y + 1)){
- spanBelow = false;
- }
+ stack.clear();
+
+ stack.add(asi(x, y));
+
+ while(stack.size > 0){
+ int popped = stack.pop();
+ x = popped % width;
+ y = popped / width;
+
+ x1 = x;
+ while(x1 >= 0 && eq(x1, y)) x1--;
x1++;
+ spanAbove = spanBelow = false;
+ while(x1 < width && eq(x1, y)){
+ writer.accept(x1, y);
+
+ if(!spanAbove && y > 0 && eq(x1, y - 1)){
+ stack.add(asi(x1, y - 1));
+ spanAbove = true;
+ }else if(spanAbove && y > 0 && eq(x1, y - 1)){
+ spanAbove = false;
+ }
+
+ if(!spanBelow && y < height - 1 && eq(x1, y + 1)){
+ stack.add(asi(x1, y + 1));
+ spanBelow = true;
+ }else if(spanBelow && y < height - 1 && eq(x1, y + 1)){
+ spanBelow = false;
+ }
+ x1++;
+ }
}
}
}
@@ -182,6 +193,14 @@ public enum EditorTool{
boolean edit, draggable;
+ public static boolean isPaint(){
+ return Core.input.keyDown(KeyCode.CONTROL_LEFT);
+ }
+
+ public static boolean isAlt(){
+ return Core.input.keyDown(KeyCode.TAB);
+ }
+
public void touched(MapEditor editor, int x, int y){
}
diff --git a/core/src/io/anuke/mindustry/editor/MapEditor.java b/core/src/io/anuke/mindustry/editor/MapEditor.java
index 532e720622..b70ab01467 100644
--- a/core/src/io/anuke/mindustry/editor/MapEditor.java
+++ b/core/src/io/anuke/mindustry/editor/MapEditor.java
@@ -1,8 +1,11 @@
package io.anuke.mindustry.editor;
-import com.badlogic.gdx.utils.ObjectMap;
+import io.anuke.arc.collection.ObjectMap;
+import io.anuke.arc.math.Mathf;
+import io.anuke.arc.util.Pack;
+import io.anuke.arc.util.Structs;
import io.anuke.mindustry.Vars;
-import io.anuke.mindustry.content.blocks.Blocks;
+import io.anuke.mindustry.content.Blocks;
import io.anuke.mindustry.editor.DrawOperation.TileOperation;
import io.anuke.mindustry.game.Team;
import io.anuke.mindustry.maps.MapTileData;
@@ -10,19 +13,17 @@ import io.anuke.mindustry.maps.MapTileData.DataPosition;
import io.anuke.mindustry.maps.MapTileData.TileDataMarker;
import io.anuke.mindustry.world.Block;
import io.anuke.mindustry.world.blocks.Floor;
-import io.anuke.ucore.util.Structs;
-import io.anuke.ucore.util.Bits;
-import io.anuke.ucore.util.Mathf;
+
import static io.anuke.mindustry.Vars.content;
+
public class MapEditor{
- public static final int[] brushSizes = {1, 2, 3, 4, 5, 9, 15};
+ public static final int[] brushSizes = {1, 2, 3, 4, 5, 9, 15, 20};
private MapTileData map;
private ObjectMap tags = new ObjectMap<>();
private MapRenderer renderer = new MapRenderer(this);
private int brushSize = 1;
- private byte elevation;
private int rotation;
private Block drawBlock = Blocks.stone;
private Team drawTeam = Team.blue;
@@ -52,14 +53,6 @@ public class MapEditor{
renderer.resize(map.width(), map.height());
}
- public byte getDrawElevation(){
- return elevation;
- }
-
- public void setDrawElevation(int elevation){
- this.elevation = (byte) elevation;
- }
-
public int getDrawRotation(){
return rotation;
}
@@ -92,18 +85,18 @@ public class MapEditor{
this.brushSize = size;
}
- public void draw(int x, int y){
- draw(x, y, drawBlock);
+ public void draw(int x, int y, boolean paint){
+ draw(x, y, paint, drawBlock);
}
- public void draw(int x, int y, Block drawBlock){
- if(x < 0 || y < 0 || x >= map.width() || y >= map.height()){
- return;
- }
+ public void draw(int x, int y, boolean paint, Block drawBlock){
+ draw(x, y, paint, drawBlock, 1.0);
+ }
+ public void draw(int x, int y, boolean paint, Block drawBlock, double chance){
byte writeID = drawBlock.id;
- byte partID = Blocks.blockpart.id;
- byte rotationTeam = Bits.packByte(drawBlock.rotate ? (byte) rotation : 0, drawBlock.synthetic() ? (byte) drawTeam.ordinal() : 0);
+ byte partID = Blocks.part.id;
+ byte rotationTeam = Pack.byteByte(drawBlock.rotate ? (byte)rotation : 0, drawBlock.synthetic() ? (byte)drawTeam.ordinal() : 0);
boolean isfloor = drawBlock instanceof Floor && drawBlock != Blocks.air;
@@ -126,13 +119,13 @@ public class MapEditor{
if(i == 1){
map.write(worldx, worldy, DataPosition.wall, partID);
map.write(worldx, worldy, DataPosition.rotationTeam, rotationTeam);
- map.write(worldx, worldy, DataPosition.link, Bits.packByte((byte) (dx + offsetx + 8), (byte) (dy + offsety + 8)));
+ map.write(worldx, worldy, DataPosition.link, Pack.byteByte((byte) (dx + offsetx + 8), (byte) (dy + offsety + 8)));
}else{
byte link = map.read(worldx, worldy, DataPosition.link);
byte block = map.read(worldx, worldy, DataPosition.wall);
if(link != 0){
- removeLinked(worldx - (Bits.getLeftByte(link) - 8), worldy - (Bits.getRightByte(link) - 8));
+ removeLinked(worldx - (Pack.leftByte(link) - 8), worldy - (Pack.rightByte(link) - 8));
}else if(content.block(block).isMultiblock()){
removeLinked(worldx, worldy);
}
@@ -152,13 +145,12 @@ public class MapEditor{
onWrite(x, y, prev);
}else{
-
for(int rx = -brushSize; rx <= brushSize; rx++){
for(int ry = -brushSize; ry <= brushSize; ry++){
- if(Mathf.dst(rx, ry) <= brushSize - 0.5f){
+ if(Mathf.dst(rx, ry) <= brushSize - 0.5f && (chance >= 0.999 || Mathf.chance(chance))){
int wx = x + rx, wy = y + ry;
- if(wx < 0 || wy < 0 || wx >= map.width() || wy >= map.height()){
+ if(wx < 0 || wy < 0 || wx >= map.width() || wy >= map.height() || (paint && !isfloor && content.block(map.read(wx, wy, DataPosition.wall)) == Blocks.air)){
continue;
}
@@ -170,13 +162,12 @@ public class MapEditor{
if(content.block(map.read(wx, wy, DataPosition.wall)).isMultiblock()){
removeLinked(wx, wy);
}else if(link != 0){
- removeLinked(wx - (Bits.getLeftByte(link) - 8), wy - (Bits.getRightByte(link) - 8));
+ removeLinked(wx - (Pack.leftByte(link) - 8), wy - (Pack.rightByte(link) - 8));
}
}
if(isfloor){
map.write(wx, wy, DataPosition.floor, writeID);
- map.write(wx, wy, DataPosition.elevation, elevation);
}else{
map.write(wx, wy, DataPosition.wall, writeID);
map.write(wx, wy, DataPosition.link, (byte) 0);
@@ -190,30 +181,6 @@ public class MapEditor{
}
}
- public void elevate(int x, int y){
- if(x < 0 || y < 0 || x >= map.width() || y >= map.height()){
- return;
- }
-
- for(int rx = -brushSize; rx <= brushSize; rx++){
- for(int ry = -brushSize; ry <= brushSize; ry++){
- if(Mathf.dst(rx, ry) <= brushSize - 0.5f){
- int wx = x + rx, wy = y + ry;
-
- if(wx < 0 || wy < 0 || wx >= map.width() || wy >= map.height()){
- continue;
- }
-
- TileDataMarker prev = getPrev(wx, wy, true);
-
- map.write(wx, wy, DataPosition.elevation, elevation);
-
- onWrite(x + rx, y + ry, prev);
- }
- }
- }
- }
-
private void removeLinked(int x, int y){
Block block = content.block(map.read(x, y, DataPosition.wall));
@@ -269,10 +236,21 @@ public class MapEditor{
}
public void resize(int width, int height){
+ MapTileData previous = map;
+ int offsetX = -(width - previous.width())/2, offsetY = -(height - previous.height())/2;
+
map = new MapTileData(width, height);
for(int x = 0; x < map.width(); x++){
for(int y = 0; y < map.height(); y++){
- map.write(x, y, DataPosition.floor, Blocks.stone.id);
+ int px = offsetX + x, py = offsetY + y;
+ if(Structs.inBounds(px, py, previous.width(), previous.height())){
+ map.write(x, y, DataPosition.floor, previous.read(px, py, DataPosition.floor));
+ map.write(x, y, DataPosition.wall, previous.read(px, py, DataPosition.wall));
+ map.write(x, y, DataPosition.link, previous.read(px, py, DataPosition.link));
+ map.write(x, y, DataPosition.rotationTeam, previous.read(px, py, DataPosition.rotationTeam));
+ }else{
+ map.write(x, y, DataPosition.floor, Blocks.stone.id);
+ }
}
}
renderer.resize(width, height);
diff --git a/core/src/io/anuke/mindustry/editor/MapEditorDialog.java b/core/src/io/anuke/mindustry/editor/MapEditorDialog.java
index 1fe31ead15..17155c2af1 100644
--- a/core/src/io/anuke/mindustry/editor/MapEditorDialog.java
+++ b/core/src/io/anuke/mindustry/editor/MapEditorDialog.java
@@ -1,43 +1,34 @@
package io.anuke.mindustry.editor;
-import com.badlogic.gdx.Gdx;
-import com.badlogic.gdx.files.FileHandle;
-import com.badlogic.gdx.graphics.Color;
-import com.badlogic.gdx.graphics.Pixmap;
-import com.badlogic.gdx.graphics.g2d.Batch;
-import com.badlogic.gdx.graphics.g2d.TextureRegion;
-import com.badlogic.gdx.math.Vector2;
-import com.badlogic.gdx.utils.Align;
-import com.badlogic.gdx.utils.Disposable;
-import com.badlogic.gdx.utils.ObjectMap;
+import io.anuke.arc.Core;
+import io.anuke.arc.collection.Array;
+import io.anuke.arc.collection.ObjectMap;
+import io.anuke.arc.files.FileHandle;
+import io.anuke.arc.function.Consumer;
+import io.anuke.arc.graphics.Color;
+import io.anuke.arc.graphics.Pixmap;
+import io.anuke.arc.graphics.g2d.TextureRegion;
+import io.anuke.arc.input.KeyCode;
+import io.anuke.arc.math.Mathf;
+import io.anuke.arc.math.geom.Vector2;
+import io.anuke.arc.scene.actions.Actions;
+import io.anuke.arc.scene.style.TextureRegionDrawable;
+import io.anuke.arc.scene.ui.*;
+import io.anuke.arc.scene.ui.layout.Table;
+import io.anuke.arc.scene.ui.layout.Unit;
+import io.anuke.arc.scene.utils.UIUtils;
+import io.anuke.arc.util.*;
import io.anuke.mindustry.Vars;
-import io.anuke.mindustry.content.blocks.StorageBlocks;
import io.anuke.mindustry.core.Platform;
import io.anuke.mindustry.game.Team;
import io.anuke.mindustry.io.MapIO;
import io.anuke.mindustry.maps.Map;
import io.anuke.mindustry.maps.MapMeta;
import io.anuke.mindustry.maps.MapTileData;
-import io.anuke.mindustry.type.Recipe;
import io.anuke.mindustry.ui.dialogs.FloatingDialog;
import io.anuke.mindustry.world.Block;
-import io.anuke.ucore.core.Core;
-import io.anuke.ucore.core.Graphics;
-import io.anuke.ucore.core.Inputs;
-import io.anuke.ucore.core.Timers;
-import io.anuke.ucore.function.Consumer;
-import io.anuke.ucore.graphics.Draw;
-import io.anuke.ucore.input.Input;
-import io.anuke.ucore.scene.actions.Actions;
-import io.anuke.ucore.scene.ui.*;
-import io.anuke.ucore.scene.ui.layout.Stack;
-import io.anuke.ucore.scene.ui.layout.Table;
-import io.anuke.ucore.scene.ui.layout.Unit;
-import io.anuke.ucore.scene.utils.UIUtils;
-import io.anuke.ucore.util.Bundles;
-import io.anuke.ucore.util.Log;
-import io.anuke.ucore.util.Mathf;
-import io.anuke.ucore.util.Strings;
+import io.anuke.mindustry.world.Block.Icon;
+import io.anuke.mindustry.world.blocks.OreBlock;
import java.io.DataInputStream;
import java.io.InputStream;
@@ -54,6 +45,7 @@ public class MapEditorDialog extends Dialog implements Disposable{
private FloatingDialog menu;
private boolean saved = false;
private boolean shownWithMap = false;
+ private Array blocksOut = new Array<>();
private ButtonGroup blockgroup;
@@ -67,36 +59,36 @@ public class MapEditorDialog extends Dialog implements Disposable{
infoDialog = new MapInfoDialog(editor);
- menu = new FloatingDialog("$text.menu");
+ menu = new FloatingDialog("$menu");
menu.addCloseButton();
float isize = 16 * 2f;
float swidth = 180f;
- menu.content().table(t -> {
+ menu.cont.table(t -> {
t.defaults().size(swidth, 60f).padBottom(5).padRight(5).padLeft(5);
- t.addImageTextButton("$text.editor.savemap", "icon-floppy-16", isize, this::save).size(swidth * 2f + 10, 60f).colspan(2);
+ t.addImageTextButton("$editor.savemap", "icon-floppy-16", isize, this::save).size(swidth * 2f + 10, 60f).colspan(2);
t.row();
- t.addImageTextButton("$text.editor.mapinfo", "icon-pencil", isize, () -> {
+ t.addImageTextButton("$editor.mapinfo", "icon-pencil", isize, () -> {
infoDialog.show();
menu.hide();
});
- t.addImageTextButton("$text.editor.resize", "icon-resize", isize, () -> {
+ t.addImageTextButton("$editor.resize", "icon-resize", isize, () -> {
resizeDialog.show();
menu.hide();
});
t.row();
- t.addImageTextButton("$text.editor.import", "icon-load-map", isize, () ->
- createDialog("$text.editor.import",
- "$text.editor.importmap", "$text.editor.importmap.description", "icon-load-map", (Runnable) loadDialog::show,
- "$text.editor.importfile", "$text.editor.importfile.description", "icon-file", (Runnable) () ->
- Platform.instance.showFileChooser("$text.loadimage", "Map Files", file -> ui.loadGraphics(() -> {
+ t.addImageTextButton("$editor.import", "icon-load-map", isize, () ->
+ createDialog("$editor.import",
+ "$editor.importmap", "$editor.importmap.description", "icon-load-map", (Runnable) loadDialog::show,
+ "$editor.importfile", "$editor.importfile.description", "icon-file", (Runnable) () ->
+ Platform.instance.showFileChooser("$loadimage", "Map Files", file -> ui.loadAnd(() -> {
try{
DataInputStream stream = new DataInputStream(file.read());
@@ -106,32 +98,32 @@ public class MapEditorDialog extends Dialog implements Disposable{
editor.beginEdit(data, meta.tags, false);
view.clearStack();
}catch(Exception e){
- ui.showError(Bundles.format("text.editor.errorimageload", Strings.parseException(e, false)));
+ ui.showError(Core.bundle.format("editor.errorimageload", Strings.parseException(e, false)));
Log.err(e);
}
}), true, mapExtension),
- "$text.editor.importimage", "$text.editor.importimage.description", "icon-file-image", (Runnable)() ->
- Platform.instance.showFileChooser("$text.loadimage", "Image Files", file ->
- ui.loadGraphics(() -> {
+ "$editor.importimage", "$editor.importimage.description", "icon-file-image", (Runnable)() ->
+ Platform.instance.showFileChooser("$loadimage", "Image Files", file ->
+ ui.loadAnd(() -> {
try{
MapTileData data = MapIO.readLegacyPixmap(new Pixmap(file));
editor.beginEdit(data, editor.getTags(), false);
view.clearStack();
}catch (Exception e){
- ui.showError(Bundles.format("text.editor.errorimageload", Strings.parseException(e, false)));
+ ui.showError(Core.bundle.format("editor.errorimageload", Strings.parseException(e, false)));
Log.err(e);
}
}), true, "png")
));
- t.addImageTextButton("$text.editor.export", "icon-save-map", isize, () -> createDialog("$text.editor.export",
- "$text.editor.exportfile", "$text.editor.exportfile.description", "icon-file", (Runnable) () ->
- Platform.instance.showFileChooser("$text.saveimage", "Map Files", file -> {
+ t.addImageTextButton("$editor.export", "icon-save-map", isize, () -> createDialog("$editor.export",
+ "$editor.exportfile", "$editor.exportfile.description", "icon-file", (Runnable) () ->
+ Platform.instance.showFileChooser("$saveimage", "Map Files", file -> {
file = file.parent().child(file.nameWithoutExtension() + "." + mapExtension);
FileHandle result = file;
- ui.loadGraphics(() -> {
+ ui.loadAnd(() -> {
try{
if(!editor.getTags().containsKey("name")){
@@ -139,7 +131,7 @@ public class MapEditorDialog extends Dialog implements Disposable{
}
MapIO.writeMap(result.write(false), editor.getTags(), editor.getMap());
}catch(Exception e){
- ui.showError(Bundles.format("text.editor.errorimagesave", Strings.parseException(e, false)));
+ ui.showError(Core.bundle.format("editor.errorimagesave", Strings.parseException(e, false)));
Log.err(e);
}
});
@@ -150,16 +142,16 @@ public class MapEditorDialog extends Dialog implements Disposable{
t.row();
});
- menu.content().row();
+ menu.cont.row();
- menu.content().addImageTextButton("$text.quit", "icon-back", isize, () -> {
+ menu.cont.addImageTextButton("$quit", "icon-back", isize, () -> {
tryExit();
menu.hide();
}).padTop(-5).size(swidth * 2f + 10, 60f);
resizeDialog = new MapResizeDialog(editor, (x, y) -> {
if(!(editor.getMap().width() == x && editor.getMap().height() == y)){
- ui.loadGraphics(() -> {
+ ui.loadAnd(() -> {
editor.resize(x, y);
view.clearStack();
});
@@ -167,7 +159,7 @@ public class MapEditorDialog extends Dialog implements Disposable{
});
loadDialog = new MapLoadDialog(map ->
- ui.loadGraphics(() -> {
+ ui.loadAnd(() -> {
try(DataInputStream stream = new DataInputStream(map.stream.get())){
MapMeta meta = MapIO.readMapMeta(stream);
MapTileData data = MapIO.readTileData(stream, meta, false);
@@ -175,7 +167,7 @@ public class MapEditorDialog extends Dialog implements Disposable{
editor.beginEdit(data, meta.tags, false);
view.clearStack();
}catch(Exception e){
- ui.showError(Bundles.format("text.editor.errormapload", Strings.parseException(e, false)));
+ ui.showError(Core.bundle.format("editor.errorimageload", Strings.parseException(e, false)));
Log.err(e);
}
}));
@@ -191,7 +183,7 @@ public class MapEditorDialog extends Dialog implements Disposable{
return;
}
- Vector2 v = pane.stageToLocalCoordinates(Graphics.mouse());
+ Vector2 v = pane.stageToLocalCoordinates(Core.input.mouse());
if(v.x >= 0 && v.y >= 0 && v.x <= pane.getWidth() && v.y <= pane.getHeight()){
Core.scene.setScrollFocus(pane);
@@ -210,11 +202,11 @@ public class MapEditorDialog extends Dialog implements Disposable{
view.clearStack();
Core.scene.setScrollFocus(view);
if(!shownWithMap){
- editor.beginEdit(new MapTileData(256, 256), new ObjectMap<>(), true);
+ editor.beginEdit(new MapTileData(200, 200), new ObjectMap<>(), true);
}
shownWithMap = false;
- Timers.runTask(10f, Platform.instance::updateRPC);
+ Time.runTask(10f, Platform.instance::updateRPC);
});
hidden(() -> {
@@ -224,22 +216,22 @@ public class MapEditorDialog extends Dialog implements Disposable{
}
@Override
- protected void drawBackground(Batch batch, float parentAlpha, float x, float y){
- drawDefaultBackground(batch, parentAlpha, x, y);
+ protected void drawBackground(float x, float y){
+ drawDefaultBackground(x, y);
}
private void save(){
String name = editor.getTags().get("name", "");
if(name.isEmpty()){
- ui.showError("$text.editor.save.noname");
+ ui.showError("$editor.save.noname");
}else{
Map map = world.maps.getByName(name);
if(map != null && !map.custom){
- ui.showError("$text.editor.save.overwrite");
+ ui.showError("$editor.save.overwrite");
}else{
world.maps.saveMap(name, editor.getMap(), editor.getTags());
- ui.showInfoFade("$text.editor.saved");
+ ui.showInfoFade("$editor.saved");
}
}
@@ -259,7 +251,7 @@ public class MapEditorDialog extends Dialog implements Disposable{
float h = 90f;
- dialog.content().defaults().size(360f, h).padBottom(5).padRight(5).padLeft(5);
+ dialog.cont.defaults().size(360f, h).padBottom(5).padRight(5).padLeft(5);
for(int i = 0; i < arguments.length; i += 4){
String name = (String) arguments[i];
@@ -267,7 +259,7 @@ public class MapEditorDialog extends Dialog implements Disposable{
String iconname = (String) arguments[i + 2];
Runnable listenable = (Runnable) arguments[i + 3];
- TextButton button = dialog.content().addButton(name, () -> {
+ TextButton button = dialog.cont.addButton(name, () -> {
listenable.run();
dialog.hide();
menu.hide();
@@ -283,7 +275,7 @@ public class MapEditorDialog extends Dialog implements Disposable{
button.row();
- dialog.content().row();
+ dialog.cont.row();
}
dialog.addCloseButton();
@@ -301,7 +293,7 @@ public class MapEditorDialog extends Dialog implements Disposable{
}
public void beginEditMap(InputStream is){
- ui.loadGraphics(() -> {
+ ui.loadAnd(() -> {
try{
shownWithMap = true;
DataInputStream stream = new DataInputStream(is);
@@ -311,7 +303,7 @@ public class MapEditorDialog extends Dialog implements Disposable{
show();
}catch(Exception e){
Log.err(e);
- ui.showError(Bundles.format("text.editor.errorimageload", Strings.parseException(e, false)));
+ ui.showError(Core.bundle.format("editor.errorimageload", Strings.parseException(e, false)));
}
});
}
@@ -326,7 +318,7 @@ public class MapEditorDialog extends Dialog implements Disposable{
public void updateSelectedBlock(){
Block block = editor.getDrawBlock();
- for(int j = 0; j < content.blocks().size; j++){
+ for(int j = 0; j < Vars.content.blocks().size; j++){
if(block.id == j && j < blockgroup.getButtons().size){
blockgroup.getButtons().get(j).setChecked(true);
break;
@@ -341,8 +333,8 @@ public class MapEditorDialog extends Dialog implements Disposable{
public void build(){
float amount = 10f, baseSize = 60f;
- float size = mobile ? (int) (Math.min(Gdx.graphics.getHeight(), Gdx.graphics.getWidth()) / amount / Unit.dp.scl(1f)) :
- Math.min(Gdx.graphics.getDisplayMode().height / amount, baseSize);
+ float size = mobile ? (int) (Math.min(Core.graphics.getHeight(), Core.graphics.getWidth()) / amount / Unit.dp.scl(1f)) :
+ Math.min(Core.graphics.getDisplayMode().height / amount, baseSize);
clearChildren();
table(cont -> {
@@ -398,7 +390,7 @@ public class MapEditorDialog extends Dialog implements Disposable{
tools.row();
addTool.accept(EditorTool.fill);
- addTool.accept(EditorTool.elevation);
+ addTool.accept(EditorTool.spray);
ImageButton rotate = tools.addImageButton("icon-arrow-16", "clear", 16 * 2f, () -> editor.setDrawRotation((editor.getDrawRotation() + 1) % 4)).get();
rotate.getImage().update(() -> {
@@ -408,8 +400,8 @@ public class MapEditorDialog extends Dialog implements Disposable{
tools.row();
- tools.table("underline", t -> t.add("$text.editor.teams"))
- .colspan(3).height(40).width(size * 3f).padBottom(3);
+ tools.table("underline", t -> t.add("$editor.teams"))
+ .colspan(3).height(40).width(size * 3f + 3f).padBottom(3);
tools.row();
@@ -439,29 +431,10 @@ public class MapEditorDialog extends Dialog implements Disposable{
slider.moved(f -> editor.setBrushSize(MapEditor.brushSizes[(int) (float) f]));
t.top();
- t.add("$text.editor.brush");
+ t.add("$editor.brush");
t.row();
t.add(slider).width(size * 3f - 20).padTop(4f);
- }).padTop(5).growX().growY().top();
-
- mid.row();
-
- mid.table("underline", t -> t.add("$text.editor.elevation"))
- .colspan(3).height(40).width(size * 3f);
-
- mid.row();
-
- mid.table("underline", t -> {
- t.margin(0);
- t.addImageButton("icon-arrow-left", "clear-partial", 16 * 2f, () -> editor.setDrawElevation(editor.getDrawElevation() - 1))
- .disabled(b -> editor.getDrawElevation() <= -1).size(size);
-
- t.label(() -> editor.getDrawElevation() == -1 ? "$text.editor.slope" : (editor.getDrawElevation() + ""))
- .size(size).get().setAlignment(Align.center, Align.center);
-
- t.addImageButton("icon-arrow-right", "clear-partial", 16 * 2f, () -> editor.setDrawElevation(editor.getDrawElevation() + 1))
- .disabled(b -> editor.getDrawElevation() >= 63).size(size);
- }).colspan(3).height(size).width(size * 3f);
+ }).padTop(5).growX().top();
}).margin(0).left().growY();
@@ -476,35 +449,35 @@ public class MapEditorDialog extends Dialog implements Disposable{
private void doInput(){
//tool select
for(int i = 0; i < EditorTool.values().length; i++){
- if(Inputs.keyTap(Input.valueOf("NUM_" + (i + 1)))){
+ if(Core.input.keyTap(KeyCode.valueOf("NUM_" + (i + 1)))){
view.setTool(EditorTool.values()[i]);
break;
}
}
- if(Inputs.keyTap(Input.R)){
+ if(Core.input.keyTap(KeyCode.R)){
editor.setDrawRotation((editor.getDrawRotation() + 1) % 4);
}
- if(Inputs.keyTap(Input.E)){
+ if(Core.input.keyTap(KeyCode.E)){
editor.setDrawRotation(Mathf.mod((editor.getDrawRotation() + 1), 4));
}
//ctrl keys (undo, redo, save)
if(UIUtils.ctrl()){
- if(Inputs.keyTap(Input.Z)){
+ if(Core.input.keyTap(KeyCode.Z)){
view.undo();
}
- if(Inputs.keyTap(Input.Y)){
+ if(Core.input.keyTap(KeyCode.Y)){
view.redo();
}
- if(Inputs.keyTap(Input.S)){
+ if(Core.input.keyTap(KeyCode.S)){
save();
}
- if(Inputs.keyTap(Input.G)){
+ if(Core.input.keyTap(KeyCode.G)){
view.setGrid(!view.isGrid());
}
}
@@ -512,7 +485,7 @@ public class MapEditorDialog extends Dialog implements Disposable{
private void tryExit(){
if(!saved){
- ui.showConfirm("$text.confirm", "$text.editor.unsaved", this::hide);
+ ui.showConfirm("$confirm", "$editor.unsaved", this::hide);
}else{
hide();
}
@@ -528,29 +501,21 @@ public class MapEditorDialog extends Dialog implements Disposable{
int i = 0;
- for(Block block : Vars.content.blocks()){
- TextureRegion[] regions = block.getCompactIcon();
- if((block.synthetic() && (Recipe.getByResult(block) == null || !control.unlocks.isUnlocked(Recipe.getByResult(block))))
- && block != StorageBlocks.core){
- continue;
- }
+ blocksOut.clear();
+ blocksOut.addAll(Vars.content.blocks());
+ blocksOut.sort((b1, b2) -> b1.synthetic() && !b2.synthetic() ? 1 : b2.synthetic() && !b1.synthetic() ? -1 :
+ b1 instanceof OreBlock && !(b2 instanceof OreBlock) ? 1 : !(b1 instanceof OreBlock) && b2 instanceof OreBlock ? -1 :
+ Integer.compare(b1.id, b2.id));
- if(Recipe.getByResult(block) != null && !Recipe.getByResult(block).visibility.shown()){
- continue;
- }
+ for(Block block : blocksOut){
+ TextureRegion region = block.icon(Icon.medium);
- if(regions.length == 0 || regions[0] == Draw.region("jjfgj")) continue;
-
- Stack stack = new Stack();
-
- for(TextureRegion region : regions){
- stack.add(new Image(region));
- }
+ if(region == Core.atlas.find("jjfgj")) continue;
ImageButton button = new ImageButton("white", "clear-toggle");
+ button.getStyle().imageUp = new TextureRegionDrawable(region);
button.clicked(() -> editor.setDrawBlock(block));
button.resizeImage(8 * 4f);
- button.replaceImage(stack);
button.update(() -> button.setChecked(editor.getDrawBlock() == block));
group.add(button);
content.add(button).size(50f);
diff --git a/core/src/io/anuke/mindustry/editor/MapInfoDialog.java b/core/src/io/anuke/mindustry/editor/MapInfoDialog.java
index 6f4a046d45..f1e81e7ab0 100644
--- a/core/src/io/anuke/mindustry/editor/MapInfoDialog.java
+++ b/core/src/io/anuke/mindustry/editor/MapInfoDialog.java
@@ -1,11 +1,11 @@
package io.anuke.mindustry.editor;
-import com.badlogic.gdx.utils.ObjectMap;
+import io.anuke.arc.Core;
+import io.anuke.arc.collection.ObjectMap;
+import io.anuke.arc.scene.ui.TextArea;
+import io.anuke.arc.scene.ui.TextField;
import io.anuke.mindustry.core.Platform;
import io.anuke.mindustry.ui.dialogs.FloatingDialog;
-import io.anuke.ucore.core.Settings;
-import io.anuke.ucore.scene.ui.TextArea;
-import io.anuke.ucore.scene.ui.TextField;
public class MapInfoDialog extends FloatingDialog{
private final MapEditor editor;
@@ -15,7 +15,7 @@ public class MapInfoDialog extends FloatingDialog{
private TextField name;
public MapInfoDialog(MapEditor editor){
- super("$text.editor.mapinfo");
+ super("$editor.mapinfo");
this.editor = editor;
addCloseButton();
@@ -28,44 +28,37 @@ public class MapInfoDialog extends FloatingDialog{
}
private void setup(){
- content().clear();
+ cont.clear();
ObjectMap tags = editor.getTags();
- content().add("$text.editor.name").padRight(8).left();
+ cont.add("$editor.name").padRight(8).left();
- content().defaults().padTop(15);
+ cont.defaults().padTop(15);
- name = content().addField(tags.get("name", ""), text -> {
+ name = cont.addField(tags.get("name", ""), text -> {
tags.put("name", text);
}).size(400, 55f).get();
- name.setMessageText("$text.unknown");
+ name.setMessageText("$unknown");
- content().row();
+ cont.row();
- content().add("$text.editor.description").padRight(8).left();
+ cont.add("$editor.description").padRight(8).left();
- description = content().addArea(tags.get("description", ""), "textarea", text -> {
+ description = cont.addArea(tags.get("description", ""), "textarea", text -> {
tags.put("description", text);
}).size(400f, 140f).get();
- content().row();
+ cont.row();
- content().add("$text.editor.author").padRight(8).left();
+ cont.add("$editor.author").padRight(8).left();
- author = content().addField(tags.get("author", Settings.getString("mapAuthor", "")), text -> {
+ author = cont.addField(tags.get("author", Core.settings.getString("mapAuthor", "")), text -> {
tags.put("author", text);
- Settings.putString("mapAuthor", text);
- Settings.save();
+ Core.settings.put("mapAuthor", text);
+ Core.settings.save();
}).size(400, 55f).get();
- author.setMessageText("$text.unknown");
-
- content().row();
-
- content().add().padRight(8).left();
- content().addCheck("$text.editor.oregen", enabled -> {
- tags.put("oregen", enabled ? "1" : "0");
- }).update(c -> c.setChecked(!tags.get("oregen", "0").equals("0"))).left();
+ author.setMessageText("$unknown");
name.change();
description.change();
diff --git a/core/src/io/anuke/mindustry/editor/MapLoadDialog.java b/core/src/io/anuke/mindustry/editor/MapLoadDialog.java
index c819cd0a3a..0955dcdc6a 100644
--- a/core/src/io/anuke/mindustry/editor/MapLoadDialog.java
+++ b/core/src/io/anuke/mindustry/editor/MapLoadDialog.java
@@ -1,14 +1,14 @@
package io.anuke.mindustry.editor;
-import com.badlogic.gdx.utils.Scaling;
+import io.anuke.arc.util.Scaling;
import io.anuke.mindustry.maps.Map;
import io.anuke.mindustry.ui.BorderImage;
import io.anuke.mindustry.ui.dialogs.FloatingDialog;
-import io.anuke.ucore.function.Consumer;
-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.arc.function.Consumer;
+import io.anuke.arc.scene.ui.ButtonGroup;
+import io.anuke.arc.scene.ui.ScrollPane;
+import io.anuke.arc.scene.ui.TextButton;
+import io.anuke.arc.scene.ui.layout.Table;
import static io.anuke.mindustry.Vars.world;
@@ -16,12 +16,12 @@ public class MapLoadDialog extends FloatingDialog{
private Map selected = null;
public MapLoadDialog(Consumer