Merge branch 'master' into feature_rich_presence
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -21,6 +21,7 @@
|
|||||||
*.war
|
*.war
|
||||||
*.ear
|
*.ear
|
||||||
hs_err_pid*
|
hs_err_pid*
|
||||||
|
crash-report-*
|
||||||
|
|
||||||
## Robovm
|
## Robovm
|
||||||
/ios/robovm-build/
|
/ios/robovm-build/
|
||||||
|
|||||||
@@ -1,24 +1,25 @@
|
|||||||
package io.anuke.mindustry;
|
package io.anuke.mindustry;
|
||||||
|
|
||||||
import java.text.DateFormat;
|
|
||||||
import java.text.NumberFormat;
|
|
||||||
import java.text.SimpleDateFormat;
|
|
||||||
import java.util.Date;
|
|
||||||
|
|
||||||
import com.badlogic.gdx.backends.android.AndroidApplication;
|
|
||||||
import com.badlogic.gdx.backends.android.AndroidApplicationConfiguration;
|
|
||||||
|
|
||||||
import android.annotation.SuppressLint;
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.telephony.TelephonyManager;
|
import android.telephony.TelephonyManager;
|
||||||
|
import com.badlogic.gdx.backends.android.AndroidApplication;
|
||||||
|
import com.badlogic.gdx.backends.android.AndroidApplicationConfiguration;
|
||||||
|
import io.anuke.kryonet.KryoClient;
|
||||||
|
import io.anuke.kryonet.KryoServer;
|
||||||
import io.anuke.mindustry.io.PlatformFunction;
|
import io.anuke.mindustry.io.PlatformFunction;
|
||||||
|
import io.anuke.mindustry.net.Net;
|
||||||
import io.anuke.ucore.function.Callable;
|
import io.anuke.ucore.function.Callable;
|
||||||
import io.anuke.ucore.scene.ui.TextField;
|
import io.anuke.ucore.scene.ui.TextField;
|
||||||
import io.anuke.ucore.scene.ui.layout.Unit;
|
import io.anuke.ucore.scene.ui.layout.Unit;
|
||||||
|
|
||||||
|
import java.text.DateFormat;
|
||||||
|
import java.text.NumberFormat;
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
public class AndroidLauncher extends AndroidApplication{
|
public class AndroidLauncher extends AndroidApplication{
|
||||||
boolean doubleScaleTablets = true;
|
boolean doubleScaleTablets = true;
|
||||||
|
|
||||||
@@ -73,6 +74,9 @@ public class AndroidLauncher extends AndroidApplication{
|
|||||||
|
|
||||||
config.hideStatusBar = true;
|
config.hideStatusBar = true;
|
||||||
|
|
||||||
|
Net.setClientProvider(new KryoClient());
|
||||||
|
Net.setServerProvider(new KryoServer());
|
||||||
|
|
||||||
initialize(new Mindustry(), config);
|
initialize(new Mindustry(), config);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
15
build.gradle
15
build.gradle
@@ -21,7 +21,7 @@ allprojects {
|
|||||||
appName = "Mindustry"
|
appName = "Mindustry"
|
||||||
gdxVersion = '1.9.8'
|
gdxVersion = '1.9.8'
|
||||||
aiVersion = '1.8.1'
|
aiVersion = '1.8.1'
|
||||||
uCoreVersion = '4fb2c63';
|
uCoreVersion = '8751c0a66c';
|
||||||
}
|
}
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
@@ -38,10 +38,10 @@ project(":desktop") {
|
|||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
compile project(":core")
|
compile project(":core")
|
||||||
|
compile project(":kryonet")
|
||||||
compile "com.badlogicgames.gdx:gdx-backend-lwjgl3:$gdxVersion"
|
compile "com.badlogicgames.gdx:gdx-backend-lwjgl3:$gdxVersion"
|
||||||
compile "com.badlogicgames.gdx:gdx-platform:$gdxVersion:natives-desktop"
|
compile "com.badlogicgames.gdx:gdx-platform:$gdxVersion:natives-desktop"
|
||||||
compile "com.badlogicgames.gdx:gdx-controllers-lwjgl3:$gdxVersion"
|
compile "com.badlogicgames.gdx:gdx-controllers-lwjgl3:$gdxVersion"
|
||||||
compile "com.esotericsoftware:kryonet:2.22.0-RC1"
|
|
||||||
compile "com.github.MinnDevelopment:Java-DiscordRPC:dbd4aac"
|
compile "com.github.MinnDevelopment:Java-DiscordRPC:dbd4aac"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -71,6 +71,7 @@ project(":android") {
|
|||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
compile project(":core")
|
compile project(":core")
|
||||||
|
compile project(":kryonet")
|
||||||
compile "com.badlogicgames.gdx:gdx-backend-android:$gdxVersion"
|
compile "com.badlogicgames.gdx:gdx-backend-android:$gdxVersion"
|
||||||
natives "com.badlogicgames.gdx:gdx-platform:$gdxVersion:natives-armeabi"
|
natives "com.badlogicgames.gdx:gdx-platform:$gdxVersion:natives-armeabi"
|
||||||
natives "com.badlogicgames.gdx:gdx-platform:$gdxVersion:natives-armeabi-v7a"
|
natives "com.badlogicgames.gdx:gdx-platform:$gdxVersion:natives-armeabi-v7a"
|
||||||
@@ -79,7 +80,6 @@ project(":android") {
|
|||||||
natives "com.badlogicgames.gdx:gdx-platform:$gdxVersion:natives-x86_64"
|
natives "com.badlogicgames.gdx:gdx-platform:$gdxVersion:natives-x86_64"
|
||||||
compile "com.badlogicgames.gdx:gdx-ai:$aiVersion"
|
compile "com.badlogicgames.gdx:gdx-ai:$aiVersion"
|
||||||
compile "com.badlogicgames.gdx:gdx-controllers-android:$gdxVersion"
|
compile "com.badlogicgames.gdx:gdx-controllers-android:$gdxVersion"
|
||||||
compile "com.esotericsoftware:kryonet:2.22.0-RC1"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -110,6 +110,15 @@ project(":core") {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
project(":kryonet") {
|
||||||
|
apply plugin: "java"
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
compile project(":core")
|
||||||
|
compile 'com.github.crykn:kryonet:2.22.1'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
tasks.eclipse.doLast {
|
tasks.eclipse.doLast {
|
||||||
delete ".project"
|
delete ".project"
|
||||||
}
|
}
|
||||||
|
|||||||
BIN
core/assets-raw/sprites/mechs/ship-standard.png
Normal file
BIN
core/assets-raw/sprites/mechs/ship-standard.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 309 B |
BIN
core/assets-raw/sprites/ui/icons/icon-host.png
Normal file
BIN
core/assets-raw/sprites/ui/icons/icon-host.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 193 B |
@@ -12,7 +12,13 @@ text.savegame=Save Game
|
|||||||
text.loadgame=Load Game
|
text.loadgame=Load Game
|
||||||
text.joingame=Join Game
|
text.joingame=Join Game
|
||||||
text.quit=Quit
|
text.quit=Quit
|
||||||
|
text.server.connected=A player has joined.
|
||||||
|
text.server.disconnected={0} has disconnected.
|
||||||
text.hostserver=Host Server
|
text.hostserver=Host Server
|
||||||
|
text.host=Host
|
||||||
|
text.hosts.discovering=Discovering LAN games
|
||||||
|
text.hosts.none=[lightgray]No hosts found!
|
||||||
|
text.joingame.byip=Join by IP...
|
||||||
text.joingame.title=Join Game
|
text.joingame.title=Join Game
|
||||||
text.joingame.ip=IP:
|
text.joingame.ip=IP:
|
||||||
text.disconnect=Disconnected.
|
text.disconnect=Disconnected.
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
Binary file not shown.
|
Before Width: | Height: | Size: 79 KiB After Width: | Height: | Size: 80 KiB |
@@ -46,7 +46,7 @@ io.anuke.ucore.scene.ui.TextButton$TextButtonStyle: {
|
|||||||
toggle: {font: default-font, fontColor: white, checked: button-down, down: button-down, up: button, over: button-over, disabled: button, disabledFontColor: grey }
|
toggle: {font: default-font, fontColor: white, checked: button-down, down: button-down, up: button, over: button-over, disabled: button, disabledFontColor: grey }
|
||||||
},
|
},
|
||||||
io.anuke.ucore.scene.ui.ImageButton$ImageButtonStyle: {
|
io.anuke.ucore.scene.ui.ImageButton$ImageButtonStyle: {
|
||||||
default: {down: button-down, up: button, over: button-over },
|
default: {down: button-down, up: button, over: button-over, imageDisabledColor: lightgray, imageUpColor: white },
|
||||||
empty: { imageDownColor: accent, imageUpColor: white},
|
empty: { imageDownColor: accent, imageUpColor: white},
|
||||||
emptytoggle: {imageCheckedColor: white, imageDownColor: white, imageUpColor: lightgray},
|
emptytoggle: {imageCheckedColor: white, imageDownColor: white, imageUpColor: lightgray},
|
||||||
static: {up: button },
|
static: {up: button },
|
||||||
|
|||||||
@@ -1,16 +1,13 @@
|
|||||||
package io.anuke.mindustry;
|
package io.anuke.mindustry;
|
||||||
|
|
||||||
import java.util.Date;
|
|
||||||
import java.util.Locale;
|
|
||||||
|
|
||||||
import com.badlogic.gdx.Gdx;
|
import com.badlogic.gdx.Gdx;
|
||||||
import com.badlogic.gdx.files.FileHandle;
|
import com.badlogic.gdx.files.FileHandle;
|
||||||
import com.badlogic.gdx.utils.Array;
|
import com.badlogic.gdx.utils.Array;
|
||||||
|
|
||||||
import com.badlogic.gdx.utils.I18NBundle;
|
import com.badlogic.gdx.utils.I18NBundle;
|
||||||
import io.anuke.mindustry.core.*;
|
import io.anuke.mindustry.core.*;
|
||||||
import io.anuke.mindustry.core.GameState.State;
|
import io.anuke.mindustry.core.GameState.State;
|
||||||
import io.anuke.mindustry.io.PlatformFunction;
|
import io.anuke.mindustry.io.PlatformFunction;
|
||||||
|
import io.anuke.mindustry.net.Net;
|
||||||
import io.anuke.mindustry.world.Block;
|
import io.anuke.mindustry.world.Block;
|
||||||
import io.anuke.mindustry.world.blocks.*;
|
import io.anuke.mindustry.world.blocks.*;
|
||||||
import io.anuke.ucore.UCore;
|
import io.anuke.ucore.UCore;
|
||||||
@@ -21,6 +18,9 @@ import io.anuke.ucore.function.Callable;
|
|||||||
import io.anuke.ucore.modules.ModuleCore;
|
import io.anuke.ucore.modules.ModuleCore;
|
||||||
import io.anuke.ucore.scene.ui.TextField;
|
import io.anuke.ucore.scene.ui.TextField;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
public class Mindustry extends ModuleCore {
|
public class Mindustry extends ModuleCore {
|
||||||
public static Callable donationsCallable;
|
public static Callable donationsCallable;
|
||||||
public static boolean hasDiscord = true;
|
public static boolean hasDiscord = true;
|
||||||
@@ -90,16 +90,9 @@ public class Mindustry extends ModuleCore {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void render(){
|
public void render(){
|
||||||
|
super.render();
|
||||||
|
|
||||||
try{
|
if(!GameState.is(State.paused) || Net.active()){
|
||||||
super.render();
|
|
||||||
}catch (RuntimeException e){
|
|
||||||
//TODO display error log
|
|
||||||
//Gdx.app.getClipboard().setContents(e.getMessage());
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!GameState.is(State.paused)){
|
|
||||||
Timers.update();
|
Timers.update();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ public class Vars{
|
|||||||
//respawn time in frames
|
//respawn time in frames
|
||||||
public static final float respawnduration = 60*4;
|
public static final float respawnduration = 60*4;
|
||||||
//time between waves in frames (on normal mode)
|
//time between waves in frames (on normal mode)
|
||||||
public static final float wavespace = 60*60*(android ? 1 : 1);
|
public static final float wavespace = 60*60*(android ? 1 : 1); //TODO revert
|
||||||
//waves can last no longer than 3 minutes, otherwise the next one spawns
|
//waves can last no longer than 3 minutes, otherwise the next one spawns
|
||||||
public static final float maxwavespace = 60*60*4f;
|
public static final float maxwavespace = 60*60*4f;
|
||||||
//advance time the pathfinding starts at
|
//advance time the pathfinding starts at
|
||||||
@@ -43,6 +43,7 @@ public class Vars{
|
|||||||
public static final int zoomScale = Math.round(Unit.dp.scl(1));
|
public static final int zoomScale = Math.round(Unit.dp.scl(1));
|
||||||
//if true, player speed will be increased, massive amounts of resources will be given on start, and other debug options will be available
|
//if true, player speed will be increased, massive amounts of resources will be given on start, and other debug options will be available
|
||||||
public static boolean debug = false;
|
public static boolean debug = false;
|
||||||
|
public static boolean debugNet = false;
|
||||||
//whether the player can clip through walls
|
//whether the player can clip through walls
|
||||||
public static boolean noclip = false;
|
public static boolean noclip = false;
|
||||||
//whether to draw chunk borders
|
//whether to draw chunk borders
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import com.badlogic.gdx.math.Vector2;
|
|||||||
|
|
||||||
import io.anuke.mindustry.Vars;
|
import io.anuke.mindustry.Vars;
|
||||||
import io.anuke.mindustry.entities.enemies.Enemy;
|
import io.anuke.mindustry.entities.enemies.Enemy;
|
||||||
|
import io.anuke.mindustry.net.Net;
|
||||||
import io.anuke.mindustry.world.SpawnPoint;
|
import io.anuke.mindustry.world.SpawnPoint;
|
||||||
import io.anuke.mindustry.world.Tile;
|
import io.anuke.mindustry.world.Tile;
|
||||||
import io.anuke.ucore.util.Angles;
|
import io.anuke.ucore.util.Angles;
|
||||||
@@ -101,20 +102,28 @@ public class Pathfind{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void update(){
|
public void update(){
|
||||||
|
int index = 0;
|
||||||
|
|
||||||
for(SpawnPoint point : Vars.control.getSpawnPoints()){
|
for(SpawnPoint point : Vars.control.getSpawnPoints()){
|
||||||
if(!point.request.pathFound){
|
if(!point.request.pathFound){
|
||||||
try{
|
try{
|
||||||
if(point.finder.search(point.request, ms)){
|
if(point.finder.search(point.request, ms)){
|
||||||
smoother.smoothPath(point.path);
|
smoother.smoothPath(point.path);
|
||||||
point.pathTiles = point.path.nodes.toArray(Tile.class);
|
point.pathTiles = point.path.nodes.toArray(Tile.class);
|
||||||
point.tempTiles = point.path.nodes.toArray(Tile.class);
|
|
||||||
|
if(Net.active() && Net.server()){
|
||||||
|
Vars.netServer.handlePathFound(index, point.pathTiles);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}catch (ArrayIndexOutOfBoundsException e){
|
}catch (ArrayIndexOutOfBoundsException e){
|
||||||
//no path
|
//no path
|
||||||
point.request.pathFound = true;
|
point.request.pathFound = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
index ++;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean finishedUpdating(){
|
public boolean finishedUpdating(){
|
||||||
@@ -133,7 +142,6 @@ public class Pathfind{
|
|||||||
point.path.clear();
|
point.path.clear();
|
||||||
|
|
||||||
point.pathTiles = null;
|
point.pathTiles = null;
|
||||||
point.tempTiles = null;
|
|
||||||
|
|
||||||
point.request = new PathFinderRequest<Tile>(point.start, Vars.control.getCore(), heuristic, point.path);
|
point.request = new PathFinderRequest<Tile>(point.start, Vars.control.getCore(), heuristic, point.path);
|
||||||
point.request.statusChanged = true; //IMPORTANT!
|
point.request.statusChanged = true; //IMPORTANT!
|
||||||
@@ -141,15 +149,15 @@ public class Pathfind{
|
|||||||
}
|
}
|
||||||
|
|
||||||
void findNode(Enemy enemy){
|
void findNode(Enemy enemy){
|
||||||
if(enemy.spawn >= Vars.control.getSpawnPoints().size){
|
if(enemy.lane >= Vars.control.getSpawnPoints().size){
|
||||||
enemy.spawn = 0;
|
enemy.lane = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(Vars.control.getSpawnPoints().get(enemy.spawn).pathTiles == null){
|
if(Vars.control.getSpawnPoints().get(enemy.lane).pathTiles == null){
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
enemy.path = Vars.control.getSpawnPoints().get(enemy.spawn).pathTiles;
|
enemy.path = Vars.control.getSpawnPoints().get(enemy.lane).pathTiles;
|
||||||
|
|
||||||
int closest = findClosest(enemy.path, enemy.x, enemy.y);
|
int closest = findClosest(enemy.path, enemy.x, enemy.y);
|
||||||
|
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ public class Control extends Module{
|
|||||||
final Array<Weapon> weapons = new Array<>();
|
final Array<Weapon> weapons = new Array<>();
|
||||||
final int[] items = new int[Item.getAllItems().size];
|
final int[] items = new int[Item.getAllItems().size];
|
||||||
|
|
||||||
public final EntityGroup<Enemy> enemyGroup = Entities.addGroup(Enemy.class);
|
public final EntityGroup<Enemy> enemyGroup = Entities.addGroup(Enemy.class).enableMapping();
|
||||||
public final EntityGroup<TileEntity> tileGroup = Entities.addGroup(TileEntity.class, false);
|
public final EntityGroup<TileEntity> tileGroup = Entities.addGroup(TileEntity.class, false);
|
||||||
public final EntityGroup<Bullet> bulletGroup = Entities.addGroup(Bullet.class);
|
public final EntityGroup<Bullet> bulletGroup = Entities.addGroup(Bullet.class);
|
||||||
public final EntityGroup<Shield> shieldGroup = Entities.addGroup(Shield.class);
|
public final EntityGroup<Shield> shieldGroup = Entities.addGroup(Shield.class);
|
||||||
@@ -187,8 +187,14 @@ public class Control extends Module{
|
|||||||
for(int i = 0; i < Vars.saveSlots; i ++){
|
for(int i = 0; i < Vars.saveSlots; i ++){
|
||||||
Settings.defaults("save-" + i + "-autosave", true);
|
Settings.defaults("save-" + i + "-autosave", true);
|
||||||
Settings.defaults("save-" + i + "-name", "untitled");
|
Settings.defaults("save-" + i + "-name", "untitled");
|
||||||
|
Settings.defaults("save-" + i + "-data", "empty");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Settings.defaultList(
|
||||||
|
"ip", "localhost",
|
||||||
|
"port", Vars.port+""
|
||||||
|
);
|
||||||
|
|
||||||
Settings.loadAll("io.anuke.moment");
|
Settings.loadAll("io.anuke.moment");
|
||||||
|
|
||||||
for(Map map : Vars.world.maps().list()){
|
for(Map map : Vars.world.maps().list()){
|
||||||
@@ -196,6 +202,7 @@ public class Control extends Module{
|
|||||||
}
|
}
|
||||||
|
|
||||||
player = new Player();
|
player = new Player();
|
||||||
|
player.isAndroid = Vars.android;
|
||||||
player.isLocal = true;
|
player.isLocal = true;
|
||||||
|
|
||||||
spawns = WaveCreator.getSpawns();
|
spawns = WaveCreator.getSpawns();
|
||||||
@@ -224,8 +231,7 @@ public class Control extends Module{
|
|||||||
Entities.clear();
|
Entities.clear();
|
||||||
enemies = 0;
|
enemies = 0;
|
||||||
|
|
||||||
if(!android)
|
player.add();
|
||||||
player.add();
|
|
||||||
|
|
||||||
player.heal();
|
player.heal();
|
||||||
clearItems();
|
clearItems();
|
||||||
@@ -355,10 +361,11 @@ public class Control extends Module{
|
|||||||
try{
|
try{
|
||||||
Enemy enemy = ClassReflection.newInstance(spawn.type);
|
Enemy enemy = ClassReflection.newInstance(spawn.type);
|
||||||
enemy.set(tile.worldx() + Mathf.range(range), tile.worldy() + Mathf.range(range));
|
enemy.set(tile.worldx() + Mathf.range(range), tile.worldy() + Mathf.range(range));
|
||||||
enemy.spawn = fl;
|
enemy.lane = fl;
|
||||||
enemy.tier = spawn.tier(wave, fl);
|
enemy.tier = spawn.tier(wave, fl);
|
||||||
|
enemy.add();
|
||||||
|
|
||||||
Effects.effect(Fx.spawn, enemy);
|
Effects.effect(Fx.spawn, enemy);
|
||||||
enemy.add(enemyGroup);
|
|
||||||
|
|
||||||
Vars.netServer.handleEnemySpawn(enemy);
|
Vars.netServer.handleEnemySpawn(enemy);
|
||||||
|
|
||||||
@@ -404,6 +411,10 @@ public class Control extends Module{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void coreDestroyed(){
|
public void coreDestroyed(){
|
||||||
|
if(Net.active() && Net.server()){
|
||||||
|
Net.closeServer();
|
||||||
|
}
|
||||||
|
|
||||||
Effects.shake(5, 6, Core.camera.position.x, Core.camera.position.y);
|
Effects.shake(5, 6, Core.camera.position.x, Core.camera.position.y);
|
||||||
Sounds.play("corexplode");
|
Sounds.play("corexplode");
|
||||||
for(int i = 0; i < 16; i ++){
|
for(int i = 0; i < 16; i ++){
|
||||||
@@ -619,7 +630,7 @@ public class Control extends Module{
|
|||||||
if(!GameState.is(State.menu)){
|
if(!GameState.is(State.menu)){
|
||||||
input.update();
|
input.update();
|
||||||
|
|
||||||
if(Inputs.keyTap("pause") && !ui.isGameOver() && (GameState.is(State.paused) || GameState.is(State.playing))){
|
if(Inputs.keyTap("pause") && !ui.isGameOver() && !Net.active() && (GameState.is(State.paused) || GameState.is(State.playing))){
|
||||||
GameState.set(GameState.is(State.playing) ? State.paused : State.playing);
|
GameState.set(GameState.is(State.playing) ? State.paused : State.playing);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -633,7 +644,7 @@ public class Control extends Module{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!GameState.is(State.paused)){
|
if(!GameState.is(State.paused) || Net.active()){
|
||||||
|
|
||||||
if(respawntime > 0){
|
if(respawntime > 0){
|
||||||
|
|
||||||
@@ -657,7 +668,7 @@ public class Control extends Module{
|
|||||||
if(enemies <= 0){
|
if(enemies <= 0){
|
||||||
wavetime -= delta();
|
wavetime -= delta();
|
||||||
|
|
||||||
if(lastUpdated < wave + 1 && wavetime < Vars.aheadPathfinding){ //start updatingbeforehand
|
if(lastUpdated < wave + 1 && wavetime < Vars.aheadPathfinding){ //start updating beforehand
|
||||||
world.pathfinder().updatePath();
|
world.pathfinder().updatePath();
|
||||||
lastUpdated = wave + 1;
|
lastUpdated = wave + 1;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,25 +1,41 @@
|
|||||||
package io.anuke.mindustry.core;
|
package io.anuke.mindustry.core;
|
||||||
|
|
||||||
import com.badlogic.gdx.Gdx;
|
import com.badlogic.gdx.Gdx;
|
||||||
|
import com.badlogic.gdx.utils.TimeUtils;
|
||||||
|
import com.badlogic.gdx.utils.reflect.ClassReflection;
|
||||||
|
import com.badlogic.gdx.utils.reflect.ReflectionException;
|
||||||
import io.anuke.mindustry.Vars;
|
import io.anuke.mindustry.Vars;
|
||||||
import io.anuke.mindustry.core.GameState.State;
|
import io.anuke.mindustry.core.GameState.State;
|
||||||
|
import io.anuke.mindustry.entities.Bullet;
|
||||||
|
import io.anuke.mindustry.entities.BulletType;
|
||||||
import io.anuke.mindustry.entities.Player;
|
import io.anuke.mindustry.entities.Player;
|
||||||
import io.anuke.mindustry.io.SaveIO;
|
import io.anuke.mindustry.entities.enemies.Enemy;
|
||||||
|
import io.anuke.mindustry.graphics.Fx;
|
||||||
|
import io.anuke.mindustry.io.NetworkIO;
|
||||||
import io.anuke.mindustry.net.Net;
|
import io.anuke.mindustry.net.Net;
|
||||||
import io.anuke.mindustry.net.Net.SendMode;
|
import io.anuke.mindustry.net.Net.SendMode;
|
||||||
import io.anuke.mindustry.net.Packets.*;
|
import io.anuke.mindustry.net.Packets.*;
|
||||||
|
import io.anuke.mindustry.net.Syncable;
|
||||||
|
import io.anuke.mindustry.net.Syncable.Interpolator;
|
||||||
import io.anuke.mindustry.resource.Weapon;
|
import io.anuke.mindustry.resource.Weapon;
|
||||||
import io.anuke.mindustry.world.Block;
|
import io.anuke.mindustry.world.Block;
|
||||||
|
import io.anuke.mindustry.world.Tile;
|
||||||
import io.anuke.ucore.UCore;
|
import io.anuke.ucore.UCore;
|
||||||
|
import io.anuke.ucore.core.Effects;
|
||||||
import io.anuke.ucore.core.Timers;
|
import io.anuke.ucore.core.Timers;
|
||||||
|
import io.anuke.ucore.entities.BaseBulletType;
|
||||||
|
import io.anuke.ucore.entities.Entity;
|
||||||
import io.anuke.ucore.modules.Module;
|
import io.anuke.ucore.modules.Module;
|
||||||
|
|
||||||
|
import java.io.DataInputStream;
|
||||||
|
import java.io.IOException;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
|
||||||
public class NetClient extends Module {
|
public class NetClient extends Module {
|
||||||
boolean connecting = false;
|
boolean connecting = false;
|
||||||
boolean gotEntities = false;
|
boolean gotEntities = false;
|
||||||
float playerSyncTime = 3;
|
float playerSyncTime = 2;
|
||||||
|
float dataTimeout = 60*10;
|
||||||
|
|
||||||
public NetClient(){
|
public NetClient(){
|
||||||
|
|
||||||
@@ -30,6 +46,19 @@ public class NetClient extends Module {
|
|||||||
Vars.ui.hideLoading();
|
Vars.ui.hideLoading();
|
||||||
Vars.ui.showLoading("$text.connecting.data");
|
Vars.ui.showLoading("$text.connecting.data");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
ConnectPacket c = new ConnectPacket();
|
||||||
|
c.name = UCore.getProperty("user.name");
|
||||||
|
c.android = Vars.android;
|
||||||
|
Net.send(c, SendMode.tcp);
|
||||||
|
|
||||||
|
Timers.runTask(dataTimeout, () -> {
|
||||||
|
if(!gotEntities){
|
||||||
|
Gdx.app.error("Mindustry", "Failed to load data!");
|
||||||
|
Vars.ui.hideLoading();
|
||||||
|
Net.disconnect();
|
||||||
|
}
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
Net.handle(Disconnect.class, packet -> {
|
Net.handle(Disconnect.class, packet -> {
|
||||||
@@ -38,6 +67,8 @@ public class NetClient extends Module {
|
|||||||
Vars.ui.hideLoading();
|
Vars.ui.hideLoading();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
GameState.set(State.menu);
|
||||||
|
|
||||||
Vars.ui.showError("$text.disconnect");
|
Vars.ui.showError("$text.disconnect");
|
||||||
connecting = false;
|
connecting = false;
|
||||||
});
|
});
|
||||||
@@ -46,7 +77,8 @@ public class NetClient extends Module {
|
|||||||
Net.handle(WorldData.class, data -> {
|
Net.handle(WorldData.class, data -> {
|
||||||
Gdx.app.postRunnable(() -> {
|
Gdx.app.postRunnable(() -> {
|
||||||
UCore.log("Recieved world data: " + data.stream.available() + " bytes.");
|
UCore.log("Recieved world data: " + data.stream.available() + " bytes.");
|
||||||
SaveIO.load(data.stream);
|
NetworkIO.load(data.stream);
|
||||||
|
Vars.player.set(Vars.control.core.worldx(), Vars.control.core.worldy() - Vars.tilesize*2);
|
||||||
|
|
||||||
GameState.set(State.playing);
|
GameState.set(State.playing);
|
||||||
connecting = false;
|
connecting = false;
|
||||||
@@ -58,7 +90,7 @@ public class NetClient extends Module {
|
|||||||
Net.handle(EntityDataPacket.class, data -> {
|
Net.handle(EntityDataPacket.class, data -> {
|
||||||
|
|
||||||
Gdx.app.postRunnable(() -> {
|
Gdx.app.postRunnable(() -> {
|
||||||
Timers.run(10f, () -> { //TODO hack
|
Timers.run(10f, () -> { //TODO hack. should only run once world data is recieved
|
||||||
Vars.control.playerGroup.remap(Vars.player, data.playerid);
|
Vars.control.playerGroup.remap(Vars.player, data.playerid);
|
||||||
|
|
||||||
for (Player player : data.players) {
|
for (Player player : data.players) {
|
||||||
@@ -76,11 +108,26 @@ public class NetClient extends Module {
|
|||||||
Net.handle(SyncPacket.class, packet -> {
|
Net.handle(SyncPacket.class, packet -> {
|
||||||
if(!gotEntities) return;
|
if(!gotEntities) return;
|
||||||
|
|
||||||
|
//TODO awful code
|
||||||
for(int i = 0; i < packet.ids.length; i ++){
|
for(int i = 0; i < packet.ids.length; i ++){
|
||||||
int id = packet.ids[i];
|
int id = packet.ids[i];
|
||||||
if(id != Vars.player.id){
|
if(id != Vars.player.id){
|
||||||
Player player = Vars.control.playerGroup.getByID(id);
|
Entity entity = null;
|
||||||
player.getInterpolator().type.read(player, packet.data[i]);
|
if(i >= packet.enemyStart){
|
||||||
|
entity = Vars.control.enemyGroup.getByID(id);
|
||||||
|
}else {
|
||||||
|
entity = Vars.control.playerGroup.getByID(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
Syncable sync = ((Syncable)entity);
|
||||||
|
|
||||||
|
if(sync == null){
|
||||||
|
Gdx.app.error("Mindustry", "Unknown entity ID: " + id + " " + (i >= packet.enemyStart ? "(enemy)" : "(player)"));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
//augh
|
||||||
|
((Interpolator)sync.getInterpolator()).type.read(entity, packet.data[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -92,25 +139,120 @@ public class NetClient extends Module {
|
|||||||
weapon.shoot(player, packet.x, packet.y, packet.rotation);
|
weapon.shoot(player, packet.x, packet.y, packet.rotation);
|
||||||
});
|
});
|
||||||
|
|
||||||
Net.handleServer(PlacePacket.class, packet -> {
|
Net.handle(PlacePacket.class, packet -> {
|
||||||
Vars.control.input.placeBlockInternal(packet.x, packet.y, Block.getByID(packet.block), packet.rotation, true, false);
|
Vars.control.input.placeBlockInternal(packet.x, packet.y, Block.getByID(packet.block), packet.rotation, true, false);
|
||||||
});
|
});
|
||||||
|
|
||||||
Net.handleServer(BreakPacket.class, packet -> {
|
Net.handle(BreakPacket.class, packet -> {
|
||||||
Vars.control.input.breakBlockInternal(packet.x, packet.y, false);
|
Vars.control.input.breakBlockInternal(packet.x, packet.y, false);
|
||||||
});
|
});
|
||||||
|
|
||||||
Net.handleServer(StateSyncPacket.class, packet -> {
|
Net.handle(StateSyncPacket.class, packet -> {
|
||||||
//TODO replace with arraycopy()
|
//TODO replace with arraycopy()
|
||||||
for(int i = 0; i < packet.items.length; i ++){
|
for(int i = 0; i < packet.items.length; i ++){
|
||||||
Vars.control.items[i] = packet.items[i];
|
Vars.control.items[i] = packet.items[i];
|
||||||
}
|
}
|
||||||
Vars.control.setWaveData(packet.enemies, packet.wave, packet.countdown);
|
Vars.control.setWaveData(packet.enemies, packet.wave, packet.countdown);
|
||||||
|
|
||||||
|
Timers.resetTime(packet.time + (float)(TimeUtils.timeSinceMillis(packet.timestamp) / 1000.0 * 60.0));
|
||||||
|
|
||||||
|
Gdx.app.postRunnable(() -> {
|
||||||
|
Vars.ui.updateItems();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
Net.handle(EnemySpawnPacket.class, spawn -> {
|
||||||
|
Gdx.app.postRunnable(() -> {
|
||||||
|
try{
|
||||||
|
Enemy enemy = ClassReflection.newInstance(spawn.type);
|
||||||
|
enemy.set(spawn.x, spawn.y);
|
||||||
|
enemy.tier = spawn.tier;
|
||||||
|
enemy.lane = spawn.lane;
|
||||||
|
enemy.id = spawn.id;
|
||||||
|
enemy.add();
|
||||||
|
|
||||||
|
Effects.effect(Fx.spawn, enemy);
|
||||||
|
}catch (ReflectionException e){
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
Net.handle(EnemyDeathPacket.class, spawn -> {
|
||||||
|
Gdx.app.postRunnable(() -> {
|
||||||
|
Enemy enemy = Vars.control.enemyGroup.getByID(spawn.id);
|
||||||
|
if (enemy != null) enemy.onDeath();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
Net.handle(PathPacket.class, packet -> {
|
||||||
|
Tile[] tiles = new Tile[packet.path.length];
|
||||||
|
for(int i = 0; i < tiles.length; i ++){
|
||||||
|
int c = packet.path[i];
|
||||||
|
tiles[i] = Vars.world.tile(c % Vars.world.width(), c / Vars.world.width());
|
||||||
|
}
|
||||||
|
Vars.control.spawnpoints.get(packet.index).pathTiles = tiles;
|
||||||
|
});
|
||||||
|
|
||||||
|
Net.handle(BulletPacket.class, packet -> {
|
||||||
|
//TODO shoot effects for enemies, clientside as well as serverside
|
||||||
|
BulletType type = (BulletType) BaseBulletType.getByID(packet.type);
|
||||||
|
Entity owner = Vars.control.enemyGroup.getByID(packet.owner);
|
||||||
|
Bullet bullet = new Bullet(type, owner, packet.x, packet.y, packet.angle).add();
|
||||||
|
});
|
||||||
|
|
||||||
|
Net.handle(BlockDestroyPacket.class, packet -> {
|
||||||
|
Tile tile = Vars.world.tile(packet.position % Vars.world.width(), packet.position / Vars.world.width());
|
||||||
|
if(tile.entity != null){
|
||||||
|
tile.entity.onDeath(true);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Net.handle(BlockUpdatePacket.class, packet -> {
|
||||||
|
Tile tile = Vars.world.tile(packet.position % Vars.world.width(), packet.position / Vars.world.width());
|
||||||
|
if(tile.entity != null){
|
||||||
|
tile.entity.health = packet.health;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Net.handle(BlockSyncPacket.class, packet -> {
|
||||||
|
//TODO implementation, load data...
|
||||||
|
DataInputStream stream = new DataInputStream(packet.stream);
|
||||||
|
|
||||||
|
try{
|
||||||
|
while(stream.available() > 0){
|
||||||
|
int pos = stream.readInt();
|
||||||
|
|
||||||
|
Tile tile = Vars.world.tile(pos % Vars.world.width(), pos / Vars.world.width());
|
||||||
|
|
||||||
|
byte times = stream.readByte();
|
||||||
|
|
||||||
|
for(int i = 0; i < times; i ++){
|
||||||
|
tile.entity.timer.getTimes()[i] = stream.readFloat();
|
||||||
|
}
|
||||||
|
|
||||||
|
tile.entity.read(stream);
|
||||||
|
}
|
||||||
|
}catch (IOException e){
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Net.handle(DisconnectPacket.class, packet -> {
|
||||||
|
Player player = Vars.control.playerGroup.getByID(packet.playerid);
|
||||||
|
|
||||||
|
if(player != null){
|
||||||
|
player.remove();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Net.handle(Player.class, player -> {
|
||||||
|
player.add();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public void update(){
|
public void update(){
|
||||||
if(!Net.client()) return;
|
if(!Net.client() || !Net.active()) return;
|
||||||
|
|
||||||
if(!GameState.is(State.menu) && Net.active()){
|
if(!GameState.is(State.menu) && Net.active()){
|
||||||
sync();
|
sync();
|
||||||
@@ -149,7 +291,7 @@ public class NetClient extends Module {
|
|||||||
if(Timers.get("syncPlayer", playerSyncTime)){
|
if(Timers.get("syncPlayer", playerSyncTime)){
|
||||||
PositionPacket packet = new PositionPacket();
|
PositionPacket packet = new PositionPacket();
|
||||||
packet.data = Vars.player.getInterpolator().type.write(Vars.player);
|
packet.data = Vars.player.getInterpolator().type.write(Vars.player);
|
||||||
Net.send(packet, SendMode.tcp); //TODO udp instead?
|
Net.send(packet, SendMode.udp); //TODO udp instead?
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,12 +2,16 @@ package io.anuke.mindustry.core;
|
|||||||
|
|
||||||
import com.badlogic.gdx.Gdx;
|
import com.badlogic.gdx.Gdx;
|
||||||
import com.badlogic.gdx.graphics.Color;
|
import com.badlogic.gdx.graphics.Color;
|
||||||
|
import com.badlogic.gdx.utils.IntArray;
|
||||||
import com.badlogic.gdx.utils.IntMap;
|
import com.badlogic.gdx.utils.IntMap;
|
||||||
|
import com.badlogic.gdx.utils.TimeUtils;
|
||||||
import io.anuke.mindustry.Vars;
|
import io.anuke.mindustry.Vars;
|
||||||
import io.anuke.mindustry.core.GameState.State;
|
import io.anuke.mindustry.core.GameState.State;
|
||||||
|
import io.anuke.mindustry.entities.BulletType;
|
||||||
import io.anuke.mindustry.entities.Player;
|
import io.anuke.mindustry.entities.Player;
|
||||||
|
import io.anuke.mindustry.entities.TileEntity;
|
||||||
import io.anuke.mindustry.entities.enemies.Enemy;
|
import io.anuke.mindustry.entities.enemies.Enemy;
|
||||||
import io.anuke.mindustry.io.SaveIO;
|
import io.anuke.mindustry.io.NetworkIO;
|
||||||
import io.anuke.mindustry.net.Net;
|
import io.anuke.mindustry.net.Net;
|
||||||
import io.anuke.mindustry.net.Net.SendMode;
|
import io.anuke.mindustry.net.Net.SendMode;
|
||||||
import io.anuke.mindustry.net.Packets.*;
|
import io.anuke.mindustry.net.Packets.*;
|
||||||
@@ -15,55 +19,90 @@ import io.anuke.mindustry.resource.ItemStack;
|
|||||||
import io.anuke.mindustry.resource.Recipe;
|
import io.anuke.mindustry.resource.Recipe;
|
||||||
import io.anuke.mindustry.resource.Weapon;
|
import io.anuke.mindustry.resource.Weapon;
|
||||||
import io.anuke.mindustry.world.Block;
|
import io.anuke.mindustry.world.Block;
|
||||||
|
import io.anuke.mindustry.world.Tile;
|
||||||
import io.anuke.ucore.UCore;
|
import io.anuke.ucore.UCore;
|
||||||
import io.anuke.ucore.core.Effects.Effect;
|
import io.anuke.ucore.core.Effects.Effect;
|
||||||
import io.anuke.ucore.core.Timers;
|
import io.anuke.ucore.core.Timers;
|
||||||
|
import io.anuke.ucore.entities.Entity;
|
||||||
import io.anuke.ucore.modules.Module;
|
import io.anuke.ucore.modules.Module;
|
||||||
|
import io.anuke.ucore.util.Bundles;
|
||||||
|
import io.anuke.ucore.util.Mathf;
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.DataOutputStream;
|
import java.io.DataOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
|
||||||
public class NetServer extends Module{
|
public class NetServer extends Module{
|
||||||
|
/**Maps connection IDs to players.*/
|
||||||
IntMap<Player> connections = new IntMap<>();
|
IntMap<Player> connections = new IntMap<>();
|
||||||
float serverSyncTime = 4, itemSyncTime = 20, blockSyncTime = 120;
|
float serverSyncTime = 4, itemSyncTime = 10, blockSyncTime = 120;
|
||||||
|
|
||||||
public NetServer(){
|
public NetServer(){
|
||||||
|
|
||||||
Net.handleServer(Connect.class, packet -> {
|
Net.handleServer(Connect.class, connect -> {
|
||||||
UCore.log("Sending world data to client (ID="+packet.id+"/"+packet.addressTCP+")");
|
UCore.log("Connection found: " + connect.addressTCP);
|
||||||
|
});
|
||||||
|
|
||||||
|
Net.handleServer(ConnectPacket.class, packet -> {
|
||||||
|
int id = Net.getLastConnection();
|
||||||
|
|
||||||
|
UCore.log("Sending world data to client (ID="+id+")");
|
||||||
|
|
||||||
WorldData data = new WorldData();
|
WorldData data = new WorldData();
|
||||||
ByteArrayOutputStream stream = new ByteArrayOutputStream();
|
ByteArrayOutputStream stream = new ByteArrayOutputStream();
|
||||||
SaveIO.write(stream);
|
NetworkIO.write(stream);
|
||||||
|
|
||||||
UCore.log("Packed " + stream.size() + " uncompressed bytes of data.");
|
UCore.log("Packed " + stream.size() + " uncompressed bytes of data.");
|
||||||
|
|
||||||
//TODO compress and uncompress when sending
|
//TODO compress and uncompress when sending
|
||||||
data.stream = new ByteArrayInputStream(stream.toByteArray());
|
data.stream = new ByteArrayInputStream(stream.toByteArray());
|
||||||
|
|
||||||
Net.sendStream(packet.id, data);
|
Net.sendStream(id, data);
|
||||||
|
|
||||||
Gdx.app.postRunnable(() -> {
|
Gdx.app.postRunnable(() -> {
|
||||||
|
Vars.ui.showInfo("$text.server.connected");
|
||||||
|
|
||||||
EntityDataPacket dp = new EntityDataPacket();
|
EntityDataPacket dp = new EntityDataPacket();
|
||||||
|
|
||||||
Player player = new Player();
|
Player player = new Player();
|
||||||
player.clientid = packet.id;
|
player.clientid = id;
|
||||||
player.set(Vars.player.x, Vars.player.y);
|
player.name = packet.name;
|
||||||
player.placerot = Vars.player.placerot;
|
player.isAndroid = packet.android;
|
||||||
|
player.set(Vars.control.core.worldx(), Vars.control.core.worldy() - Vars.tilesize*2);
|
||||||
player.add();
|
player.add();
|
||||||
connections.put(packet.id, player);
|
connections.put(id, player);
|
||||||
|
|
||||||
dp.playerid = player.id;
|
dp.playerid = player.id;
|
||||||
dp.players = Vars.control.playerGroup.all().toArray(Player.class);
|
dp.players = Vars.control.playerGroup.all().toArray(Player.class);
|
||||||
|
|
||||||
UCore.log("Sending entities: " + Arrays.toString(dp.players));
|
UCore.log("Sending entities: " + Arrays.toString(dp.players));
|
||||||
|
|
||||||
Net.sendTo(packet.id, dp, SendMode.tcp);
|
Net.sendExcept(id, player, SendMode.tcp);
|
||||||
|
|
||||||
|
Net.sendTo(id, dp, SendMode.tcp);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Net.handleServer(Disconnect.class, packet -> {
|
||||||
|
Player player = connections.get(packet.id);
|
||||||
|
|
||||||
|
if(player == null) {
|
||||||
|
Gdx.app.postRunnable(() -> Vars.ui.showInfo(Bundles.format("text.server.disconnected", "<???>")));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Gdx.app.postRunnable(() -> Vars.ui.showInfo(Bundles.format("text.server.disconnected", player.name)));
|
||||||
|
|
||||||
|
player.remove();
|
||||||
|
|
||||||
|
DisconnectPacket dc = new DisconnectPacket();
|
||||||
|
dc.playerid = player.id;
|
||||||
|
|
||||||
|
Net.send(dc, SendMode.tcp);
|
||||||
|
});
|
||||||
|
|
||||||
Net.handleServer(PositionPacket.class, pos -> {
|
Net.handleServer(PositionPacket.class, pos -> {
|
||||||
Player player = connections.get(Net.getLastConnection());
|
Player player = connections.get(Net.getLastConnection());
|
||||||
player.getInterpolator().type.read(player, pos.data);
|
player.getInterpolator().type.read(player, pos.data);
|
||||||
@@ -112,8 +151,58 @@ public class NetServer extends Module{
|
|||||||
Net.send(packet, SendMode.udp);
|
Net.send(packet, SendMode.udp);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void handleEnemySpawn(Enemy enemy){
|
public void handleBullet(BulletType type, Entity owner, float x, float y, float angle, short damage){
|
||||||
|
BulletPacket packet = new BulletPacket();
|
||||||
|
packet.x = x;
|
||||||
|
packet.y = y;
|
||||||
|
packet.angle = angle;
|
||||||
|
packet.damage = damage;
|
||||||
|
packet.owner = owner.id;
|
||||||
|
packet.type = type.id;
|
||||||
|
Net.send(packet, SendMode.udp);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void handlePathFound(int index, Tile[] tiles){
|
||||||
|
PathPacket packet = new PathPacket();
|
||||||
|
int[] out = new int[tiles.length];
|
||||||
|
|
||||||
|
for(int p = 0; p < out.length; p ++){
|
||||||
|
out[p] = tiles[p].packedPosition();
|
||||||
|
}
|
||||||
|
|
||||||
|
packet.path = out;
|
||||||
|
packet.index = (byte)index;
|
||||||
|
Net.send(packet, SendMode.tcp);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void handleEnemySpawn(Enemy enemy){
|
||||||
|
EnemySpawnPacket packet = new EnemySpawnPacket();
|
||||||
|
packet.type = enemy.getClass();
|
||||||
|
packet.lane = (byte)enemy.lane;
|
||||||
|
packet.tier = (byte)enemy.tier;
|
||||||
|
packet.x = enemy.x;
|
||||||
|
packet.y = enemy.y;
|
||||||
|
packet.id = enemy.id;
|
||||||
|
Net.send(packet, SendMode.tcp);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void handleEnemyDeath(Enemy enemy){
|
||||||
|
EnemyDeathPacket packet = new EnemyDeathPacket();
|
||||||
|
packet.id = enemy.id;
|
||||||
|
Net.send(packet, SendMode.tcp);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void handleBlockDestroyed(TileEntity entity){
|
||||||
|
BlockDestroyPacket packet = new BlockDestroyPacket();
|
||||||
|
packet.position = entity.tile.packedPosition();
|
||||||
|
Net.send(packet, SendMode.tcp);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void handleBlockDamaged(TileEntity entity){
|
||||||
|
BlockUpdatePacket packet = new BlockUpdatePacket();
|
||||||
|
packet.health = entity.health;
|
||||||
|
packet.position = entity.tile.packedPosition();
|
||||||
|
Net.send(packet, SendMode.udp);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void update(){
|
public void update(){
|
||||||
@@ -130,11 +219,11 @@ public class NetServer extends Module{
|
|||||||
|
|
||||||
if(Timers.get("serverSync", serverSyncTime)){
|
if(Timers.get("serverSync", serverSyncTime)){
|
||||||
SyncPacket packet = new SyncPacket();
|
SyncPacket packet = new SyncPacket();
|
||||||
int amount = Vars.control.playerGroup.amount();
|
int amount = Vars.control.playerGroup.amount() + Vars.control.enemyGroup.amount();
|
||||||
packet.ids = new int[amount];
|
packet.ids = new int[amount];
|
||||||
packet.data = new float[amount][0];
|
packet.data = new float[amount][0];
|
||||||
|
|
||||||
int index = 0;
|
short index = 0;
|
||||||
|
|
||||||
for(Player player : Vars.control.playerGroup.all()){
|
for(Player player : Vars.control.playerGroup.all()){
|
||||||
float[] out = player.getInterpolator().type.write(player);
|
float[] out = player.getInterpolator().type.write(player);
|
||||||
@@ -144,6 +233,16 @@ public class NetServer extends Module{
|
|||||||
index ++;
|
index ++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
packet.enemyStart = index;
|
||||||
|
|
||||||
|
for(Enemy enemy : Vars.control.enemyGroup.all()){
|
||||||
|
float[] out = enemy.getInterpolator().type.write(enemy);
|
||||||
|
packet.data[index] = out;
|
||||||
|
packet.ids[index] = enemy.id;
|
||||||
|
|
||||||
|
index ++;
|
||||||
|
}
|
||||||
|
|
||||||
Net.send(packet, SendMode.udp);
|
Net.send(packet, SendMode.udp);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -153,25 +252,71 @@ public class NetServer extends Module{
|
|||||||
packet.countdown = Vars.control.getWaveCountdown();
|
packet.countdown = Vars.control.getWaveCountdown();
|
||||||
packet.enemies = Vars.control.getEnemiesRemaining();
|
packet.enemies = Vars.control.getEnemiesRemaining();
|
||||||
packet.wave = Vars.control.getWave();
|
packet.wave = Vars.control.getWave();
|
||||||
|
packet.time = Timers.time();
|
||||||
|
packet.timestamp = TimeUtils.millis();
|
||||||
|
|
||||||
Net.send(packet, SendMode.udp);
|
Net.send(packet, SendMode.udp);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(Timers.get("serverBlockSync", blockSyncTime)){
|
if(Timers.get("serverBlockSync", blockSyncTime)){
|
||||||
BlockSyncPacket packet = new BlockSyncPacket();
|
|
||||||
|
|
||||||
|
IntArray connections = Net.getConnections();
|
||||||
|
|
||||||
|
for(int i = 0; i < connections.size; i ++){
|
||||||
|
int id = connections.get(i);
|
||||||
|
Player player = this.connections.get(id);
|
||||||
|
if(player == null) continue;
|
||||||
|
int x = Mathf.scl2(player.x, Vars.tilesize);
|
||||||
|
int y = Mathf.scl2(player.y, Vars.tilesize);
|
||||||
|
int w = 16;
|
||||||
|
int h = 12;
|
||||||
|
sendBlockSync(id, x, y, w, h);
|
||||||
|
}
|
||||||
|
|
||||||
|
//TODO sync to each player entity
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void sendBlockSync(int client){
|
public void sendBlockSync(int client, int x, int y, int viewx, int viewy){
|
||||||
BlockSyncPacket packet = new BlockSyncPacket();
|
BlockSyncPacket packet = new BlockSyncPacket();
|
||||||
|
|
||||||
ByteArrayOutputStream bs = new ByteArrayOutputStream();
|
ByteArrayOutputStream bs = new ByteArrayOutputStream();
|
||||||
DataOutputStream stream = new DataOutputStream(bs);
|
|
||||||
|
|
||||||
|
try {
|
||||||
|
DataOutputStream stream = new DataOutputStream(bs);
|
||||||
|
|
||||||
|
for (int rx = -viewx / 2; rx <= viewx / 2; rx++) {
|
||||||
|
for (int ry = -viewy / 2; ry <= viewy / 2; ry++) {
|
||||||
|
Tile tile = Vars.world.tile(x + rx, y + ry);
|
||||||
|
|
||||||
|
if (tile == null || tile.entity == null) continue;
|
||||||
|
|
||||||
|
stream.writeInt(tile.packedPosition());
|
||||||
|
byte times = 0;
|
||||||
|
|
||||||
|
for(; times < tile.entity.timer.getTimes().length; times ++){
|
||||||
|
if(tile.entity.timer.getTimes()[times] <= 1f){
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
stream.writeByte(times);
|
||||||
|
|
||||||
|
for(int i = 0; i < times; i ++){
|
||||||
|
stream.writeFloat(tile.entity.timer.getTimes()[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
tile.entity.write(stream);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}catch (IOException e){
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
//TODO finish
|
||||||
|
|
||||||
packet.stream = new ByteArrayInputStream(bs.toByteArray());
|
packet.stream = new ByteArrayInputStream(bs.toByteArray());
|
||||||
|
|
||||||
|
Net.sendStream(client, packet);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -418,10 +418,8 @@ public class Renderer extends RendererModule{
|
|||||||
drawHealth(entity);
|
drawHealth(entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!Vars.android && Vars.showPlayer) {
|
for(Player player : Vars.control.playerGroup.all()){
|
||||||
for(Player player : Vars.control.playerGroup.all()){
|
if(!player.isDead() && !player.isAndroid) drawHealth(player);
|
||||||
if(!player.isDead()) drawHealth(player);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ import io.anuke.ucore.function.Listenable;
|
|||||||
import io.anuke.ucore.modules.SceneModule;
|
import io.anuke.ucore.modules.SceneModule;
|
||||||
import io.anuke.ucore.scene.Element;
|
import io.anuke.ucore.scene.Element;
|
||||||
import io.anuke.ucore.scene.Skin;
|
import io.anuke.ucore.scene.Skin;
|
||||||
|
import io.anuke.ucore.scene.actions.Actions;
|
||||||
import io.anuke.ucore.scene.builders.build;
|
import io.anuke.ucore.scene.builders.build;
|
||||||
import io.anuke.ucore.scene.builders.label;
|
import io.anuke.ucore.scene.builders.label;
|
||||||
import io.anuke.ucore.scene.builders.table;
|
import io.anuke.ucore.scene.builders.table;
|
||||||
@@ -178,27 +179,6 @@ public class UI extends SceneModule{
|
|||||||
editorDialog = new MapEditorDialog(editor);
|
editorDialog = new MapEditorDialog(editor);
|
||||||
}
|
}
|
||||||
|
|
||||||
join = new FloatingDialog("$text.joingame.title");
|
|
||||||
join.content().add("$text.joingame.ip").left();
|
|
||||||
join.content().addField("localhost", text -> lastip = text).size(180f, 54f);
|
|
||||||
join.content().row();
|
|
||||||
join.content().add("$text.server.port").left();
|
|
||||||
join.content().addField(Vars.port + "", new DigitsOnlyFilter(), text -> lastport = Strings.parseInt(text)).size(180f, 54f);
|
|
||||||
join.buttons().defaults().size(140f, 60f).pad(4f);
|
|
||||||
join.buttons().addButton("$text.cancel", join::hide);
|
|
||||||
join.buttons().addButton("$text.ok", () -> {
|
|
||||||
showLoading("$text.connecting");
|
|
||||||
|
|
||||||
Timers.runTask(2f, () -> {
|
|
||||||
try{
|
|
||||||
Net.connect(lastip, lastport);
|
|
||||||
}catch (IOException e) {
|
|
||||||
showError(Bundles.format("text.connectfail", Strings.parseException(e, false)));
|
|
||||||
hideLoading();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}).disabled(b -> lastip.isEmpty() || lastport == Integer.MIN_VALUE);
|
|
||||||
|
|
||||||
settingserror = new Dialog("Warning", "dialog");
|
settingserror = new Dialog("Warning", "dialog");
|
||||||
settingserror.content().add("[crimson]Failed to access local storage.\nSettings will not be saved.");
|
settingserror.content().add("[crimson]Failed to access local storage.\nSettings will not be saved.");
|
||||||
settingserror.content().margin(10f);
|
settingserror.content().margin(10f);
|
||||||
@@ -208,6 +188,8 @@ public class UI extends SceneModule{
|
|||||||
gameerror.content().labelWrap("$text.error.crashmessage").width(600f).pad(10f);
|
gameerror.content().labelWrap("$text.error.crashmessage").width(600f).pad(10f);
|
||||||
gameerror.buttons().addButton("#text.ok", gameerror::hide).size(200f, 50);
|
gameerror.buttons().addButton("#text.ok", gameerror::hide).size(200f, 50);
|
||||||
|
|
||||||
|
join = new JoinDialog();
|
||||||
|
|
||||||
discord = new Dialog("Discord", "dialog");
|
discord = new Dialog("Discord", "dialog");
|
||||||
discord.content().margin(12f);
|
discord.content().margin(12f);
|
||||||
discord.content().add("$text.discord");
|
discord.content().add("$text.discord");
|
||||||
@@ -258,7 +240,7 @@ public class UI extends SceneModule{
|
|||||||
|
|
||||||
prefs.hidden(()->{
|
prefs.hidden(()->{
|
||||||
if(!GameState.is(State.menu)){
|
if(!GameState.is(State.menu)){
|
||||||
if(!wasPaused)
|
if(!wasPaused || Net.active())
|
||||||
GameState.set(State.playing);
|
GameState.set(State.playing);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -269,7 +251,7 @@ public class UI extends SceneModule{
|
|||||||
if(menu.getScene() != null){
|
if(menu.getScene() != null){
|
||||||
wasPaused = menu.wasPaused;
|
wasPaused = menu.wasPaused;
|
||||||
}
|
}
|
||||||
GameState.set(State.paused);
|
if(!Net.active()) GameState.set(State.paused);
|
||||||
menu.hide();
|
menu.hide();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -468,6 +450,25 @@ public class UI extends SceneModule{
|
|||||||
tooltip.hide();
|
tooltip.hide();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void showInfo(String info){
|
||||||
|
scene.table().add(info).get().getParent().actions(Actions.fadeOut(4f), Actions.removeActor());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void showHostServer(){
|
||||||
|
showTextInput("$text.hostserver", "$text.server.port", Vars.port + "", new DigitsOnlyFilter(), text -> {
|
||||||
|
int result = Strings.parseInt(text);
|
||||||
|
if(result == Integer.MIN_VALUE || result >= 65535){
|
||||||
|
Vars.ui.showError("$text.server.invalidport");
|
||||||
|
}else{
|
||||||
|
try{
|
||||||
|
Net.host(result);
|
||||||
|
}catch (IOException e){
|
||||||
|
Vars.ui.showError(Bundles.format("text.server.error", Strings.parseException(e, false)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
public void showAbout(){
|
public void showAbout(){
|
||||||
about.show();
|
about.show();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,25 +1,31 @@
|
|||||||
package io.anuke.mindustry.core;
|
package io.anuke.mindustry.core;
|
||||||
|
|
||||||
import static io.anuke.mindustry.Vars.*;
|
|
||||||
|
|
||||||
import com.badlogic.gdx.math.GridPoint2;
|
import com.badlogic.gdx.math.GridPoint2;
|
||||||
import com.badlogic.gdx.math.MathUtils;
|
import com.badlogic.gdx.math.MathUtils;
|
||||||
import com.badlogic.gdx.math.Vector2;
|
import com.badlogic.gdx.math.Vector2;
|
||||||
import com.badlogic.gdx.utils.Array;
|
import com.badlogic.gdx.utils.Array;
|
||||||
|
|
||||||
import io.anuke.mindustry.Vars;
|
import io.anuke.mindustry.Vars;
|
||||||
import io.anuke.mindustry.ai.Pathfind;
|
import io.anuke.mindustry.ai.Pathfind;
|
||||||
import io.anuke.mindustry.core.GameState.State;
|
import io.anuke.mindustry.core.GameState.State;
|
||||||
import io.anuke.mindustry.entities.TileEntity;
|
import io.anuke.mindustry.entities.TileEntity;
|
||||||
import io.anuke.mindustry.io.Maps;
|
import io.anuke.mindustry.io.Maps;
|
||||||
import io.anuke.mindustry.world.*;
|
import io.anuke.mindustry.net.Net;
|
||||||
import io.anuke.mindustry.world.blocks.*;
|
import io.anuke.mindustry.world.Block;
|
||||||
|
import io.anuke.mindustry.world.Generator;
|
||||||
|
import io.anuke.mindustry.world.Map;
|
||||||
|
import io.anuke.mindustry.world.Tile;
|
||||||
|
import io.anuke.mindustry.world.blocks.Blocks;
|
||||||
|
import io.anuke.mindustry.world.blocks.DistributionBlocks;
|
||||||
|
import io.anuke.mindustry.world.blocks.ProductionBlocks;
|
||||||
|
import io.anuke.mindustry.world.blocks.WeaponBlocks;
|
||||||
import io.anuke.ucore.entities.Entities;
|
import io.anuke.ucore.entities.Entities;
|
||||||
import io.anuke.ucore.entities.Entity;
|
import io.anuke.ucore.entities.Entity;
|
||||||
import io.anuke.ucore.modules.Module;
|
import io.anuke.ucore.modules.Module;
|
||||||
import io.anuke.ucore.util.Mathf;
|
import io.anuke.ucore.util.Mathf;
|
||||||
import io.anuke.ucore.util.Tmp;
|
import io.anuke.ucore.util.Tmp;
|
||||||
|
|
||||||
|
import static io.anuke.mindustry.Vars.*;
|
||||||
|
|
||||||
public class World extends Module{
|
public class World extends Module{
|
||||||
private int seed;
|
private int seed;
|
||||||
|
|
||||||
@@ -36,7 +42,8 @@ public class World extends Module{
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void update(){
|
public void update(){
|
||||||
pathfind.update();
|
if(!(Net.active() && Net.client()))
|
||||||
|
pathfind.update();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import io.anuke.mindustry.world.Tile;
|
|||||||
import io.anuke.mindustry.world.blocks.Blocks;
|
import io.anuke.mindustry.world.blocks.Blocks;
|
||||||
import io.anuke.ucore.core.*;
|
import io.anuke.ucore.core.*;
|
||||||
import io.anuke.ucore.entities.DestructibleEntity;
|
import io.anuke.ucore.entities.DestructibleEntity;
|
||||||
|
import io.anuke.ucore.entities.SolidEntity;
|
||||||
import io.anuke.ucore.util.Angles;
|
import io.anuke.ucore.util.Angles;
|
||||||
import io.anuke.ucore.util.Mathf;
|
import io.anuke.ucore.util.Mathf;
|
||||||
|
|
||||||
@@ -20,9 +21,13 @@ public class Player extends DestructibleEntity implements Syncable{
|
|||||||
private static final float speed = 1.1f;
|
private static final float speed = 1.1f;
|
||||||
private static final float dashSpeed = 1.8f;
|
private static final float dashSpeed = 1.8f;
|
||||||
|
|
||||||
|
public String name = "player name";
|
||||||
public transient Weapon weapon = Weapon.blaster;
|
public transient Weapon weapon = Weapon.blaster;
|
||||||
public Mech mech = Mech.standard;
|
public Mech mech = Mech.standard;
|
||||||
public float angle;
|
public float angle;
|
||||||
|
public boolean isAndroid;
|
||||||
|
|
||||||
|
public transient float targetAngle = 0f;
|
||||||
|
|
||||||
public transient int clientid;
|
public transient int clientid;
|
||||||
public transient boolean isLocal = false;
|
public transient boolean isLocal = false;
|
||||||
@@ -43,16 +48,21 @@ public class Player extends DestructibleEntity implements Syncable{
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Interpolator getInterpolator() {
|
public Interpolator<Player> getInterpolator() {
|
||||||
return inter;
|
return inter;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void damage(int amount){
|
public void damage(int amount){
|
||||||
if(!Vars.debug && !Vars.android)
|
if(!Vars.debug)
|
||||||
super.damage(amount);
|
super.damage(amount);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean collides(SolidEntity other){
|
||||||
|
return super.collides(other) && !isAndroid;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onDeath(){
|
public void onDeath(){
|
||||||
if(isLocal){
|
if(isLocal){
|
||||||
@@ -79,20 +89,26 @@ public class Player extends DestructibleEntity implements Syncable{
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void draw(){
|
public void draw(){
|
||||||
if(Vars.debug && (!Vars.showPlayer || !Vars.showUI)) return;
|
if(isAndroid && isLocal){
|
||||||
|
angle = Mathf.lerpAngDelta(angle, targetAngle, 0.2f);
|
||||||
|
}
|
||||||
|
|
||||||
|
if((Vars.debug && (!Vars.showPlayer || !Vars.showUI)) || (isAndroid && isLocal)) return;
|
||||||
|
|
||||||
|
String part = isAndroid ? "ship" : "mech";
|
||||||
|
|
||||||
if(Vars.snapCamera && Settings.getBool("smoothcam") && Settings.getBool("pixelate")){
|
if(Vars.snapCamera && Settings.getBool("smoothcam") && Settings.getBool("pixelate")){
|
||||||
Draw.rect("mech-"+mech.name(), (int)x, (int)y, angle-90);
|
Draw.rect(part+"-"+mech.name(), (int)x, (int)y, angle-90);
|
||||||
}else{
|
}else{
|
||||||
Draw.rect("mech-"+mech.name(), x, y, angle-90);
|
Draw.rect(part+"-"+mech.name(), x, y, angle-90);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void update(){
|
public void update(){
|
||||||
if(!isLocal){
|
if(!isLocal || isAndroid){
|
||||||
if(!isDead()) inter.update(this);
|
if(!isDead() && !isLocal) inter.update(this);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -151,4 +167,9 @@ public class Player extends DestructibleEntity implements Syncable{
|
|||||||
public Player add(){
|
public Player add(){
|
||||||
return add(Vars.control.playerGroup);
|
return add(Vars.control.playerGroup);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "Player{" + id + ", android=" + isAndroid + ", local=" + isLocal + ", " + x + ", " + y + "}\n";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,12 +1,9 @@
|
|||||||
package io.anuke.mindustry.entities;
|
package io.anuke.mindustry.entities;
|
||||||
|
|
||||||
import java.io.DataInputStream;
|
|
||||||
import java.io.DataOutputStream;
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
import io.anuke.mindustry.Vars;
|
import io.anuke.mindustry.Vars;
|
||||||
import io.anuke.mindustry.entities.enemies.Enemy;
|
import io.anuke.mindustry.entities.enemies.Enemy;
|
||||||
import io.anuke.mindustry.graphics.Fx;
|
import io.anuke.mindustry.graphics.Fx;
|
||||||
|
import io.anuke.mindustry.net.Net;
|
||||||
import io.anuke.mindustry.resource.Item;
|
import io.anuke.mindustry.resource.Item;
|
||||||
import io.anuke.mindustry.world.Block;
|
import io.anuke.mindustry.world.Block;
|
||||||
import io.anuke.mindustry.world.Tile;
|
import io.anuke.mindustry.world.Tile;
|
||||||
@@ -18,6 +15,10 @@ import io.anuke.ucore.entities.Entity;
|
|||||||
import io.anuke.ucore.util.Mathf;
|
import io.anuke.ucore.util.Mathf;
|
||||||
import io.anuke.ucore.util.Timer;
|
import io.anuke.ucore.util.Timer;
|
||||||
|
|
||||||
|
import java.io.DataInputStream;
|
||||||
|
import java.io.DataOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
public class TileEntity extends Entity{
|
public class TileEntity extends Entity{
|
||||||
public Tile tile;
|
public Tile tile;
|
||||||
public int[] items = new int[Item.getAllItems().size];
|
public int[] items = new int[Item.getAllItems().size];
|
||||||
@@ -54,19 +55,28 @@ public class TileEntity extends Entity{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void onDeath(){
|
public void onDeath(){
|
||||||
|
onDeath(false);
|
||||||
|
}
|
||||||
|
|
||||||
if(tile.block() == ProductionBlocks.core){
|
public void onDeath(boolean force){
|
||||||
Vars.control.coreDestroyed();
|
if(Net.active() && Net.server()){
|
||||||
|
Vars.netServer.handleBlockDestroyed(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!dead) {
|
if(!Net.active() || Net.server() || force){
|
||||||
dead = true;
|
if(tile.block() == ProductionBlocks.core){
|
||||||
Block block = tile.block();
|
Vars.control.coreDestroyed();
|
||||||
|
}
|
||||||
|
|
||||||
block.onDestroyed(tile);
|
if(!dead) {
|
||||||
|
dead = true;
|
||||||
|
Block block = tile.block();
|
||||||
|
|
||||||
Vars.world.removeBlock(tile);
|
block.onDestroyed(tile);
|
||||||
remove();
|
|
||||||
|
Vars.world.removeBlock(tile);
|
||||||
|
remove();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -80,6 +90,10 @@ public class TileEntity extends Entity{
|
|||||||
int amount = tile.block().handleDamage(tile, damage);
|
int amount = tile.block().handleDamage(tile, damage);
|
||||||
health -= amount;
|
health -= amount;
|
||||||
if(health <= 0) onDeath();
|
if(health <= 0) onDeath();
|
||||||
|
|
||||||
|
if(Net.active() && Net.server()){
|
||||||
|
Vars.netServer.handleBlockDamaged(this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean collide(Bullet other){
|
public boolean collide(Bullet other){
|
||||||
|
|||||||
@@ -3,21 +3,32 @@ package io.anuke.mindustry.entities.enemies;
|
|||||||
import com.badlogic.gdx.graphics.Color;
|
import com.badlogic.gdx.graphics.Color;
|
||||||
import com.badlogic.gdx.math.Vector2;
|
import com.badlogic.gdx.math.Vector2;
|
||||||
import com.badlogic.gdx.utils.reflect.ClassReflection;
|
import com.badlogic.gdx.utils.reflect.ClassReflection;
|
||||||
|
|
||||||
import io.anuke.mindustry.Vars;
|
import io.anuke.mindustry.Vars;
|
||||||
import io.anuke.mindustry.entities.*;
|
import io.anuke.mindustry.entities.Bullet;
|
||||||
|
import io.anuke.mindustry.entities.BulletType;
|
||||||
|
import io.anuke.mindustry.entities.TileEntity;
|
||||||
import io.anuke.mindustry.graphics.Fx;
|
import io.anuke.mindustry.graphics.Fx;
|
||||||
import io.anuke.mindustry.graphics.Shaders;
|
import io.anuke.mindustry.graphics.Shaders;
|
||||||
|
import io.anuke.mindustry.net.Net;
|
||||||
|
import io.anuke.mindustry.net.Syncable;
|
||||||
import io.anuke.mindustry.world.Tile;
|
import io.anuke.mindustry.world.Tile;
|
||||||
import io.anuke.mindustry.world.blocks.Blocks;
|
import io.anuke.mindustry.world.blocks.Blocks;
|
||||||
import io.anuke.ucore.UCore;
|
import io.anuke.ucore.core.Draw;
|
||||||
import io.anuke.ucore.core.*;
|
import io.anuke.ucore.core.Effects;
|
||||||
import io.anuke.ucore.entities.*;
|
import io.anuke.ucore.core.Graphics;
|
||||||
import io.anuke.ucore.util.*;
|
import io.anuke.ucore.core.Timers;
|
||||||
|
import io.anuke.ucore.entities.DestructibleEntity;
|
||||||
|
import io.anuke.ucore.entities.Entities;
|
||||||
|
import io.anuke.ucore.entities.Entity;
|
||||||
|
import io.anuke.ucore.entities.SolidEntity;
|
||||||
|
import io.anuke.ucore.util.Angles;
|
||||||
|
import io.anuke.ucore.util.Mathf;
|
||||||
|
import io.anuke.ucore.util.Timer;
|
||||||
|
import io.anuke.ucore.util.Tmp;
|
||||||
|
|
||||||
import static io.anuke.mindustry.Vars.world;
|
import static io.anuke.mindustry.Vars.world;
|
||||||
|
|
||||||
public class Enemy extends DestructibleEntity{
|
public class Enemy extends DestructibleEntity implements Syncable{
|
||||||
public final static Color[] tierColors = { Color.valueOf("ffe451"), Color.valueOf("f48e20"), Color.valueOf("ff6757"), Color.valueOf("ff2d86") };
|
public final static Color[] tierColors = { Color.valueOf("ffe451"), Color.valueOf("f48e20"), Color.valueOf("ff6757"), Color.valueOf("ff2d86") };
|
||||||
public final static int maxtier = 4;
|
public final static int maxtier = 4;
|
||||||
public final static float maxIdle = 60*1.5f;
|
public final static float maxIdle = 60*1.5f;
|
||||||
@@ -37,17 +48,19 @@ public class Enemy extends DestructibleEntity{
|
|||||||
protected int damage;
|
protected int damage;
|
||||||
protected Enemy spawner;
|
protected Enemy spawner;
|
||||||
protected int spawned = 0;
|
protected int spawned = 0;
|
||||||
protected float angle;
|
|
||||||
protected boolean targetCore = false;
|
protected boolean targetCore = false;
|
||||||
protected boolean stopNearCore = true;
|
protected boolean stopNearCore = true;
|
||||||
protected float mass = 1f;
|
protected float mass = 1f;
|
||||||
protected String className;
|
protected String className;
|
||||||
|
|
||||||
|
protected Interpolator<Enemy> inter = new Interpolator(SyncType.enemy);
|
||||||
|
|
||||||
public float idletime = 0f;
|
public float idletime = 0f;
|
||||||
public int spawn;
|
public int lane;
|
||||||
public int node = -1;
|
public int node = -1;
|
||||||
public Tile[] path;
|
public Tile[] path;
|
||||||
|
|
||||||
|
public float angle;
|
||||||
public float xvelocity, yvelocity;
|
public float xvelocity, yvelocity;
|
||||||
public Entity target;
|
public Entity target;
|
||||||
public int tier = 1;
|
public int tier = 1;
|
||||||
@@ -65,11 +78,20 @@ public class Enemy extends DestructibleEntity{
|
|||||||
className = ClassReflection.getSimpleName(getClass()).toLowerCase();
|
className = ClassReflection.getSimpleName(getClass()).toLowerCase();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Interpolator<Enemy> getInterpolator() {
|
||||||
|
return inter;
|
||||||
|
}
|
||||||
|
|
||||||
public float drawSize(){
|
public float drawSize(){
|
||||||
return 12;
|
return 12;
|
||||||
}
|
}
|
||||||
|
|
||||||
void move(){
|
void move(){
|
||||||
|
if(Net.client() && Net.active()){
|
||||||
|
inter.update(this);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
Tile core = Vars.control.getCore();
|
Tile core = Vars.control.getCore();
|
||||||
|
|
||||||
if(idletime > maxIdleLife){
|
if(idletime > maxIdleLife){
|
||||||
@@ -152,9 +174,21 @@ public class Enemy extends DestructibleEntity{
|
|||||||
}
|
}
|
||||||
|
|
||||||
void shoot(BulletType bullet, float rotation){
|
void shoot(BulletType bullet, float rotation){
|
||||||
Angles.translation(angle + rotation, length);
|
|
||||||
Bullet out = new Bullet(bullet, this, x + Angles.x(), y + Angles.y(), this.angle + rotation).add();
|
if(!(Net.active() && Net.client())) {
|
||||||
out.damage = (int) (damage * Vars.multiplier);
|
Angles.translation(angle + rotation, length);
|
||||||
|
Bullet out = new Bullet(bullet, this, x + Angles.x(), y + Angles.y(), this.angle + rotation).add();
|
||||||
|
out.damage = (int) (damage * Vars.multiplier);
|
||||||
|
onShoot(bullet, rotation);
|
||||||
|
|
||||||
|
if(Net.active() && Net.server()){
|
||||||
|
Vars.netServer.handleBullet(bullet, this, x + Angles.x(), y + Angles.y(), this.angle + rotation, (short) (damage * Vars.multiplier));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void onShoot(BulletType type, float rotation){
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -184,6 +218,10 @@ public class Enemy extends DestructibleEntity{
|
|||||||
Effects.sound("bang2", this);
|
Effects.sound("bang2", this);
|
||||||
remove();
|
remove();
|
||||||
dead = true;
|
dead = true;
|
||||||
|
|
||||||
|
if(Net.active() && Net.server()){
|
||||||
|
Vars.netServer.handleEnemyDeath(this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -258,7 +296,7 @@ public class Enemy extends DestructibleEntity{
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <T extends Entity> T add(){
|
public Enemy add(){
|
||||||
return (T) add(Vars.control.enemyGroup);
|
return add(Vars.control.enemyGroup);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ public class FortressEnemy extends Enemy{
|
|||||||
Angles.translation(angle, 20f);
|
Angles.translation(angle, 20f);
|
||||||
|
|
||||||
FastEnemy enemy = new FastEnemy();
|
FastEnemy enemy = new FastEnemy();
|
||||||
enemy.spawn = spawn;
|
enemy.lane = lane;
|
||||||
enemy.tier = this.tier;
|
enemy.tier = this.tier;
|
||||||
enemy.spawner = this;
|
enemy.spawner = this;
|
||||||
enemy.set(x + Angles.x(), y + Angles.y());
|
enemy.set(x + Angles.x(), y + Angles.y());
|
||||||
@@ -53,9 +53,8 @@ public class FortressEnemy extends Enemy{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void shoot(BulletType type){
|
void onShoot(BulletType type, float rotation){
|
||||||
super.shoot(bullet);
|
|
||||||
Effects.effect(Fx.largeCannonShot, x + Angles.x(), y + Angles.y(), angle);
|
Effects.effect(Fx.largeCannonShot, x + Angles.x(), y + Angles.y(), angle);
|
||||||
Effects.shake(3f, 3f, this);
|
Effects.shake(3f, 3f, this);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,15 +1,15 @@
|
|||||||
package io.anuke.mindustry.input;
|
package io.anuke.mindustry.input;
|
||||||
|
|
||||||
import static io.anuke.mindustry.Vars.*;
|
|
||||||
|
|
||||||
import com.badlogic.gdx.Gdx;
|
import com.badlogic.gdx.Gdx;
|
||||||
import com.badlogic.gdx.input.GestureDetector.GestureAdapter;
|
import com.badlogic.gdx.input.GestureDetector.GestureAdapter;
|
||||||
import com.badlogic.gdx.math.Vector2;
|
import com.badlogic.gdx.math.Vector2;
|
||||||
|
|
||||||
import io.anuke.mindustry.Vars;
|
import io.anuke.mindustry.Vars;
|
||||||
import io.anuke.ucore.core.Core;
|
import io.anuke.ucore.core.Core;
|
||||||
import io.anuke.ucore.core.Inputs;
|
import io.anuke.ucore.core.Inputs;
|
||||||
import io.anuke.ucore.scene.ui.layout.Unit;
|
import io.anuke.ucore.scene.ui.layout.Unit;
|
||||||
|
import io.anuke.ucore.util.Mathf;
|
||||||
|
|
||||||
|
import static io.anuke.mindustry.Vars.*;
|
||||||
|
|
||||||
public class GestureHandler extends GestureAdapter{
|
public class GestureHandler extends GestureAdapter{
|
||||||
AndroidInput input;
|
AndroidInput input;
|
||||||
@@ -49,8 +49,10 @@ public class GestureHandler extends GestureAdapter{
|
|||||||
|
|
||||||
if(!Vars.control.showCursor() && !(player.recipe != null && Vars.control.hasItems(player.recipe.requirements) && player.placeMode.lockCamera) &&
|
if(!Vars.control.showCursor() && !(player.recipe != null && Vars.control.hasItems(player.recipe.requirements) && player.placeMode.lockCamera) &&
|
||||||
!(player.recipe == null && player.breakMode.lockCamera)){
|
!(player.recipe == null && player.breakMode.lockCamera)){
|
||||||
player.x -= deltaX*Core.camera.zoom/Core.cameraScale;
|
float dx = deltaX*Core.camera.zoom/Core.cameraScale, dy = deltaY*Core.camera.zoom/Core.cameraScale;
|
||||||
player.y += deltaY*Core.camera.zoom/Core.cameraScale;
|
player.x -= dx;
|
||||||
|
player.y += dy;
|
||||||
|
player.targetAngle = Mathf.atan2(dx, -dy);
|
||||||
}else if(player.placeMode.lockCamera && (player.placeMode.pan && player.recipe != null)){
|
}else if(player.placeMode.lockCamera && (player.placeMode.pan && player.recipe != null)){
|
||||||
input.mousex += deltaX;
|
input.mousex += deltaX;
|
||||||
input.mousey += deltaY;
|
input.mousey += deltaY;
|
||||||
|
|||||||
297
core/src/io/anuke/mindustry/io/NetworkIO.java
Normal file
297
core/src/io/anuke/mindustry/io/NetworkIO.java
Normal file
@@ -0,0 +1,297 @@
|
|||||||
|
package io.anuke.mindustry.io;
|
||||||
|
|
||||||
|
import com.badlogic.gdx.files.FileHandle;
|
||||||
|
import com.badlogic.gdx.utils.TimeUtils;
|
||||||
|
import com.badlogic.gdx.utils.reflect.ClassReflection;
|
||||||
|
import io.anuke.mindustry.Vars;
|
||||||
|
import io.anuke.mindustry.entities.enemies.Enemy;
|
||||||
|
import io.anuke.mindustry.world.Block;
|
||||||
|
import io.anuke.mindustry.world.GameMode;
|
||||||
|
import io.anuke.mindustry.world.Tile;
|
||||||
|
import io.anuke.mindustry.world.blocks.Blocks;
|
||||||
|
import io.anuke.mindustry.world.blocks.types.BlockPart;
|
||||||
|
import io.anuke.mindustry.world.blocks.types.Rock;
|
||||||
|
import io.anuke.ucore.core.Timers;
|
||||||
|
import io.anuke.ucore.entities.Entities;
|
||||||
|
|
||||||
|
import java.io.*;
|
||||||
|
|
||||||
|
import static io.anuke.mindustry.Vars.android;
|
||||||
|
import static io.anuke.mindustry.io.SaveIO.enemyIDs;
|
||||||
|
import static io.anuke.mindustry.io.SaveIO.idEnemies;
|
||||||
|
|
||||||
|
public class NetworkIO {
|
||||||
|
private static final int fileVersionID = 13;
|
||||||
|
|
||||||
|
public static void write(OutputStream os){
|
||||||
|
|
||||||
|
try(DataOutputStream stream = new DataOutputStream(os)){
|
||||||
|
|
||||||
|
//--META--
|
||||||
|
stream.writeInt(fileVersionID); //version id
|
||||||
|
stream.writeFloat(Timers.time()); //timer time
|
||||||
|
stream.writeLong(TimeUtils.millis()); //timestamp
|
||||||
|
|
||||||
|
//--GENERAL STATE--
|
||||||
|
stream.writeByte(Vars.control.getMode().ordinal()); //gamemode
|
||||||
|
stream.writeByte(Vars.world.getMap().id); //map ID
|
||||||
|
|
||||||
|
stream.writeInt(Vars.control.getWave()); //wave
|
||||||
|
stream.writeFloat(Vars.control.getWaveCountdown()); //wave countdown
|
||||||
|
|
||||||
|
//--INVENTORY--
|
||||||
|
|
||||||
|
for(int i = 0; i < Vars.control.getItems().length; i ++){
|
||||||
|
stream.writeInt(Vars.control.getItems()[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
//--ENEMIES--
|
||||||
|
|
||||||
|
int totalEnemies = 0;
|
||||||
|
|
||||||
|
for(Enemy entity : Vars.control.enemyGroup.all()){
|
||||||
|
if(idEnemies.containsKey(entity.getClass())){
|
||||||
|
totalEnemies ++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
stream.writeInt(totalEnemies); //enemy amount
|
||||||
|
|
||||||
|
for(Enemy enemy : Vars.control.enemyGroup.all()){
|
||||||
|
if(idEnemies.containsKey(enemy.getClass())){
|
||||||
|
stream.writeInt(enemy.id);
|
||||||
|
stream.writeByte(idEnemies.get(enemy.getClass())); //type
|
||||||
|
stream.writeByte(enemy.lane); //lane
|
||||||
|
stream.writeFloat(enemy.x); //x
|
||||||
|
stream.writeFloat(enemy.y); //y
|
||||||
|
stream.writeByte(enemy.tier); //tier
|
||||||
|
stream.writeShort(enemy.health); //health
|
||||||
|
stream.writeShort(enemy.node); //current node
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//--MAP DATA--
|
||||||
|
|
||||||
|
//seed
|
||||||
|
stream.writeInt(Vars.world.getSeed());
|
||||||
|
|
||||||
|
int totalblocks = 0;
|
||||||
|
int totalrocks = 0;
|
||||||
|
|
||||||
|
for(int x = 0; x < Vars.world.width(); x ++){
|
||||||
|
for(int y = 0; y < Vars.world.height(); y ++){
|
||||||
|
Tile tile = Vars.world.tile(x, y);
|
||||||
|
|
||||||
|
if(tile.breakable()){
|
||||||
|
if(tile.block() instanceof Rock){
|
||||||
|
totalrocks ++;
|
||||||
|
}else{
|
||||||
|
totalblocks ++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//amount of rocks
|
||||||
|
stream.writeInt(totalrocks);
|
||||||
|
|
||||||
|
//write all rocks
|
||||||
|
for(int x = 0; x < Vars.world.width(); x ++) {
|
||||||
|
for (int y = 0; y < Vars.world.height(); y++) {
|
||||||
|
Tile tile = Vars.world.tile(x, y);
|
||||||
|
|
||||||
|
if (tile.block() instanceof Rock) {
|
||||||
|
stream.writeInt(tile.packedPosition());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//tile amount
|
||||||
|
stream.writeInt(totalblocks);
|
||||||
|
|
||||||
|
for(int x = 0; x < Vars.world.width(); x ++){
|
||||||
|
for(int y = 0; y < Vars.world.height(); y ++){
|
||||||
|
Tile tile = Vars.world.tile(x, y);
|
||||||
|
|
||||||
|
if(tile.breakable() && !(tile.block() instanceof Rock)){
|
||||||
|
|
||||||
|
stream.writeInt(x + y*Vars.world.width()); //tile pos
|
||||||
|
//TODO will break if block number gets over BYTE_MAX
|
||||||
|
stream.writeByte(tile.block().id); //block ID
|
||||||
|
|
||||||
|
if(tile.block() instanceof BlockPart){
|
||||||
|
stream.writeByte(tile.link);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(tile.entity != null){
|
||||||
|
stream.writeByte(tile.getRotation()); //placerot
|
||||||
|
stream.writeShort(tile.entity.health); //health
|
||||||
|
|
||||||
|
//items
|
||||||
|
for(int i = 0; i < tile.entity.items.length; i ++){
|
||||||
|
stream.writeInt(tile.entity.items[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
//timer data
|
||||||
|
|
||||||
|
//amount of active timers
|
||||||
|
byte times = 0;
|
||||||
|
|
||||||
|
for(; times < tile.entity.timer.getTimes().length; times ++){
|
||||||
|
if(tile.entity.timer.getTimes()[times] <= 1){
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
stream.writeByte(times);
|
||||||
|
|
||||||
|
for(int i = 0; i < times; i ++){
|
||||||
|
stream.writeFloat(tile.entity.timer.getTimes()[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
tile.entity.write(stream);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}catch (IOException e){
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void load(FileHandle file){
|
||||||
|
load(file.read());
|
||||||
|
}
|
||||||
|
|
||||||
|
//TODO GWT support
|
||||||
|
public static void load(InputStream is){
|
||||||
|
|
||||||
|
try(DataInputStream stream = new DataInputStream(is)){
|
||||||
|
|
||||||
|
int version = stream.readInt();
|
||||||
|
float timerTime = stream.readFloat();
|
||||||
|
long timestamp = stream.readLong();
|
||||||
|
|
||||||
|
Timers.resetTime(timerTime + (TimeUtils.timeSinceMillis(timestamp) / 1000f) * 60f);
|
||||||
|
|
||||||
|
if(version != fileVersionID){
|
||||||
|
throw new RuntimeException("Save file version mismatch!");
|
||||||
|
}
|
||||||
|
|
||||||
|
//general state
|
||||||
|
byte mode = stream.readByte();
|
||||||
|
byte mapid = stream.readByte();
|
||||||
|
|
||||||
|
int wave = stream.readInt();
|
||||||
|
float wavetime = stream.readFloat();
|
||||||
|
|
||||||
|
Vars.control.setMode(GameMode.values()[mode]);
|
||||||
|
|
||||||
|
//inventory
|
||||||
|
for(int i = 0; i < Vars.control.getItems().length; i ++){
|
||||||
|
Vars.control.getItems()[i] = stream.readInt();
|
||||||
|
}
|
||||||
|
|
||||||
|
Vars.ui.updateItems();
|
||||||
|
|
||||||
|
//enemies
|
||||||
|
|
||||||
|
Entities.clear();
|
||||||
|
|
||||||
|
int enemies = stream.readInt();
|
||||||
|
|
||||||
|
for(int i = 0; i < enemies; i ++){
|
||||||
|
int id = stream.readInt();
|
||||||
|
byte type = stream.readByte();
|
||||||
|
int lane = stream.readByte();
|
||||||
|
float x = stream.readFloat();
|
||||||
|
float y = stream.readFloat();
|
||||||
|
byte tier = stream.readByte();
|
||||||
|
short health = stream.readShort();
|
||||||
|
short node = stream.readShort();
|
||||||
|
|
||||||
|
try{
|
||||||
|
Enemy enemy = ClassReflection.newInstance(enemyIDs.get(type));
|
||||||
|
enemy.id = id;
|
||||||
|
enemy.lane = lane;
|
||||||
|
enemy.health = health;
|
||||||
|
enemy.x = x;
|
||||||
|
enemy.y = y;
|
||||||
|
enemy.tier = tier;
|
||||||
|
enemy.node = node;
|
||||||
|
enemy.add(Vars.control.enemyGroup);
|
||||||
|
}catch (Exception e){
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Vars.control.setWaveData(enemies, wave, wavetime);
|
||||||
|
|
||||||
|
Vars.player.add();
|
||||||
|
|
||||||
|
//map
|
||||||
|
|
||||||
|
int seed = stream.readInt();
|
||||||
|
|
||||||
|
Vars.world.loadMap(Vars.world.maps().getMap(mapid), seed);
|
||||||
|
Vars.renderer.clearTiles();
|
||||||
|
|
||||||
|
for(int x = 0; x < Vars.world.width(); x ++){
|
||||||
|
for(int y = 0; y < Vars.world.height(); y ++){
|
||||||
|
Tile tile = Vars.world.tile(x, y);
|
||||||
|
|
||||||
|
//remove breakables like rocks
|
||||||
|
if(tile.breakable()){
|
||||||
|
Vars.world.tile(x, y).setBlock(Blocks.air);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int rocks = stream.readInt();
|
||||||
|
|
||||||
|
for(int i = 0; i < rocks; i ++){
|
||||||
|
int pos = stream.readInt();
|
||||||
|
Tile tile = Vars.world.tile(pos % Vars.world.width(), pos / Vars.world.width());
|
||||||
|
Block result = io.anuke.mindustry.world.Generator.rocks.get(tile.floor());
|
||||||
|
if(result != null) tile.setBlock(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
int tiles = stream.readInt();
|
||||||
|
|
||||||
|
for(int i = 0; i < tiles; i ++){
|
||||||
|
int pos = stream.readInt();
|
||||||
|
byte blockid = stream.readByte();
|
||||||
|
|
||||||
|
Tile tile = Vars.world.tile(pos % Vars.world.width(), pos / Vars.world.width());
|
||||||
|
tile.setBlock(Block.getByID(blockid));
|
||||||
|
|
||||||
|
if(tile.block() == Blocks.blockpart){
|
||||||
|
tile.link = stream.readByte();
|
||||||
|
}
|
||||||
|
|
||||||
|
if(tile.entity != null){
|
||||||
|
byte rotation = stream.readByte();
|
||||||
|
short health = stream.readShort();
|
||||||
|
|
||||||
|
tile.entity.health = health;
|
||||||
|
tile.setRotation(rotation);
|
||||||
|
|
||||||
|
for(int j = 0; j < tile.entity.items.length; j ++){
|
||||||
|
tile.entity.items[j] = stream.readInt();
|
||||||
|
}
|
||||||
|
|
||||||
|
byte timers = stream.readByte();
|
||||||
|
for(int time = 0; time < timers; time ++){
|
||||||
|
tile.entity.timer.getTimes()[time] = stream.readFloat();
|
||||||
|
}
|
||||||
|
|
||||||
|
tile.entity.read(stream);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}catch (IOException e){
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,28 +1,31 @@
|
|||||||
package io.anuke.mindustry.io;
|
package io.anuke.mindustry.io;
|
||||||
|
|
||||||
import static io.anuke.mindustry.Vars.android;
|
|
||||||
|
|
||||||
import java.io.*;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Date;
|
|
||||||
|
|
||||||
import com.badlogic.gdx.Gdx;
|
|
||||||
import com.badlogic.gdx.files.FileHandle;
|
import com.badlogic.gdx.files.FileHandle;
|
||||||
import com.badlogic.gdx.utils.Array;
|
import com.badlogic.gdx.utils.Array;
|
||||||
|
import com.badlogic.gdx.utils.Base64Coder;
|
||||||
import com.badlogic.gdx.utils.ObjectMap;
|
import com.badlogic.gdx.utils.ObjectMap;
|
||||||
import com.badlogic.gdx.utils.TimeUtils;
|
import com.badlogic.gdx.utils.TimeUtils;
|
||||||
import com.badlogic.gdx.utils.reflect.ClassReflection;
|
import com.badlogic.gdx.utils.reflect.ClassReflection;
|
||||||
|
|
||||||
import io.anuke.mindustry.Mindustry;
|
import io.anuke.mindustry.Mindustry;
|
||||||
import io.anuke.mindustry.Vars;
|
import io.anuke.mindustry.Vars;
|
||||||
import io.anuke.mindustry.entities.enemies.*;
|
import io.anuke.mindustry.entities.enemies.*;
|
||||||
import io.anuke.mindustry.resource.Item;
|
import io.anuke.mindustry.resource.Item;
|
||||||
import io.anuke.mindustry.resource.Weapon;
|
import io.anuke.mindustry.resource.Weapon;
|
||||||
import io.anuke.mindustry.world.*;
|
import io.anuke.mindustry.world.Block;
|
||||||
|
import io.anuke.mindustry.world.GameMode;
|
||||||
|
import io.anuke.mindustry.world.Map;
|
||||||
|
import io.anuke.mindustry.world.Tile;
|
||||||
import io.anuke.mindustry.world.blocks.Blocks;
|
import io.anuke.mindustry.world.blocks.Blocks;
|
||||||
import io.anuke.ucore.core.Core;
|
import io.anuke.ucore.core.Core;
|
||||||
|
import io.anuke.ucore.core.Settings;
|
||||||
import io.anuke.ucore.entities.Entities;
|
import io.anuke.ucore.entities.Entities;
|
||||||
|
|
||||||
|
import java.io.*;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
import static io.anuke.mindustry.Vars.android;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Save format:
|
* Save format:
|
||||||
*
|
*
|
||||||
@@ -84,7 +87,7 @@ public class SaveIO{
|
|||||||
private static final int fileVersionID = 12;
|
private static final int fileVersionID = 12;
|
||||||
|
|
||||||
//TODO automatic registration of types?
|
//TODO automatic registration of types?
|
||||||
private static final Array<Class<? extends Enemy>> enemyIDs = Array.with(
|
public static final Array<Class<? extends Enemy>> enemyIDs = Array.with(
|
||||||
Enemy.class,
|
Enemy.class,
|
||||||
FastEnemy.class,
|
FastEnemy.class,
|
||||||
RapidEnemy.class,
|
RapidEnemy.class,
|
||||||
@@ -98,78 +101,78 @@ public class SaveIO{
|
|||||||
EmpEnemy.class
|
EmpEnemy.class
|
||||||
);
|
);
|
||||||
|
|
||||||
private static final ObjectMap<Class<? extends Enemy>, Byte> idEnemies = new ObjectMap<Class<? extends Enemy>, Byte>(){{
|
public static final ObjectMap<Class<? extends Enemy>, Byte> idEnemies = new ObjectMap<Class<? extends Enemy>, Byte>(){{
|
||||||
for(int i = 0; i < enemyIDs.size; i ++){
|
for(int i = 0; i < enemyIDs.size; i ++){
|
||||||
put(enemyIDs.get(i), (byte)i);
|
put(enemyIDs.get(i), (byte)i);
|
||||||
}
|
}
|
||||||
}};
|
}};
|
||||||
|
|
||||||
public static void saveToSlot(int slot){
|
public static void saveToSlot(int slot){
|
||||||
write(fileFor(slot));
|
if(Vars.gwt){
|
||||||
|
ByteArrayOutputStream stream = new ByteArrayOutputStream();
|
||||||
|
write(stream);
|
||||||
|
Settings.putString("save-"+slot+"-data", new String(Base64Coder.encode(stream.toByteArray())));
|
||||||
|
Settings.save();
|
||||||
|
}else{
|
||||||
|
write(fileFor(slot));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void loadFromSlot(int slot){
|
public static void loadFromSlot(int slot){
|
||||||
load(fileFor(slot));
|
if(Vars.gwt){
|
||||||
|
String string = Settings.getString("save-"+slot+"-data");
|
||||||
|
ByteArrayInputStream stream = new ByteArrayInputStream(Base64Coder.decode(string));
|
||||||
|
load(stream);
|
||||||
|
}else{
|
||||||
|
load(fileFor(slot));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static DataInputStream readSlotMeta(int slot){
|
||||||
|
if(Vars.gwt){
|
||||||
|
String string = Settings.getString("save-"+slot+"-data");
|
||||||
|
byte[] bytes = Base64Coder.decode(string);
|
||||||
|
return new DataInputStream(new ByteArrayInputStream(bytes));
|
||||||
|
}else{
|
||||||
|
return new DataInputStream(fileFor(slot).read());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isSaveValid(int slot){
|
public static boolean isSaveValid(int slot){
|
||||||
return isSaveValid(fileFor(slot));
|
try {
|
||||||
}
|
return isSaveValid(readSlotMeta(slot));
|
||||||
|
|
||||||
public static boolean isSaveValid(FileHandle file){
|
|
||||||
try(DataInputStream stream = new DataInputStream(file.read())){
|
|
||||||
int version = stream.readInt(); //read version
|
|
||||||
stream.readLong(); //read last saved time
|
|
||||||
stream.readByte(); //read the gamemode
|
|
||||||
byte map = stream.readByte(); //read the map
|
|
||||||
return version == fileVersionID && Vars.world.maps().getMap(map) != null;
|
|
||||||
}catch (Exception e){
|
}catch (Exception e){
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String getTimeString(int slot){
|
public static boolean isSaveValid(FileHandle file){
|
||||||
|
return isSaveValid(new DataInputStream(file.read()));
|
||||||
|
}
|
||||||
|
|
||||||
try(DataInputStream stream = new DataInputStream(fileFor(slot).read())){
|
public static boolean isSaveValid(DataInputStream stream){
|
||||||
stream.readInt();
|
|
||||||
Date date = new Date(stream.readLong());
|
try{
|
||||||
return Mindustry.platforms.format(date);
|
SaveMeta meta = getData(stream);
|
||||||
}catch (IOException e){
|
return meta.version == fileVersionID && meta.map != null;
|
||||||
throw new RuntimeException(e);
|
}catch (Exception e){
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int getWave(int slot){
|
public static SaveMeta getData(int slot){
|
||||||
|
return getData(readSlotMeta(slot));
|
||||||
try(DataInputStream stream = new DataInputStream(fileFor(slot).read())){
|
|
||||||
stream.readInt(); //read version
|
|
||||||
stream.readLong(); //read last saved time
|
|
||||||
stream.readByte(); //read the gamemode
|
|
||||||
stream.readByte(); //read the map
|
|
||||||
return stream.readInt(); //read the wave
|
|
||||||
}catch (IOException e){
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static GameMode getMode(int slot){
|
public static SaveMeta getData(DataInputStream stream){
|
||||||
|
|
||||||
try(DataInputStream stream = new DataInputStream(fileFor(slot).read())){
|
try{
|
||||||
stream.readInt(); //read version
|
int version = stream.readInt(); //read version
|
||||||
stream.readLong(); //read last saved time
|
long time = stream.readLong(); //read last saved time
|
||||||
return GameMode.values()[stream.readByte()]; //read the gamemode
|
byte mode = stream.readByte(); //read the gamemode
|
||||||
}catch (IOException e){
|
byte map = stream.readByte(); //read the map
|
||||||
throw new RuntimeException(e);
|
int wave = stream.readInt(); //read the wave
|
||||||
}
|
return new SaveMeta(version, time, mode, map, wave);
|
||||||
}
|
|
||||||
|
|
||||||
public static Map getMap(int slot){
|
|
||||||
|
|
||||||
try(DataInputStream stream = new DataInputStream(fileFor(slot).read())){
|
|
||||||
stream.readInt(); //read version
|
|
||||||
stream.readLong(); //read last saved time
|
|
||||||
stream.readByte(); //read the gamemode
|
|
||||||
return Vars.world.maps().getMap(stream.readByte()); //read the map
|
|
||||||
}catch (IOException e){
|
}catch (IOException e){
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
@@ -245,7 +248,7 @@ public class SaveIO{
|
|||||||
for(Enemy enemy : Vars.control.enemyGroup.all()){
|
for(Enemy enemy : Vars.control.enemyGroup.all()){
|
||||||
if(idEnemies.containsKey(enemy.getClass())){
|
if(idEnemies.containsKey(enemy.getClass())){
|
||||||
stream.writeByte(idEnemies.get(enemy.getClass())); //type
|
stream.writeByte(idEnemies.get(enemy.getClass())); //type
|
||||||
stream.writeByte(enemy.spawn); //lane
|
stream.writeByte(enemy.lane); //lane
|
||||||
stream.writeFloat(enemy.x); //x
|
stream.writeFloat(enemy.x); //x
|
||||||
stream.writeFloat(enemy.y); //y
|
stream.writeFloat(enemy.y); //y
|
||||||
stream.writeByte(enemy.tier); //tier
|
stream.writeByte(enemy.tier); //tier
|
||||||
@@ -391,7 +394,7 @@ public class SaveIO{
|
|||||||
|
|
||||||
try{
|
try{
|
||||||
Enemy enemy = ClassReflection.newInstance(enemyIDs.get(type));
|
Enemy enemy = ClassReflection.newInstance(enemyIDs.get(type));
|
||||||
enemy.spawn = lane;
|
enemy.lane = lane;
|
||||||
enemy.health = health;
|
enemy.health = health;
|
||||||
enemy.x = x;
|
enemy.x = x;
|
||||||
enemy.y = y;
|
enemy.y = y;
|
||||||
|
|||||||
24
core/src/io/anuke/mindustry/io/SaveMeta.java
Normal file
24
core/src/io/anuke/mindustry/io/SaveMeta.java
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
package io.anuke.mindustry.io;
|
||||||
|
|
||||||
|
import io.anuke.mindustry.Mindustry;
|
||||||
|
import io.anuke.mindustry.Vars;
|
||||||
|
import io.anuke.mindustry.world.GameMode;
|
||||||
|
import io.anuke.mindustry.world.Map;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
public class SaveMeta {
|
||||||
|
public int version;
|
||||||
|
public String date;
|
||||||
|
public GameMode mode;
|
||||||
|
public Map map;
|
||||||
|
public int wave;
|
||||||
|
|
||||||
|
public SaveMeta(int version, long date, int mode, int map, int wave){
|
||||||
|
this.version = version;
|
||||||
|
this.date = Mindustry.platforms.format(new Date(date));
|
||||||
|
this.mode = GameMode.values()[mode];
|
||||||
|
this.map = Vars.world.maps().getMap(map);
|
||||||
|
this.wave = wave;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,12 +2,7 @@ package io.anuke.mindustry.io;
|
|||||||
|
|
||||||
import com.badlogic.gdx.files.FileHandle;
|
import com.badlogic.gdx.files.FileHandle;
|
||||||
import com.badlogic.gdx.utils.Array;
|
import com.badlogic.gdx.utils.Array;
|
||||||
import com.badlogic.gdx.utils.Timer;
|
|
||||||
import com.badlogic.gdx.utils.Timer.Task;
|
|
||||||
import com.badlogic.gdx.utils.async.AsyncExecutor;
|
import com.badlogic.gdx.utils.async.AsyncExecutor;
|
||||||
import com.badlogic.gdx.utils.reflect.ClassReflection;
|
|
||||||
import com.badlogic.gdx.utils.reflect.Field;
|
|
||||||
import com.badlogic.gdx.utils.reflect.ReflectionException;
|
|
||||||
import io.anuke.mindustry.Vars;
|
import io.anuke.mindustry.Vars;
|
||||||
import io.anuke.mindustry.core.GameState;
|
import io.anuke.mindustry.core.GameState;
|
||||||
import io.anuke.mindustry.core.GameState.State;
|
import io.anuke.mindustry.core.GameState.State;
|
||||||
@@ -31,7 +26,9 @@ public class Saves {
|
|||||||
saves.clear();
|
saves.clear();
|
||||||
for(int i = 0; i < Vars.saveSlots; i ++){
|
for(int i = 0; i < Vars.saveSlots; i ++){
|
||||||
if(SaveIO.isSaveValid(i)){
|
if(SaveIO.isSaveValid(i)){
|
||||||
saves.add(new SaveSlot(i));
|
SaveSlot slot = new SaveSlot(i);
|
||||||
|
saves.add(slot);
|
||||||
|
slot.meta = SaveIO.getData(i);
|
||||||
nextSlot = i + 1;
|
nextSlot = i + 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -78,6 +75,7 @@ public class Saves {
|
|||||||
slot.setName(name);
|
slot.setName(name);
|
||||||
saves.add(slot);
|
saves.add(slot);
|
||||||
SaveIO.saveToSlot(slot.index);
|
SaveIO.saveToSlot(slot.index);
|
||||||
|
slot.meta = SaveIO.getData(slot.index);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Array<SaveSlot> getSaveSlots(){
|
public Array<SaveSlot> getSaveSlots(){
|
||||||
@@ -86,6 +84,7 @@ public class Saves {
|
|||||||
|
|
||||||
public class SaveSlot{
|
public class SaveSlot{
|
||||||
public final int index;
|
public final int index;
|
||||||
|
SaveMeta meta;
|
||||||
|
|
||||||
public SaveSlot(int index){
|
public SaveSlot(int index){
|
||||||
this.index = index;
|
this.index = index;
|
||||||
@@ -94,19 +93,21 @@ public class Saves {
|
|||||||
public void load(){
|
public void load(){
|
||||||
current = this;
|
current = this;
|
||||||
SaveIO.loadFromSlot(index);
|
SaveIO.loadFromSlot(index);
|
||||||
|
meta = SaveIO.getData(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void save(){
|
public void save(){
|
||||||
current = this;
|
current = this;
|
||||||
SaveIO.saveToSlot(index);
|
SaveIO.saveToSlot(index);
|
||||||
|
meta = SaveIO.getData(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getDate(){
|
public String getDate(){
|
||||||
return SaveIO.getTimeString(index);
|
return meta.date;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Map getMap(){
|
public Map getMap(){
|
||||||
return SaveIO.getMap(index);
|
return meta.map;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getName(){
|
public String getName(){
|
||||||
@@ -119,11 +120,11 @@ public class Saves {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public int getWave(){
|
public int getWave(){
|
||||||
return SaveIO.getWave(index);
|
return meta.wave;
|
||||||
}
|
}
|
||||||
|
|
||||||
public GameMode getMode(){
|
public GameMode getMode(){
|
||||||
return SaveIO.getMode(index);
|
return meta.mode;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isAutosave(){
|
public boolean isAutosave(){
|
||||||
@@ -156,6 +157,7 @@ public class Saves {
|
|||||||
|
|
||||||
public void delete(){
|
public void delete(){
|
||||||
SaveIO.fileFor(index).delete();
|
SaveIO.fileFor(index).delete();
|
||||||
|
saves.removeValue(this, true);
|
||||||
if(this == current){
|
if(this == current){
|
||||||
current = null;
|
current = null;
|
||||||
}
|
}
|
||||||
|
|||||||
11
core/src/io/anuke/mindustry/net/Address.java
Normal file
11
core/src/io/anuke/mindustry/net/Address.java
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
package io.anuke.mindustry.net;
|
||||||
|
|
||||||
|
public class Address {
|
||||||
|
public final String name;
|
||||||
|
public final String address;
|
||||||
|
|
||||||
|
public Address(String name, String address){
|
||||||
|
this.name = name;
|
||||||
|
this.address = address;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,8 +1,11 @@
|
|||||||
package io.anuke.mindustry.net;
|
package io.anuke.mindustry.net;
|
||||||
|
|
||||||
import com.badlogic.gdx.Gdx;
|
import com.badlogic.gdx.Gdx;
|
||||||
|
import com.badlogic.gdx.utils.Array;
|
||||||
|
import com.badlogic.gdx.utils.IntArray;
|
||||||
import com.badlogic.gdx.utils.IntMap;
|
import com.badlogic.gdx.utils.IntMap;
|
||||||
import com.badlogic.gdx.utils.ObjectMap;
|
import com.badlogic.gdx.utils.ObjectMap;
|
||||||
|
import com.badlogic.gdx.utils.async.AsyncExecutor;
|
||||||
import io.anuke.mindustry.net.Streamable.StreamBegin;
|
import io.anuke.mindustry.net.Streamable.StreamBegin;
|
||||||
import io.anuke.mindustry.net.Streamable.StreamBuilder;
|
import io.anuke.mindustry.net.Streamable.StreamBuilder;
|
||||||
import io.anuke.mindustry.net.Streamable.StreamChunk;
|
import io.anuke.mindustry.net.Streamable.StreamChunk;
|
||||||
@@ -21,6 +24,7 @@ public class Net{
|
|||||||
|
|
||||||
private static int lastConnection = -1;
|
private static int lastConnection = -1;
|
||||||
private static IntMap<StreamBuilder> streams = new IntMap<>();
|
private static IntMap<StreamBuilder> streams = new IntMap<>();
|
||||||
|
private static AsyncExecutor executor = new AsyncExecutor(4);
|
||||||
|
|
||||||
/**Connect to an address.*/
|
/**Connect to an address.*/
|
||||||
public static void connect(String ip, int port) throws IOException{
|
public static void connect(String ip, int port) throws IOException{
|
||||||
@@ -49,6 +53,23 @@ public class Net{
|
|||||||
active = false;
|
active = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**Starts discovering servers on a different thread. Does not work with GWT.
|
||||||
|
* Callback is run on the main libGDX thread.*/
|
||||||
|
public static void discoverServers(Consumer<Array<Address>> cons){
|
||||||
|
executor.submit(() -> {
|
||||||
|
Array<Address> arr = clientProvider.discover();
|
||||||
|
Gdx.app.postRunnable(() -> {
|
||||||
|
cons.accept(arr);
|
||||||
|
});
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**Returns a list of all connections IDs.*/
|
||||||
|
public static IntArray getConnections(){
|
||||||
|
return serverProvider.getConnections();
|
||||||
|
}
|
||||||
|
|
||||||
/**Send an object to all connected clients, or to the server if this is a client.*/
|
/**Send an object to all connected clients, or to the server if this is a client.*/
|
||||||
public static void send(Object object, SendMode mode){
|
public static void send(Object object, SendMode mode){
|
||||||
if(server){
|
if(server){
|
||||||
@@ -146,6 +167,12 @@ public class Net{
|
|||||||
return !server;
|
return !server;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void dispose(){
|
||||||
|
clientProvider.dispose();
|
||||||
|
serverProvider.dispose();
|
||||||
|
executor.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
/**Register classes that will be sent. Must be done for all classes.*/
|
/**Register classes that will be sent. Must be done for all classes.*/
|
||||||
public static void registerClasses(Class<?>... classes){
|
public static void registerClasses(Class<?>... classes){
|
||||||
clientProvider.register(classes);
|
clientProvider.register(classes);
|
||||||
@@ -164,8 +191,12 @@ public class Net{
|
|||||||
public int getPing();
|
public int getPing();
|
||||||
/**Disconnect from the server.*/
|
/**Disconnect from the server.*/
|
||||||
public void disconnect();
|
public void disconnect();
|
||||||
|
/**Discover servers. This should block for a certain amount of time, and will most likely be run in a different thread.*/
|
||||||
|
public Array<Address> discover();
|
||||||
/**Register classes to be sent.*/
|
/**Register classes to be sent.*/
|
||||||
public void register(Class<?>... types);
|
public void register(Class<?>... types);
|
||||||
|
/**Close all connections.*/
|
||||||
|
public void dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**Server implementation.*/
|
/**Server implementation.*/
|
||||||
@@ -182,8 +213,14 @@ public class Net{
|
|||||||
public void sendExcept(int id, Object object, SendMode mode);
|
public void sendExcept(int id, Object object, SendMode mode);
|
||||||
/**Close the server connection.*/
|
/**Close the server connection.*/
|
||||||
public void close();
|
public void close();
|
||||||
|
/**Return all connected users.*/
|
||||||
|
public IntArray getConnections();
|
||||||
/**Register classes to be sent.*/
|
/**Register classes to be sent.*/
|
||||||
public void register(Class<?>... types);
|
public void register(Class<?>... types);
|
||||||
|
/**Returns the ping for a certain connection.*/
|
||||||
|
public int getPingFor(int connection);
|
||||||
|
/**Close all connections.*/
|
||||||
|
public void dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum SendMode{
|
public enum SendMode{
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package io.anuke.mindustry.net;
|
package io.anuke.mindustry.net;
|
||||||
|
|
||||||
import io.anuke.mindustry.entities.Player;
|
import io.anuke.mindustry.entities.Player;
|
||||||
|
import io.anuke.mindustry.entities.enemies.Enemy;
|
||||||
|
|
||||||
/**Class for storing all packets.*/
|
/**Class for storing all packets.*/
|
||||||
public class Packets {
|
public class Packets {
|
||||||
@@ -27,16 +28,27 @@ public class Packets {
|
|||||||
public static class SyncPacket{
|
public static class SyncPacket{
|
||||||
public int[] ids;
|
public int[] ids;
|
||||||
public float[][] data;
|
public float[][] data;
|
||||||
|
public short enemyStart;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class BlockSyncPacket extends Streamable{
|
public static class BlockSyncPacket extends Streamable{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class StateSyncPacket {
|
public static class ConnectPacket{
|
||||||
|
public String name;
|
||||||
|
public boolean android;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class DisconnectPacket{
|
||||||
|
public int playerid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class StateSyncPacket{
|
||||||
public int[] items;
|
public int[] items;
|
||||||
public float countdown;
|
public float countdown, time;
|
||||||
public int enemies, wave;
|
public int enemies, wave;
|
||||||
|
public long timestamp;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class PositionPacket{
|
public static class PositionPacket{
|
||||||
@@ -55,6 +67,12 @@ public class Packets {
|
|||||||
public int playerid;
|
public int playerid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static class BulletPacket{
|
||||||
|
public int type, owner;
|
||||||
|
public float x, y, angle;
|
||||||
|
public short damage;
|
||||||
|
}
|
||||||
|
|
||||||
public static class PlacePacket{
|
public static class PlacePacket{
|
||||||
public int playerid;
|
public int playerid;
|
||||||
public byte rotation;
|
public byte rotation;
|
||||||
@@ -66,4 +84,28 @@ public class Packets {
|
|||||||
public int playerid;
|
public int playerid;
|
||||||
public short x, y;
|
public short x, y;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static class EnemySpawnPacket{
|
||||||
|
public Class<? extends Enemy> type;
|
||||||
|
public byte lane, tier;
|
||||||
|
public float x, y;
|
||||||
|
public int id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class EnemyDeathPacket{
|
||||||
|
public int id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class PathPacket{
|
||||||
|
public int[] path;
|
||||||
|
public byte index;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class BlockDestroyPacket{
|
||||||
|
public int position;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class BlockUpdatePacket{
|
||||||
|
public int health, position;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package io.anuke.mindustry.net;
|
|||||||
import com.badlogic.gdx.math.Vector2;
|
import com.badlogic.gdx.math.Vector2;
|
||||||
import com.badlogic.gdx.utils.Array;
|
import com.badlogic.gdx.utils.Array;
|
||||||
import io.anuke.mindustry.entities.Player;
|
import io.anuke.mindustry.entities.Player;
|
||||||
|
import io.anuke.mindustry.entities.enemies.*;
|
||||||
import io.anuke.mindustry.net.Packets.*;
|
import io.anuke.mindustry.net.Packets.*;
|
||||||
import io.anuke.mindustry.net.Streamable.StreamBegin;
|
import io.anuke.mindustry.net.Streamable.StreamBegin;
|
||||||
import io.anuke.mindustry.net.Streamable.StreamChunk;
|
import io.anuke.mindustry.net.Streamable.StreamChunk;
|
||||||
@@ -24,12 +25,21 @@ public class Registrator {
|
|||||||
BreakPacket.class,
|
BreakPacket.class,
|
||||||
StateSyncPacket.class,
|
StateSyncPacket.class,
|
||||||
BlockSyncPacket.class,
|
BlockSyncPacket.class,
|
||||||
|
EnemySpawnPacket.class,
|
||||||
|
PathPacket.class,
|
||||||
|
BulletPacket.class,
|
||||||
|
EnemyDeathPacket.class,
|
||||||
|
BlockUpdatePacket.class,
|
||||||
|
BlockDestroyPacket.class,
|
||||||
|
ConnectPacket.class,
|
||||||
|
DisconnectPacket.class,
|
||||||
|
|
||||||
Class.class,
|
Class.class,
|
||||||
byte[].class,
|
byte[].class,
|
||||||
float[].class,
|
float[].class,
|
||||||
float[][].class,
|
float[][].class,
|
||||||
int[].class,
|
int[].class,
|
||||||
|
int[][].class,
|
||||||
Entity[].class,
|
Entity[].class,
|
||||||
Player[].class,
|
Player[].class,
|
||||||
Array.class,
|
Array.class,
|
||||||
@@ -37,7 +47,19 @@ public class Registrator {
|
|||||||
|
|
||||||
Entity.class,
|
Entity.class,
|
||||||
Player.class,
|
Player.class,
|
||||||
Mech.class
|
Mech.class,
|
||||||
|
|
||||||
|
Enemy.class,
|
||||||
|
FastEnemy.class,
|
||||||
|
RapidEnemy.class,
|
||||||
|
FlamerEnemy.class,
|
||||||
|
TankEnemy.class,
|
||||||
|
BlastEnemy.class,
|
||||||
|
MortarEnemy.class,
|
||||||
|
TestEnemy.class,
|
||||||
|
HealerEnemy.class,
|
||||||
|
TitanEnemy.class,
|
||||||
|
EmpEnemy.class
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,9 +2,15 @@ package io.anuke.mindustry.net;
|
|||||||
|
|
||||||
import com.badlogic.gdx.math.Vector2;
|
import com.badlogic.gdx.math.Vector2;
|
||||||
import io.anuke.mindustry.entities.Player;
|
import io.anuke.mindustry.entities.Player;
|
||||||
|
import io.anuke.mindustry.entities.enemies.Enemy;
|
||||||
|
import io.anuke.mindustry.graphics.Fx;
|
||||||
|
import io.anuke.ucore.core.Effects;
|
||||||
|
import io.anuke.ucore.core.Timers;
|
||||||
import io.anuke.ucore.entities.Entity;
|
import io.anuke.ucore.entities.Entity;
|
||||||
|
import io.anuke.ucore.util.Angles;
|
||||||
import io.anuke.ucore.util.Mathf;
|
import io.anuke.ucore.util.Mathf;
|
||||||
|
|
||||||
|
//TODO clean up this giant mess
|
||||||
public interface Syncable {
|
public interface Syncable {
|
||||||
|
|
||||||
public Interpolator<?> getInterpolator();
|
public Interpolator<?> getInterpolator();
|
||||||
@@ -29,6 +35,37 @@ public interface Syncable {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void update(Player entity, Interpolator interpolator) {
|
public void update(Player entity, Interpolator interpolator) {
|
||||||
|
Interpolator i = entity.getInterpolator();
|
||||||
|
if(i.target.dst(entity.x, entity.y) > 16 && !entity.isAndroid){
|
||||||
|
entity.set(i.target.x, i.target.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(entity.isAndroid && i.target.dst(entity.x, entity.y) > 2f && Timers.get(entity, "dashfx", 2)){
|
||||||
|
Angles.translation(entity.angle + 180, 3f);
|
||||||
|
Effects.effect(Fx.dashsmoke, entity.x + Angles.x(), entity.y + Angles.y());
|
||||||
|
}
|
||||||
|
|
||||||
|
entity.x = Mathf.lerpDelta(entity.x, i.target.x, 0.4f);
|
||||||
|
entity.y = Mathf.lerpDelta(entity.y, i.target.y, 0.4f);
|
||||||
|
entity.angle = Mathf.lerpAngDelta(entity.angle, i.targetrot, 0.6f);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
public static final SyncType<Enemy> enemy = new SyncType<Enemy>() {
|
||||||
|
@Override
|
||||||
|
public float[] write(Enemy entity) {
|
||||||
|
return new float[]{entity.x, entity.y, entity.angle, entity.health};
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void read(Enemy entity, float[] data) {
|
||||||
|
entity.getInterpolator().target.set(data[0], data[1]);
|
||||||
|
entity.getInterpolator().targetrot = data[2];
|
||||||
|
entity.health = (int)data[3];
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void update(Enemy entity, Interpolator interpolator) {
|
||||||
Interpolator i = entity.getInterpolator();
|
Interpolator i = entity.getInterpolator();
|
||||||
if(i.target.dst(entity.x, entity.y) > 16){
|
if(i.target.dst(entity.x, entity.y) > 16){
|
||||||
entity.set(i.target.x, i.target.y);
|
entity.set(i.target.x, i.target.y);
|
||||||
@@ -44,6 +81,7 @@ public interface Syncable {
|
|||||||
public static class Interpolator<T extends Entity> {
|
public static class Interpolator<T extends Entity> {
|
||||||
public SyncType<T> type;
|
public SyncType<T> type;
|
||||||
public Vector2 target = new Vector2();
|
public Vector2 target = new Vector2();
|
||||||
|
public Vector2 last = new Vector2();
|
||||||
public float targetrot;
|
public float targetrot;
|
||||||
|
|
||||||
public Interpolator(SyncType<T> type){
|
public Interpolator(SyncType<T> type){
|
||||||
|
|||||||
@@ -13,10 +13,10 @@ public class Item{
|
|||||||
steel = new Item("steel"),
|
steel = new Item("steel"),
|
||||||
titanium = new Item("titanium"),
|
titanium = new Item("titanium"),
|
||||||
dirium = new Item("dirium"),
|
dirium = new Item("dirium"),
|
||||||
uranium = new Item("uranium"),
|
uranium = new Item("uranium");
|
||||||
sand = new Item("sand"),
|
/*sand = new Item("sand"),
|
||||||
glass = new Item("glass"),
|
glass = new Item("glass"),
|
||||||
silicon = new Item("silicon");
|
silicon = new Item("silicon");*/
|
||||||
|
|
||||||
public final int id;
|
public final int id;
|
||||||
public final String name;
|
public final String name;
|
||||||
|
|||||||
103
core/src/io/anuke/mindustry/ui/JoinDialog.java
Normal file
103
core/src/io/anuke/mindustry/ui/JoinDialog.java
Normal file
@@ -0,0 +1,103 @@
|
|||||||
|
package io.anuke.mindustry.ui;
|
||||||
|
|
||||||
|
import com.badlogic.gdx.utils.Array;
|
||||||
|
import io.anuke.mindustry.Mindustry;
|
||||||
|
import io.anuke.mindustry.Vars;
|
||||||
|
import io.anuke.mindustry.net.Address;
|
||||||
|
import io.anuke.mindustry.net.Net;
|
||||||
|
import io.anuke.ucore.core.Settings;
|
||||||
|
import io.anuke.ucore.core.Timers;
|
||||||
|
import io.anuke.ucore.scene.style.Drawable;
|
||||||
|
import io.anuke.ucore.scene.ui.Dialog;
|
||||||
|
import io.anuke.ucore.scene.ui.TextButton;
|
||||||
|
import io.anuke.ucore.scene.ui.TextField.TextFieldFilter.DigitsOnlyFilter;
|
||||||
|
import io.anuke.ucore.scene.ui.layout.Table;
|
||||||
|
import io.anuke.ucore.util.Bundles;
|
||||||
|
import io.anuke.ucore.util.Strings;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
public class JoinDialog extends FloatingDialog {
|
||||||
|
Dialog join;
|
||||||
|
Table hosts = new Table();
|
||||||
|
float w = 400;
|
||||||
|
|
||||||
|
public JoinDialog(){
|
||||||
|
super("$text.joingame");
|
||||||
|
|
||||||
|
addCloseButton();
|
||||||
|
|
||||||
|
join = new FloatingDialog("$text.joingame.title");
|
||||||
|
join.content().add("$text.joingame.ip").left();
|
||||||
|
Mindustry.platforms.addDialog(join.content().addField(Settings.getString("ip"),text ->{
|
||||||
|
Settings.putString("ip", text);
|
||||||
|
Settings.save();
|
||||||
|
}).size(180f, 54f).get());
|
||||||
|
|
||||||
|
join.content().row();
|
||||||
|
join.content().add("$text.server.port").left();
|
||||||
|
Mindustry.platforms.addDialog(join.content()
|
||||||
|
.addField(Settings.getString("port"), new DigitsOnlyFilter(), text ->{
|
||||||
|
Settings.putString("port", text);
|
||||||
|
Settings.save();
|
||||||
|
})
|
||||||
|
.size(180f, 54f).get());
|
||||||
|
join.buttons().defaults().size(140f, 60f).pad(4f);
|
||||||
|
join.buttons().addButton("$text.cancel", join::hide);
|
||||||
|
join.buttons().addButton("$text.ok", () ->
|
||||||
|
connect(Settings.getString("port"), Integer.parseInt(Settings.getString("port")))
|
||||||
|
).disabled(b -> Settings.getString("ip").isEmpty() || Integer.parseInt(Settings.getString("port")) == Integer.MIN_VALUE);
|
||||||
|
|
||||||
|
setup();
|
||||||
|
|
||||||
|
shown(() -> {
|
||||||
|
hosts.clear();
|
||||||
|
hosts.background("button");
|
||||||
|
hosts.label(() -> "[accent]" + Bundles.get("text.hosts.discovering") + new String(new char[(int)(Timers.time() / 10) % 4]).replace("\0", ".")).pad(10f);
|
||||||
|
Net.discoverServers(list -> {
|
||||||
|
addHosts(list);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void setup(){
|
||||||
|
hosts.background("button");
|
||||||
|
content().clear();
|
||||||
|
content().add(hosts).width(w).pad(0);
|
||||||
|
content().row();
|
||||||
|
content().addButton("$text.joingame.byip", "clear", join::show).width(w).height(80f);
|
||||||
|
}
|
||||||
|
|
||||||
|
void addHosts(Array<Address> array){
|
||||||
|
hosts.clear();
|
||||||
|
|
||||||
|
if(array.size == 0){
|
||||||
|
hosts.add("$text.hosts.none").pad(20f);
|
||||||
|
}else {
|
||||||
|
for (Address a : array) {
|
||||||
|
TextButton button = hosts.addButton("[accent]"+a.name, "clear", () -> {
|
||||||
|
connect(a.address, Vars.port);
|
||||||
|
}).width(w).height(80f).pad(4f).get();
|
||||||
|
button.left();
|
||||||
|
button.row();
|
||||||
|
button.add("[lightgray]" + a.address + " / " + Vars.port).pad(4).left();
|
||||||
|
|
||||||
|
hosts.row();
|
||||||
|
hosts.background((Drawable) null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void connect(String ip, int port){
|
||||||
|
Vars.ui.showLoading("$text.connecting");
|
||||||
|
|
||||||
|
Timers.runTask(2f, () -> {
|
||||||
|
try{
|
||||||
|
Net.connect(ip, port);
|
||||||
|
}catch (IOException e) {
|
||||||
|
Vars.ui.showError(Bundles.format("text.connectfail", Strings.parseException(e, false)));
|
||||||
|
Vars.ui.hideLoading();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,23 +1,18 @@
|
|||||||
package io.anuke.mindustry.ui;
|
package io.anuke.mindustry.ui;
|
||||||
|
|
||||||
import static io.anuke.mindustry.Vars.ui;
|
|
||||||
|
|
||||||
import com.badlogic.gdx.utils.reflect.ClassReflection;
|
import com.badlogic.gdx.utils.reflect.ClassReflection;
|
||||||
import io.anuke.mindustry.Vars;
|
import io.anuke.mindustry.Vars;
|
||||||
import io.anuke.mindustry.core.GameState;
|
import io.anuke.mindustry.core.GameState;
|
||||||
import io.anuke.mindustry.core.GameState.State;
|
import io.anuke.mindustry.core.GameState.State;
|
||||||
import io.anuke.mindustry.net.Net;
|
import io.anuke.mindustry.net.Net;
|
||||||
import io.anuke.ucore.UCore;
|
|
||||||
import io.anuke.ucore.core.Timers;
|
import io.anuke.ucore.core.Timers;
|
||||||
import io.anuke.ucore.scene.Element;
|
import io.anuke.ucore.scene.Element;
|
||||||
import io.anuke.ucore.scene.builders.build;
|
import io.anuke.ucore.scene.builders.build;
|
||||||
import io.anuke.ucore.scene.builders.imagebutton;
|
import io.anuke.ucore.scene.builders.imagebutton;
|
||||||
import io.anuke.ucore.scene.ui.ImageButton;
|
import io.anuke.ucore.scene.ui.ImageButton;
|
||||||
import io.anuke.ucore.scene.ui.TextField.TextFieldFilter.DigitsOnlyFilter;
|
|
||||||
import io.anuke.ucore.util.Bundles;
|
import io.anuke.ucore.util.Bundles;
|
||||||
import io.anuke.ucore.util.Strings;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import static io.anuke.mindustry.Vars.ui;
|
||||||
|
|
||||||
public class MenuDialog extends FloatingDialog{
|
public class MenuDialog extends FloatingDialog{
|
||||||
private SaveDialog save = new SaveDialog();
|
private SaveDialog save = new SaveDialog();
|
||||||
@@ -25,14 +20,14 @@ public class MenuDialog extends FloatingDialog{
|
|||||||
public boolean wasPaused = false;
|
public boolean wasPaused = false;
|
||||||
|
|
||||||
public MenuDialog() {
|
public MenuDialog() {
|
||||||
super("Paused");
|
super("$text.menu");
|
||||||
setup();
|
setup();
|
||||||
}
|
}
|
||||||
|
|
||||||
void setup(){
|
void setup(){
|
||||||
shown(() -> {
|
shown(() -> {
|
||||||
wasPaused = GameState.is(State.paused);
|
wasPaused = GameState.is(State.paused);
|
||||||
GameState.set(State.paused);
|
if(!Net.active()) GameState.set(State.paused);
|
||||||
});
|
});
|
||||||
|
|
||||||
if(!Vars.android){
|
if(!Vars.android){
|
||||||
@@ -40,7 +35,7 @@ public class MenuDialog extends FloatingDialog{
|
|||||||
|
|
||||||
content().addButton("$text.back", () -> {
|
content().addButton("$text.back", () -> {
|
||||||
hide();
|
hide();
|
||||||
if(!wasPaused)
|
if(!wasPaused || Net.active())
|
||||||
GameState.set(State.playing);
|
GameState.set(State.playing);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -49,39 +44,25 @@ public class MenuDialog extends FloatingDialog{
|
|||||||
ui.showPrefs();
|
ui.showPrefs();
|
||||||
});
|
});
|
||||||
|
|
||||||
if(!Vars.gwt){
|
content().row();
|
||||||
content().row();
|
content().addButton("$text.savegame", () -> {
|
||||||
content().addButton("$text.savegame", () -> {
|
save.show();
|
||||||
save.show();
|
});
|
||||||
});
|
|
||||||
|
|
||||||
content().row();
|
content().row();
|
||||||
content().addButton("$text.loadgame", () -> {
|
content().addButton("$text.loadgame", () -> {
|
||||||
load.show();
|
load.show();
|
||||||
});
|
});
|
||||||
}
|
|
||||||
|
|
||||||
content().row();
|
content().row();
|
||||||
|
|
||||||
content().addButton("$text.hostserver", () -> {
|
content().addButton("$text.hostserver", () -> ui.showHostServer())
|
||||||
Vars.ui.showTextInput("$text.hostserver", "$text.server.port", Vars.port + "", new DigitsOnlyFilter(), text -> {
|
.disabled(b -> Net.active() || (Net.active() && !Net.server()));
|
||||||
int result = Strings.parseInt(text);
|
|
||||||
if(result == Integer.MIN_VALUE || result >= 65535){
|
|
||||||
Vars.ui.showError("$text.server.invalidport");
|
|
||||||
}else{
|
|
||||||
try{
|
|
||||||
Net.host(result);
|
|
||||||
}catch (IOException e){
|
|
||||||
Vars.ui.showError(Bundles.format("text.server.error", Strings.parseException(e, false)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}).disabled(b -> Net.active() || (Net.active() && !Net.server()));
|
|
||||||
|
|
||||||
content().row();
|
content().row();
|
||||||
|
|
||||||
content().addButton("$text.quit", () -> {
|
content().addButton("$text.quit", () -> {
|
||||||
Vars.ui.showConfirm("$text.confirm", "$text.quit.confirm", () -> {
|
ui.showConfirm("$text.confirm", "$text.quit.confirm", () -> {
|
||||||
runSave();
|
runSave();
|
||||||
hide();
|
hide();
|
||||||
GameState.set(State.menu);
|
GameState.set(State.menu);
|
||||||
@@ -106,8 +87,12 @@ public class MenuDialog extends FloatingDialog{
|
|||||||
|
|
||||||
new imagebutton("icon-save", isize, ()-> save.show()).text("$text.save").padTop(4f);
|
new imagebutton("icon-save", isize, ()-> save.show()).text("$text.save").padTop(4f);
|
||||||
|
|
||||||
|
content().row();
|
||||||
|
|
||||||
new imagebutton("icon-load", isize, () -> load.show()).text("$text.load").padTop(4f);
|
new imagebutton("icon-load", isize, () -> load.show()).text("$text.load").padTop(4f);
|
||||||
|
|
||||||
|
new imagebutton("icon-host", isize, () -> ui.showHostServer()).text("$text.host").padTop(4f);
|
||||||
|
|
||||||
new imagebutton("icon-quit", isize, () -> {
|
new imagebutton("icon-quit", isize, () -> {
|
||||||
Vars.ui.showConfirm("$text.confirm", "$text.quit.confirm", () -> {
|
Vars.ui.showConfirm("$text.confirm", "$text.quit.confirm", () -> {
|
||||||
runSave();
|
runSave();
|
||||||
|
|||||||
@@ -1,34 +1,26 @@
|
|||||||
package io.anuke.mindustry.ui.fragments;
|
package io.anuke.mindustry.ui.fragments;
|
||||||
|
|
||||||
import static io.anuke.mindustry.Vars.*;
|
|
||||||
|
|
||||||
import com.badlogic.gdx.Game;
|
|
||||||
import com.badlogic.gdx.Gdx;
|
import com.badlogic.gdx.Gdx;
|
||||||
import com.badlogic.gdx.graphics.Color;
|
import com.badlogic.gdx.graphics.Color;
|
||||||
|
|
||||||
import com.badlogic.gdx.math.Interpolation;
|
import com.badlogic.gdx.math.Interpolation;
|
||||||
import io.anuke.mindustry.Mindustry;
|
|
||||||
import io.anuke.mindustry.Vars;
|
import io.anuke.mindustry.Vars;
|
||||||
import io.anuke.mindustry.core.GameState;
|
import io.anuke.mindustry.core.GameState;
|
||||||
import io.anuke.mindustry.core.GameState.State;
|
import io.anuke.mindustry.core.GameState.State;
|
||||||
import io.anuke.mindustry.resource.Item;
|
import io.anuke.mindustry.net.Net;
|
||||||
import io.anuke.mindustry.world.GameMode;
|
|
||||||
import io.anuke.ucore.UCore;
|
|
||||||
import io.anuke.ucore.core.Core;
|
import io.anuke.ucore.core.Core;
|
||||||
import io.anuke.ucore.core.Draw;
|
|
||||||
import io.anuke.ucore.core.Settings;
|
import io.anuke.ucore.core.Settings;
|
||||||
import io.anuke.ucore.scene.actions.Actions;
|
import io.anuke.ucore.scene.actions.Actions;
|
||||||
import io.anuke.ucore.scene.builders.imagebutton;
|
import io.anuke.ucore.scene.builders.imagebutton;
|
||||||
import io.anuke.ucore.scene.builders.label;
|
import io.anuke.ucore.scene.builders.label;
|
||||||
import io.anuke.ucore.scene.builders.table;
|
import io.anuke.ucore.scene.builders.table;
|
||||||
import io.anuke.ucore.scene.event.Touchable;
|
import io.anuke.ucore.scene.event.Touchable;
|
||||||
import io.anuke.ucore.scene.ui.Image;
|
|
||||||
import io.anuke.ucore.scene.ui.ImageButton;
|
import io.anuke.ucore.scene.ui.ImageButton;
|
||||||
import io.anuke.ucore.scene.ui.Label;
|
import io.anuke.ucore.scene.ui.Label;
|
||||||
import io.anuke.ucore.scene.ui.layout.Cell;
|
|
||||||
import io.anuke.ucore.scene.ui.layout.Table;
|
import io.anuke.ucore.scene.ui.layout.Table;
|
||||||
import io.anuke.ucore.util.Bundles;
|
import io.anuke.ucore.util.Bundles;
|
||||||
|
|
||||||
|
import static io.anuke.mindustry.Vars.*;
|
||||||
|
|
||||||
public class HudFragment implements Fragment{
|
public class HudFragment implements Fragment{
|
||||||
private ImageButton menu, flip, pause;
|
private ImageButton menu, flip, pause;
|
||||||
private Table respawntable;
|
private Table respawntable;
|
||||||
@@ -74,7 +66,8 @@ public class HudFragment implements Fragment{
|
|||||||
|
|
||||||
pause = new imagebutton("icon-pause", isize, ()->{
|
pause = new imagebutton("icon-pause", isize, ()->{
|
||||||
GameState.set(GameState.is(State.paused) ? State.playing : State.paused);
|
GameState.set(GameState.is(State.paused) ? State.playing : State.paused);
|
||||||
}).update(i -> i.getStyle().imageUp = Core.skin.getDrawable(GameState.is(State.paused) ? "icon-play" : "icon-pause")).get();
|
}).update(i -> i.getStyle().imageUp = Core.skin.getDrawable(GameState.is(State.paused) ? "icon-play" : "icon-pause")).cell
|
||||||
|
.disabled(b -> Net.active()).get();
|
||||||
|
|
||||||
}}.end();
|
}}.end();
|
||||||
|
|
||||||
@@ -105,7 +98,7 @@ public class HudFragment implements Fragment{
|
|||||||
|
|
||||||
//paused table
|
//paused table
|
||||||
new table(){{
|
new table(){{
|
||||||
visible(()->GameState.is(State.paused));
|
visible(()->GameState.is(State.paused) && !Net.active());
|
||||||
atop();
|
atop();
|
||||||
|
|
||||||
new table("pane"){{
|
new table("pane"){{
|
||||||
@@ -157,6 +150,14 @@ public class HudFragment implements Fragment{
|
|||||||
|
|
||||||
}}.end();
|
}}.end();
|
||||||
|
|
||||||
|
if(Vars.debugNet) {
|
||||||
|
new table() {{
|
||||||
|
new label(() -> "players: " + Vars.control.playerGroup.amount());
|
||||||
|
row();
|
||||||
|
new label(() -> "" + Vars.control.playerGroup.all());
|
||||||
|
}}.end();
|
||||||
|
}
|
||||||
|
|
||||||
blockfrag.build();
|
blockfrag.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,6 @@
|
|||||||
package io.anuke.mindustry.ui.fragments;
|
package io.anuke.mindustry.ui.fragments;
|
||||||
|
|
||||||
import static io.anuke.mindustry.Vars.*;
|
|
||||||
|
|
||||||
import com.badlogic.gdx.Gdx;
|
import com.badlogic.gdx.Gdx;
|
||||||
|
|
||||||
import io.anuke.mindustry.Mindustry;
|
import io.anuke.mindustry.Mindustry;
|
||||||
import io.anuke.mindustry.core.GameState;
|
import io.anuke.mindustry.core.GameState;
|
||||||
import io.anuke.mindustry.core.GameState.State;
|
import io.anuke.mindustry.core.GameState.State;
|
||||||
@@ -12,6 +9,8 @@ import io.anuke.mindustry.ui.PressGroup;
|
|||||||
import io.anuke.ucore.scene.builders.imagebutton;
|
import io.anuke.ucore.scene.builders.imagebutton;
|
||||||
import io.anuke.ucore.scene.builders.table;
|
import io.anuke.ucore.scene.builders.table;
|
||||||
|
|
||||||
|
import static io.anuke.mindustry.Vars.*;
|
||||||
|
|
||||||
public class MenuFragment implements Fragment{
|
public class MenuFragment implements Fragment{
|
||||||
|
|
||||||
public void build(){
|
public void build(){
|
||||||
@@ -36,10 +35,10 @@ public class MenuFragment implements Fragment{
|
|||||||
add(new MenuButton("$text.tutorial", group, ()-> control.playMap(world.maps().getMap("tutorial"))));
|
add(new MenuButton("$text.tutorial", group, ()-> control.playMap(world.maps().getMap("tutorial"))));
|
||||||
row();
|
row();
|
||||||
|
|
||||||
if(!gwt){
|
add(new MenuButton("$text.loadgame", group, ui::showLoadGame));
|
||||||
add(new MenuButton("$text.loadgame", group, ui::showLoadGame));
|
row();
|
||||||
row();
|
|
||||||
|
|
||||||
|
if(!gwt){
|
||||||
add(new MenuButton("$text.editor", group, ui::showEditor));
|
add(new MenuButton("$text.editor", group, ui::showEditor));
|
||||||
row();
|
row();
|
||||||
}
|
}
|
||||||
@@ -73,6 +72,8 @@ public class MenuFragment implements Fragment{
|
|||||||
|
|
||||||
new imagebutton("icon-tools", isize, () -> ui.showPrefs()).text("$text.settings").padTop(4f);
|
new imagebutton("icon-tools", isize, () -> ui.showPrefs()).text("$text.settings").padTop(4f);
|
||||||
|
|
||||||
|
new imagebutton("icon-add", isize, () -> ui.showJoinGame()).text("$text.joingame").padTop(4f);
|
||||||
|
|
||||||
if(Mindustry.donationsCallable != null){
|
if(Mindustry.donationsCallable != null){
|
||||||
new imagebutton("icon-donate", isize, () -> {
|
new imagebutton("icon-donate", isize, () -> {
|
||||||
Mindustry.donationsCallable.run();
|
Mindustry.donationsCallable.run();
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ import io.anuke.ucore.noise.Noise;
|
|||||||
import io.anuke.ucore.util.Mathf;
|
import io.anuke.ucore.util.Mathf;
|
||||||
|
|
||||||
public class Generator{
|
public class Generator{
|
||||||
static final ObjectMap<Block, Block> rocks = new ObjectMap(){{
|
public static final ObjectMap<Block, Block> rocks = new ObjectMap(){{
|
||||||
put(Blocks.stone, Blocks.rock);
|
put(Blocks.stone, Blocks.rock);
|
||||||
put(Blocks.snow, Blocks.icerock);
|
put(Blocks.snow, Blocks.icerock);
|
||||||
put(Blocks.grass, Blocks.shrub);
|
put(Blocks.grass, Blocks.shrub);
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ import io.anuke.mindustry.ai.SmoothGraphPath;
|
|||||||
public class SpawnPoint{
|
public class SpawnPoint{
|
||||||
public Tile start;
|
public Tile start;
|
||||||
public Tile[] pathTiles;
|
public Tile[] pathTiles;
|
||||||
public Tile[] tempTiles;
|
|
||||||
public PathFinder<Tile> finder;
|
public PathFinder<Tile> finder;
|
||||||
public SmoothGraphPath path = new SmoothGraphPath();
|
public SmoothGraphPath path = new SmoothGraphPath();
|
||||||
public PathFinderRequest<Tile> request;
|
public PathFinderRequest<Tile> request;
|
||||||
|
|||||||
@@ -1,16 +1,15 @@
|
|||||||
package io.anuke.mindustry.world;
|
package io.anuke.mindustry.world;
|
||||||
|
|
||||||
import static io.anuke.mindustry.Vars.tilesize;
|
|
||||||
|
|
||||||
import com.badlogic.gdx.math.Vector2;
|
import com.badlogic.gdx.math.Vector2;
|
||||||
import com.badlogic.gdx.utils.Array;
|
import com.badlogic.gdx.utils.Array;
|
||||||
|
|
||||||
import io.anuke.mindustry.Vars;
|
import io.anuke.mindustry.Vars;
|
||||||
import io.anuke.mindustry.entities.TileEntity;
|
import io.anuke.mindustry.entities.TileEntity;
|
||||||
import io.anuke.mindustry.world.blocks.Blocks;
|
import io.anuke.mindustry.world.blocks.Blocks;
|
||||||
import io.anuke.ucore.util.Bits;
|
import io.anuke.ucore.util.Bits;
|
||||||
import io.anuke.ucore.util.Mathf;
|
import io.anuke.ucore.util.Mathf;
|
||||||
|
|
||||||
|
import static io.anuke.mindustry.Vars.tilesize;
|
||||||
|
|
||||||
|
|
||||||
public class Tile{
|
public class Tile{
|
||||||
private static final Array<Tile> tmpArray = new Array<>();
|
private static final Array<Tile> tmpArray = new Array<>();
|
||||||
@@ -35,6 +34,10 @@ public class Tile{
|
|||||||
iSetFloor(floor);
|
iSetFloor(floor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int packedPosition(){
|
||||||
|
return x + y * Vars.world.width();
|
||||||
|
}
|
||||||
|
|
||||||
private void iSetFloor(Block floor){
|
private void iSetFloor(Block floor){
|
||||||
byte id = (byte)floor.id;
|
byte id = (byte)floor.id;
|
||||||
blocks = Bits.packShort(id, getWallID());
|
blocks = Bits.packShort(id, getWallID());
|
||||||
|
|||||||
@@ -138,34 +138,23 @@ public class Blocks{
|
|||||||
solid = true;
|
solid = true;
|
||||||
}},
|
}},
|
||||||
|
|
||||||
shrub = new Block("shrub"){{
|
shrub = new Rock("shrub"){
|
||||||
shadow = "shrubshadow";
|
|
||||||
breakable = true;
|
|
||||||
breaktime = 10;
|
|
||||||
}},
|
|
||||||
|
|
||||||
rock = new Block("rock"){{
|
},
|
||||||
shadow = "rockshadow";
|
|
||||||
breakable = true;
|
rock = new Rock("rock"){{
|
||||||
breaktime = 15;
|
|
||||||
variants = 2;
|
variants = 2;
|
||||||
varyShadow = true;
|
varyShadow = true;
|
||||||
drops = new ItemStack(Item.stone, 3);
|
drops = new ItemStack(Item.stone, 3);
|
||||||
}},
|
}},
|
||||||
|
|
||||||
icerock = new Block("icerock"){{
|
icerock = new Rock("icerock"){{
|
||||||
shadow = "rockshadow";
|
|
||||||
breakable = true;
|
|
||||||
breaktime = 15;
|
|
||||||
variants = 2;
|
variants = 2;
|
||||||
varyShadow = true;
|
varyShadow = true;
|
||||||
drops = new ItemStack(Item.stone, 3);
|
drops = new ItemStack(Item.stone, 3);
|
||||||
}},
|
}},
|
||||||
|
|
||||||
blackrock = new Block("blackrock"){{
|
blackrock = new Rock("blackrock"){{
|
||||||
shadow = "blackrockshadow";
|
|
||||||
breakable = true;
|
|
||||||
breaktime = 15;
|
|
||||||
variants = 1;
|
variants = 1;
|
||||||
varyShadow = true;
|
varyShadow = true;
|
||||||
drops = new ItemStack(Item.stone, 3);
|
drops = new ItemStack(Item.stone, 3);
|
||||||
|
|||||||
13
core/src/io/anuke/mindustry/world/blocks/types/Rock.java
Normal file
13
core/src/io/anuke/mindustry/world/blocks/types/Rock.java
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
package io.anuke.mindustry.world.blocks.types;
|
||||||
|
|
||||||
|
import io.anuke.mindustry.world.Block;
|
||||||
|
|
||||||
|
public class Rock extends Block {
|
||||||
|
|
||||||
|
public Rock(String name) {
|
||||||
|
super(name);
|
||||||
|
shadow = name+"shadow";
|
||||||
|
breakable = true;
|
||||||
|
breaktime = 10;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,15 +1,7 @@
|
|||||||
package io.anuke.mindustry.world.blocks.types.distribution;
|
package io.anuke.mindustry.world.blocks.types.distribution;
|
||||||
|
|
||||||
import static io.anuke.mindustry.Vars.tilesize;
|
|
||||||
|
|
||||||
import java.io.DataInputStream;
|
|
||||||
import java.io.DataOutputStream;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.*;
|
|
||||||
|
|
||||||
import com.badlogic.gdx.utils.Array;
|
import com.badlogic.gdx.utils.Array;
|
||||||
import com.badlogic.gdx.utils.IntArray;
|
import com.badlogic.gdx.utils.IntArray;
|
||||||
|
|
||||||
import io.anuke.mindustry.entities.TileEntity;
|
import io.anuke.mindustry.entities.TileEntity;
|
||||||
import io.anuke.mindustry.resource.Item;
|
import io.anuke.mindustry.resource.Item;
|
||||||
import io.anuke.mindustry.world.Block;
|
import io.anuke.mindustry.world.Block;
|
||||||
@@ -17,7 +9,20 @@ import io.anuke.mindustry.world.Layer;
|
|||||||
import io.anuke.mindustry.world.Tile;
|
import io.anuke.mindustry.world.Tile;
|
||||||
import io.anuke.ucore.core.Draw;
|
import io.anuke.ucore.core.Draw;
|
||||||
import io.anuke.ucore.core.Timers;
|
import io.anuke.ucore.core.Timers;
|
||||||
import io.anuke.ucore.util.*;
|
import io.anuke.ucore.util.Bits;
|
||||||
|
import io.anuke.ucore.util.Mathf;
|
||||||
|
import io.anuke.ucore.util.Strings;
|
||||||
|
import io.anuke.ucore.util.Tmp;
|
||||||
|
|
||||||
|
import java.io.DataInputStream;
|
||||||
|
import java.io.DataOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.AbstractList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Comparator;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import static io.anuke.mindustry.Vars.tilesize;
|
||||||
|
|
||||||
public class Conveyor extends Block{
|
public class Conveyor extends Block{
|
||||||
private static ItemPos pos1 = new ItemPos();
|
private static ItemPos pos1 = new ItemPos();
|
||||||
@@ -182,6 +187,7 @@ public class Conveyor extends Block{
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void read(DataInputStream stream) throws IOException{
|
public void read(DataInputStream stream) throws IOException{
|
||||||
|
convey.clear();
|
||||||
int amount = stream.readInt();
|
int amount = stream.readInt();
|
||||||
convey.ensureCapacity(amount);
|
convey.ensureCapacity(amount);
|
||||||
|
|
||||||
|
|||||||
@@ -1,15 +1,14 @@
|
|||||||
package io.anuke.mindustry.world.blocks.types.production;
|
package io.anuke.mindustry.world.blocks.types.production;
|
||||||
|
|
||||||
import java.util.Arrays;
|
|
||||||
|
|
||||||
import com.badlogic.gdx.utils.Array;
|
import com.badlogic.gdx.utils.Array;
|
||||||
|
|
||||||
import io.anuke.mindustry.graphics.Fx;
|
import io.anuke.mindustry.graphics.Fx;
|
||||||
import io.anuke.mindustry.resource.Item;
|
import io.anuke.mindustry.resource.Item;
|
||||||
import io.anuke.mindustry.world.Block;
|
import io.anuke.mindustry.world.Block;
|
||||||
import io.anuke.mindustry.world.Tile;
|
import io.anuke.mindustry.world.Tile;
|
||||||
import io.anuke.ucore.core.Effects;
|
import io.anuke.ucore.core.Effects;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
public class Crafter extends Block{
|
public class Crafter extends Block{
|
||||||
protected final int timerDump = timers++;
|
protected final int timerDump = timers++;
|
||||||
|
|
||||||
@@ -32,7 +31,7 @@ public class Crafter extends Block{
|
|||||||
@Override
|
@Override
|
||||||
public void update(Tile tile){
|
public void update(Tile tile){
|
||||||
|
|
||||||
if(tile.entity.timer.get(timerDump, 20) && tile.entity.hasItem(result)){
|
if(tile.entity.timer.get(timerDump, 15) && tile.entity.hasItem(result)){
|
||||||
tryDump(tile, -1, result);
|
tryDump(tile, -1, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -52,13 +51,11 @@ public class Crafter extends Block{
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean acceptItem(Item item, Tile dest, Tile source){
|
public boolean acceptItem(Item item, Tile dest, Tile source){
|
||||||
boolean craft = false;
|
|
||||||
for(Item req : requirements){
|
for(Item req : requirements){
|
||||||
if(item == req){
|
if(item == req){
|
||||||
craft = true;
|
return true;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return craft;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -75,7 +75,7 @@ public class LiquidCrafter extends LiquidBlock{
|
|||||||
Effects.effect(craftEffect, tile.worldx(), tile.worldy());
|
Effects.effect(craftEffect, tile.worldx(), tile.worldy());
|
||||||
}
|
}
|
||||||
|
|
||||||
if(entity.timer.get(timerDump, 30)){
|
if(entity.timer.get(timerDump, 15)){
|
||||||
tryDump(tile, -1, output);
|
tryDump(tile, -1, output);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,32 +6,25 @@ import club.minnced.discord.rpc.DiscordRichPresence;
|
|||||||
import com.badlogic.gdx.backends.lwjgl3.Lwjgl3Application;
|
import com.badlogic.gdx.backends.lwjgl3.Lwjgl3Application;
|
||||||
import com.badlogic.gdx.backends.lwjgl3.Lwjgl3ApplicationConfiguration;
|
import com.badlogic.gdx.backends.lwjgl3.Lwjgl3ApplicationConfiguration;
|
||||||
import com.badlogic.gdx.utils.Array;
|
import com.badlogic.gdx.utils.Array;
|
||||||
import com.esotericsoftware.kryonet.*;
|
import io.anuke.kryonet.KryoClient;
|
||||||
import com.esotericsoftware.kryonet.util.InputStreamSender;
|
import io.anuke.kryonet.KryoServer;
|
||||||
import com.esotericsoftware.minlog.Log;
|
|
||||||
import io.anuke.mindustry.Mindustry;
|
import io.anuke.mindustry.Mindustry;
|
||||||
import io.anuke.mindustry.Vars;
|
import io.anuke.mindustry.Vars;
|
||||||
import io.anuke.mindustry.io.PlatformFunction;
|
import io.anuke.mindustry.io.PlatformFunction;
|
||||||
import io.anuke.mindustry.net.Net;
|
import io.anuke.mindustry.net.Net;
|
||||||
import io.anuke.mindustry.net.Net.ClientProvider;
|
|
||||||
import io.anuke.mindustry.net.Net.SendMode;
|
|
||||||
import io.anuke.mindustry.net.Net.ServerProvider;
|
|
||||||
import io.anuke.mindustry.net.Packets.Connect;
|
|
||||||
import io.anuke.mindustry.net.Packets.Disconnect;
|
|
||||||
import io.anuke.mindustry.net.Registrator;
|
|
||||||
import io.anuke.mindustry.net.Streamable;
|
|
||||||
import io.anuke.mindustry.net.Streamable.StreamBegin;
|
|
||||||
import io.anuke.mindustry.net.Streamable.StreamChunk;
|
|
||||||
import io.anuke.ucore.UCore;
|
|
||||||
import io.anuke.ucore.scene.ui.TextField;
|
import io.anuke.ucore.scene.ui.TextField;
|
||||||
|
import io.anuke.ucore.util.Strings;
|
||||||
|
|
||||||
|
import javax.swing.*;
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Paths;
|
||||||
import java.text.DateFormat;
|
import java.text.DateFormat;
|
||||||
import java.text.NumberFormat;
|
import java.text.NumberFormat;
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
|
||||||
public class DesktopLauncher {
|
public class DesktopLauncher {
|
||||||
@@ -74,219 +67,57 @@ public class DesktopLauncher {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onSceneChange(String state, String details, String icon) {
|
public void onSceneChange(String state, String details, String icon) {
|
||||||
DiscordRPC lib = DiscordRPC.INSTANCE;
|
DiscordRPC lib = DiscordRPC.INSTANCE;
|
||||||
|
|
||||||
String applicationId = "397335883319083018";
|
String applicationId = "397335883319083018";
|
||||||
|
|
||||||
DiscordEventHandlers handlers = new DiscordEventHandlers();
|
DiscordEventHandlers handlers = new DiscordEventHandlers();
|
||||||
|
|
||||||
lib.Discord_Initialize(applicationId, handlers, true, "");
|
lib.Discord_Initialize(applicationId, handlers, true, "");
|
||||||
|
|
||||||
DiscordRichPresence presence = new DiscordRichPresence();
|
DiscordRichPresence presence = new DiscordRichPresence();
|
||||||
presence.startTimestamp = System.currentTimeMillis() / 1000; // epoch second
|
presence.startTimestamp = System.currentTimeMillis() / 1000; // epoch second
|
||||||
presence.state = state;
|
presence.state = state;
|
||||||
//presence.details = details;
|
//presence.details = details;
|
||||||
presence.largeImageKey = "logo";
|
presence.largeImageKey = "logo";
|
||||||
presence.largeImageText = details;
|
presence.largeImageText = details;
|
||||||
lib.Discord_UpdatePresence(presence);
|
lib.Discord_UpdatePresence(presence);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onGameExit() {
|
public void onGameExit() {
|
||||||
DiscordRPC.INSTANCE.Discord_Shutdown();
|
DiscordRPC.INSTANCE.Discord_Shutdown();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Mindustry.args = Array.with(arg);
|
Mindustry.args = Array.with(arg);
|
||||||
|
|
||||||
Log.set(Log.LEVEL_DEBUG);
|
Net.setClientProvider(new KryoClient());
|
||||||
|
Net.setServerProvider(new KryoServer());
|
||||||
|
|
||||||
Net.setClientProvider(new ClientProvider() {
|
try {
|
||||||
Client client;
|
new Lwjgl3Application(new Mindustry(), config);
|
||||||
|
}catch (Exception e){
|
||||||
|
e.printStackTrace();
|
||||||
|
|
||||||
{
|
//don't create crash logs for me, as it's expected
|
||||||
client = new Client();
|
if(System.getProperty("user.name").equals("anuke")) return;
|
||||||
client.start();
|
|
||||||
client.addListener(new Listener(){
|
|
||||||
@Override
|
|
||||||
public void connected (Connection connection) {
|
|
||||||
Connect c = new Connect();
|
|
||||||
c.id = connection.getID();
|
|
||||||
c.addressTCP = connection.getRemoteAddressTCP().toString();
|
|
||||||
Net.handleClientReceived(c);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
String result = Strings.parseException(e, true);
|
||||||
public void disconnected (Connection connection) {
|
boolean failed = false;
|
||||||
Disconnect c = new Disconnect();
|
|
||||||
Net.handleClientReceived(c);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
String filename = "crash-report-" + DateFormat.getDateTimeInstance().format(new Date()) + ".txt";
|
||||||
public void received (Connection connection, Object object) {
|
|
||||||
if(object instanceof FrameworkMessage) return;
|
|
||||||
Net.handleClientReceived(object);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
register(Registrator.getClasses());
|
try{
|
||||||
}
|
Files.write(Paths.get(filename), result.getBytes());
|
||||||
|
}catch (IOException i){
|
||||||
|
i.printStackTrace();
|
||||||
|
failed = true;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
JOptionPane.showMessageDialog(null, "An error has occured: \n" + result + "\n\n" +
|
||||||
public void connect(String ip, int port) throws IOException {
|
(!failed ? "A crash report has been written to " + new File(filename).getAbsolutePath() + ".\nPlease send this file to the developer!"
|
||||||
client.connect(5000, ip, port, port);
|
: "Failed to generate crash report.\nPlease send an image of this crash log to the developer!"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void disconnect() {
|
|
||||||
client.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void send(Object object, SendMode mode) {
|
|
||||||
if(mode == SendMode.tcp){
|
|
||||||
client.sendTCP(object);
|
|
||||||
}else{
|
|
||||||
client.sendUDP(object);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void updatePing() {
|
|
||||||
client.updateReturnTripTime();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getPing() {
|
|
||||||
return client.getReturnTripTime();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void register(Class<?>... types) {
|
|
||||||
for(Class<?> c : types){
|
|
||||||
client.getKryo().register(c);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
Net.setServerProvider(new ServerProvider() {
|
|
||||||
Server server;
|
|
||||||
|
|
||||||
{
|
|
||||||
server = new Server();
|
|
||||||
Thread thread = new Thread(server, "Kryonet Server");
|
|
||||||
thread.setDaemon(true);
|
|
||||||
thread.start();
|
|
||||||
server.addListener(new Listener(){
|
|
||||||
@Override
|
|
||||||
public void connected (Connection connection) {
|
|
||||||
Connect c = new Connect();
|
|
||||||
c.id = connection.getID();
|
|
||||||
c.addressTCP = connection.getRemoteAddressTCP().toString();
|
|
||||||
Net.handleServerReceived(c, c.id);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void disconnected (Connection connection) {
|
|
||||||
Disconnect c = new Disconnect();
|
|
||||||
c.id = connection.getID();
|
|
||||||
Net.handleServerReceived(c, c.id);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void received (Connection connection, Object object) {
|
|
||||||
if(object instanceof FrameworkMessage) return;
|
|
||||||
Net.handleServerReceived(object, connection.getID());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
register(Registrator.getClasses());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void host(int port) throws IOException {
|
|
||||||
server.bind(port, port);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void close() {
|
|
||||||
server.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void sendStream(int id, Streamable stream) {
|
|
||||||
Connection connection = getByID(id);
|
|
||||||
|
|
||||||
connection.addListener(new InputStreamSender(stream.stream, 512) {
|
|
||||||
int id;
|
|
||||||
|
|
||||||
protected void start () {
|
|
||||||
//send an object so the receiving side knows how to handle the following chunks
|
|
||||||
StreamBegin begin = new StreamBegin();
|
|
||||||
begin.total = stream.stream.available();
|
|
||||||
begin.type = stream.getClass();
|
|
||||||
connection.sendTCP(begin);
|
|
||||||
id = begin.id;
|
|
||||||
UCore.log("Sending begin packet: " + begin);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected Object next (byte[] bytes) {
|
|
||||||
StreamChunk chunk = new StreamChunk();
|
|
||||||
chunk.id = id;
|
|
||||||
chunk.data = bytes;
|
|
||||||
UCore.log("Sending chunk of size " + chunk.data.length);
|
|
||||||
return chunk; //wrap the byte[] with an object so the receiving side knows how to handle it.
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void send(Object object, SendMode mode) {
|
|
||||||
if(mode == SendMode.tcp){
|
|
||||||
server.sendToAllTCP(object);
|
|
||||||
}else{
|
|
||||||
server.sendToAllUDP(object);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void sendTo(int id, Object object, SendMode mode) {
|
|
||||||
if(mode == SendMode.tcp){
|
|
||||||
server.sendToTCP(id, object);
|
|
||||||
}else{
|
|
||||||
server.sendToUDP(id, object);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void sendExcept(int id, Object object, SendMode mode) {
|
|
||||||
if(mode == SendMode.tcp){
|
|
||||||
server.sendToAllExceptTCP(id, object);
|
|
||||||
}else{
|
|
||||||
server.sendToAllExceptUDP(id, object);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void register(Class<?>... types) {
|
|
||||||
for(Class<?> c : types){
|
|
||||||
server.getKryo().register(c);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Connection getByID(int id){
|
|
||||||
for(Connection con : server.getConnections()){
|
|
||||||
if(con.getID() == id){
|
|
||||||
return con;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new RuntimeException("Unable to find connection with ID " + id + "! Current connections: "
|
|
||||||
+ Arrays.toString(server.getConnections()));
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
new Lwjgl3Application(new Mindustry(), config);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
4
kryonet/build.gradle
Normal file
4
kryonet/build.gradle
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
apply plugin: "java"
|
||||||
|
|
||||||
|
sourceCompatibility = 1.8
|
||||||
|
sourceSets.main.java.srcDirs = [ "src/" ]
|
||||||
BIN
kryonet/build/libs/kryonet-release.jar
Normal file
BIN
kryonet/build/libs/kryonet-release.jar
Normal file
Binary file not shown.
2
kryonet/build/tmp/jar/MANIFEST.MF
Normal file
2
kryonet/build/tmp/jar/MANIFEST.MF
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
Manifest-Version: 1.0
|
||||||
|
|
||||||
133
kryonet/src/io/anuke/kryonet/KryoClient.java
Normal file
133
kryonet/src/io/anuke/kryonet/KryoClient.java
Normal file
@@ -0,0 +1,133 @@
|
|||||||
|
package io.anuke.kryonet;
|
||||||
|
|
||||||
|
import com.badlogic.gdx.Gdx;
|
||||||
|
import com.badlogic.gdx.utils.Array;
|
||||||
|
import com.badlogic.gdx.utils.ObjectSet;
|
||||||
|
import com.esotericsoftware.kryonet.Client;
|
||||||
|
import com.esotericsoftware.kryonet.Connection;
|
||||||
|
import com.esotericsoftware.kryonet.FrameworkMessage;
|
||||||
|
import com.esotericsoftware.kryonet.Listener;
|
||||||
|
import io.anuke.mindustry.Vars;
|
||||||
|
import io.anuke.mindustry.net.Address;
|
||||||
|
import io.anuke.mindustry.net.Net;
|
||||||
|
import io.anuke.mindustry.net.Net.ClientProvider;
|
||||||
|
import io.anuke.mindustry.net.Net.SendMode;
|
||||||
|
import io.anuke.mindustry.net.Packets.Connect;
|
||||||
|
import io.anuke.mindustry.net.Packets.Disconnect;
|
||||||
|
import io.anuke.mindustry.net.Registrator;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.InetAddress;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class KryoClient implements ClientProvider{
|
||||||
|
Client client;
|
||||||
|
|
||||||
|
public KryoClient(){
|
||||||
|
client = new Client();
|
||||||
|
client.start();
|
||||||
|
client.addListener(new Listener(){
|
||||||
|
@Override
|
||||||
|
public void connected (Connection connection) {
|
||||||
|
Connect c = new Connect();
|
||||||
|
c.id = connection.getID();
|
||||||
|
c.addressTCP = connection.getRemoteAddressTCP().toString();
|
||||||
|
|
||||||
|
try{
|
||||||
|
Net.handleClientReceived(c);
|
||||||
|
}catch (Exception e){
|
||||||
|
Gdx.app.exit();
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void disconnected (Connection connection) {
|
||||||
|
Disconnect c = new Disconnect();
|
||||||
|
|
||||||
|
try{
|
||||||
|
Net.handleClientReceived(c);
|
||||||
|
}catch (Exception e){
|
||||||
|
Gdx.app.exit();
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void received (Connection connection, Object object) {
|
||||||
|
if(object instanceof FrameworkMessage) return;
|
||||||
|
|
||||||
|
try{
|
||||||
|
Net.handleClientReceived(object);
|
||||||
|
}catch (Exception e){
|
||||||
|
Gdx.app.exit();
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
register(Registrator.getClasses());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void connect(String ip, int port) throws IOException {
|
||||||
|
client.connect(5000, ip, port, port);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void disconnect() {
|
||||||
|
client.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void send(Object object, SendMode mode) {
|
||||||
|
if(mode == SendMode.tcp){
|
||||||
|
client.sendTCP(object);
|
||||||
|
}else{
|
||||||
|
client.sendUDP(object);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void updatePing() {
|
||||||
|
client.updateReturnTripTime();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getPing() {
|
||||||
|
return client.getReturnTripTime();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Array<Address> discover(){
|
||||||
|
List<InetAddress> list = client.discoverHosts(Vars.port, 5000);
|
||||||
|
ObjectSet<String> hostnames = new ObjectSet<>();
|
||||||
|
Array<Address> result = new Array<>();
|
||||||
|
|
||||||
|
for(InetAddress a : list){
|
||||||
|
if(!hostnames.contains(a.getHostName()))
|
||||||
|
result.add(new Address(a.getCanonicalHostName(), a.getHostAddress()));
|
||||||
|
hostnames.add(a.getHostName());
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void register(Class<?>... types) {
|
||||||
|
for(Class<?> c : types){
|
||||||
|
client.getKryo().register(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void dispose(){
|
||||||
|
try {
|
||||||
|
client.dispose();
|
||||||
|
}catch (IOException e){
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
181
kryonet/src/io/anuke/kryonet/KryoServer.java
Normal file
181
kryonet/src/io/anuke/kryonet/KryoServer.java
Normal file
@@ -0,0 +1,181 @@
|
|||||||
|
package io.anuke.kryonet;
|
||||||
|
|
||||||
|
import com.badlogic.gdx.Gdx;
|
||||||
|
import com.badlogic.gdx.utils.IntArray;
|
||||||
|
import com.esotericsoftware.kryonet.Connection;
|
||||||
|
import com.esotericsoftware.kryonet.FrameworkMessage;
|
||||||
|
import com.esotericsoftware.kryonet.Listener;
|
||||||
|
import com.esotericsoftware.kryonet.Server;
|
||||||
|
import com.esotericsoftware.kryonet.util.InputStreamSender;
|
||||||
|
import io.anuke.mindustry.net.Net;
|
||||||
|
import io.anuke.mindustry.net.Net.SendMode;
|
||||||
|
import io.anuke.mindustry.net.Net.ServerProvider;
|
||||||
|
import io.anuke.mindustry.net.Packets.Connect;
|
||||||
|
import io.anuke.mindustry.net.Packets.Disconnect;
|
||||||
|
import io.anuke.mindustry.net.Registrator;
|
||||||
|
import io.anuke.mindustry.net.Streamable;
|
||||||
|
import io.anuke.mindustry.net.Streamable.StreamBegin;
|
||||||
|
import io.anuke.mindustry.net.Streamable.StreamChunk;
|
||||||
|
import io.anuke.ucore.UCore;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
public class KryoServer implements ServerProvider {
|
||||||
|
Server server;
|
||||||
|
IntArray connections = new IntArray();
|
||||||
|
|
||||||
|
public KryoServer(){
|
||||||
|
server = new Server();
|
||||||
|
Thread thread = new Thread(server, "Kryonet Server");
|
||||||
|
thread.setDaemon(true);
|
||||||
|
thread.start();
|
||||||
|
server.addListener(new Listener(){
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void connected (Connection connection) {
|
||||||
|
Connect c = new Connect();
|
||||||
|
c.id = connection.getID();
|
||||||
|
c.addressTCP = connection.getRemoteAddressTCP().toString();
|
||||||
|
|
||||||
|
try {
|
||||||
|
Net.handleServerReceived(c, c.id);
|
||||||
|
connections.add(c.id);
|
||||||
|
}catch (Exception e){
|
||||||
|
Gdx.app.exit();
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void disconnected (Connection connection) {
|
||||||
|
Disconnect c = new Disconnect();
|
||||||
|
c.id = connection.getID();
|
||||||
|
|
||||||
|
try{
|
||||||
|
Net.handleServerReceived(c, c.id);
|
||||||
|
}catch (Exception e){
|
||||||
|
Gdx.app.exit();
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
connections.removeValue(c.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void received (Connection connection, Object object) {
|
||||||
|
if(object instanceof FrameworkMessage) return;
|
||||||
|
|
||||||
|
try{
|
||||||
|
Net.handleServerReceived(object, connection.getID());
|
||||||
|
}catch (Exception e){
|
||||||
|
Gdx.app.exit();
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
register(Registrator.getClasses());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IntArray getConnections() {
|
||||||
|
return connections;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void host(int port) throws IOException {
|
||||||
|
server.bind(port, port);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void close() {
|
||||||
|
server.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void sendStream(int id, Streamable stream) {
|
||||||
|
Connection connection = getByID(id);
|
||||||
|
|
||||||
|
connection.addListener(new InputStreamSender(stream.stream, 512) {
|
||||||
|
int id;
|
||||||
|
|
||||||
|
protected void start () {
|
||||||
|
//send an object so the receiving side knows how to handle the following chunks
|
||||||
|
StreamBegin begin = new StreamBegin();
|
||||||
|
begin.total = stream.stream.available();
|
||||||
|
begin.type = stream.getClass();
|
||||||
|
connection.sendTCP(begin);
|
||||||
|
id = begin.id;
|
||||||
|
UCore.log("Sending begin packet: " + begin);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Object next (byte[] bytes) {
|
||||||
|
StreamChunk chunk = new StreamChunk();
|
||||||
|
chunk.id = id;
|
||||||
|
chunk.data = bytes;
|
||||||
|
UCore.log("Sending chunk of size " + chunk.data.length);
|
||||||
|
return chunk; //wrap the byte[] with an object so the receiving side knows how to handle it.
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void send(Object object, SendMode mode) {
|
||||||
|
if(mode == SendMode.tcp){
|
||||||
|
server.sendToAllTCP(object);
|
||||||
|
}else{
|
||||||
|
server.sendToAllUDP(object);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void sendTo(int id, Object object, SendMode mode) {
|
||||||
|
if(mode == SendMode.tcp){
|
||||||
|
server.sendToTCP(id, object);
|
||||||
|
}else{
|
||||||
|
server.sendToUDP(id, object);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void sendExcept(int id, Object object, SendMode mode) {
|
||||||
|
if(mode == SendMode.tcp){
|
||||||
|
server.sendToAllExceptTCP(id, object);
|
||||||
|
}else{
|
||||||
|
server.sendToAllExceptUDP(id, object);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getPingFor(int connection) {
|
||||||
|
return getByID(connection).getReturnTripTime();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void register(Class<?>... types) {
|
||||||
|
for(Class<?> c : types){
|
||||||
|
server.getKryo().register(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void dispose(){
|
||||||
|
try {
|
||||||
|
server.dispose();
|
||||||
|
}catch (IOException e){
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Connection getByID(int id){
|
||||||
|
for(Connection con : server.getConnections()){
|
||||||
|
if(con.getID() == id){
|
||||||
|
return con;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new RuntimeException("Unable to find connection with ID " + id + "! Current connections: "
|
||||||
|
+ Arrays.toString(server.getConnections()));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
include 'desktop', 'html', 'core', 'android'
|
include 'desktop', 'html', 'core', 'android', 'kryonet'
|
||||||
|
|
||||||
if(System.properties["release"] == null || System.properties["release"].equals("false")){
|
if(System.properties["release"] == null || System.properties["release"].equals("false")){
|
||||||
if (new File(settingsDir, '../uCore').exists()) {
|
if (new File(settingsDir, '../uCore').exists()) {
|
||||||
|
|||||||
Reference in New Issue
Block a user