diff --git a/.gitignore b/.gitignore
index 4e59ef8187..9968b90f8e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -23,8 +23,6 @@ saves/
steam_appid.txt
/test_files/
/annotations/build/
-/desktop-sdl/build/
-desktop-sdl/build/
/android/assets/mindustry-maps/
/android/assets/mindustry-saves/
/core/assets/gifexport/
@@ -35,6 +33,7 @@ desktop-sdl/build/
ios/robovm.properties
packr-out/
config/
+changelog
*.gif
version.properties
diff --git a/.travis.yml b/.travis.yml
index 171280c268..f0586c145c 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -13,7 +13,7 @@ deploy:
api_key:
secure: Cv5wFtWt62/A24EvSEQvMow7gKPbZ3oATEFPuSghhB2TQz1dA40Zee3Qvk4LFlpLrhYo4K0ZSczCZRGpR+hCd8+Dpww52bheYEvWuh3ZQfvu/fXtEx2j5PwP1qMpmIgSxETV/gkD7l9FImdh0VzktYiAvQfmi0bEocG9/D4QwjFpNat7iwBdcMiw1MvAygpdIWRsjiw0RKlB2mWarmoHhQ7Gu7qlU3j50uaEvcrtmU0pBUPggNQwQRv32i9NPvNFxrqqlUjDLIS8JFea99zCkp8BwYqbEvBIMzd+Qip1/stLJJA3+cDUClbsDtg8rAVetzpOrdLEEBmqShFe5MDl2yEHcsgpN9CFsyTaUfvB3P3rVjizvycMm42IsUkXQiarm5xTQ/TIA8Rd8AHiSKuweNCg1Fd5SFaRtKy8JVLXuxyfUccmyje6hhz2L4lS2Wfj3mAG7sqZUCXhWP79EKdGkiPOjKv4CwXEKmuH3BMVqPlNUZJr9Eg3sV1FG0h2l+MVOOnR635qdUbb49sYojYxVruMLX0BH1c4ZCu230m8CUoWA1Em1QNI75ya7+9Y5T6AsgWDVpBvdUo9fWNbdp+VQ0GskFQsJD5wtnxbcbHeFiERAgGBm7z6qt9u9LrQpBH+dsW52ADvYsu3L4nQEa+sdMHwTTwmGY+iUvsxu0DqxGg=
file:
- - desktop/build/libs/desktop-release.jar
+ - desktop/build/libs/Mindustry.jar
- server/build/libs/server-release.jar
on:
repo: Anuken/Mindustry
diff --git a/README.md b/README.md
index 791a99452b..b0ec7c49e3 100644
--- a/README.md
+++ b/README.md
@@ -36,7 +36,7 @@ If the terminal returns `Permission denied` or `Command not found` on Mac/Linux,
---
Gradle may take up to several minutes to download files. Be patient.
-After building, the output .JAR file should be in `/desktop/build/libs/desktop-release.jar` for desktop builds, and in `/server/build/libs/server-release.jar` for server builds.
+After building, the output .JAR file should be in `/desktop/build/libs/Mindustry.jar` for desktop builds, and in `/server/build/libs/server-release.jar` for server builds.
### Downloads
diff --git a/android/build.gradle b/android/build.gradle
index e24bbab771..b1b9ef5628 100644
--- a/android/build.gradle
+++ b/android/build.gradle
@@ -8,7 +8,7 @@ buildscript{
}
dependencies{
- classpath 'com.android.tools.build:gradle:3.4.2'
+ classpath 'com.android.tools.build:gradle:3.5.0'
}
}
diff --git a/build.gradle b/build.gradle
index b743d32379..11c75a5436 100644
--- a/build.gradle
+++ b/build.gradle
@@ -146,23 +146,6 @@ allprojects{
project(":desktop"){
apply plugin: "java"
- dependencies{
- compile project(":core")
- compile project(":net")
-
- if(debugged()) compile project(":debug")
-
- compile "com.badlogicgames.gdx:gdx-platform:$gdxVersion:natives-desktop"
- compile "com.badlogicgames.gdx:gdx-freetype-platform:$gdxVersion:natives-desktop"
-
- compile arcModule("backends:backend-lwjgl3")
- compile 'com.github.MinnDevelopment:java-discord-rpc:v2.0.2'
- }
-}
-
-project(":desktop-sdl"){
- apply plugin: "java"
-
dependencies{
compile project(":core")
compile project(":net")
@@ -318,3 +301,24 @@ project(":net"){
compile "org.lz4:lz4-java:1.4.1"
}
}
+
+task deployAll{
+ task cleanDeployOutput{
+ doFirst{
+ if("${getBuildVersion()}" == "custom build" || "${getBuildVersion()}" == "") throw new IllegalArgumentException("----\n\nSET A BUILD NUMBER FIRST!\n\n----")
+ if(!project.hasProperty("release")) throw new IllegalArgumentException("----\n\nSET THE RELEASE PROJECT PROPERTY FIRST!\n\n----")
+
+ delete{
+ delete "deploy/"
+ }
+ }
+ }
+
+ dependsOn cleanDeployOutput
+ dependsOn "desktop:packrLinux64"
+ dependsOn "desktop:packrWindows64"
+ dependsOn "desktop:packrWindows32"
+ dependsOn "desktop:packrMacOS"
+ dependsOn "server:deploy"
+ dependsOn "android:deploy"
+}
\ No newline at end of file
diff --git a/core/assets/bundles/bundle.properties b/core/assets/bundles/bundle.properties
index 4f6f4be95d..9fe58d1b1b 100644
--- a/core/assets/bundles/bundle.properties
+++ b/core/assets/bundles/bundle.properties
@@ -75,6 +75,7 @@ server.kicked.nameEmpty = Your chosen name is invalid.
server.kicked.idInUse = You are already on this server! Connecting with two accounts is not permitted.
server.kicked.customClient = This server does not support custom builds. Download an official version.
server.kicked.gameover = Game over!
+server.versions = Your version:[accent] {0}[]\nServer version:[accent] {1}[]
host.info = The [accent]host[] button hosts a server on port [scarlet]6567[]. \nAnybody on the same [lightgray]wifi or local network[] should be able to see your server in their server list.\n\nIf you want people to be able to connect from anywhere by IP, [accent]port forwarding[] is required.\n\n[lightgray]Note: If someone is experiencing trouble connecting to your LAN game, make sure you have allowed Mindustry access to your local network in your firewall settings. Note that public networks sometimes do not allow server discovery.
join.info = Here, you can enter a [accent]server IP[] to connect to, or discover [accent]local network[] servers to connect to.\nBoth LAN and WAN multiplayer is supported.\n\n[lightgray]Note: There is no automatic global server list; if you want to connect to someone by IP, you would need to ask the host for their IP.
hostserver = Host Multiplayer Game
diff --git a/core/assets/maps/veins.msav b/core/assets/maps/veins.msav
index 87e62486c7..133d783abc 100644
Binary files a/core/assets/maps/veins.msav and b/core/assets/maps/veins.msav differ
diff --git a/core/src/io/anuke/mindustry/content/TechTree.java b/core/src/io/anuke/mindustry/content/TechTree.java
index 6ca60ed2c1..10930e51a5 100644
--- a/core/src/io/anuke/mindustry/content/TechTree.java
+++ b/core/src/io/anuke/mindustry/content/TechTree.java
@@ -227,12 +227,14 @@ public class TechTree implements ContentList{
node(turbineGenerator, () -> {
node(thermalGenerator, () -> {
- node(rtgGenerator, () -> {
- node(differentialGenerator, () -> {
- node(thoriumReactor, () -> {
- node(impactReactor, () -> {
+ node(differentialGenerator, () -> {
+ node(thoriumReactor, () -> {
+ node(impactReactor, () -> {
+
+ });
+
+ node(rtgGenerator, () -> {
- });
});
});
});
diff --git a/core/src/io/anuke/mindustry/core/Control.java b/core/src/io/anuke/mindustry/core/Control.java
index b4fbdc2151..2406ca7556 100644
--- a/core/src/io/anuke/mindustry/core/Control.java
+++ b/core/src/io/anuke/mindustry/core/Control.java
@@ -84,7 +84,7 @@ public class Control implements ApplicationListener{
});
Events.on(PlayEvent.class, event -> {
- player.setTeam(state.rules.pvp ? netServer.assignTeam(playerGroup.all()) : defaultTeam);
+ player.setTeam(state.rules.pvp ? netServer.assignTeam(player, playerGroup.all()) : defaultTeam);
player.setDead(true);
player.add();
diff --git a/core/src/io/anuke/mindustry/core/NetServer.java b/core/src/io/anuke/mindustry/core/NetServer.java
index ede04df856..8d210cb930 100644
--- a/core/src/io/anuke/mindustry/core/NetServer.java
+++ b/core/src/io/anuke/mindustry/core/NetServer.java
@@ -176,7 +176,7 @@ public class NetServer implements ApplicationListener{
//playing in pvp mode automatically assigns players to teams
if(state.rules.pvp){
- player.setTeam(assignTeam(playerGroup.all()));
+ player.setTeam(assignTeam(player, playerGroup.all()));
Log.info("Auto-assigned player {0} to team {1}.", player.name, player.getTeam());
}
@@ -194,13 +194,13 @@ public class NetServer implements ApplicationListener{
});
}
- public Team assignTeam(Iterable players){
+ public Team assignTeam(Player current, Iterable players){
//find team with minimum amount of players and auto-assign player to that.
return Structs.findMin(Team.all, team -> {
if(state.teams.isActive(team) && !state.teams.get(team).cores.isEmpty()){
int count = 0;
for(Player other : players){
- if(other.getTeam() == team){
+ if(other.getTeam() == team && other != current){
count++;
}
}
diff --git a/core/src/io/anuke/mindustry/entities/type/Player.java b/core/src/io/anuke/mindustry/entities/type/Player.java
index dbc26c34fb..6d0ab81cc5 100644
--- a/core/src/io/anuke/mindustry/entities/type/Player.java
+++ b/core/src/io/anuke/mindustry/entities/type/Player.java
@@ -527,7 +527,9 @@ public class Player extends Unit implements BuilderMinerTrait, ShooterTrait{
spawner = null;
}
- avoidOthers();
+ if(isLocal || Net.server()){
+ avoidOthers();
+ }
Tile tile = world.tileWorld(x, y);
diff --git a/core/src/io/anuke/mindustry/maps/Maps.java b/core/src/io/anuke/mindustry/maps/Maps.java
index e2360e16e5..aebe5859b0 100644
--- a/core/src/io/anuke/mindustry/maps/Maps.java
+++ b/core/src/io/anuke/mindustry/maps/Maps.java
@@ -214,7 +214,12 @@ public class Maps implements Disposable{
return filters;
}else{
- return JsonIO.read(Array.class, str);
+ try{
+ return JsonIO.read(Array.class, str);
+ }catch(Exception e){
+ e.printStackTrace();
+ return readFilters("");
+ }
}
}
diff --git a/core/src/io/anuke/mindustry/ui/dialogs/JoinDialog.java b/core/src/io/anuke/mindustry/ui/dialogs/JoinDialog.java
index 71f72577fc..7b1486c270 100644
--- a/core/src/io/anuke/mindustry/ui/dialogs/JoinDialog.java
+++ b/core/src/io/anuke/mindustry/ui/dialogs/JoinDialog.java
@@ -1,21 +1,20 @@
package io.anuke.mindustry.ui.dialogs;
-import io.anuke.annotations.Annotations.Serialize;
-import io.anuke.arc.Core;
-import io.anuke.arc.collection.Array;
-import io.anuke.arc.graphics.Color;
-import io.anuke.arc.math.Mathf;
-import io.anuke.arc.scene.style.Drawable;
+import io.anuke.annotations.Annotations.*;
+import io.anuke.arc.*;
+import io.anuke.arc.collection.*;
+import io.anuke.arc.graphics.*;
+import io.anuke.arc.math.*;
+import io.anuke.arc.scene.style.*;
import io.anuke.arc.scene.ui.*;
-import io.anuke.arc.scene.ui.layout.Cell;
-import io.anuke.arc.scene.ui.layout.Table;
-import io.anuke.arc.util.Strings;
-import io.anuke.arc.util.Time;
-import io.anuke.mindustry.Vars;
-import io.anuke.mindustry.core.Platform;
-import io.anuke.mindustry.game.Version;
-import io.anuke.mindustry.net.Host;
+import io.anuke.arc.scene.ui.layout.*;
+import io.anuke.arc.util.*;
+import io.anuke.mindustry.*;
+import io.anuke.mindustry.core.*;
+import io.anuke.mindustry.game.*;
import io.anuke.mindustry.net.Net;
+import io.anuke.mindustry.net.*;
+import io.anuke.mindustry.net.Packets.*;
import static io.anuke.mindustry.Vars.*;
@@ -97,9 +96,14 @@ public class JoinDialog extends FloatingDialog{
TextButton button = buttons[0] = remote.addButton("[accent]" + server.displayIP(), "clear", () -> {
if(!buttons[0].childrenPressed()){
- connect(server.ip, server.port);
+ if(server.lastHost != null && server.lastHost.version != Version.build && Version.build != -1 && server.lastHost.version != -1){
+ ui.showInfo("[scarlet]" + (server.lastHost.version > Version.build ? KickReason.clientOutdated : KickReason.serverOutdated).toString() + "\n[]" +
+ Core.bundle.format("server.versions", Version.build, server.lastHost.version));
+ }else{
+ connect(server.ip, server.port);
+ }
}
- }).width(targetWidth()).height(130f).pad(4f).get();
+ }).width(targetWidth()).pad(4f).get();
button.getLabel().setWrap(true);
diff --git a/core/src/io/anuke/mindustry/ui/dialogs/ZoneInfoDialog.java b/core/src/io/anuke/mindustry/ui/dialogs/ZoneInfoDialog.java
index 36baa4125f..55de763cc2 100644
--- a/core/src/io/anuke/mindustry/ui/dialogs/ZoneInfoDialog.java
+++ b/core/src/io/anuke/mindustry/ui/dialogs/ZoneInfoDialog.java
@@ -113,9 +113,16 @@ public class ZoneInfoDialog extends FloatingDialog{
t.add("$zone.resources").padRight(6);
if(zone.resources.length > 0){
- for(Item item : zone.resources){
- t.addImage(item.icon(Item.Icon.medium)).size(8 * 3);
- }
+ t.table(r -> {
+ t.left();
+ int i = 0;
+ for(Item item : zone.resources){
+ r.addImage(item.icon(Item.Icon.medium)).size(8 * 3);
+ if(++i % 4 == 0){
+ r.row();
+ }
+ }
+ });
}else{
t.add("$none");
}
diff --git a/core/src/io/anuke/mindustry/ui/fragments/HudFragment.java b/core/src/io/anuke/mindustry/ui/fragments/HudFragment.java
index 6c6b0beaaf..72a01f3070 100644
--- a/core/src/io/anuke/mindustry/ui/fragments/HudFragment.java
+++ b/core/src/io/anuke/mindustry/ui/fragments/HudFragment.java
@@ -242,9 +242,9 @@ public class HudFragment extends Fragment{
IntFormat fps = new IntFormat("fps");
IntFormat ping = new IntFormat("ping");
- info.label(() -> fps.get(Core.graphics.getFramesPerSecond())).left();
+ info.label(() -> fps.get(Core.graphics.getFramesPerSecond())).left().style("outline");
info.row();
- info.label(() -> ping.get(Net.getPing())).visible(Net::client).left();
+ info.label(() -> ping.get(Net.getPing())).visible(Net::client).left().style("outline");
}).top().left();
});
diff --git a/core/src/io/anuke/mindustry/world/Block.java b/core/src/io/anuke/mindustry/world/Block.java
index 577d40771e..189911c66f 100644
--- a/core/src/io/anuke/mindustry/world/Block.java
+++ b/core/src/io/anuke/mindustry/world/Block.java
@@ -294,9 +294,7 @@ public class Block extends BlockStorage{
/** Called after the block is placed by this client. */
@CallSuper
public void playerPlaced(Tile tile){
- if(outputsPower && !consumesPower){
- PowerNode.lastPlaced = tile.pos();
- }
+
}
/** Called after the block is placed by anyone. */
diff --git a/core/src/io/anuke/mindustry/world/blocks/power/PowerNode.java b/core/src/io/anuke/mindustry/world/blocks/power/PowerNode.java
index 86220b6acc..358fb27a43 100644
--- a/core/src/io/anuke/mindustry/world/blocks/power/PowerNode.java
+++ b/core/src/io/anuke/mindustry/world/blocks/power/PowerNode.java
@@ -2,6 +2,7 @@ package io.anuke.mindustry.world.blocks.power;
import io.anuke.annotations.Annotations.*;
import io.anuke.arc.*;
+import io.anuke.arc.collection.*;
import io.anuke.arc.function.*;
import io.anuke.arc.graphics.*;
import io.anuke.arc.graphics.g2d.*;
@@ -20,9 +21,7 @@ import io.anuke.mindustry.world.meta.*;
import static io.anuke.mindustry.Vars.*;
public class PowerNode extends PowerBlock{
- //last distribution block placed
- public static int lastPlaced = -1;
-
+ protected ObjectSet graphs = new ObjectSet<>();
protected Vector2 t1 = new Vector2(), t2 = new Vector2();
protected TextureRegion laser, laserEnd;
@@ -99,23 +98,11 @@ public class PowerNode extends PowerBlock{
() -> Mathf.clamp(entity.power.graph.getPowerProduced() / entity.power.graph.getPowerNeeded())));
}
- @Override
- public void playerPlaced(Tile tile){
- Tile before = world.tile(lastPlaced);
-
- if(linkValid(tile, before) && !before.entity.proximity().contains(tile)){
- Call.linkPowerNodes(null, tile, before);
- }
-
- lastPlaced = tile.pos();
- super.playerPlaced(tile);
- }
-
@Override
public void placed(Tile tile){
if(Net.client()) return;
- Predicate valid = other -> other != null && other != tile && ((!other.block().outputsPower && other.block().consumesPower) || (other.block().outputsPower && !other.block().consumesPower)) && linkValid(tile, other)
+ Predicate valid = other -> other != null && other != tile && ((!other.block().outputsPower && other.block().consumesPower) || (other.block().outputsPower && !other.block().consumesPower) || other.block() instanceof PowerNode) && linkValid(tile, other)
&& !other.entity.proximity().contains(tile) && other.entity.power.graph != tile.entity.power.graph;
tempTiles.clear();
@@ -132,6 +119,28 @@ public class PowerNode extends PowerBlock{
super.placed(tile);
}
+ private void getPotentialLinks(Tile tile, Consumer others){
+ Predicate valid = other -> other != null && other != tile && other.entity != null && other.entity.power != null &&
+ ((!other.block().outputsPower && other.block().consumesPower) || (other.block().outputsPower && !other.block().consumesPower) || other.block() instanceof PowerNode) &&
+ overlaps(tile.x * tilesize + offset(), tile.y *tilesize + offset(), other, laserRange * tilesize)
+ && !other.entity.proximity().contains(tile) && !graphs.contains(other.entity.power.graph);
+
+ tempTiles.clear();
+ graphs.clear();
+ Geometry.circle(tile.x, tile.y, (int)(laserRange + 1), (x, y) -> {
+ Tile other = world.ltile(x, y);
+ if(valid.test(other)){
+ tempTiles.add(other);
+ }
+ });
+
+ tempTiles.sort(Structs.comparingFloat(t -> t.dst2(tile)));
+ tempTiles.each(valid, t -> {
+ graphs.add(t.entity.power.graph);
+ others.accept(t);
+ });
+ }
+
@Override
public void setStats(){
super.setStats();
@@ -213,6 +222,11 @@ public class PowerNode extends PowerBlock{
Draw.color(Pal.placing);
Drawf.circles(x * tilesize + offset(), y * tilesize + offset(), laserRange * tilesize);
+ getPotentialLinks(tile, other -> {
+ Drawf.square(other.drawx(), other.drawy(), other.block().size * tilesize / 2f + 2f, Pal.place);
+ });
+
+ /*
for(int cx = (int)(x - laserRange - 1); cx <= x + laserRange + 1; cx++){
for(int cy = (int)(y - laserRange - 1); cy <= y + laserRange + 1; cy++){
Tile link = world.ltile(cx, cy);
@@ -221,7 +235,7 @@ public class PowerNode extends PowerBlock{
Drawf.square(link.drawx(), link.drawy(), link.block().size * tilesize / 2f + 2f, link.pos() == lastPlaced ? Pal.place : Pal.accent);
}
}
- }
+ }*/
Draw.reset();
}
diff --git a/core/src/io/anuke/mindustry/world/blocks/production/LiquidConverter.java b/core/src/io/anuke/mindustry/world/blocks/production/LiquidConverter.java
index d53f6268c0..7c9da8619d 100644
--- a/core/src/io/anuke/mindustry/world/blocks/production/LiquidConverter.java
+++ b/core/src/io/anuke/mindustry/world/blocks/production/LiquidConverter.java
@@ -12,6 +12,11 @@ public class LiquidConverter extends GenericCrafter{
hasLiquids = true;
}
+ @Override
+ public boolean outputsItems(){
+ return false;
+ }
+
@Override
public void init(){
ConsumeLiquidBase cl = consumes.get(ConsumeType.liquid);
diff --git a/desktop-sdl/build.gradle b/desktop-sdl/build.gradle
deleted file mode 100644
index 08cf179196..0000000000
--- a/desktop-sdl/build.gradle
+++ /dev/null
@@ -1,99 +0,0 @@
-apply plugin: "java"
-
-sourceCompatibility = 1.8
-sourceSets.main.java.srcDirs = [ "src/" ]
-
-project.ext.mainClassName = "io.anuke.mindustry.desktopsdl.DesktopLauncher"
-project.ext.assetsDir = new File("../core/assets")
-
-def IKVM_DIR = System.env.IKVM_HOME
-def getTarget = { return project.hasProperty("target") ? project.properties["target"] : "windows" }
-
-task run(dependsOn: classes, type: JavaExec){
- main = project.mainClassName
- classpath = sourceSets.main.runtimeClasspath
- standardInput = System.in
- workingDir = project.assetsDir
- ignoreExitValue = true
-
- if(System.getProperty("os.name").toLowerCase().contains("mac")){
- jvmArgs("-XstartOnFirstThread", "-Djava.awt.headless=true")
- }
-
- if(project.hasProperty("args")){
- args Eval.me(project.getProperties()["args"])
- }
-
- if(args.contains("debug")){
- main = "io.anuke.mindustry.DebugLauncher"
- }
-}
-
-task dist(type: Jar, dependsOn: classes){
- from files(sourceSets.main.output.classesDirs)
- from files(sourceSets.main.output.resourcesDir)
- from {configurations.compile.collect {zipTree(it)}}
- from files(project.assetsDir)
-
- //use target = all for all platforms
- def target = getTarget()
- if(target.contains("windows")) exclude('**.so', "**.dylib")
- if(target == "mac") exclude('**.so', "**.dll")
- if(target == "linux") exclude('**.dll', "**.dylib")
- archivesBaseName = appName + "-" + target
-
- manifest{
- attributes 'Main-Class': project.mainClassName
- }
-}
-
-task steamdist(dependsOn: dist){
- doLast{
- copy{
- from "build/libs/Mindustry-linux-release.jar"
- into "/home/anuke/.steam/steam/steamapps/common/Mindustry"
- rename { String fileName ->
- fileName.replace("Mindustry-linux-release", "desktop-release")
- }
- }
- }
-}
-
-task ikZip(type: Zip){
- def filename = "$appName-${getTarget()}-${version}"
-
- from "build/libs/$filename"
- archiveName = "${generateDeployName(getTarget())}.zip"
-}
-
-task ikdist{
- dependsOn dist
- finalizedBy ikZip
-
- doLast{
- def filename = "$appName-${getTarget()}-${version}"
- def folder = "build/libs/$filename"
- def baseArgs = System.properties['os.name'].toLowerCase().contains('windows') ? [] : ["mono"]
- def args = baseArgs + ["$IKVM_DIR/ikvmc.exe", "-target:winexe", "-out:build/libs/${filename}.exe", "build/libs/${filename}.jar"]
- if(file("../core/assets/sprites/icon.ico").exists()){
- args += ["-win32icon:../core/assets/sprites/icon.ico"]
- }else if(file("../core/assets/icons/icon.ico").exists()){
- args += ["-win32icon:../core/assets/icons/icon.ico"]
- }
-
- exec{
- commandLine args
- }
-
- copy{
- from file("build/libs/${filename}.exe")
- into file(folder)
- }
-
- copy{
- from(getTarget().contains("32") ? "$IKVM_DIR/libraries_32" : "$IKVM_DIR/libraries")
- into folder
- }
- }
-}
-
diff --git a/desktop-sdl/src/io/anuke/mindustry/desktopsdl/DesktopLauncher.java b/desktop-sdl/src/io/anuke/mindustry/desktopsdl/DesktopLauncher.java
deleted file mode 100644
index 260cde9c7a..0000000000
--- a/desktop-sdl/src/io/anuke/mindustry/desktopsdl/DesktopLauncher.java
+++ /dev/null
@@ -1,31 +0,0 @@
-package io.anuke.mindustry.desktopsdl;
-import io.anuke.arc.Files.*;
-import io.anuke.arc.backends.sdl.*;
-import io.anuke.mindustry.*;
-import io.anuke.mindustry.core.*;
-import io.anuke.mindustry.desktopsdl.steam.*;
-import io.anuke.mindustry.net.*;
-
-public class DesktopLauncher{
-
- public static void main(String[] arg){
- try{
- Platform.instance = new DesktopPlatform(arg);
-
- Net.setClientProvider(new ArcNetClient());
- Net.setServerProvider(new ServerSteam(new ArcNetServer()));
-
- new SdlApplication(new Mindustry(), new SdlConfig(){{
- title = "Mindustry";
- maximized = true;
- depth = 0;
- stencil = 0;
- width = 900;
- height = 700;
- setWindowIcon(FileType.Internal, "icons/icon_64.png");
- }});
- }catch(Throwable e){
- DesktopPlatform.handleCrash(e);
- }
- }
-}
diff --git a/desktop-sdl/src/io/anuke/mindustry/desktopsdl/DesktopPlatform.java b/desktop-sdl/src/io/anuke/mindustry/desktopsdl/DesktopPlatform.java
deleted file mode 100644
index 98f7a07175..0000000000
--- a/desktop-sdl/src/io/anuke/mindustry/desktopsdl/DesktopPlatform.java
+++ /dev/null
@@ -1,180 +0,0 @@
-package io.anuke.mindustry.desktopsdl;
-
-import club.minnced.discord.rpc.*;
-import com.codedisaster.steamworks.*;
-import io.anuke.arc.*;
-import io.anuke.arc.backends.sdl.jni.*;
-import io.anuke.arc.collection.*;
-import io.anuke.arc.files.*;
-import io.anuke.arc.function.*;
-import io.anuke.arc.util.*;
-import io.anuke.arc.util.serialization.*;
-import io.anuke.mindustry.*;
-import io.anuke.mindustry.core.GameState.*;
-import io.anuke.mindustry.core.*;
-import io.anuke.mindustry.desktopsdl.steam.*;
-import io.anuke.mindustry.game.EventType.*;
-import io.anuke.mindustry.net.Net;
-import io.anuke.mindustry.net.*;
-import io.anuke.mindustry.ui.dialogs.*;
-
-import java.net.*;
-import java.util.*;
-
-import static io.anuke.mindustry.Vars.*;
-
-
-public class DesktopPlatform extends Platform{
- static boolean useDiscord = OS.is64Bit, useSteam = true;
- final static String applicationId = "610508934456934412";
- String[] args;
-
- public DesktopPlatform(String[] args){
- this.args = args;
-
- testMobile = Array.with(args).contains("-testMobile");
-
- if(useDiscord){
- try{
- DiscordEventHandlers handlers = new DiscordEventHandlers();
- DiscordRPC.INSTANCE.Discord_Initialize(applicationId, handlers, true, "");
-
- Runtime.getRuntime().addShutdownHook(new Thread(DiscordRPC.INSTANCE::Discord_Shutdown));
- }catch(Throwable t){
- useDiscord = false;
- Log.err("Failed to initialize discord.", t);
- }
- }
-
- if(useSteam){
- Vars.steam = true;
- try{
- SteamAPI.loadLibraries();
- if(!SteamAPI.init()){
- Log.info("Steam client not running. Make sure Steam is running!");
- }else{
- //times per second
- float interval = 20f;
- Interval i = new Interval();
-
- //run steam callbacks
- Events.on(GameLoadEvent.class, event -> {
- //update callbacks
- Core.app.addListener(new ApplicationListener(){
- @Override
- public void update(){
- if(i.get(interval)){
- if(SteamAPI.isSteamRunning()){
- SteamAPI.runCallbacks();
- }
- }
- }
- });
-
- Core.app.post(() -> new ClientSteam());
- });
- //steam shutdown hook
- Runtime.getRuntime().addShutdownHook(new Thread(SteamAPI::shutdown));
- }
- }catch(Exception e){
- Log.err("Failed to load Steam native libraries.");
- e.printStackTrace();
- }
- }
- }
-
- static void handleCrash(Throwable e){
- Consumer dialog = Runnable::run;
- boolean badGPU = false;
-
- if(e.getMessage() != null && (e.getMessage().contains("Couldn't create window") || e.getMessage().contains("OpenGL 2.0 or higher"))){
-
- dialog.accept(() -> message(
- e.getMessage().contains("Couldn't create window") ? "A graphics initialization error has occured! Try to update your graphics drivers:\n" + e.getMessage() :
- "Your graphics card does not support OpenGL 2.0!\n" +
- "Try to update your graphics drivers.\n\n" +
- "(If that doesn't work, your computer just doesn't support Mindustry.)"));
- badGPU = true;
- }
-
- boolean fbgp = badGPU;
-
- CrashSender.send(e, file -> {
- if(!fbgp){
- dialog.accept(() -> message("A crash has occured. It has been saved in:\n" + file.getAbsolutePath() + "\n" + (e.getMessage() == null ? "" : "\n" + e.getMessage())));
- }
- });
- }
-
- @Override
- public void showFileChooser(String text, String content, Consumer cons, boolean open, Predicate filetype){
- new FileChooser(text, file -> filetype.test(file.extension().toLowerCase()), open, cons).show();
- }
-
- @Override
- public void updateRPC(){
-
- if(!useDiscord) return;
-
- DiscordRichPresence presence = new DiscordRichPresence();
-
- if(!state.is(State.menu)){
- String map = world.getMap() == null ? "Unknown Map" : world.isZone() ? world.getZone().localizedName : Strings.capitalize(world.getMap().name());
- String mode = state.rules.pvp ? "PvP" : state.rules.attackMode ? "Attack" : "Survival";
- String players = Net.active() && playerGroup.size() > 1 ? " | " + playerGroup.size() + " Players" : "";
-
- presence.state = mode + players;
-
- if(!state.rules.waves){
- presence.details = map;
- }else{
- presence.details = map + " | Wave " + state.wave;
- presence.largeImageText = "Wave " + state.wave;
- }
- }else{
- if(ui.editor != null && ui.editor.isShown()){
- presence.state = "In Editor";
- }else if(ui.deploy != null && ui.deploy.isShown()){
- presence.state = "In Launch Selection";
- }else{
- presence.state = "In Menu";
- }
- }
-
- presence.largeImageKey = "logo";
-
- DiscordRPC.INSTANCE.Discord_UpdatePresence(presence);
- }
-
- @Override
- public String getUUID(){
- try{
- Enumeration e = NetworkInterface.getNetworkInterfaces();
- NetworkInterface out;
- for(out = e.nextElement(); (out.getHardwareAddress() == null || !validAddress(out.getHardwareAddress())) && e.hasMoreElements(); out = e.nextElement()) ;
-
- byte[] bytes = out.getHardwareAddress();
- byte[] result = new byte[8];
- System.arraycopy(bytes, 0, result, 0, bytes.length);
-
- String str = new String(Base64Coder.encode(result));
-
- if(str.equals("AAAAAAAAAOA=") || str.equals("AAAAAAAAAAA=")) throw new RuntimeException("Bad UUID.");
-
- return str;
- }catch(Exception e){
- return super.getUUID();
- }
- }
-
- private static void message(String message){
- SDL.SDL_ShowSimpleMessageBox(SDL.SDL_MESSAGEBOX_ERROR, "oh no", message);
- }
-
- private boolean validAddress(byte[] bytes){
- if(bytes == null) return false;
- byte[] result = new byte[8];
- System.arraycopy(bytes, 0, result, 0, bytes.length);
- return !new String(Base64Coder.encode(result)).equals("AAAAAAAAAOA=") && !new String(Base64Coder.encode(result)).equals("AAAAAAAAAAA=");
- }
-}
diff --git a/desktop/build.gradle b/desktop/build.gradle
index 65139a81c3..76adfe2684 100644
--- a/desktop/build.gradle
+++ b/desktop/build.gradle
@@ -1,43 +1,28 @@
+import com.badlogicgames.packr.Packr
+import com.badlogicgames.packr.PackrConfig
+
apply plugin: "java"
sourceCompatibility = 1.8
-sourceSets.main.java.srcDirs = ["src/"]
+sourceSets.main.java.srcDirs = [ "src/" ]
project.ext.mainClassName = "io.anuke.mindustry.desktop.DesktopLauncher"
project.ext.assetsDir = new File("../core/assets")
-def IKVM_DIR = System.env.IKVM_HOME
-
-import com.badlogicgames.packr.Packr
-import com.badlogicgames.packr.PackrConfig
-
def JDK_DIR = "$System.env.PACKR_DIR"
def ICON_DIR = new File("core/assets/icons/icon.icns")
-ext.getPlatform = {
- def lc = project.hasProperty("platform") ? platform.toLowerCase() : ""
- if(lc == "windows64"){
- return PackrConfig.Platform.Windows64
- }else if(lc == "windows32"){
- return PackrConfig.Platform.Windows32
- }else if(lc == "linux"){
- return PackrConfig.Platform.Linux64
- }else if(lc == "mac"){
- return PackrConfig.Platform.MacOS
- }else{
- throw new InvalidUserDataException("Invalid platform. Set platform with -Pplatform=windows64/windows32/linux/mac")
- }
-}
-
task run(dependsOn: classes, type: JavaExec){
main = project.mainClassName
classpath = sourceSets.main.runtimeClasspath
standardInput = System.in
workingDir = project.assetsDir
- if(System.getProperty("os.name").toLowerCase().contains("mac")){
- jvmArgs "-XstartOnFirstThread"
- }
ignoreExitValue = true
+
+ if(System.getProperty("os.name").toLowerCase().contains("mac")){
+ jvmArgs("-XstartOnFirstThread", "-Djava.awt.headless=true")
+ }
+
if(project.hasProperty("args")){
args Eval.me(project.getProperties()["args"])
}
@@ -47,132 +32,122 @@ task run(dependsOn: classes, type: JavaExec){
}
}
-task debug(dependsOn: classes, type: JavaExec){
- main = project.mainClassName
- classpath = sourceSets.main.runtimeClasspath
- standardInput = System.in
- workingDir = project.assetsDir
- ignoreExitValue = true
- debug = true
-}
-
-task dist(type: Jar){
- dependsOn classes
-
- writeVersion()
+task dist(type: Jar, dependsOn: classes){
from files(sourceSets.main.output.classesDirs)
from files(sourceSets.main.output.resourcesDir)
- from{ configurations.compile.collect{ zipTree(it) } }
+ from {configurations.compile.collect {zipTree(it)}}
from files(project.assetsDir)
+ archiveName = "${appName}.jar"
+
manifest{
attributes 'Main-Class': project.mainClassName
}
}
-//note: call desktop:dist beforehand
-task packrCmd(){
-
+task steamdist(dependsOn: dist){
doLast{
- def config = new PackrConfig()
- config.with{
- config.executable = appName
- verbose = true
- platform = getPlatform()
- bundleIdentifier = getPackage() + ".mac"
- iconResource = ICON_DIR
- outDir = file("packr-out/")
- mainClass = project.ext.mainClassName
- classpath = ["desktop/build/libs/desktop-release.jar"]
- removePlatformLibs = ["desktop/build/libs/desktop-release.jar"]
-
- vmArgs = ["Djava.net.preferIPv4Stack=true"]
- minimizeJre = "desktop/packr_minimize.json"
- jdk = JDK_DIR + "jdk-${getPlatform().toString().toLowerCase()}.zip"
-
- if(getPlatform() == PackrConfig.Platform.MacOS){
- vmArgs += "XstartOnFirstThread"
+ copy{
+ from "build/libs/Mindustry-linux-release.jar"
+ into "/home/anuke/.steam/steam/steamapps/common/Mindustry"
+ rename { String fileName ->
+ fileName.replace("Mindustry-linux-release", "desktop-release")
}
}
-
- new Packr().pack(config)
- }
-}
-
-task copyTemplate(){
- doLast{
- copy{
- into "packr-out/"
- from "${JDK_DIR}/templates/${getPlatform().toString().toLowerCase()}"
- }
-
- copy{
- into "packr-out/"
- from "build/libs/desktop-release.jar"
- }
}
}
-task packrZip(){
- task clearOut(type: Delete){
- doLast{
- delete "packr-out/"
- }
- }
+PackrConfig.Platform.values().each{ platform ->
+ task "packr${platform.toString()}"{
+ def platformName = platform.toString().replace('64', '').replace('32', '').replace('MacOS', 'Mac')
- task fixMac(type: Copy){
- dependsOn "packrCmd"
-
- into "packr-out/" + appName + ".app/Contents/"
- from "packr-out/Contents/"
-
- doLast{
- delete{
- delete "packr-out/Contents/"
- }
- }
- }
-
- task fixWindows32(type: Copy){
- dependsOn "packrCmd"
-
- into "packr-out/jre/bin/"
- from JDK_DIR + "zip.dll"
- rename("zip.dll", "ojdkbuild_zlib.dll")
+ dependsOn dist
doLast{
copy{
- into "packr-out/jre/bin/"
- from JDK_DIR + "zip.dll"
+ into "build/packr/"
+ rename("${appName}.jar", "desktop.jar")
+ from "build/libs/${appName}.jar"
+ }
+
+ delete{
+ delete "build/packr/output/"
+ }
+
+ if(platform == PackrConfig.Platform.Windows32 || platform == PackrConfig.Platform.Windows64){
+ copy{
+ into "build/packr/output"
+ from "${JDK_DIR}/templates/${platform.toString().toLowerCase()}"
+ }
+
+ copy{
+ into "build/packr/output/jre"
+ rename("${appName}.jar", "desktop.jar")
+ from "build/libs/${appName}.jar"
+ }
+ }else{
+ def config = new PackrConfig()
+ config.with{
+ config.executable = appName
+ config.platform = platform
+ verbose = true
+ bundleIdentifier = getPackage() + ".mac"
+ iconResource = ICON_DIR
+ outDir = file("build/packr/output")
+ mainClass = project.ext.mainClassName
+ classpath = ["desktop/build/packr/desktop.jar"]
+ removePlatformLibs = ["desktop/build/packr/desktop.jar"]
+
+ vmArgs = ["Djava.net.preferIPv4Stack=true"]
+ minimizeJre = "desktop/packr_minimize.json"
+ jdk = JDK_DIR + "jdk-${platform.toString().toLowerCase()}.zip"
+
+ if(platform == PackrConfig.Platform.MacOS){
+ vmArgs += "XstartOnFirstThread"
+ }
+ }
+
+ new Packr().pack(config)
+
+ if(platform == PackrConfig.Platform.Linux64){
+ copy{
+ into "build/packr/output/jre/"
+ from "build/packr/output/desktop.jar"
+ }
+
+ delete{
+ delete "build/packr/output/desktop.jar"
+ }
+
+ file("build/packr/output/config.json").text = file("build/packr/output/config.json").text.replace("desktop.jar", "jre/desktop.jar")
+ }
+
+ if(platform == PackrConfig.Platform.MacOS){
+ copy{
+ into "build/packr/${appName}.app/Contents/"
+ from "build/packr/Contents/"
+ }
+
+ delete{
+ delete "build/packr/Contents/"
+ }
+ }
}
}
+
+ task "zip${platform.toString()}"(type: Zip){
+ from "build/packr/output"
+ archiveName "${generateDeployName(platform.toString())}.zip"
+ destinationDir(file("../deploy"))
+
+ doLast{
+ delete{
+ delete "build/packr/"
+ }
+ }
+ }
+
+ finalizedBy "zip${platform.toString()}"
}
-
- finalizedBy "clearOut"
-
- if(project.hasProperty("platform")){
- def plat = getPlatform()
- if(plat == PackrConfig.Platform.Windows32 || plat == PackrConfig.Platform.Windows64){
- dependsOn "copyTemplate"
- }else{
- dependsOn "packrCmd"
-
- if(getPlatform() == PackrConfig.Platform.MacOS){
- dependsOn "fixMac"
- }
-
- if(getPlatform() == PackrConfig.Platform.Windows32){
- dependsOn "fixWindows32"
- }
- }
-
- task rzip(type: Zip){
- from "packr-out/"
- archiveName "${generateDeployName(getPlatform().toString())}.zip"
- destinationDir(file("packr-export"))
- }
-
- finalizedBy 'rzip'
- }
-}
\ No newline at end of file
+}
diff --git a/desktop/packr_minimize.json b/desktop/packr_minimize.json
index 8be61942cc..a9e19bc83a 100644
--- a/desktop/packr_minimize.json
+++ b/desktop/packr_minimize.json
@@ -27,13 +27,25 @@
"com/sun/jndi",
"com/sun/xml",
"com/sun/script",
- "sum/awt",
+ "sun/awt",
"sun/java2d",
"sun/font",
"sun/rmi",
"sun/swing",
"java/util/stream",
"com/sun/media",
+ "sun/print",
+ "sun/awt",
+ "sun/instrument",
+ "sun/security/tools",
+ "sun/security/smartcardio",
+ "sun/audio",
+ "javax/xml",
+ "javax/sound",
+ "javax/script",
+ "java/beans",
+ "java/applet",
+ "java/rmi",
"com/sun/naming",
"java/awt",
"com/sun/org/apache/xpath",
diff --git a/desktop/src/io/anuke/mindustry/desktop/DesktopLauncher.java b/desktop/src/io/anuke/mindustry/desktop/DesktopLauncher.java
index d87a547712..571b7a752e 100644
--- a/desktop/src/io/anuke/mindustry/desktop/DesktopLauncher.java
+++ b/desktop/src/io/anuke/mindustry/desktop/DesktopLauncher.java
@@ -1,27 +1,30 @@
package io.anuke.mindustry.desktop;
-import io.anuke.arc.backends.lwjgl3.Lwjgl3Application;
-import io.anuke.arc.backends.lwjgl3.Lwjgl3ApplicationConfiguration;
-import io.anuke.mindustry.Mindustry;
-import io.anuke.mindustry.core.Platform;
+import io.anuke.arc.Files.*;
+import io.anuke.arc.backends.sdl.*;
+import io.anuke.mindustry.*;
+import io.anuke.mindustry.core.*;
+import io.anuke.mindustry.desktop.steam.*;
import io.anuke.mindustry.net.*;
public class DesktopLauncher{
public static void main(String[] arg){
try{
- Lwjgl3ApplicationConfiguration config = new Lwjgl3ApplicationConfiguration();
- config.setTitle("Mindustry");
- config.setMaximized(true);
- config.setBackBufferConfig(8, 8, 8, 8, 0, 0, 0);
- config.setWindowedMode(900, 600);
- config.setWindowIcon("icons/icon_64.png");
-
Platform.instance = new DesktopPlatform(arg);
Net.setClientProvider(new ArcNetClient());
- Net.setServerProvider(new ArcNetServer());
- new Lwjgl3Application(new Mindustry(), config);
+ Net.setServerProvider(new SteamServerImpl(new ArcNetServer()));
+
+ new SdlApplication(new Mindustry(), new SdlConfig(){{
+ title = "Mindustry";
+ maximized = true;
+ depth = 0;
+ stencil = 0;
+ width = 900;
+ height = 700;
+ setWindowIcon(FileType.Internal, "icons/icon_64.png");
+ }});
}catch(Throwable e){
DesktopPlatform.handleCrash(e);
}
diff --git a/desktop/src/io/anuke/mindustry/desktop/DesktopPlatform.java b/desktop/src/io/anuke/mindustry/desktop/DesktopPlatform.java
index 92da3ecb1c..357a735494 100644
--- a/desktop/src/io/anuke/mindustry/desktop/DesktopPlatform.java
+++ b/desktop/src/io/anuke/mindustry/desktop/DesktopPlatform.java
@@ -1,26 +1,30 @@
package io.anuke.mindustry.desktop;
import club.minnced.discord.rpc.*;
-import io.anuke.arc.collection.Array;
-import io.anuke.arc.files.FileHandle;
-import io.anuke.arc.function.Consumer;
-import io.anuke.arc.function.Predicate;
+import com.codedisaster.steamworks.*;
+import io.anuke.arc.*;
+import io.anuke.arc.backends.sdl.jni.*;
+import io.anuke.arc.collection.*;
+import io.anuke.arc.files.*;
+import io.anuke.arc.function.*;
import io.anuke.arc.util.*;
-import io.anuke.arc.util.serialization.Base64Coder;
-import io.anuke.mindustry.core.GameState.State;
-import io.anuke.mindustry.core.Platform;
-import io.anuke.mindustry.net.CrashSender;
+import io.anuke.arc.util.serialization.*;
+import io.anuke.mindustry.*;
+import io.anuke.mindustry.core.GameState.*;
+import io.anuke.mindustry.core.*;
+import io.anuke.mindustry.game.EventType.*;
import io.anuke.mindustry.net.Net;
-import io.anuke.mindustry.ui.dialogs.FileChooser;
-import org.lwjgl.util.tinyfd.TinyFileDialogs;
+import io.anuke.mindustry.net.*;
+import io.anuke.mindustry.ui.dialogs.*;
-import java.net.NetworkInterface;
+import java.net.*;
import java.util.*;
import static io.anuke.mindustry.Vars.*;
+
public class DesktopPlatform extends Platform{
- static boolean useDiscord = OS.is64Bit;
+ static boolean useDiscord = OS.is64Bit, useSteam = true;
final static String applicationId = "610508934456934412";
String[] args;
@@ -40,19 +44,55 @@ public class DesktopPlatform extends Platform{
Log.err("Failed to initialize discord.", t);
}
}
+
+ if(useSteam){
+ Vars.steam = true;
+ try{
+ SteamAPI.loadLibraries();
+ if(!SteamAPI.init()){
+ Log.info("Steam client not running. Make sure Steam is running!");
+ }else{
+ //times per second
+ float interval = 20f;
+ Interval i = new Interval();
+
+ //run steam callbacks
+ Events.on(GameLoadEvent.class, event -> {
+ //update callbacks
+ Core.app.addListener(new ApplicationListener(){
+ @Override
+ public void update(){
+ if(i.get(interval)){
+ if(SteamAPI.isSteamRunning()){
+ SteamAPI.runCallbacks();
+ }
+ }
+ }
+ });
+
+ //Core.app.post(() -> new ClientSteam());
+ });
+ //steam shutdown hook
+ Runtime.getRuntime().addShutdownHook(new Thread(SteamAPI::shutdown));
+ }
+ }catch(Exception e){
+ Log.err("Failed to load Steam native libraries.");
+ e.printStackTrace();
+ }
+ }
}
static void handleCrash(Throwable e){
- Consumer dialog = r -> new Thread(r).start();
+ Consumer dialog = Runnable::run;
boolean badGPU = false;
if(e.getMessage() != null && (e.getMessage().contains("Couldn't create window") || e.getMessage().contains("OpenGL 2.0 or higher"))){
- dialog.accept(() -> TinyFileDialogs.tinyfd_messageBox("oh no",
+ dialog.accept(() -> message(
e.getMessage().contains("Couldn't create window") ? "A graphics initialization error has occured! Try to update your graphics drivers:\n" + e.getMessage() :
"Your graphics card does not support OpenGL 2.0!\n" +
"Try to update your graphics drivers.\n\n" +
- "(If that doesn't work, your computer just doesn't support Mindustry.)", "ok", "error", true));
+ "(If that doesn't work, your computer just doesn't support Mindustry.)"));
badGPU = true;
}
@@ -60,7 +100,7 @@ public class DesktopPlatform extends Platform{
CrashSender.send(e, file -> {
if(!fbgp){
- dialog.accept(() -> TinyFileDialogs.tinyfd_messageBox("oh no", "A crash has occured. It has been saved in:\n" + file.getAbsolutePath(), "ok", "error", true));
+ dialog.accept(() -> message("A crash has occured. It has been saved in:\n" + file.getAbsolutePath() + "\n" + (e.getMessage() == null ? "" : "\n" + e.getMessage())));
}
});
}
@@ -118,7 +158,7 @@ public class DesktopPlatform extends Platform{
String str = new String(Base64Coder.encode(result));
- if(str.equals("AAAAAAAAAOA=")) throw new RuntimeException("Bad UUID.");
+ if(str.equals("AAAAAAAAAOA=") || str.equals("AAAAAAAAAAA=")) throw new RuntimeException("Bad UUID.");
return str;
}catch(Exception e){
@@ -126,10 +166,14 @@ public class DesktopPlatform extends Platform{
}
}
+ private static void message(String message){
+ SDL.SDL_ShowSimpleMessageBox(SDL.SDL_MESSAGEBOX_ERROR, "oh no", message);
+ }
+
private boolean validAddress(byte[] bytes){
if(bytes == null) return false;
byte[] result = new byte[8];
System.arraycopy(bytes, 0, result, 0, bytes.length);
- return !new String(Base64Coder.encode(result)).equals("AAAAAAAAAOA=");
+ return !new String(Base64Coder.encode(result)).equals("AAAAAAAAAOA=") && !new String(Base64Coder.encode(result)).equals("AAAAAAAAAAA=");
}
}
diff --git a/desktop-sdl/src/io/anuke/mindustry/desktopsdl/steam/ClientSteam.java b/desktop/src/io/anuke/mindustry/desktop/steam/SteamClientImpl.java
similarity index 74%
rename from desktop-sdl/src/io/anuke/mindustry/desktopsdl/steam/ClientSteam.java
rename to desktop/src/io/anuke/mindustry/desktop/steam/SteamClientImpl.java
index cecb90e97c..8f8a90cbd6 100644
--- a/desktop-sdl/src/io/anuke/mindustry/desktopsdl/steam/ClientSteam.java
+++ b/desktop/src/io/anuke/mindustry/desktop/steam/SteamClientImpl.java
@@ -1,4 +1,4 @@
-package io.anuke.mindustry.desktopsdl.steam;
+package io.anuke.mindustry.desktop.steam;
import com.codedisaster.steamworks.*;
import com.codedisaster.steamworks.SteamFriends.*;
@@ -6,12 +6,11 @@ import com.codedisaster.steamworks.SteamMatchmaking.*;
import com.codedisaster.steamworks.SteamNetworking.*;
import io.anuke.arc.collection.*;
import io.anuke.arc.util.*;
-import io.anuke.mindustry.net.Net.*;
-import io.anuke.mindustry.net.*;
+import io.anuke.mindustry.desktop.steam.SteamServerImpl.*;
import java.nio.*;
-public class ClientSteam implements SteamNetworkingCallback, SteamMatchmakingCallback{
+public class SteamClientImpl implements SteamNetworkingCallback, SteamMatchmakingCallback{
private SteamNetworking snet;
private SteamMatchmaking smat;
@@ -19,7 +18,7 @@ public class ClientSteam implements SteamNetworkingCallback, SteamMatchmakingCal
//maps steam ID -> valid net connection
private IntMap connections = new IntMap<>();
- public ClientSteam(){
+ public SteamClientImpl(){
//snet = new SteamNetworking(this);
//smat = new SteamMatchmaking(this);
@@ -53,46 +52,6 @@ public class ClientSteam implements SteamNetworkingCallback, SteamMatchmakingCal
snet.acceptP2PSessionWithUser(steamIDRemote);
}
- class SteamConnection extends NetConnection{
- public final SteamID connection;
-
- public SteamConnection(int id, String address, SteamID connection){
- super(id, address);
- this.connection = connection;
- }
-
- @Override
- public boolean isConnected(){
- return false;//connection.isConnected();
- }
-
- @Override
- public void send(Object object, SendMode mode){
- //TODO
- /*
- try{
- if(mode == SendMode.tcp){
- connection.sendTCP(object);
- }else{
- connection.sendUDP(object);
- }
- }catch(Exception e){
- Log.err(e);
- Log.info("Error sending packet. Disconnecting invalid client!");
- connection.close();
-
- ArcNetServer.KryoConnection k = getByKryoID(connection.getID());
- if(k != null) connections.remove(k);
- }*/
- }
-
- @Override
- public void close(){
- //TODO
- //if(connection.isConnected()) connection.close();
- }
- }
-
@Override
public void onFavoritesListChanged(int ip, int queryPort, int connPort, int appID, int flags, boolean add, int accountID){
@@ -185,8 +144,8 @@ public class ClientSteam implements SteamNetworkingCallback, SteamMatchmakingCal
}
});
- friends.activateGameOverlay(OverlayDialog.Friends);
- //friends.activateGameOverlayInviteDialog(steamIDLobby);
+ //friends.activateGameOverlay(OverlayDialog.Friends);
+ friends.activateGameOverlayInviteDialog(steamIDLobby);
}
}
diff --git a/desktop/src/io/anuke/mindustry/desktop/steam/SteamFriendsImpl.java b/desktop/src/io/anuke/mindustry/desktop/steam/SteamFriendsImpl.java
new file mode 100644
index 0000000000..1497508ebf
--- /dev/null
+++ b/desktop/src/io/anuke/mindustry/desktop/steam/SteamFriendsImpl.java
@@ -0,0 +1,52 @@
+package io.anuke.mindustry.desktop.steam;
+
+import com.codedisaster.steamworks.*;
+import com.codedisaster.steamworks.SteamFriends.*;
+
+public class SteamFriendsImpl implements SteamFriendsCallback{
+ public final SteamFriends friends;
+
+ public SteamFriendsImpl(){
+ friends = new SteamFriends(this);
+ }
+
+ @Override
+ public void onSetPersonaNameResponse(boolean b, boolean b1, SteamResult steamResult){
+
+ }
+
+ @Override
+ public void onPersonaStateChange(SteamID steamID, PersonaChange personaChange){
+
+ }
+
+ @Override
+ public void onGameOverlayActivated(boolean b){
+
+ }
+
+ @Override
+ public void onGameLobbyJoinRequested(SteamID steamID, SteamID steamID1){
+
+ }
+
+ @Override
+ public void onAvatarImageLoaded(SteamID steamID, int i, int i1, int i2){
+
+ }
+
+ @Override
+ public void onFriendRichPresenceUpdate(SteamID steamID, int i){
+
+ }
+
+ @Override
+ public void onGameRichPresenceJoinRequested(SteamID steamID, String s){
+
+ }
+
+ @Override
+ public void onGameServerChangeRequested(String s, String s1){
+
+ }
+}
diff --git a/desktop-sdl/src/io/anuke/mindustry/desktopsdl/steam/ServerSteam.java b/desktop/src/io/anuke/mindustry/desktop/steam/SteamServerImpl.java
similarity index 67%
rename from desktop-sdl/src/io/anuke/mindustry/desktopsdl/steam/ServerSteam.java
rename to desktop/src/io/anuke/mindustry/desktop/steam/SteamServerImpl.java
index 229735504a..a9cc0f4bfd 100644
--- a/desktop-sdl/src/io/anuke/mindustry/desktopsdl/steam/ServerSteam.java
+++ b/desktop/src/io/anuke/mindustry/desktop/steam/SteamServerImpl.java
@@ -1,4 +1,4 @@
-package io.anuke.mindustry.desktopsdl.steam;
+package io.anuke.mindustry.desktop.steam;
import com.codedisaster.steamworks.*;
import com.codedisaster.steamworks.SteamMatchmaking.*;
@@ -6,28 +6,28 @@ import com.codedisaster.steamworks.SteamNetworking.*;
import io.anuke.arc.*;
import io.anuke.arc.collection.*;
import io.anuke.arc.util.*;
-import io.anuke.mindustry.desktopsdl.steam.ClientSteam.*;
import io.anuke.mindustry.net.Net.*;
import io.anuke.mindustry.net.*;
import java.io.*;
import java.nio.*;
-public class ServerSteam implements ServerProvider, SteamNetworkingCallback, SteamMatchmakingCallback{
+public class SteamServerImpl implements ServerProvider, SteamNetworkingCallback, SteamMatchmakingCallback{
private final static int maxLobbyPlayers = 32;
+ private final PacketSerializer serializer = new PacketSerializer();
+ private final ByteBuffer writeBuffer = ByteBuffer.allocateDirect(1024 * 4);
private final SteamNetworking snet = new SteamNetworking(this);
private final SteamMatchmaking smat = new SteamMatchmaking(this);
+ private final SteamFriendsImpl friends = new SteamFriendsImpl();
private final ServerProvider server;
- //buffer for steam API calls
- private ByteBuffer steamBuffer = ByteBuffer.allocateDirect(1024 * 128);
//maps steam ID -> valid net connection
private IntMap steamConnections = new IntMap<>();
private SteamID currentLobby;
- public ServerSteam(ServerProvider server){
+ public SteamServerImpl(ServerProvider server){
this.server = server;
}
@@ -39,26 +39,6 @@ public class ServerSteam implements ServerProvider, SteamNetworkingCallback, Ste
smat.createLobby(LobbyType.values()[Core.settings.getInt("lobbytype", 1)], maxLobbyPlayers);
}
- @Override
- public void sendStream(int id, Streamable stream){
- server.sendStream(id, stream);
- }
-
- @Override
- public void send(Object object, SendMode mode){
- server.send(object, mode);
- }
-
- @Override
- public void sendTo(int id, Object object, SendMode mode){
- server.sendTo(id, object, mode);
- }
-
- @Override
- public void sendExcept(int id, Object object, SendMode mode){
- server.sendExcept(id, object, mode);
- }
-
@Override
public void close(){
server.close();
@@ -66,6 +46,9 @@ public class ServerSteam implements ServerProvider, SteamNetworkingCallback, Ste
//TODO kick everyone who is in this lobby?
smat.leaveLobby(currentLobby);
currentLobby = null;
+ for(SteamConnection con : steamConnections.values()){
+ con.close();
+ }
}
}
@@ -75,7 +58,7 @@ public class ServerSteam implements ServerProvider, SteamNetworkingCallback, Ste
}
@Override
- public Array extends NetConnection> getConnections(){
+ public Iterable extends NetConnection> getConnections(){
return server.getConnections();
}
@@ -157,4 +140,37 @@ public class ServerSteam implements ServerProvider, SteamNetworkingCallback, Ste
//accept users on request
snet.acceptP2PSessionWithUser(steamIDRemote);
}
+
+ public class SteamConnection extends NetConnection{
+ final SteamID sid;
+
+ public SteamConnection(SteamID sid){
+ super(sid.getAccountID() + "");
+ this.sid = sid;
+ }
+
+ @Override
+ public void send(Object object, SendMode mode){
+ try{
+ writeBuffer.limit(writeBuffer.capacity());
+ writeBuffer.position(0);
+ serializer.write(writeBuffer, object);
+ writeBuffer.flip();
+
+ snet.sendP2PPacket(sid, writeBuffer, mode == SendMode.tcp ? P2PSend.Reliable : P2PSend.UnreliableNoDelay, 0);
+ }catch(Exception e){
+ Log.err(e);
+ Log.info("Error sending packet. Disconnecting invalid client!");
+ close();
+
+ SteamConnection k = steamConnections.get(sid.getAccountID());
+ if(k != null) steamConnections.remove(sid.getAccountID());
+ }
+ }
+
+ @Override
+ public void close(){
+ snet.closeP2PSessionWithUser(sid);
+ }
+ }
}
diff --git a/desktop-sdl/src/io/anuke/mindustry/desktopsdl/steam/WorkshopImpl.java b/desktop/src/io/anuke/mindustry/desktop/steam/WorkshopImpl.java
similarity index 97%
rename from desktop-sdl/src/io/anuke/mindustry/desktopsdl/steam/WorkshopImpl.java
rename to desktop/src/io/anuke/mindustry/desktop/steam/WorkshopImpl.java
index a4e59a9b54..e106cf97ad 100644
--- a/desktop-sdl/src/io/anuke/mindustry/desktopsdl/steam/WorkshopImpl.java
+++ b/desktop/src/io/anuke/mindustry/desktop/steam/WorkshopImpl.java
@@ -1,4 +1,4 @@
-package io.anuke.mindustry.desktopsdl.steam;
+package io.anuke.mindustry.desktop.steam;
import com.codedisaster.steamworks.*;
import com.codedisaster.steamworks.SteamRemoteStorage.*;
diff --git a/fastlane/Appfile b/fastlane/Appfile
new file mode 100644
index 0000000000..3aad746bc0
--- /dev/null
+++ b/fastlane/Appfile
@@ -0,0 +1,2 @@
+json_key_file(ENV["FASTLANE_KEY_FILE"])
+package_name("io.anuke.mindustry")
diff --git a/fastlane/Fastfile b/fastlane/Fastfile
new file mode 100644
index 0000000000..17a304bf4f
--- /dev/null
+++ b/fastlane/Fastfile
@@ -0,0 +1,46 @@
+# This file contains the fastlane.tools configuration
+# You can find the documentation at https://docs.fastlane.tools
+#
+# For a list of all available actions, check out
+#
+# https://docs.fastlane.tools/actions
+#
+# For a list of all available plugins, check out
+#
+# https://docs.fastlane.tools/plugins/available-plugins
+#
+
+# Uncomment the line if you want fastlane to automatically update itself
+# update_fastlane
+
+default_platform(:android)
+
+platform :android do
+ desc "Runs all the tests"
+ lane :test do
+ gradle(task: "test")
+ end
+
+ desc "Submit a new Beta Build to Crashlytics Beta"
+ lane :beta do
+ gradle(task: "clean assembleRelease")
+ crashlytics
+
+ # sh "your_script.sh"
+ # You can also use other beta testing services here
+ end
+
+ desc "Deploy a new version to the Google Play"
+ lane :deploy do
+ gradle(task: "clean assembleRelease")
+ upload_to_play_store
+ end
+
+ #lane :playstore do
+ # gradle(
+ # task: 'assemble',
+ # build_type: 'Release'
+ # )
+ # upload_to_play_store # Uploads the APK built in the gradle step above and releases it to all production users
+ #end
+end
diff --git a/fastlane/metadata/android/en-US/changelogs/12203.txt b/fastlane/metadata/android/en-US/changelogs/12203.txt
new file mode 100644
index 0000000000..942424c5ea
--- /dev/null
+++ b/fastlane/metadata/android/en-US/changelogs/12203.txt
@@ -0,0 +1,3 @@
+- Fixed incorrect attribution in credits; music was made by "A Drop A Day"
+- Removed unneeded 3.5 upgrade dialog that sometimes showed up in main menu
+- Added information dialog regarding v4 beta
\ No newline at end of file
diff --git a/fastlane/metadata/android/en-US/changelogs/12205.txt b/fastlane/metadata/android/en-US/changelogs/12205.txt
new file mode 100644
index 0000000000..70bcab4bfc
--- /dev/null
+++ b/fastlane/metadata/android/en-US/changelogs/12205.txt
@@ -0,0 +1,4 @@
+- Fixed incorrect attribution in credits; music was made by "A Drop A Day"
+- Removed unneeded 3.5 upgrade dialog that sometimes showed up in main menu
+- Added information dialog regarding v4 beta
+- Fixed Discord link
\ No newline at end of file
diff --git a/fastlane/metadata/android/en-US/changelogs/26593.txt b/fastlane/metadata/android/en-US/changelogs/26593.txt
new file mode 100644
index 0000000000..610563a652
--- /dev/null
+++ b/fastlane/metadata/android/en-US/changelogs/26593.txt
@@ -0,0 +1 @@
+sound.
\ No newline at end of file
diff --git a/fastlane/metadata/android/en-US/changelogs/27434.txt b/fastlane/metadata/android/en-US/changelogs/27434.txt
new file mode 100644
index 0000000000..5240303123
--- /dev/null
+++ b/fastlane/metadata/android/en-US/changelogs/27434.txt
@@ -0,0 +1 @@
+everything
\ No newline at end of file
diff --git a/fastlane/metadata/android/en-US/changelogs/27476.txt b/fastlane/metadata/android/en-US/changelogs/27476.txt
new file mode 100644
index 0000000000..ec779fbdba
--- /dev/null
+++ b/fastlane/metadata/android/en-US/changelogs/27476.txt
@@ -0,0 +1 @@
+Fixed some minor sound/multiplayer issues
\ No newline at end of file
diff --git a/fastlane/metadata/android/en-US/changelogs/27689.txt b/fastlane/metadata/android/en-US/changelogs/27689.txt
new file mode 100644
index 0000000000..92e8a8c47e
--- /dev/null
+++ b/fastlane/metadata/android/en-US/changelogs/27689.txt
@@ -0,0 +1 @@
+Bugfixes
\ No newline at end of file
diff --git a/fastlane/metadata/android/en-US/changelogs/27770.txt b/fastlane/metadata/android/en-US/changelogs/27770.txt
new file mode 100644
index 0000000000..04d19b551f
--- /dev/null
+++ b/fastlane/metadata/android/en-US/changelogs/27770.txt
@@ -0,0 +1 @@
+Added ambient sounds for machines.
\ No newline at end of file
diff --git a/fastlane/metadata/android/en-US/changelogs/27997.txt b/fastlane/metadata/android/en-US/changelogs/27997.txt
new file mode 100644
index 0000000000..2b2809c72d
--- /dev/null
+++ b/fastlane/metadata/android/en-US/changelogs/27997.txt
@@ -0,0 +1,2 @@
+The first release of version 4.0; an update that has been in the works for over a year.
+Extensive changes, including new gamemodes, customizable rules, a new editor, new graphics, new enemies, unit production, new progression, a campaign, and more. See the in-game changelog link for specific details of what has been added and removed over the past year.
\ No newline at end of file
diff --git a/fastlane/metadata/android/en-US/changelogs/28409.txt b/fastlane/metadata/android/en-US/changelogs/28409.txt
new file mode 100644
index 0000000000..670c65cc45
--- /dev/null
+++ b/fastlane/metadata/android/en-US/changelogs/28409.txt
@@ -0,0 +1,2 @@
+Fixed multiplayer not syncing positions and shots correctly on certain networks or situations.
+Various other bugfixes.
\ No newline at end of file
diff --git a/fastlane/metadata/android/en-US/changelogs/721.txt b/fastlane/metadata/android/en-US/changelogs/721.txt
new file mode 100644
index 0000000000..8361896cef
--- /dev/null
+++ b/fastlane/metadata/android/en-US/changelogs/721.txt
@@ -0,0 +1,5 @@
+- Fixed most formatted numbers being missing from Spanish translation
+- Fixed wave timer being extremely slow at high TPS with multithreading enabled
+- Fixed scrolling on player menu causing the whole screen to pan
+- Updated Polish translation
+- Updated Russian translation with new text (Thanks to @Prosta4okua)
\ No newline at end of file
diff --git a/fastlane/metadata/android/en-US/full_description.txt b/fastlane/metadata/android/en-US/full_description.txt
new file mode 100644
index 0000000000..b9958053f1
--- /dev/null
+++ b/fastlane/metadata/android/en-US/full_description.txt
@@ -0,0 +1,14 @@
+Create elaborate supply chains of conveyor belts to feed ammo into your turrets, produce materials to use for building, and defend your structures from waves of enemies. Play with your friends in cross-platform multiplayer co-op games, or challenge them in team-based PvP matches.
+
+Feature include:
+- 24 built-in maps
+- A campaign, complete with a tech tree and unlockable areas
+- 4 powerful wave bosses to defeat
+- Energy, liquid and item transportation systems
+- 19 different types of drones, mechs and ships
+- 120+ technology blocks to master
+- 75+ different environmental blocks
+- Cross-platform multiplayer via local networks or dedicated servers
+- Custom game rules: Change block costs, enemy stats, starting items, wave timing and more
+- A powerful editor, with tools to randomly generate ores, terrain, decoration and apply symmetry to maps
+- Customizable map wave layouts
\ No newline at end of file
diff --git a/fastlane/metadata/android/en-US/images/featureGraphic.png b/fastlane/metadata/android/en-US/images/featureGraphic.png
new file mode 100644
index 0000000000..90e27dddca
Binary files /dev/null and b/fastlane/metadata/android/en-US/images/featureGraphic.png differ
diff --git a/fastlane/metadata/android/en-US/images/icon.png b/fastlane/metadata/android/en-US/images/icon.png
new file mode 100644
index 0000000000..705e880a20
Binary files /dev/null and b/fastlane/metadata/android/en-US/images/icon.png differ
diff --git a/fastlane/metadata/android/en-US/images/phoneScreenshots/1.png b/fastlane/metadata/android/en-US/images/phoneScreenshots/1.png
new file mode 100644
index 0000000000..44949de11d
Binary files /dev/null and b/fastlane/metadata/android/en-US/images/phoneScreenshots/1.png differ
diff --git a/fastlane/metadata/android/en-US/images/phoneScreenshots/2.png b/fastlane/metadata/android/en-US/images/phoneScreenshots/2.png
new file mode 100644
index 0000000000..7d37a27105
Binary files /dev/null and b/fastlane/metadata/android/en-US/images/phoneScreenshots/2.png differ
diff --git a/fastlane/metadata/android/en-US/images/phoneScreenshots/3.png b/fastlane/metadata/android/en-US/images/phoneScreenshots/3.png
new file mode 100644
index 0000000000..53525bbd13
Binary files /dev/null and b/fastlane/metadata/android/en-US/images/phoneScreenshots/3.png differ
diff --git a/fastlane/metadata/android/en-US/images/phoneScreenshots/4.png b/fastlane/metadata/android/en-US/images/phoneScreenshots/4.png
new file mode 100644
index 0000000000..091f53243c
Binary files /dev/null and b/fastlane/metadata/android/en-US/images/phoneScreenshots/4.png differ
diff --git a/fastlane/metadata/android/en-US/images/phoneScreenshots/5.png b/fastlane/metadata/android/en-US/images/phoneScreenshots/5.png
new file mode 100644
index 0000000000..952aa2aa54
Binary files /dev/null and b/fastlane/metadata/android/en-US/images/phoneScreenshots/5.png differ
diff --git a/fastlane/metadata/android/en-US/images/phoneScreenshots/6.png b/fastlane/metadata/android/en-US/images/phoneScreenshots/6.png
new file mode 100644
index 0000000000..3830432e4f
Binary files /dev/null and b/fastlane/metadata/android/en-US/images/phoneScreenshots/6.png differ
diff --git a/fastlane/metadata/android/en-US/images/phoneScreenshots/7.png b/fastlane/metadata/android/en-US/images/phoneScreenshots/7.png
new file mode 100644
index 0000000000..8fa92e537d
Binary files /dev/null and b/fastlane/metadata/android/en-US/images/phoneScreenshots/7.png differ
diff --git a/fastlane/metadata/android/en-US/images/sevenInchScreenshots/1.png b/fastlane/metadata/android/en-US/images/sevenInchScreenshots/1.png
new file mode 100644
index 0000000000..286795f87f
Binary files /dev/null and b/fastlane/metadata/android/en-US/images/sevenInchScreenshots/1.png differ
diff --git a/fastlane/metadata/android/en-US/images/sevenInchScreenshots/2.png b/fastlane/metadata/android/en-US/images/sevenInchScreenshots/2.png
new file mode 100644
index 0000000000..7d37a27105
Binary files /dev/null and b/fastlane/metadata/android/en-US/images/sevenInchScreenshots/2.png differ
diff --git a/fastlane/metadata/android/en-US/images/sevenInchScreenshots/3.png b/fastlane/metadata/android/en-US/images/sevenInchScreenshots/3.png
new file mode 100644
index 0000000000..091f53243c
Binary files /dev/null and b/fastlane/metadata/android/en-US/images/sevenInchScreenshots/3.png differ
diff --git a/fastlane/metadata/android/en-US/short_description.txt b/fastlane/metadata/android/en-US/short_description.txt
new file mode 100644
index 0000000000..b6b5a942cd
--- /dev/null
+++ b/fastlane/metadata/android/en-US/short_description.txt
@@ -0,0 +1 @@
+A factory-based sandbox tower defense game.
\ No newline at end of file
diff --git a/fastlane/metadata/android/en-US/title.txt b/fastlane/metadata/android/en-US/title.txt
new file mode 100644
index 0000000000..2beb939017
--- /dev/null
+++ b/fastlane/metadata/android/en-US/title.txt
@@ -0,0 +1 @@
+Mindustry
\ No newline at end of file
diff --git a/fastlane/metadata/android/en-US/video.txt b/fastlane/metadata/android/en-US/video.txt
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/fastlane/metadata/android/ru-RU/full_description.txt b/fastlane/metadata/android/ru-RU/full_description.txt
new file mode 100644
index 0000000000..03219413cc
--- /dev/null
+++ b/fastlane/metadata/android/ru-RU/full_description.txt
@@ -0,0 +1,15 @@
+Создавайте сложные логистические сети для переноса боеприпасов для турелей, добывайте ресурсы для строительства, и защищайте их от различных волн врагов.
+Играйте с друзьями в кроссплатформенные кооперативные игры, или бросьте им вызов в командных PvP-матчах.
+
+Особенности игры:
+- 24 встроенные карты
+- Кампания, с полноценным технологическим древом и прогрессией карт
+- 4 вида мощных боссов
+- Системы для транспорта электроэнергии, жидкостей и ресурсов
+- 19 видов дронов, кораблей и наземных боевых единиц
+- Более 120 блоков в техногическом древе
+- Более 75 видов натуральных блоков
+- Кроссплатформенный мультиплеер с поддержкой как и локальных сетей, так и серверов
+- Пользовательские настройки игры — изменяйте цену блоков, силу врагов, количество стартовых ресурсов, интервал между волнами и т.д.
+- Редактор карт с бесчисленными возможностями, инструментами для случайной генерации руд, рельефа, декораций, а также для симметрии карт
+- Настраиваемые раскладки волн для карт
\ No newline at end of file
diff --git a/fastlane/metadata/android/ru-RU/short_description.txt b/fastlane/metadata/android/ru-RU/short_description.txt
new file mode 100644
index 0000000000..b6b5a942cd
--- /dev/null
+++ b/fastlane/metadata/android/ru-RU/short_description.txt
@@ -0,0 +1 @@
+A factory-based sandbox tower defense game.
\ No newline at end of file
diff --git a/fastlane/metadata/android/ru-RU/title.txt b/fastlane/metadata/android/ru-RU/title.txt
new file mode 100644
index 0000000000..2beb939017
--- /dev/null
+++ b/fastlane/metadata/android/ru-RU/title.txt
@@ -0,0 +1 @@
+Mindustry
\ No newline at end of file
diff --git a/fastlane/metadata/android/ru-RU/video.txt b/fastlane/metadata/android/ru-RU/video.txt
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/ios/data/Default-568h@2x~iphone.png b/ios/data/Default-568h@2x~iphone.png
index 153c6efdf4..9a0e377f65 100644
Binary files a/ios/data/Default-568h@2x~iphone.png and b/ios/data/Default-568h@2x~iphone.png differ
diff --git a/ios/data/Default-667h.png b/ios/data/Default-667h.png
index b3acc10e67..b5a4b57681 100644
Binary files a/ios/data/Default-667h.png and b/ios/data/Default-667h.png differ
diff --git a/ios/data/Default-736h.png b/ios/data/Default-736h.png
index f5a22468a3..8d05a25f44 100644
Binary files a/ios/data/Default-736h.png and b/ios/data/Default-736h.png differ
diff --git a/ios/data/Default-Landscape-736h.png b/ios/data/Default-Landscape-736h.png
index 04e32d4d7e..70badabb86 100644
Binary files a/ios/data/Default-Landscape-736h.png and b/ios/data/Default-Landscape-736h.png differ
diff --git a/ios/data/Default-Landscape@2x~ipad.png b/ios/data/Default-Landscape@2x~ipad.png
index 239e218934..da2884cfd1 100644
Binary files a/ios/data/Default-Landscape@2x~ipad.png and b/ios/data/Default-Landscape@2x~ipad.png differ
diff --git a/ios/data/Default-Landscape~ipad.png b/ios/data/Default-Landscape~ipad.png
index 7374a80f75..3b101edc7e 100644
Binary files a/ios/data/Default-Landscape~ipad.png and b/ios/data/Default-Landscape~ipad.png differ
diff --git a/ios/data/Default-Portrait@2x~ipad.png b/ios/data/Default-Portrait@2x~ipad.png
index c00e06f4e4..0989e62081 100644
Binary files a/ios/data/Default-Portrait@2x~ipad.png and b/ios/data/Default-Portrait@2x~ipad.png differ
diff --git a/ios/data/Default-Portrait~ipad.png b/ios/data/Default-Portrait~ipad.png
index 030e88c898..9f980c961a 100644
Binary files a/ios/data/Default-Portrait~ipad.png and b/ios/data/Default-Portrait~ipad.png differ
diff --git a/ios/data/Default@2x~iphone.png b/ios/data/Default@2x~iphone.png
index 5724809f89..710599b407 100644
Binary files a/ios/data/Default@2x~iphone.png and b/ios/data/Default@2x~iphone.png differ
diff --git a/ios/data/Default~iphone.png b/ios/data/Default~iphone.png
index fa72316347..527d691cc0 100644
Binary files a/ios/data/Default~iphone.png and b/ios/data/Default~iphone.png differ
diff --git a/ios/src/io/anuke/mindustry/IOSLauncher.java b/ios/src/io/anuke/mindustry/IOSLauncher.java
index 15988c3424..4161d44017 100644
--- a/ios/src/io/anuke/mindustry/IOSLauncher.java
+++ b/ios/src/io/anuke/mindustry/IOSLauncher.java
@@ -40,7 +40,7 @@ public class IOSLauncher extends IOSApplication.Delegate{
@Override
public void shareFile(FileHandle file){
Log.info("Attempting to share file " + file);
- FileHandle to = Core.files.absolute(getDocumentsDirectory()).child(file.name()/* + ".png"*/);
+ FileHandle to = Core.files.absolute(getDocumentsDirectory()).child(file.name());
file.copyTo(to);
NSURL url = new NSURL(to.file());
@@ -53,7 +53,6 @@ public class IOSLauncher extends IOSApplication.Delegate{
@Override
public void beginForceLandscape(){
- Log.info("begin force landscape");
forced = true;
UINavigationController.attemptRotationToDeviceOrientation();
}
diff --git a/server/src/io/anuke/mindustry/server/ServerControl.java b/server/src/io/anuke/mindustry/server/ServerControl.java
index 0cffac9591..42bc75d0ef 100644
--- a/server/src/io/anuke/mindustry/server/ServerControl.java
+++ b/server/src/io/anuke/mindustry/server/ServerControl.java
@@ -700,10 +700,11 @@ public class ServerControl implements ApplicationListener{
run.run();
logic.play();
state.rules = world.getMap().applyRules(lastMode);
+
for(Player p : players){
p.reset();
if(state.rules.pvp){
- p.setTeam(netServer.assignTeam(new ArrayIterable<>(players)));
+ p.setTeam(netServer.assignTeam(p, new ArrayIterable<>(players)));
}
netServer.sendWorldData(p, p.con.id);
}
diff --git a/settings.gradle b/settings.gradle
index 20085aa2fb..41b5080058 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -1,4 +1,4 @@
-include 'desktop', 'desktop-sdl', 'core', 'net', 'server', 'ios', 'annotations', 'tools', 'tests'
+include 'desktop', 'core', 'net', 'server', 'ios', 'annotations', 'tools', 'tests'
def use = { String name ->
include(name)