Merge
3
.gitignore
vendored
@@ -23,8 +23,6 @@ saves/
|
|||||||
steam_appid.txt
|
steam_appid.txt
|
||||||
/test_files/
|
/test_files/
|
||||||
/annotations/build/
|
/annotations/build/
|
||||||
/desktop-sdl/build/
|
|
||||||
desktop-sdl/build/
|
|
||||||
/android/assets/mindustry-maps/
|
/android/assets/mindustry-maps/
|
||||||
/android/assets/mindustry-saves/
|
/android/assets/mindustry-saves/
|
||||||
/core/assets/gifexport/
|
/core/assets/gifexport/
|
||||||
@@ -35,6 +33,7 @@ desktop-sdl/build/
|
|||||||
ios/robovm.properties
|
ios/robovm.properties
|
||||||
packr-out/
|
packr-out/
|
||||||
config/
|
config/
|
||||||
|
changelog
|
||||||
*.gif
|
*.gif
|
||||||
|
|
||||||
version.properties
|
version.properties
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ deploy:
|
|||||||
api_key:
|
api_key:
|
||||||
secure: Cv5wFtWt62/A24EvSEQvMow7gKPbZ3oATEFPuSghhB2TQz1dA40Zee3Qvk4LFlpLrhYo4K0ZSczCZRGpR+hCd8+Dpww52bheYEvWuh3ZQfvu/fXtEx2j5PwP1qMpmIgSxETV/gkD7l9FImdh0VzktYiAvQfmi0bEocG9/D4QwjFpNat7iwBdcMiw1MvAygpdIWRsjiw0RKlB2mWarmoHhQ7Gu7qlU3j50uaEvcrtmU0pBUPggNQwQRv32i9NPvNFxrqqlUjDLIS8JFea99zCkp8BwYqbEvBIMzd+Qip1/stLJJA3+cDUClbsDtg8rAVetzpOrdLEEBmqShFe5MDl2yEHcsgpN9CFsyTaUfvB3P3rVjizvycMm42IsUkXQiarm5xTQ/TIA8Rd8AHiSKuweNCg1Fd5SFaRtKy8JVLXuxyfUccmyje6hhz2L4lS2Wfj3mAG7sqZUCXhWP79EKdGkiPOjKv4CwXEKmuH3BMVqPlNUZJr9Eg3sV1FG0h2l+MVOOnR635qdUbb49sYojYxVruMLX0BH1c4ZCu230m8CUoWA1Em1QNI75ya7+9Y5T6AsgWDVpBvdUo9fWNbdp+VQ0GskFQsJD5wtnxbcbHeFiERAgGBm7z6qt9u9LrQpBH+dsW52ADvYsu3L4nQEa+sdMHwTTwmGY+iUvsxu0DqxGg=
|
secure: Cv5wFtWt62/A24EvSEQvMow7gKPbZ3oATEFPuSghhB2TQz1dA40Zee3Qvk4LFlpLrhYo4K0ZSczCZRGpR+hCd8+Dpww52bheYEvWuh3ZQfvu/fXtEx2j5PwP1qMpmIgSxETV/gkD7l9FImdh0VzktYiAvQfmi0bEocG9/D4QwjFpNat7iwBdcMiw1MvAygpdIWRsjiw0RKlB2mWarmoHhQ7Gu7qlU3j50uaEvcrtmU0pBUPggNQwQRv32i9NPvNFxrqqlUjDLIS8JFea99zCkp8BwYqbEvBIMzd+Qip1/stLJJA3+cDUClbsDtg8rAVetzpOrdLEEBmqShFe5MDl2yEHcsgpN9CFsyTaUfvB3P3rVjizvycMm42IsUkXQiarm5xTQ/TIA8Rd8AHiSKuweNCg1Fd5SFaRtKy8JVLXuxyfUccmyje6hhz2L4lS2Wfj3mAG7sqZUCXhWP79EKdGkiPOjKv4CwXEKmuH3BMVqPlNUZJr9Eg3sV1FG0h2l+MVOOnR635qdUbb49sYojYxVruMLX0BH1c4ZCu230m8CUoWA1Em1QNI75ya7+9Y5T6AsgWDVpBvdUo9fWNbdp+VQ0GskFQsJD5wtnxbcbHeFiERAgGBm7z6qt9u9LrQpBH+dsW52ADvYsu3L4nQEa+sdMHwTTwmGY+iUvsxu0DqxGg=
|
||||||
file:
|
file:
|
||||||
- desktop/build/libs/desktop-release.jar
|
- desktop/build/libs/Mindustry.jar
|
||||||
- server/build/libs/server-release.jar
|
- server/build/libs/server-release.jar
|
||||||
on:
|
on:
|
||||||
repo: Anuken/Mindustry
|
repo: Anuken/Mindustry
|
||||||
|
|||||||
@@ -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. <br>
|
Gradle may take up to several minutes to download files. Be patient. <br>
|
||||||
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
|
### Downloads
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ buildscript{
|
|||||||
}
|
}
|
||||||
|
|
||||||
dependencies{
|
dependencies{
|
||||||
classpath 'com.android.tools.build:gradle:3.4.2'
|
classpath 'com.android.tools.build:gradle:3.5.0'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
38
build.gradle
@@ -146,23 +146,6 @@ allprojects{
|
|||||||
project(":desktop"){
|
project(":desktop"){
|
||||||
apply plugin: "java"
|
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{
|
dependencies{
|
||||||
compile project(":core")
|
compile project(":core")
|
||||||
compile project(":net")
|
compile project(":net")
|
||||||
@@ -318,3 +301,24 @@ project(":net"){
|
|||||||
compile "org.lz4:lz4-java:1.4.1"
|
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"
|
||||||
|
}
|
||||||
@@ -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.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.customClient = This server does not support custom builds. Download an official version.
|
||||||
server.kicked.gameover = Game over!
|
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.
|
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.
|
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
|
hostserver = Host Multiplayer Game
|
||||||
|
|||||||
@@ -227,12 +227,14 @@ public class TechTree implements ContentList{
|
|||||||
|
|
||||||
node(turbineGenerator, () -> {
|
node(turbineGenerator, () -> {
|
||||||
node(thermalGenerator, () -> {
|
node(thermalGenerator, () -> {
|
||||||
node(rtgGenerator, () -> {
|
node(differentialGenerator, () -> {
|
||||||
node(differentialGenerator, () -> {
|
node(thoriumReactor, () -> {
|
||||||
node(thoriumReactor, () -> {
|
node(impactReactor, () -> {
|
||||||
node(impactReactor, () -> {
|
|
||||||
|
});
|
||||||
|
|
||||||
|
node(rtgGenerator, () -> {
|
||||||
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -84,7 +84,7 @@ public class Control implements ApplicationListener{
|
|||||||
});
|
});
|
||||||
|
|
||||||
Events.on(PlayEvent.class, event -> {
|
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.setDead(true);
|
||||||
player.add();
|
player.add();
|
||||||
|
|
||||||
|
|||||||
@@ -176,7 +176,7 @@ public class NetServer implements ApplicationListener{
|
|||||||
|
|
||||||
//playing in pvp mode automatically assigns players to teams
|
//playing in pvp mode automatically assigns players to teams
|
||||||
if(state.rules.pvp){
|
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());
|
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<Player> players){
|
public Team assignTeam(Player current, Iterable<Player> players){
|
||||||
//find team with minimum amount of players and auto-assign player to that.
|
//find team with minimum amount of players and auto-assign player to that.
|
||||||
return Structs.findMin(Team.all, team -> {
|
return Structs.findMin(Team.all, team -> {
|
||||||
if(state.teams.isActive(team) && !state.teams.get(team).cores.isEmpty()){
|
if(state.teams.isActive(team) && !state.teams.get(team).cores.isEmpty()){
|
||||||
int count = 0;
|
int count = 0;
|
||||||
for(Player other : players){
|
for(Player other : players){
|
||||||
if(other.getTeam() == team){
|
if(other.getTeam() == team && other != current){
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -527,7 +527,9 @@ public class Player extends Unit implements BuilderMinerTrait, ShooterTrait{
|
|||||||
spawner = null;
|
spawner = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
avoidOthers();
|
if(isLocal || Net.server()){
|
||||||
|
avoidOthers();
|
||||||
|
}
|
||||||
|
|
||||||
Tile tile = world.tileWorld(x, y);
|
Tile tile = world.tileWorld(x, y);
|
||||||
|
|
||||||
|
|||||||
@@ -214,7 +214,12 @@ public class Maps implements Disposable{
|
|||||||
|
|
||||||
return filters;
|
return filters;
|
||||||
}else{
|
}else{
|
||||||
return JsonIO.read(Array.class, str);
|
try{
|
||||||
|
return JsonIO.read(Array.class, str);
|
||||||
|
}catch(Exception e){
|
||||||
|
e.printStackTrace();
|
||||||
|
return readFilters("");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,21 +1,20 @@
|
|||||||
package io.anuke.mindustry.ui.dialogs;
|
package io.anuke.mindustry.ui.dialogs;
|
||||||
|
|
||||||
import io.anuke.annotations.Annotations.Serialize;
|
import io.anuke.annotations.Annotations.*;
|
||||||
import io.anuke.arc.Core;
|
import io.anuke.arc.*;
|
||||||
import io.anuke.arc.collection.Array;
|
import io.anuke.arc.collection.*;
|
||||||
import io.anuke.arc.graphics.Color;
|
import io.anuke.arc.graphics.*;
|
||||||
import io.anuke.arc.math.Mathf;
|
import io.anuke.arc.math.*;
|
||||||
import io.anuke.arc.scene.style.Drawable;
|
import io.anuke.arc.scene.style.*;
|
||||||
import io.anuke.arc.scene.ui.*;
|
import io.anuke.arc.scene.ui.*;
|
||||||
import io.anuke.arc.scene.ui.layout.Cell;
|
import io.anuke.arc.scene.ui.layout.*;
|
||||||
import io.anuke.arc.scene.ui.layout.Table;
|
import io.anuke.arc.util.*;
|
||||||
import io.anuke.arc.util.Strings;
|
import io.anuke.mindustry.*;
|
||||||
import io.anuke.arc.util.Time;
|
import io.anuke.mindustry.core.*;
|
||||||
import io.anuke.mindustry.Vars;
|
import io.anuke.mindustry.game.*;
|
||||||
import io.anuke.mindustry.core.Platform;
|
|
||||||
import io.anuke.mindustry.game.Version;
|
|
||||||
import io.anuke.mindustry.net.Host;
|
|
||||||
import io.anuke.mindustry.net.Net;
|
import io.anuke.mindustry.net.Net;
|
||||||
|
import io.anuke.mindustry.net.*;
|
||||||
|
import io.anuke.mindustry.net.Packets.*;
|
||||||
|
|
||||||
import static io.anuke.mindustry.Vars.*;
|
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", () -> {
|
TextButton button = buttons[0] = remote.addButton("[accent]" + server.displayIP(), "clear", () -> {
|
||||||
if(!buttons[0].childrenPressed()){
|
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);
|
button.getLabel().setWrap(true);
|
||||||
|
|
||||||
|
|||||||
@@ -113,9 +113,16 @@ public class ZoneInfoDialog extends FloatingDialog{
|
|||||||
t.add("$zone.resources").padRight(6);
|
t.add("$zone.resources").padRight(6);
|
||||||
|
|
||||||
if(zone.resources.length > 0){
|
if(zone.resources.length > 0){
|
||||||
for(Item item : zone.resources){
|
t.table(r -> {
|
||||||
t.addImage(item.icon(Item.Icon.medium)).size(8 * 3);
|
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{
|
}else{
|
||||||
t.add("$none");
|
t.add("$none");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -242,9 +242,9 @@ public class HudFragment extends Fragment{
|
|||||||
IntFormat fps = new IntFormat("fps");
|
IntFormat fps = new IntFormat("fps");
|
||||||
IntFormat ping = new IntFormat("ping");
|
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.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();
|
}).top().left();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -294,9 +294,7 @@ public class Block extends BlockStorage{
|
|||||||
/** Called after the block is placed by this client. */
|
/** Called after the block is placed by this client. */
|
||||||
@CallSuper
|
@CallSuper
|
||||||
public void playerPlaced(Tile tile){
|
public void playerPlaced(Tile tile){
|
||||||
if(outputsPower && !consumesPower){
|
|
||||||
PowerNode.lastPlaced = tile.pos();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Called after the block is placed by anyone. */
|
/** Called after the block is placed by anyone. */
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package io.anuke.mindustry.world.blocks.power;
|
|||||||
|
|
||||||
import io.anuke.annotations.Annotations.*;
|
import io.anuke.annotations.Annotations.*;
|
||||||
import io.anuke.arc.*;
|
import io.anuke.arc.*;
|
||||||
|
import io.anuke.arc.collection.*;
|
||||||
import io.anuke.arc.function.*;
|
import io.anuke.arc.function.*;
|
||||||
import io.anuke.arc.graphics.*;
|
import io.anuke.arc.graphics.*;
|
||||||
import io.anuke.arc.graphics.g2d.*;
|
import io.anuke.arc.graphics.g2d.*;
|
||||||
@@ -20,9 +21,7 @@ import io.anuke.mindustry.world.meta.*;
|
|||||||
import static io.anuke.mindustry.Vars.*;
|
import static io.anuke.mindustry.Vars.*;
|
||||||
|
|
||||||
public class PowerNode extends PowerBlock{
|
public class PowerNode extends PowerBlock{
|
||||||
//last distribution block placed
|
protected ObjectSet<PowerGraph> graphs = new ObjectSet<>();
|
||||||
public static int lastPlaced = -1;
|
|
||||||
|
|
||||||
protected Vector2 t1 = new Vector2(), t2 = new Vector2();
|
protected Vector2 t1 = new Vector2(), t2 = new Vector2();
|
||||||
protected TextureRegion laser, laserEnd;
|
protected TextureRegion laser, laserEnd;
|
||||||
|
|
||||||
@@ -99,23 +98,11 @@ public class PowerNode extends PowerBlock{
|
|||||||
() -> Mathf.clamp(entity.power.graph.getPowerProduced() / entity.power.graph.getPowerNeeded())));
|
() -> 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
|
@Override
|
||||||
public void placed(Tile tile){
|
public void placed(Tile tile){
|
||||||
if(Net.client()) return;
|
if(Net.client()) return;
|
||||||
|
|
||||||
Predicate<Tile> valid = other -> other != null && other != tile && ((!other.block().outputsPower && other.block().consumesPower) || (other.block().outputsPower && !other.block().consumesPower)) && linkValid(tile, other)
|
Predicate<Tile> 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;
|
&& !other.entity.proximity().contains(tile) && other.entity.power.graph != tile.entity.power.graph;
|
||||||
|
|
||||||
tempTiles.clear();
|
tempTiles.clear();
|
||||||
@@ -132,6 +119,28 @@ public class PowerNode extends PowerBlock{
|
|||||||
super.placed(tile);
|
super.placed(tile);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void getPotentialLinks(Tile tile, Consumer<Tile> others){
|
||||||
|
Predicate<Tile> 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
|
@Override
|
||||||
public void setStats(){
|
public void setStats(){
|
||||||
super.setStats();
|
super.setStats();
|
||||||
@@ -213,6 +222,11 @@ public class PowerNode extends PowerBlock{
|
|||||||
Draw.color(Pal.placing);
|
Draw.color(Pal.placing);
|
||||||
Drawf.circles(x * tilesize + offset(), y * tilesize + offset(), laserRange * tilesize);
|
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 cx = (int)(x - laserRange - 1); cx <= x + laserRange + 1; cx++){
|
||||||
for(int cy = (int)(y - laserRange - 1); cy <= y + laserRange + 1; cy++){
|
for(int cy = (int)(y - laserRange - 1); cy <= y + laserRange + 1; cy++){
|
||||||
Tile link = world.ltile(cx, 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);
|
Drawf.square(link.drawx(), link.drawy(), link.block().size * tilesize / 2f + 2f, link.pos() == lastPlaced ? Pal.place : Pal.accent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}*/
|
||||||
|
|
||||||
Draw.reset();
|
Draw.reset();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,6 +12,11 @@ public class LiquidConverter extends GenericCrafter{
|
|||||||
hasLiquids = true;
|
hasLiquids = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean outputsItems(){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void init(){
|
public void init(){
|
||||||
ConsumeLiquidBase cl = consumes.get(ConsumeType.liquid);
|
ConsumeLiquidBase cl = consumes.get(ConsumeType.liquid);
|
||||||
|
|||||||
@@ -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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -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<Runnable> 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<FileHandle> cons, boolean open, Predicate<String> 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<NetworkInterface> 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=");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,43 +1,28 @@
|
|||||||
|
import com.badlogicgames.packr.Packr
|
||||||
|
import com.badlogicgames.packr.PackrConfig
|
||||||
|
|
||||||
apply plugin: "java"
|
apply plugin: "java"
|
||||||
|
|
||||||
sourceCompatibility = 1.8
|
sourceCompatibility = 1.8
|
||||||
sourceSets.main.java.srcDirs = ["src/"]
|
sourceSets.main.java.srcDirs = [ "src/" ]
|
||||||
|
|
||||||
project.ext.mainClassName = "io.anuke.mindustry.desktop.DesktopLauncher"
|
project.ext.mainClassName = "io.anuke.mindustry.desktop.DesktopLauncher"
|
||||||
project.ext.assetsDir = new File("../core/assets")
|
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 JDK_DIR = "$System.env.PACKR_DIR"
|
||||||
def ICON_DIR = new File("core/assets/icons/icon.icns")
|
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){
|
task run(dependsOn: classes, type: JavaExec){
|
||||||
main = project.mainClassName
|
main = project.mainClassName
|
||||||
classpath = sourceSets.main.runtimeClasspath
|
classpath = sourceSets.main.runtimeClasspath
|
||||||
standardInput = System.in
|
standardInput = System.in
|
||||||
workingDir = project.assetsDir
|
workingDir = project.assetsDir
|
||||||
if(System.getProperty("os.name").toLowerCase().contains("mac")){
|
|
||||||
jvmArgs "-XstartOnFirstThread"
|
|
||||||
}
|
|
||||||
ignoreExitValue = true
|
ignoreExitValue = true
|
||||||
|
|
||||||
|
if(System.getProperty("os.name").toLowerCase().contains("mac")){
|
||||||
|
jvmArgs("-XstartOnFirstThread", "-Djava.awt.headless=true")
|
||||||
|
}
|
||||||
|
|
||||||
if(project.hasProperty("args")){
|
if(project.hasProperty("args")){
|
||||||
args Eval.me(project.getProperties()["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.classesDirs)
|
||||||
from files(sourceSets.main.output.resourcesDir)
|
from files(sourceSets.main.output.resourcesDir)
|
||||||
from{ configurations.compile.collect{ zipTree(it) } }
|
from {configurations.compile.collect {zipTree(it)}}
|
||||||
from files(project.assetsDir)
|
from files(project.assetsDir)
|
||||||
|
|
||||||
|
archiveName = "${appName}.jar"
|
||||||
|
|
||||||
manifest{
|
manifest{
|
||||||
attributes 'Main-Class': project.mainClassName
|
attributes 'Main-Class': project.mainClassName
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//note: call desktop:dist beforehand
|
task steamdist(dependsOn: dist){
|
||||||
task packrCmd(){
|
|
||||||
|
|
||||||
doLast{
|
doLast{
|
||||||
def config = new PackrConfig()
|
copy{
|
||||||
config.with{
|
from "build/libs/Mindustry-linux-release.jar"
|
||||||
config.executable = appName
|
into "/home/anuke/.steam/steam/steamapps/common/Mindustry"
|
||||||
verbose = true
|
rename { String fileName ->
|
||||||
platform = getPlatform()
|
fileName.replace("Mindustry-linux-release", "desktop-release")
|
||||||
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"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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(){
|
PackrConfig.Platform.values().each{ platform ->
|
||||||
task clearOut(type: Delete){
|
task "packr${platform.toString()}"{
|
||||||
doLast{
|
def platformName = platform.toString().replace('64', '').replace('32', '').replace('MacOS', 'Mac')
|
||||||
delete "packr-out/"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
task fixMac(type: Copy){
|
dependsOn dist
|
||||||
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")
|
|
||||||
|
|
||||||
doLast{
|
doLast{
|
||||||
copy{
|
copy{
|
||||||
into "packr-out/jre/bin/"
|
into "build/packr/"
|
||||||
from JDK_DIR + "zip.dll"
|
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'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -27,13 +27,25 @@
|
|||||||
"com/sun/jndi",
|
"com/sun/jndi",
|
||||||
"com/sun/xml",
|
"com/sun/xml",
|
||||||
"com/sun/script",
|
"com/sun/script",
|
||||||
"sum/awt",
|
"sun/awt",
|
||||||
"sun/java2d",
|
"sun/java2d",
|
||||||
"sun/font",
|
"sun/font",
|
||||||
"sun/rmi",
|
"sun/rmi",
|
||||||
"sun/swing",
|
"sun/swing",
|
||||||
"java/util/stream",
|
"java/util/stream",
|
||||||
"com/sun/media",
|
"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",
|
"com/sun/naming",
|
||||||
"java/awt",
|
"java/awt",
|
||||||
"com/sun/org/apache/xpath",
|
"com/sun/org/apache/xpath",
|
||||||
|
|||||||
@@ -1,27 +1,30 @@
|
|||||||
package io.anuke.mindustry.desktop;
|
package io.anuke.mindustry.desktop;
|
||||||
|
|
||||||
import io.anuke.arc.backends.lwjgl3.Lwjgl3Application;
|
import io.anuke.arc.Files.*;
|
||||||
import io.anuke.arc.backends.lwjgl3.Lwjgl3ApplicationConfiguration;
|
import io.anuke.arc.backends.sdl.*;
|
||||||
import io.anuke.mindustry.Mindustry;
|
import io.anuke.mindustry.*;
|
||||||
import io.anuke.mindustry.core.Platform;
|
import io.anuke.mindustry.core.*;
|
||||||
|
import io.anuke.mindustry.desktop.steam.*;
|
||||||
import io.anuke.mindustry.net.*;
|
import io.anuke.mindustry.net.*;
|
||||||
|
|
||||||
public class DesktopLauncher{
|
public class DesktopLauncher{
|
||||||
|
|
||||||
public static void main(String[] arg){
|
public static void main(String[] arg){
|
||||||
try{
|
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);
|
Platform.instance = new DesktopPlatform(arg);
|
||||||
|
|
||||||
Net.setClientProvider(new ArcNetClient());
|
Net.setClientProvider(new ArcNetClient());
|
||||||
Net.setServerProvider(new ArcNetServer());
|
Net.setServerProvider(new SteamServerImpl(new ArcNetServer()));
|
||||||
new Lwjgl3Application(new Mindustry(), config);
|
|
||||||
|
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){
|
}catch(Throwable e){
|
||||||
DesktopPlatform.handleCrash(e);
|
DesktopPlatform.handleCrash(e);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,26 +1,30 @@
|
|||||||
package io.anuke.mindustry.desktop;
|
package io.anuke.mindustry.desktop;
|
||||||
|
|
||||||
import club.minnced.discord.rpc.*;
|
import club.minnced.discord.rpc.*;
|
||||||
import io.anuke.arc.collection.Array;
|
import com.codedisaster.steamworks.*;
|
||||||
import io.anuke.arc.files.FileHandle;
|
import io.anuke.arc.*;
|
||||||
import io.anuke.arc.function.Consumer;
|
import io.anuke.arc.backends.sdl.jni.*;
|
||||||
import io.anuke.arc.function.Predicate;
|
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.*;
|
||||||
import io.anuke.arc.util.serialization.Base64Coder;
|
import io.anuke.arc.util.serialization.*;
|
||||||
import io.anuke.mindustry.core.GameState.State;
|
import io.anuke.mindustry.*;
|
||||||
import io.anuke.mindustry.core.Platform;
|
import io.anuke.mindustry.core.GameState.*;
|
||||||
import io.anuke.mindustry.net.CrashSender;
|
import io.anuke.mindustry.core.*;
|
||||||
|
import io.anuke.mindustry.game.EventType.*;
|
||||||
import io.anuke.mindustry.net.Net;
|
import io.anuke.mindustry.net.Net;
|
||||||
import io.anuke.mindustry.ui.dialogs.FileChooser;
|
import io.anuke.mindustry.net.*;
|
||||||
import org.lwjgl.util.tinyfd.TinyFileDialogs;
|
import io.anuke.mindustry.ui.dialogs.*;
|
||||||
|
|
||||||
import java.net.NetworkInterface;
|
import java.net.*;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
import static io.anuke.mindustry.Vars.*;
|
import static io.anuke.mindustry.Vars.*;
|
||||||
|
|
||||||
|
|
||||||
public class DesktopPlatform extends Platform{
|
public class DesktopPlatform extends Platform{
|
||||||
static boolean useDiscord = OS.is64Bit;
|
static boolean useDiscord = OS.is64Bit, useSteam = true;
|
||||||
final static String applicationId = "610508934456934412";
|
final static String applicationId = "610508934456934412";
|
||||||
String[] args;
|
String[] args;
|
||||||
|
|
||||||
@@ -40,19 +44,55 @@ public class DesktopPlatform extends Platform{
|
|||||||
Log.err("Failed to initialize discord.", t);
|
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){
|
static void handleCrash(Throwable e){
|
||||||
Consumer<Runnable> dialog = r -> new Thread(r).start();
|
Consumer<Runnable> dialog = Runnable::run;
|
||||||
boolean badGPU = false;
|
boolean badGPU = false;
|
||||||
|
|
||||||
if(e.getMessage() != null && (e.getMessage().contains("Couldn't create window") || e.getMessage().contains("OpenGL 2.0 or higher"))){
|
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() :
|
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" +
|
"Your graphics card does not support OpenGL 2.0!\n" +
|
||||||
"Try to update your graphics drivers.\n\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;
|
badGPU = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -60,7 +100,7 @@ public class DesktopPlatform extends Platform{
|
|||||||
|
|
||||||
CrashSender.send(e, file -> {
|
CrashSender.send(e, file -> {
|
||||||
if(!fbgp){
|
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));
|
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;
|
return str;
|
||||||
}catch(Exception e){
|
}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){
|
private boolean validAddress(byte[] bytes){
|
||||||
if(bytes == null) return false;
|
if(bytes == null) return false;
|
||||||
byte[] result = new byte[8];
|
byte[] result = new byte[8];
|
||||||
System.arraycopy(bytes, 0, result, 0, bytes.length);
|
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=");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
package io.anuke.mindustry.desktopsdl.steam;
|
package io.anuke.mindustry.desktop.steam;
|
||||||
|
|
||||||
import com.codedisaster.steamworks.*;
|
import com.codedisaster.steamworks.*;
|
||||||
import com.codedisaster.steamworks.SteamFriends.*;
|
import com.codedisaster.steamworks.SteamFriends.*;
|
||||||
@@ -6,12 +6,11 @@ import com.codedisaster.steamworks.SteamMatchmaking.*;
|
|||||||
import com.codedisaster.steamworks.SteamNetworking.*;
|
import com.codedisaster.steamworks.SteamNetworking.*;
|
||||||
import io.anuke.arc.collection.*;
|
import io.anuke.arc.collection.*;
|
||||||
import io.anuke.arc.util.*;
|
import io.anuke.arc.util.*;
|
||||||
import io.anuke.mindustry.net.Net.*;
|
import io.anuke.mindustry.desktop.steam.SteamServerImpl.*;
|
||||||
import io.anuke.mindustry.net.*;
|
|
||||||
|
|
||||||
import java.nio.*;
|
import java.nio.*;
|
||||||
|
|
||||||
public class ClientSteam implements SteamNetworkingCallback, SteamMatchmakingCallback{
|
public class SteamClientImpl implements SteamNetworkingCallback, SteamMatchmakingCallback{
|
||||||
private SteamNetworking snet;
|
private SteamNetworking snet;
|
||||||
private SteamMatchmaking smat;
|
private SteamMatchmaking smat;
|
||||||
|
|
||||||
@@ -19,7 +18,7 @@ public class ClientSteam implements SteamNetworkingCallback, SteamMatchmakingCal
|
|||||||
//maps steam ID -> valid net connection
|
//maps steam ID -> valid net connection
|
||||||
private IntMap<SteamConnection> connections = new IntMap<>();
|
private IntMap<SteamConnection> connections = new IntMap<>();
|
||||||
|
|
||||||
public ClientSteam(){
|
public SteamClientImpl(){
|
||||||
//snet = new SteamNetworking(this);
|
//snet = new SteamNetworking(this);
|
||||||
//smat = new SteamMatchmaking(this);
|
//smat = new SteamMatchmaking(this);
|
||||||
|
|
||||||
@@ -53,46 +52,6 @@ public class ClientSteam implements SteamNetworkingCallback, SteamMatchmakingCal
|
|||||||
snet.acceptP2PSessionWithUser(steamIDRemote);
|
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
|
@Override
|
||||||
public void onFavoritesListChanged(int ip, int queryPort, int connPort, int appID, int flags, boolean add, int accountID){
|
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.activateGameOverlay(OverlayDialog.Friends);
|
||||||
//friends.activateGameOverlayInviteDialog(steamIDLobby);
|
friends.activateGameOverlayInviteDialog(steamIDLobby);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -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){
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package io.anuke.mindustry.desktopsdl.steam;
|
package io.anuke.mindustry.desktop.steam;
|
||||||
|
|
||||||
import com.codedisaster.steamworks.*;
|
import com.codedisaster.steamworks.*;
|
||||||
import com.codedisaster.steamworks.SteamMatchmaking.*;
|
import com.codedisaster.steamworks.SteamMatchmaking.*;
|
||||||
@@ -6,28 +6,28 @@ import com.codedisaster.steamworks.SteamNetworking.*;
|
|||||||
import io.anuke.arc.*;
|
import io.anuke.arc.*;
|
||||||
import io.anuke.arc.collection.*;
|
import io.anuke.arc.collection.*;
|
||||||
import io.anuke.arc.util.*;
|
import io.anuke.arc.util.*;
|
||||||
import io.anuke.mindustry.desktopsdl.steam.ClientSteam.*;
|
|
||||||
import io.anuke.mindustry.net.Net.*;
|
import io.anuke.mindustry.net.Net.*;
|
||||||
import io.anuke.mindustry.net.*;
|
import io.anuke.mindustry.net.*;
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.nio.*;
|
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 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 SteamNetworking snet = new SteamNetworking(this);
|
||||||
private final SteamMatchmaking smat = new SteamMatchmaking(this);
|
private final SteamMatchmaking smat = new SteamMatchmaking(this);
|
||||||
|
private final SteamFriendsImpl friends = new SteamFriendsImpl();
|
||||||
private final ServerProvider server;
|
private final ServerProvider server;
|
||||||
|
|
||||||
//buffer for steam API calls
|
|
||||||
private ByteBuffer steamBuffer = ByteBuffer.allocateDirect(1024 * 128);
|
|
||||||
//maps steam ID -> valid net connection
|
//maps steam ID -> valid net connection
|
||||||
private IntMap<SteamConnection> steamConnections = new IntMap<>();
|
private IntMap<SteamConnection> steamConnections = new IntMap<>();
|
||||||
|
|
||||||
private SteamID currentLobby;
|
private SteamID currentLobby;
|
||||||
|
|
||||||
public ServerSteam(ServerProvider server){
|
public SteamServerImpl(ServerProvider server){
|
||||||
this.server = 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);
|
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
|
@Override
|
||||||
public void close(){
|
public void close(){
|
||||||
server.close();
|
server.close();
|
||||||
@@ -66,6 +46,9 @@ public class ServerSteam implements ServerProvider, SteamNetworkingCallback, Ste
|
|||||||
//TODO kick everyone who is in this lobby?
|
//TODO kick everyone who is in this lobby?
|
||||||
smat.leaveLobby(currentLobby);
|
smat.leaveLobby(currentLobby);
|
||||||
currentLobby = null;
|
currentLobby = null;
|
||||||
|
for(SteamConnection con : steamConnections.values()){
|
||||||
|
con.close();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -75,7 +58,7 @@ public class ServerSteam implements ServerProvider, SteamNetworkingCallback, Ste
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Array<? extends NetConnection> getConnections(){
|
public Iterable<? extends NetConnection> getConnections(){
|
||||||
return server.getConnections();
|
return server.getConnections();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -157,4 +140,37 @@ public class ServerSteam implements ServerProvider, SteamNetworkingCallback, Ste
|
|||||||
//accept users on request
|
//accept users on request
|
||||||
snet.acceptP2PSessionWithUser(steamIDRemote);
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package io.anuke.mindustry.desktopsdl.steam;
|
package io.anuke.mindustry.desktop.steam;
|
||||||
|
|
||||||
import com.codedisaster.steamworks.*;
|
import com.codedisaster.steamworks.*;
|
||||||
import com.codedisaster.steamworks.SteamRemoteStorage.*;
|
import com.codedisaster.steamworks.SteamRemoteStorage.*;
|
||||||
2
fastlane/Appfile
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
json_key_file(ENV["FASTLANE_KEY_FILE"])
|
||||||
|
package_name("io.anuke.mindustry")
|
||||||
46
fastlane/Fastfile
Normal file
@@ -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
|
||||||
3
fastlane/metadata/android/en-US/changelogs/12203.txt
Normal file
@@ -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
|
||||||
4
fastlane/metadata/android/en-US/changelogs/12205.txt
Normal file
@@ -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
|
||||||
1
fastlane/metadata/android/en-US/changelogs/26593.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
sound.
|
||||||
1
fastlane/metadata/android/en-US/changelogs/27434.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
everything
|
||||||
1
fastlane/metadata/android/en-US/changelogs/27476.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
Fixed some minor sound/multiplayer issues
|
||||||
1
fastlane/metadata/android/en-US/changelogs/27689.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
Bugfixes
|
||||||
1
fastlane/metadata/android/en-US/changelogs/27770.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
Added ambient sounds for machines.
|
||||||
2
fastlane/metadata/android/en-US/changelogs/27997.txt
Normal file
@@ -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.
|
||||||
2
fastlane/metadata/android/en-US/changelogs/28409.txt
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
Fixed multiplayer not syncing positions and shots correctly on certain networks or situations.
|
||||||
|
Various other bugfixes.
|
||||||
5
fastlane/metadata/android/en-US/changelogs/721.txt
Normal file
@@ -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)
|
||||||
14
fastlane/metadata/android/en-US/full_description.txt
Normal file
@@ -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
|
||||||
BIN
fastlane/metadata/android/en-US/images/featureGraphic.png
Normal file
|
After Width: | Height: | Size: 649 KiB |
BIN
fastlane/metadata/android/en-US/images/icon.png
Normal file
|
After Width: | Height: | Size: 70 KiB |
BIN
fastlane/metadata/android/en-US/images/phoneScreenshots/1.png
Normal file
|
After Width: | Height: | Size: 583 KiB |
BIN
fastlane/metadata/android/en-US/images/phoneScreenshots/2.png
Normal file
|
After Width: | Height: | Size: 1.1 MiB |
BIN
fastlane/metadata/android/en-US/images/phoneScreenshots/3.png
Normal file
|
After Width: | Height: | Size: 709 KiB |
BIN
fastlane/metadata/android/en-US/images/phoneScreenshots/4.png
Normal file
|
After Width: | Height: | Size: 952 KiB |
BIN
fastlane/metadata/android/en-US/images/phoneScreenshots/5.png
Normal file
|
After Width: | Height: | Size: 642 KiB |
BIN
fastlane/metadata/android/en-US/images/phoneScreenshots/6.png
Normal file
|
After Width: | Height: | Size: 260 KiB |
BIN
fastlane/metadata/android/en-US/images/phoneScreenshots/7.png
Normal file
|
After Width: | Height: | Size: 570 KiB |
|
After Width: | Height: | Size: 890 KiB |
|
After Width: | Height: | Size: 1.1 MiB |
|
After Width: | Height: | Size: 952 KiB |
1
fastlane/metadata/android/en-US/short_description.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
A factory-based sandbox tower defense game.
|
||||||
1
fastlane/metadata/android/en-US/title.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
Mindustry
|
||||||
0
fastlane/metadata/android/en-US/video.txt
Normal file
15
fastlane/metadata/android/ru-RU/full_description.txt
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
Создавайте сложные логистические сети для переноса боеприпасов для турелей, добывайте ресурсы для строительства, и защищайте их от различных волн врагов.
|
||||||
|
Играйте с друзьями в кроссплатформенные кооперативные игры, или бросьте им вызов в командных PvP-матчах.
|
||||||
|
|
||||||
|
Особенности игры:
|
||||||
|
- 24 встроенные карты
|
||||||
|
- Кампания, с полноценным технологическим древом и прогрессией карт
|
||||||
|
- 4 вида мощных боссов
|
||||||
|
- Системы для транспорта электроэнергии, жидкостей и ресурсов
|
||||||
|
- 19 видов дронов, кораблей и наземных боевых единиц
|
||||||
|
- Более 120 блоков в техногическом древе
|
||||||
|
- Более 75 видов натуральных блоков
|
||||||
|
- Кроссплатформенный мультиплеер с поддержкой как и локальных сетей, так и серверов
|
||||||
|
- Пользовательские настройки игры — изменяйте цену блоков, силу врагов, количество стартовых ресурсов, интервал между волнами и т.д.
|
||||||
|
- Редактор карт с бесчисленными возможностями, инструментами для случайной генерации руд, рельефа, декораций, а также для симметрии карт
|
||||||
|
- Настраиваемые раскладки волн для карт
|
||||||
1
fastlane/metadata/android/ru-RU/short_description.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
A factory-based sandbox tower defense game.
|
||||||
1
fastlane/metadata/android/ru-RU/title.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
Mindustry
|
||||||
0
fastlane/metadata/android/ru-RU/video.txt
Normal file
|
Before Width: | Height: | Size: 996 KiB After Width: | Height: | Size: 706 KiB |
|
Before Width: | Height: | Size: 1.3 MiB After Width: | Height: | Size: 905 KiB |
|
Before Width: | Height: | Size: 2.8 MiB After Width: | Height: | Size: 2.0 MiB |
|
Before Width: | Height: | Size: 2.2 MiB After Width: | Height: | Size: 1.6 MiB |
|
Before Width: | Height: | Size: 2.8 MiB After Width: | Height: | Size: 1.8 MiB |
|
Before Width: | Height: | Size: 993 KiB After Width: | Height: | Size: 632 KiB |
|
Before Width: | Height: | Size: 3.1 MiB After Width: | Height: | Size: 2.1 MiB |
|
Before Width: | Height: | Size: 1.1 MiB After Width: | Height: | Size: 725 KiB |
|
Before Width: | Height: | Size: 890 KiB After Width: | Height: | Size: 598 KiB |
|
Before Width: | Height: | Size: 278 KiB After Width: | Height: | Size: 204 KiB |
@@ -40,7 +40,7 @@ public class IOSLauncher extends IOSApplication.Delegate{
|
|||||||
@Override
|
@Override
|
||||||
public void shareFile(FileHandle file){
|
public void shareFile(FileHandle file){
|
||||||
Log.info("Attempting to share file " + 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);
|
file.copyTo(to);
|
||||||
|
|
||||||
NSURL url = new NSURL(to.file());
|
NSURL url = new NSURL(to.file());
|
||||||
@@ -53,7 +53,6 @@ public class IOSLauncher extends IOSApplication.Delegate{
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void beginForceLandscape(){
|
public void beginForceLandscape(){
|
||||||
Log.info("begin force landscape");
|
|
||||||
forced = true;
|
forced = true;
|
||||||
UINavigationController.attemptRotationToDeviceOrientation();
|
UINavigationController.attemptRotationToDeviceOrientation();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -700,10 +700,11 @@ public class ServerControl implements ApplicationListener{
|
|||||||
run.run();
|
run.run();
|
||||||
logic.play();
|
logic.play();
|
||||||
state.rules = world.getMap().applyRules(lastMode);
|
state.rules = world.getMap().applyRules(lastMode);
|
||||||
|
|
||||||
for(Player p : players){
|
for(Player p : players){
|
||||||
p.reset();
|
p.reset();
|
||||||
if(state.rules.pvp){
|
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);
|
netServer.sendWorldData(p, p.con.id);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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 ->
|
def use = { String name ->
|
||||||
include(name)
|
include(name)
|
||||||
|
|||||||