mirror of
https://github.com/Anuken/Mindustry.git
synced 2025-02-26 15:27:19 +07:00
Started working on discovery, implemented GWT saving
This commit is contained in:
parent
1b55d00254
commit
24248df4af
@ -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");
|
||||
|
@ -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();
|
||||
|
@ -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);
|
||||
}
|
||||
|
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;
|
||||
}
|
||||
}
|
@ -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(){
|
||||
|
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,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{
|
||||
|
12
core/src/io/anuke/mindustry/ui/JoinDialog.java
Normal file
12
core/src/io/anuke/mindustry/ui/JoinDialog.java
Normal file
@ -0,0 +1,12 @@
|
||||
package io.anuke.mindustry.ui;
|
||||
|
||||
public class JoinDialog extends FloatingDialog {
|
||||
|
||||
public JoinDialog(){
|
||||
super("$text.joingame");
|
||||
}
|
||||
|
||||
void setup(){
|
||||
content().clear();
|
||||
}
|
||||
}
|
@ -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();
|
||||
|
||||
|
@ -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();
|
||||
|
Binary file not shown.
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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){
|
||||
|
Loading…
Reference in New Issue
Block a user