Algunas pruebas más con JSON y el BackEnd.

Se han creado algunas de las clases que conformarán el Backend del juego.
Estas clases no están completas en cuanto a funcionalidad, pero sí los datos.
Se continúa con las pruebas para cargar y guardar todos estos datos en archivos JSON.
This commit is contained in:
2022-05-18 23:18:15 +02:00
parent c652a36ec6
commit 8341662e3d
10 changed files with 538 additions and 112 deletions
+34 -6
View File
@@ -4,6 +4,20 @@ import com.badlogic.gdx.utils.Null;
import java.util.HashMap;
/*
ToDo:
- Sistema de Atributos.
- Revisar constructores y sus parámetros.
- Revisar Getters/Setters y privacidad de variables.
- ¿Mover variables arriba?
- ¿?
*/
/***
* Almacena los datos relativos a una máquina.
* @author Daniel García
*/
public class Machine
{
/*-------------
@@ -23,6 +37,11 @@ public class Machine
this.attributes = new HashMap<>();
}
private Machine(Machine machine)
{
//Privatizamos el constructor de copia.
//No debería ser necesario (Java no hace copias de objetos). Pero por si acaso.
}
/*----------------
* Getters/Setters
* -------------*/
@@ -33,6 +52,14 @@ public class Machine
public boolean isEsDeRecursos() { return esDeRecursos; }
public void setEsDeRecursos(boolean esDeRecursos) { this.esDeRecursos = esDeRecursos; }
public HashMap<String, Integer> getAttributes() { return attributes; }
public String getTileSetID() { return tileSetID; }
public void setTileSetID(String tileSetID) { this.tileSetID = tileSetID; }
public int getTilePos() { return tilePos; }
public void setTilePos(int tilePos) { this.tilePos = tilePos; }
/*-------------
* Methods
* -------------*/
@@ -66,13 +93,14 @@ public class Machine
String machineID;
public HashMap<String, Integer> attributes;
/*
Permite a la room saber si se debe realizar comprobación con la capacidad máxima...
Lo sé, es muy cutre, pero te callas.
Piensa en algo mejor, no te jode...
*/
boolean esDeRecursos;
/*
Permiten una asociación sencilla con los datos para el renderizado.
Es más cómodo que usar Enums en código o hardcodear estos valores.
De nada, equipo de frontend.
*/
String tileSetID;
int tilePos;
}
@@ -1,9 +1,24 @@
package uberelectron.gameSystems;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.files.FileHandle;
import com.badlogic.gdx.utils.Json;
import com.badlogic.gdx.utils.JsonWriter;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
/*
ToDo:
- Comprobar que los archivos (los paths) existen.
*/
/***
* Esta clase carga los datos de las máquinas desde el JSON de datos y almacena los "prefabs" de las mismas.
* Carga los datos de las máquinas desde el JSON de datos y almacena los "prefabs" de las mismas.
*
* @author Daniel García
*/
public class MachineLoader
{
@@ -21,26 +36,75 @@ public class MachineLoader
* -------------*/
/**
* Carga del archivo JSON indicado con los datos de cada máquina.
* @param path Ubicación del JSON
* Carga una lista de máquinas desde el archivo JSON.
* @param path Ubicación del JSON (Path interno).
*/
public void LoadFile(String path)
public void LoadFromJSON(String path)
{
//TODO: Itera por las máquinas, cargándolas.
//Cargamos las máquinas en un ArrayList.
Json json = new Json();
FileHandle file = Gdx.files.internal(path);
ArrayList<Machine> list = json.fromJson(ArrayList.class, file);
//Iteramos y añadimos las máquinas al mapa identificadas por su ID.
for(Machine mc : list)
{
machineMap.put(mc.getMachineID(), mc);
}
//Limpiamos.
list.clear();
}
/***
* Permite guardar el estado del machineLoader (las máquinas del mapa) a un JSON.
* Utilizado para debug o herramientas de desarrollo.
* @param path Ubicación en que guardar el JSON (Path local).
*/
public void SaveToJSON(String path)
{
//Creamos y configuramos el serializador.
Json json = new Json();
json.setOutputType(JsonWriter.OutputType.json);
json.setUsePrototypes(false);
//Obtenemos una lista de las máquinas almacenadas y las convertimos en JSON.
Collection<Machine> mcList = machineMap.values();
String jsonData = json.toJson(mcList);
//Abrimos el archivo y escribimos los datos.
FileHandle file = Gdx.files.local(path);
file.writeString(json.prettyPrint(jsonData), false);
}
/***
* Añade al mapa la máquina pasada por parámetro. Utiliza el ID de la máquina como Key.
* @param machineToAdd Máquina que añadir al mapa.
*/
public void AddMachine(Machine machineToAdd)
{
machineMap.put(machineToAdd.machineID, machineToAdd);
}
/***
* Permite obtener un puntero a una máquina dado su ID.
* @param machineID ID de la máquina a obtener.
* @return Puntero a la máquina pedida.
*/
public Machine GetMachine(String machineID)
{
Machine mc = machineMap.get(machineID);
if(mc == null)
{
System.err.println("El mapa no contiene una máquina de ID: " + machineID);
System.out.println("El mapa no contiene una máquina de ID: " + machineID);
}
if(!mc.getMachineID().equals(machineID))
{
System.err.println("Hay una inconsistencia en los IDs de máquina: "
+ mc.getMachineID() + "!=" + machineID);
}
return mc;
}
@@ -49,6 +113,6 @@ public class MachineLoader
/*-------------
* Variables
* -------------*/
HashMap<String, Machine> machineMap;
private HashMap<String, Machine> machineMap;
}
+10 -83
View File
@@ -10,8 +10,12 @@ import java.util.HashMap;
de esta forma, si no quedan huecos, ComprobarMaquina() retorna false. No es necesario serializarlo.
*/
public class Room implements Json.Serializable
/***
* Clase que contiene los datos de la Sala y realiza permite interactuar con ellos.
*
* @author Daniel García.
*/
public class Room
{
/*-------------
* Constructors
@@ -68,6 +72,7 @@ public class Room implements Json.Serializable
public void AddMachine(int x, int y, Machine machineToAdd)
{
//Comprobamos si tenemos los recursos suficientes para añadir la máquina.
if(!ComprobarMaquina(machineToAdd))
{
@@ -92,7 +97,6 @@ public class Room implements Json.Serializable
// Con unos if-else comprobamos/añadimos en el que corresponda según sea la máquina.
public boolean ComprobarCapacidad(String attribute, int valorComprobar)
{
Integer max = recursosMaximos.get(attribute);
if(max == null)
{
@@ -135,11 +139,13 @@ public class Room implements Json.Serializable
// int height;
Vector2 roomSize;
//Permite saber de qué tileSet son los ints de bgData.
String tileSetID;
int[][] bgData;
Machine[][] machineData;
//Únicamente, para probar la serialización como array.
String[][] machineData_Test;
//String[][] machineData_Test;
//Atributos de la sala.
@@ -149,83 +155,4 @@ public class Room implements Json.Serializable
HashMap<String, Integer> recursosMaximos;
boolean esOnline = false;
//ToDo: Esto hay que moverlo a RoomLoader y ponerlo como Json.Serializer<Room> pues en RoomLoader tenemos un ptr a Game.MachineLoader
// y por tanto podemos pedir las máquinas directamente. La otra forma es que Game sea un Singleton...
@Override
public void write(Json json)
{
//Crearlo como un objeto puede venir bien si lo vamos a tener junto a otros datos externos.
// Hay que tener cuidado no rompamos el Read.
//json.writeObjectStart("Room");
json.writeValue("RoomName", roomName);
json.writeValue("RoomSize", roomSize);
json.writeValue("BackgroundData", bgData);
//Datos de máquinas.
json.writeArrayStart("MaquinasData");
for(int y = 0; y < machineData.length; y++)
{
json.writeArrayStart();
for(int x = 0; x < machineData[y].length; x++)
{
//Sólo nos interesa el ID de la máquina,
Machine mc = machineData[y][x];
if(mc == null)
{
json.writeValue(null);
} else {
json.writeValue(mc.machineID);
}
}
json.writeArrayEnd();
}
json.writeArrayEnd();
//json.writeObjectEnd();
//En principio, los recursos ocupados/disponibles los podemos reconstruir al cargar a
// partir de las máquinas que haya.
}
@Override
public void read(Json json, JsonValue jsonData)
{
//jsonData = jsonData.child();
roomName = jsonData.get("RoomName").asString();
roomSize = new Vector2();
roomSize.x = jsonData.get("RoomSize").get("x").asFloat();
roomSize.y = jsonData.get("RoomSize").get("y").asFloat();
//ToDo: En principio, bgData es el tamaño de la sala (el grid de máquinas) + 2 (para paredes).
bgData = new int[(int)roomSize.y][(int)roomSize.x];
for(int y = 0; y < bgData.length; y++)
{
bgData[y] = jsonData.get("BackgroundData").get(y).asIntArray();
}
machineData = new Machine[(int)roomSize.y][(int)roomSize.x];
machineData_Test = new String[(int)roomSize.y][(int)roomSize.x];
//ToDO: Revisar si el bucle de JsonValue.java es más eficiente.
for (int y = 0; y < machineData.length; y++)
{
//Obtenemos el array de esta "y".
JsonValue yData = jsonData.get("MaquinasData").get(y);
// yData = yData.child;
//
// for (; yData != null; yData = yData.next)
// {
// String val = yData.asString();
// }
for(int x = 0; x < machineData[y].length; x++)
{
//ToDo: En vez de guardar al String, se debería obtener un ptr a la máquina en cuestión desde MachineLoader.
machineData_Test[y][x] = yData.get(x).asString();
}
}
//Luego cargamos el resto... Si es que lo hay.
}
}
@@ -0,0 +1,258 @@
package uberelectron.gameSystems;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.files.FileHandle;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.utils.Json;
import com.badlogic.gdx.utils.JsonValue;
import com.badlogic.gdx.utils.JsonWriter;
import java.util.HashMap;
/*
ToDo:
- Cuestiones de "Privacidad" de variables.
- Revisar que los Ptrs son Ptrs.
- Comprobar que los archivos (los paths) existen.
*/
/***
* Clase encargada de gestionar las diferentes salas:
* Cargarlas, guardarlas, almacenarlas, ...
* Cada sala está guardada en su propio JSON.
*
* @author Daniel García.
*/
public class RoomLoader
{
public RoomLoader()
{
currentRoom = null;
loadedRooms = new HashMap<>();
mcLoader = null;
loaderJson = new Json();
loaderJson.setSerializer(Room.class, roomSerializer);
}
public RoomLoader(MachineLoader mcLoader)
{
currentRoom = null;
loadedRooms = new HashMap<>();
this.mcLoader = mcLoader;
loaderJson = new Json();
loaderJson.setSerializer(Room.class, roomSerializer);
}
/***
* Carga una Room desde un archivo.
* @param path Ubicación del archivo JSON de datos de la Room.
*/
public void LoadRoomFromJSON(String path)
{
FileHandle file = Gdx.files.internal(path);
Room r = loaderJson.fromJson(Room.class, file);
loadedRooms.put(r.roomName, r);
System.out.println("Se ha cargado la Room " + r.roomName + " correctamente.");
}
/***
* Guarda la Room indicada al archivo indicado.
* @param roomID ID de la Room a guardar.
* @param path Ubicación del archivo JSON de destino.
*/
public void SaveRoomToJSON(String roomID, String path)
{
Room rSave = loadedRooms.get(roomID);
if(rSave == null)
{
System.err.println("No es posible guardar la Room: " + roomID +
"; ¿Está cargada?");
return;
}
String data = loaderJson.toJson(rSave);
FileHandle file = Gdx.files.local(path);
file.writeString(loaderJson.prettyPrint(data), false);
System.out.println("Se ha guardado la room " + roomID + " en " + path);
}
/***
* Descarga una Room dado su ID.
* @param roomID ID de la Room a descargar.
*/
public void UnloadRoom(String roomID)
{
loadedRooms.remove(roomID);
//¿Habría que matar al objeto manualmente?
//¿Quizás debamos hacerlo un recurso de LibGDX para poder matarlo?
}
/***
* Permite saber si una Room está cargada.
* @param roomID ID de la Room a comprobar.
* @return True si está cargada, False si no lo está.
*/
public boolean isRoomLoader(String roomID)
{
return loadedRooms.containsKey(roomID);
}
/***
* Establece la Room activa.
* La Room debe estar cargada para poder ser la activa.
* @param roomID ID de la Room Activa.
*/
public void SetCurrentRoom(String roomID)
{
Room r = loadedRooms.get(roomID);
if(r == null)
{
System.err.println("No se puede activar la room " + roomID + " ; No está cargada.");
}
currentRoom = r;
}
/***
* Devuelve la Room actualmente activa.
* @return Ptr a la Room actualmente activa.
*/
public Room GetCurrentRoom()
{
return currentRoom;
}
//DEBUG: Para hacer pruebas desde BackEndTest.java.
public void AddRoom(Room rToAdd)
{
loadedRooms.put(rToAdd.roomName, rToAdd);
}
/*-------------
* Variables
* -------------*/
Room currentRoom;
HashMap<String, Room> loadedRooms;
//ToDo: Revisar si lo dejamos así o lo sacamos directamente desde Game.
MachineLoader mcLoader;
Json loaderJson;
Json.Serializer<Room> roomSerializer = new Json.Serializer<Room>()
{
@Override
public void write(Json json, Room object, Class knownType)
{
//Crearlo como un objeto puede venir bien si lo vamos a tener junto a otros datos externos.
// Hay que tener cuidado no rompamos el Read.
json.setOutputType(JsonWriter.OutputType.json);
json.writeObjectStart();
json.writeValue("RoomName", object.roomName);
json.writeValue("RoomSize", object.roomSize);
json.writeValue("BackgroundData", object.bgData);
//Datos de máquinas. Creamos un JSON array bidimensional.
json.writeArrayStart("MaquinasData");
for(int y = 0; y < object.machineData.length; y++)
{
json.writeArrayStart();
for(int x = 0; x < object.machineData[y].length; x++)
{
//Almacenamos el ID de la máquina.
Machine mc = object.machineData[y][x];
if(mc == null)
{
//Si no hay máquina será un Null.
json.writeValue(null);
} else
{
json.writeValue(mc.machineID);
}
}
json.writeArrayEnd();
}
json.writeArrayEnd();
json.writeObjectEnd();
//En principio, los recursos ocupados/disponibles los podemos reconstruir al cargar a
// partir de las máquinas que haya en la sala.
// Quizás habría que crear un método en Room que hiciera eso.
}
@Override
public Room read(Json json, JsonValue jsonData, Class type)
{
//Instanciamos la nueva sala y modificaremos sus variables.
Room room = new Room();
//jsonData = jsonData.child();
room.roomName = jsonData.get("RoomName").asString();
room.roomSize = new Vector2();
room.roomSize.x = jsonData.get("RoomSize").get("x").asFloat();
room.roomSize.y = jsonData.get("RoomSize").get("y").asFloat();
//ToDo: En principio, bgData debería ser el tamaño de la sala (el grid de máquinas) + 2 (para paredes).
room.bgData = new int[(int)room.roomSize.y][(int)room.roomSize.x];
for(int y = 0; y < room.bgData.length; y++)
{
room.bgData[y] = jsonData.get("BackgroundData").get(y).asIntArray();
}
/*
Cargamos los datos relativos a las máquinas.
Únicamente guardamos su ID, pues lo que nos interesa guardar en la sala es un ptr.
Las máquinas reales viven dentro del mcLoader.
*/
room.machineData = new Machine[(int)room.roomSize.y][(int)room.roomSize.x];
//room.machineData_Test = new String[(int)room.roomSize.y][(int)room.roomSize.x];
//ToDO: Revisar si el bucle de JsonValue.java es más eficiente.
for (int y = 0; y < room.machineData.length; y++)
{
//Obtenemos el array de esta "y".
JsonValue yData = jsonData.get("MaquinasData").get(y);
for(int x = 0; x < room.machineData[y].length; x++)
{
//ToDo: Revisar el acceso al mcLoader....
String mcName = yData.get(x).asString();
//En caso de que no haya máquina (en el JSON haya null) -> Establecemos Null.
// TODO: Recuerda que los null de JSON devuelven un objeto null.
if(mcName == null)
{
//Nos podemos saltar la asignación... (Java por defecto establece null al crear el Array).
room.machineData[y][x] = null;
continue;
}
//Obtenemos un ptr a la máquina que corresponda.
room.machineData[y][x] = mcLoader.GetMachine(mcName);
//room.machineData_Test[y][x] = yData.get(x).asString();
}
}
// ToDo: Los atributos de la sala se generan al cargar la sala contando las máquinas que haya.
return room;
}
};
}
@@ -0,0 +1,19 @@
package uberelectron.gameSystems;
import java.util.HashMap;
/***
* Clase contenedora para los datos de guardado de la partida.
*
* @author Daniel García.
*/
public class Save
{
int dinero;
/*
Indica si el jugador tiene comprada esa sala y, por tanto, ha de aparecer/cargarse.
*/
HashMap<String, Boolean> ownedRoom;
}
+51 -14
View File
@@ -3,12 +3,20 @@ package uberelectron.testgame;
import com.badlogic.gdx.Screen;
import com.badlogic.gdx.utils.Json;
import uberelectron.gameSystems.Machine;
import uberelectron.gameSystems.MachineLoader;
import uberelectron.gameSystems.Room;
import uberelectron.gameSystems.RoomLoader;
public class BackEndTest implements Screen
{
final testGame game;
public static MachineLoader mcLoader = new MachineLoader();
/***
* Clase para la realización de pruebas del BackEnd.
* Carga, guardado y gestión de los diversos datos.
* @param game Ptr a la clase Game.
*/
public BackEndTest(final testGame game)
{
this.game = game;
@@ -18,28 +26,57 @@ public class BackEndTest implements Screen
testMach.AddAtribute("Test", 5);
testMach.AddAtribute("Otro", -2);
testMach.setEsDeRecursos(true);
testMach.setTileSetID("Machine_Set");
testMach.setTilePos(3);
Json json = new Json();
String text = json.toJson(testMach);
Machine mach2 = new Machine();
mach2.setMachineID("test_mach2");
mach2.AddAtribute("Test2", 3);
mach2.AddAtribute("Otro", -6);
mach2.setEsDeRecursos(true);
mach2.setTileSetID("Machine_Set");
mach2.setTilePos(4);
System.out.println(json.prettyPrint(text));
/*
---- MachineLoader Tests.
*/
Machine mkLoad = json.fromJson(Machine.class, text);
//mcLoader = new MachineLoader();
mcLoader.AddMachine(testMach);
mcLoader.AddMachine(mach2);
Room testRoom = new Room("testRoom", 8, 5);
testRoom.LoadRoom();
testRoom.AddMachine(5,3, testMach);
testRoom.AddMachine(6,3, mkLoad);
// mcLoader.SaveToJSON("assets/data/testMachines.json");
// mcLoader.LoadFromJSON("data/testMachines.json");
//
// Machine recuperar = mcLoader.GetMachine("base_raspi_mk1");
// System.out.println("Pues eso...");
String textRoom = json.toJson(testRoom);
System.out.println(json.prettyPrint(textRoom));
Room loadedRoom = json.fromJson(Room.class, textRoom);
System.out.println("Pues eso...");
/*
------ RoomLoader Tests
*/
RoomLoader rmLoader = new RoomLoader(mcLoader);
rmLoader.LoadRoomFromJSON("data/testRoom.json");
// Room testRoom = new Room("testRoom", 8, 5);
// testRoom.LoadRoom();
// testRoom.AddMachine(3,2, testMach);
// testRoom.AddMachine(4,2, mach2);
//
// rmLoader.AddRoom(testRoom);
// rmLoader.SaveRoomToJSON("testRoom", "assets/data/testRoom.json");
//
// String textRoom = json.toJson(testRoom);
// System.out.println(json.prettyPrint(textRoom));
//
// Room loadedRoom = json.fromJson(Room.class, textRoom);
//
// System.out.println("Pues eso...");
System.out.println("Prueba completada.");
}