Started working on discovery, implemented GWT saving

This commit is contained in:
Anuken 2018-01-01 21:33:51 -05:00
parent 1b55d00254
commit 24248df4af
13 changed files with 190 additions and 61 deletions

View File

@ -185,6 +185,7 @@ public class Control extends Module{
for(int i = 0; i < Vars.saveSlots; i ++){
Settings.defaults("save-" + i + "-autosave", true);
Settings.defaults("save-" + i + "-name", "untitled");
Settings.defaults("save-" + i + "-data", "empty");
}
Settings.loadAll("io.anuke.moment");

View File

@ -35,6 +35,7 @@ public class NetClient extends Module {
boolean connecting = false;
boolean gotEntities = false;
float playerSyncTime = 2;
float dataTimeout = 60*10;
public NetClient(){
@ -50,6 +51,14 @@ public class NetClient extends Module {
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 -> {
@ -243,7 +252,7 @@ public class NetClient extends Module {
}
public void update(){
if(!Net.client()) return;
if(!Net.client() || !Net.active()) return;
if(!GameState.is(State.menu) && Net.active()){
sync();

View File

@ -2,6 +2,7 @@ package io.anuke.mindustry.io;
import com.badlogic.gdx.files.FileHandle;
import com.badlogic.gdx.utils.Array;
import com.badlogic.gdx.utils.Base64Coder;
import com.badlogic.gdx.utils.ObjectMap;
import com.badlogic.gdx.utils.TimeUtils;
import com.badlogic.gdx.utils.reflect.ClassReflection;
@ -16,6 +17,7 @@ import io.anuke.mindustry.world.Map;
import io.anuke.mindustry.world.Tile;
import io.anuke.mindustry.world.blocks.Blocks;
import io.anuke.ucore.core.Core;
import io.anuke.ucore.core.Settings;
import io.anuke.ucore.entities.Entities;
import java.io.*;
@ -106,71 +108,71 @@ public class SaveIO{
}};
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){
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){
return isSaveValid(fileFor(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;
try {
return isSaveValid(readSlotMeta(slot));
}catch (Exception e){
return false;
}
}
public static String getTimeString(int slot){
try(DataInputStream stream = new DataInputStream(fileFor(slot).read())){
stream.readInt();
Date date = new Date(stream.readLong());
return Mindustry.platforms.format(date);
}catch (IOException e){
throw new RuntimeException(e);
public static boolean isSaveValid(FileHandle file){
return isSaveValid(new DataInputStream(file.read()));
}
public static boolean isSaveValid(DataInputStream stream){
try{
SaveMeta meta = getData(stream);
return meta.version == fileVersionID && meta.map != null;
}catch (Exception e){
return false;
}
}
public static int getWave(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
stream.readByte(); //read the map
return stream.readInt(); //read the wave
}catch (IOException e){
throw new RuntimeException(e);
}
public static SaveMeta getData(int slot){
return getData(readSlotMeta(slot));
}
public static GameMode getMode(int slot){
public static SaveMeta getData(DataInputStream stream){
try(DataInputStream stream = new DataInputStream(fileFor(slot).read())){
stream.readInt(); //read version
stream.readLong(); //read last saved time
return GameMode.values()[stream.readByte()]; //read the gamemode
}catch (IOException e){
throw new RuntimeException(e);
}
}
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
try{
int version = stream.readInt(); //read version
long time = stream.readLong(); //read last saved time
byte mode = stream.readByte(); //read the gamemode
byte map = stream.readByte(); //read the map
int wave = stream.readInt(); //read the wave
return new SaveMeta(version, time, mode, map, wave);
}catch (IOException e){
throw new RuntimeException(e);
}

View 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;
}
}

View File

@ -26,7 +26,9 @@ public class Saves {
saves.clear();
for(int i = 0; i < Vars.saveSlots; 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;
}
}
@ -73,6 +75,7 @@ public class Saves {
slot.setName(name);
saves.add(slot);
SaveIO.saveToSlot(slot.index);
slot.meta = SaveIO.getData(slot.index);
}
public Array<SaveSlot> getSaveSlots(){
@ -81,6 +84,7 @@ public class Saves {
public class SaveSlot{
public final int index;
SaveMeta meta;
public SaveSlot(int index){
this.index = index;
@ -89,19 +93,21 @@ public class Saves {
public void load(){
current = this;
SaveIO.loadFromSlot(index);
meta = SaveIO.getData(index);
}
public void save(){
current = this;
SaveIO.saveToSlot(index);
meta = SaveIO.getData(index);
}
public String getDate(){
return SaveIO.getTimeString(index);
return meta.date;
}
public Map getMap(){
return SaveIO.getMap(index);
return meta.map;
}
public String getName(){
@ -114,11 +120,11 @@ public class Saves {
}
public int getWave(){
return SaveIO.getWave(index);
return meta.wave;
}
public GameMode getMode(){
return SaveIO.getMode(index);
return meta.mode;
}
public boolean isAutosave(){

View 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;
}
}

View File

@ -1,9 +1,11 @@
package io.anuke.mindustry.net;
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.ObjectMap;
import com.badlogic.gdx.utils.async.AsyncExecutor;
import io.anuke.mindustry.net.Streamable.StreamBegin;
import io.anuke.mindustry.net.Streamable.StreamBuilder;
import io.anuke.mindustry.net.Streamable.StreamChunk;
@ -22,6 +24,7 @@ public class Net{
private static int lastConnection = -1;
private static IntMap<StreamBuilder> streams = new IntMap<>();
private static AsyncExecutor executor = new AsyncExecutor(4);
/**Connect to an address.*/
public static void connect(String ip, int port) throws IOException{
@ -50,6 +53,18 @@ public class Net{
active = false;
}
/**Starts discovering servers on a different thread. Does not work with GWT.
* Callback is run on the main libGDX thread.*/
public 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();
@ -152,6 +167,12 @@ public class Net{
return !server;
}
public static void dispose(){
clientProvider.dispose();
serverProvider.dispose();
executor.dispose();
}
/**Register classes that will be sent. Must be done for all classes.*/
public static void registerClasses(Class<?>... classes){
clientProvider.register(classes);
@ -170,8 +191,12 @@ public class Net{
public int getPing();
/**Disconnect from the server.*/
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.*/
public void register(Class<?>... types);
/**Close all connections.*/
public void dispose();
}
/**Server implementation.*/
@ -194,6 +219,8 @@ public class Net{
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{

View File

@ -0,0 +1,12 @@
package io.anuke.mindustry.ui;
public class JoinDialog extends FloatingDialog {
public JoinDialog(){
super("$text.joingame");
}
void setup(){
content().clear();
}
}

View File

@ -44,7 +44,7 @@ public class MenuDialog extends FloatingDialog{
ui.showPrefs();
});
if(!Vars.gwt){
//if(!Vars.gwt){
content().row();
content().addButton("$text.savegame", () -> {
save.show();
@ -54,7 +54,7 @@ public class MenuDialog extends FloatingDialog{
content().addButton("$text.loadgame", () -> {
load.show();
});
}
//}
content().row();

View File

@ -34,10 +34,11 @@ public class MenuFragment implements Fragment{
add(new MenuButton("$text.tutorial", group, ()-> control.playMap(world.maps().getMap("tutorial"))));
row();
add(new MenuButton("$text.loadgame", group, ui::showLoadGame));
row();
if(!gwt){
add(new MenuButton("$text.loadgame", group, ui::showLoadGame));
row();
add(new MenuButton("$text.editor", group, ui::showEditor));
row();

View File

@ -1,10 +1,13 @@
package io.anuke.kryonet;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.utils.Array;
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;
@ -13,6 +16,8 @@ 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;
@ -93,10 +98,32 @@ public class KryoClient implements ClientProvider{
return client.getReturnTripTime();
}
@Override
public Array<Address> discover(){
List<InetAddress> list = client.discoverHosts(Vars.port, 5000);
Array<Address> result = new Array<>();
for(InetAddress a : list){
result.add(new Address(a.getHostName(), a.getHostAddress()));
}
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);
}
}
}

View File

@ -159,6 +159,15 @@ public class KryoServer implements ServerProvider {
}
}
@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){