Auto-generated serialization code

This commit is contained in:
Anuken
2018-09-09 16:19:53 -04:00
parent dadc83800b
commit 2cb6e454c8
13 changed files with 160 additions and 41 deletions
+1 -1
View File
@@ -21,7 +21,7 @@
/android/assets/mindustry-saves/ /android/assets/mindustry-saves/
/core/assets/gifexport/ /core/assets/gifexport/
/core/assets/version.properties /core/assets/version.properties
/core/assets/locales.json /core/assets/locales
/ios/src/io/anuke/mindustry/gen/ /ios/src/io/anuke/mindustry/gen/
*.gif *.gif
@@ -11,6 +11,13 @@ import java.lang.annotation.Target;
*/ */
public class Annotations{ public class Annotations{
/** Marks a class as serializable.*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.CLASS)
public @interface Serialize{
}
public enum PacketPriority{ public enum PacketPriority{
/** Gets put in a queue and processed if not connected. */ /** Gets put in a queue and processed if not connected. */
normal, normal,
@@ -0,0 +1,110 @@
package io.anuke.annotations;
import com.squareup.javapoet.*;
import io.anuke.annotations.Annotations.Serialize;
import javax.annotation.processing.*;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.Modifier;
import javax.lang.model.element.TypeElement;
import javax.lang.model.element.VariableElement;
import javax.lang.model.util.ElementFilter;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import java.util.List;
import java.util.Set;
@SupportedSourceVersion(SourceVersion.RELEASE_8)
@SupportedAnnotationTypes({
"io.anuke.annotations.Annotations.Serialize"
})
public class SerializeAnnotationProcessor extends AbstractProcessor{
/**Target class name.*/
private static final String className = "Serialization";
/** Name of the base package to put all the generated classes. */
private static final String packageName = "io.anuke.mindustry.gen";
private int round;
@Override
public synchronized void init(ProcessingEnvironment processingEnv){
super.init(processingEnv);
//put all relevant utils into utils class
Utils.typeUtils = processingEnv.getTypeUtils();
Utils.elementUtils = processingEnv.getElementUtils();
Utils.filer = processingEnv.getFiler();
Utils.messager = processingEnv.getMessager();
}
@Override
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv){
if(round++ != 0) return false; //only process 1 round
try{
Set<TypeElement> elements = ElementFilter.typesIn(roundEnv.getElementsAnnotatedWith(Serialize.class));
TypeSpec.Builder classBuilder = TypeSpec.classBuilder(className).addModifiers(Modifier.PUBLIC);
MethodSpec.Builder method = MethodSpec.methodBuilder("init").addModifiers(Modifier.PUBLIC, Modifier.STATIC);
for(TypeElement elem : elements){
TypeName type = TypeName.get(elem.asType());
TypeSpec.Builder serializer = TypeSpec.anonymousClassBuilder("")
.addSuperinterface(ParameterizedTypeName.get(
ClassName.get(Class.forName("io.anuke.ucore.io.TypeSerializer")), type));
MethodSpec.Builder writeMethod = MethodSpec.methodBuilder("write")
.returns(void.class)
.addParameter(DataOutput.class, "stream")
.addParameter(type, "object")
.addAnnotation(Override.class)
.addException(IOException.class)
.addModifiers(Modifier.PUBLIC);
MethodSpec.Builder readMethod = MethodSpec.methodBuilder("read")
.returns(type)
.addParameter(DataInput.class, "stream")
.addAnnotation(Override.class)
.addException(IOException.class)
.addModifiers(Modifier.PUBLIC);
readMethod.addStatement("$L object = new $L()", type, type);
List<VariableElement> fields = ElementFilter.fieldsIn(Utils.elementUtils.getAllMembers(elem));
for(VariableElement field : fields){
if(field.getModifiers().contains(Modifier.STATIC) || field.getModifiers().contains(Modifier.TRANSIENT) || field.getModifiers().contains(Modifier.PRIVATE)) continue;
String name = field.getSimpleName().toString();
String typeName = Utils.typeUtils.erasure(field.asType()).toString().replace('$', '.');
String capName = Character.toUpperCase(typeName.charAt(0)) + typeName.substring(1);
if(field.asType().getKind().isPrimitive()){
writeMethod.addStatement("stream.write" + capName + "(object." + name + ")");
readMethod.addStatement("object." + name + "= stream.read" + capName + "()");
}else{
writeMethod.addStatement("io.anuke.ucore.core.Settings.getSerializer(" + typeName+ ".class).write(stream, object." + name + ")");
readMethod.addStatement("object." + name + " = (" +typeName+")io.anuke.ucore.core.Settings.getSerializer(" + typeName+ ".class).read(stream)");
}
}
readMethod.addStatement("return object");
serializer.addMethod(writeMethod.build());
serializer.addMethod(readMethod.build());
method.addStatement("io.anuke.ucore.core.Settings.setSerializer($N, $L)", Utils.elementUtils.getBinaryName(elem).toString().replace('$', '.') + ".class", serializer.build());
}
classBuilder.addMethod(method.build());
//write result
JavaFile.builder(packageName, classBuilder.build()).build().writeTo(Utils.filer);
return true;
}catch(Exception e){
e.printStackTrace();
throw new RuntimeException(e);
}
}
}
+5 -9
View File
@@ -27,7 +27,7 @@ allprojects {
appName = 'Mindustry' appName = 'Mindustry'
gdxVersion = '1.9.8' gdxVersion = '1.9.8'
roboVMVersion = '2.3.0' roboVMVersion = '2.3.0'
uCoreVersion = '7aa05daa277ffb67cda3d2d047c37b2f441e4e4e' uCoreVersion = '7fafee20b6bf5615e009d2be20d1c1331d1e66c1'
getVersionString = { getVersionString = {
String buildVersion = getBuildVersion() String buildVersion = getBuildVersion()
@@ -44,14 +44,13 @@ allprojects {
} }
generateLocales = { generateLocales = {
def output = '["en",' def output = 'en\n'
def bundles = new File(project(':core').projectDir, 'assets/bundles/') def bundles = new File(project(':core').projectDir, 'assets/bundles/')
bundles.listFiles().each { other -> bundles.listFiles().each { other ->
if(other.name == "bundle.properties") return; if(other.name == "bundle.properties") return;
output += '"' + other.name.substring("bundle".length() + 1, other.name.lastIndexOf('.')) + '",' output += other.name.substring("bundle".length() + 1, other.name.lastIndexOf('.')) + "\n"
} }
output = (output.substring(0, output.size() - 1) + "]") new File(project(':core').projectDir, 'assets/locales').text = output;
new File(project(':core').projectDir, 'assets/locales.json').text = output;
} }
writeVersion = { writeVersion = {
@@ -118,9 +117,6 @@ project(":html") {
compile "com.badlogicgames.gdx:gdx-controllers-gwt:$gdxVersion:sources" compile "com.badlogicgames.gdx:gdx-controllers-gwt:$gdxVersion:sources"
} }
compileJava.options.compilerArgs = [
"-processor", "io.anuke.annotations.RemoteMethodAnnotationProcessor"
]
} }
project(":ios") { project(":ios") {
@@ -185,7 +181,7 @@ project(":core") {
} }
compileJava.options.compilerArgs = [ compileJava.options.compilerArgs = [
"-processor", "io.anuke.annotations.RemoteMethodAnnotationProcessor" "-processor", "io.anuke.annotations.RemoteMethodAnnotationProcessor,io.anuke.annotations.SerializeAnnotationProcessor"
] ]
} }
+3 -2
View File
@@ -4,7 +4,6 @@ import com.badlogic.gdx.Application.ApplicationType;
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.graphics.Color; import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.utils.Json;
import io.anuke.mindustry.core.*; import io.anuke.mindustry.core.*;
import io.anuke.mindustry.entities.Player; import io.anuke.mindustry.entities.Player;
import io.anuke.mindustry.entities.TileEntity; import io.anuke.mindustry.entities.TileEntity;
@@ -16,6 +15,7 @@ import io.anuke.mindustry.entities.traits.SyncTrait;
import io.anuke.mindustry.entities.units.BaseUnit; import io.anuke.mindustry.entities.units.BaseUnit;
import io.anuke.mindustry.game.Team; import io.anuke.mindustry.game.Team;
import io.anuke.mindustry.game.Version; import io.anuke.mindustry.game.Version;
import io.anuke.mindustry.gen.Serialization;
import io.anuke.mindustry.net.Net; import io.anuke.mindustry.net.Net;
import io.anuke.mindustry.world.blocks.defense.ForceProjector.ShieldEntity; import io.anuke.mindustry.world.blocks.defense.ForceProjector.ShieldEntity;
import io.anuke.ucore.entities.Entities; import io.anuke.ucore.entities.Entities;
@@ -138,9 +138,10 @@ public class Vars{
public static final Translator[] tmptr = new Translator[]{new Translator(), new Translator(), new Translator(), new Translator()}; public static final Translator[] tmptr = new Translator[]{new Translator(), new Translator(), new Translator(), new Translator()};
public static void init(){ public static void init(){
Serialization.init();
//load locales //load locales
String[] stra = new Json().fromJson(String[].class, Gdx.files.internal("locales.json")); String[] stra = Gdx.files.internal("locales").readString().split("\n");
locales = new Locale[stra.length]; locales = new Locale[stra.length];
for(int i = 0; i < locales.length; i++){ for(int i = 0; i < locales.length; i++){
String code = stra[i]; String code = stra[i];
@@ -51,6 +51,7 @@ public class Control extends Module{
private Throwable error; private Throwable error;
public Control(){ public Control(){
saves = new Saves(); saves = new Saves();
db = new ContentDatabase(); db = new ContentDatabase();
@@ -68,7 +68,7 @@ public class ContentDatabase{
} }
public void load(){ public void load(){
ObjectMap<ContentType, Array<String>> result = Settings.getJson("content-database", ObjectMap.class); ObjectMap<ContentType, Array<String>> result = Settings.getBinary("content-database", ObjectMap.class, () -> new ObjectMap<>());
for(Entry<ContentType, Array<String>> entry : result.entries()){ for(Entry<ContentType, Array<String>> entry : result.entries()){
ObjectSet<String> set = new ObjectSet<>(); ObjectSet<String> set = new ObjectSet<>();
@@ -87,7 +87,7 @@ public class ContentDatabase{
write.put(entry.key, entry.value.iterator().toArray()); write.put(entry.key, entry.value.iterator().toArray());
} }
Settings.putJson("content-database", write); Settings.putBinary("content-database", write);
Settings.save(); Settings.save();
dirty = false; dirty = false;
} }
+8 -7
View File
@@ -2,6 +2,7 @@ package io.anuke.mindustry.game;
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.IntArray;
import com.badlogic.gdx.utils.IntMap; import com.badlogic.gdx.utils.IntMap;
import com.badlogic.gdx.utils.TimeUtils; import com.badlogic.gdx.utils.TimeUtils;
import io.anuke.mindustry.core.GameState.State; import io.anuke.mindustry.core.GameState.State;
@@ -44,9 +45,10 @@ public class Saves{
public void load(){ public void load(){
saves.clear(); saves.clear();
int[] slots = Settings.getJson("save-slots", int[].class); IntArray slots = Settings.getBinary("save-slots", IntArray.class, IntArray::new);
for(int index : slots){ for(int i = 0; i < slots.size; i ++){
int index = slots.get(i);
if(SaveIO.isSaveValid(index)){ if(SaveIO.isSaveValid(index)){
SaveSlot slot = new SaveSlot(index); SaveSlot slot = new SaveSlot(index);
saves.add(slot); saves.add(slot);
@@ -138,11 +140,10 @@ public class Saves{
} }
private void saveSlots(){ private void saveSlots(){
int[] result = new int[saves.size]; IntArray result = new IntArray(saves.size);
for(int i = 0; i < result.length; i++){ for(int i = 0; i < saves.size; i++) result.add(saves.get(i).index);
result[i] = saves.get(i).index;
} Settings.putBinary("save-slots", result);
Settings.putJson("save-slots", result);
Settings.save(); Settings.save();
} }
+3 -3
View File
@@ -90,7 +90,7 @@ public class Maps implements Disposable{
Settings.putString("map-data-" + name, new String(Base64Coder.encode(stream.toByteArray()))); Settings.putString("map-data-" + name, new String(Base64Coder.encode(stream.toByteArray())));
if(!customMapNames.contains(name, false)){ if(!customMapNames.contains(name, false)){
customMapNames.add(name); customMapNames.add(name);
Settings.putJson("custom-maps", customMapNames); Settings.putBinary("custom-maps", customMapNames);
} }
Settings.save(); Settings.save();
} }
@@ -130,7 +130,7 @@ public class Maps implements Disposable{
} else { } else {
customMapNames.removeValue(map.name, false); customMapNames.removeValue(map.name, false);
Settings.putString("map-data-" + map.name, ""); Settings.putString("map-data-" + map.name, "");
Settings.putJson("custom-maps", customMapNames); Settings.putBinary("custom-maps", customMapNames);
Settings.save(); Settings.save();
} }
} }
@@ -163,7 +163,7 @@ public class Maps implements Disposable{
} }
}else{ }else{
customMapNames = Settings.getJson("custom-maps", Array.class); customMapNames = Settings.getBinary("custom-maps", Array.class, () -> new Array<>());
for(String name : customMapNames){ for(String name : customMapNames){
try{ try{
@@ -2,6 +2,7 @@ package io.anuke.mindustry.maps;
import com.badlogic.gdx.graphics.Texture; import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.utils.Array; import com.badlogic.gdx.utils.Array;
import io.anuke.annotations.Annotations.Serialize;
import io.anuke.mindustry.game.Difficulty; import io.anuke.mindustry.game.Difficulty;
import io.anuke.mindustry.game.Saves.SaveSlot; import io.anuke.mindustry.game.Saves.SaveSlot;
import io.anuke.mindustry.game.SpawnGroup; import io.anuke.mindustry.game.SpawnGroup;
@@ -12,6 +13,7 @@ import io.anuke.ucore.util.Bits;
import static io.anuke.mindustry.Vars.control; import static io.anuke.mindustry.Vars.control;
@Serialize
public class Sector{ public class Sector{
/**Position on the map, can be positive or negative.*/ /**Position on the map, can be positive or negative.*/
public short x, y; public short x, y;
@@ -29,10 +29,6 @@ public class Sectors{
private GridMap<Sector> grid = new GridMap<>(); private GridMap<Sector> grid = new GridMap<>();
public Sectors(){
Settings.json().addClassTag("Sector", Sector.class);
}
public void playSector(Sector sector){ public void playSector(Sector sector){
if(sector.hasSave() && SaveIO.breakingVersions.contains(sector.getSave().getBuild())){ if(sector.hasSave() && SaveIO.breakingVersions.contains(sector.getSave().getBuild())){
sector.getSave().delete(); sector.getSave().delete();
@@ -117,7 +113,7 @@ public class Sectors{
} }
grid.clear(); grid.clear();
Array<Sector> out = Settings.getJson("sectors", Array.class); Array<Sector> out = Settings.getBinary("sectors", Array.class, () -> new Array<>());
for(Sector sector : out){ for(Sector sector : out){
createTexture(sector); createTexture(sector);
@@ -141,7 +137,7 @@ public class Sectors{
out.add(sector); out.add(sector);
} }
Settings.putJson("sectors", out); Settings.putBinary("sectors", out);
Settings.save(); Settings.save();
} }
@@ -3,6 +3,7 @@ package io.anuke.mindustry.net;
import com.badlogic.gdx.utils.Array; import com.badlogic.gdx.utils.Array;
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 io.anuke.annotations.Annotations.Serialize;
import io.anuke.ucore.core.Settings; import io.anuke.ucore.core.Settings;
import static io.anuke.mindustry.Vars.headless; import static io.anuke.mindustry.Vars.headless;
@@ -276,16 +277,17 @@ public class Administration{
} }
public void save(){ public void save(){
Settings.putJson("player-info", playerInfo); Settings.putBinary("player-info", playerInfo);
Settings.putJson("banned-ips", bannedIPs); Settings.putBinary("banned-ips", bannedIPs);
Settings.save(); Settings.save();
} }
private void load(){ private void load(){
playerInfo = Settings.getJson("player-info", ObjectMap.class); playerInfo = Settings.getBinary("player-info", ObjectMap.class, () -> new ObjectMap<>());
bannedIPs = Settings.getJson("banned-ips", Array.class); bannedIPs = Settings.getBinary("banned-ips", Array.class, () -> new Array<>());
} }
@Serialize
public static class PlayerInfo{ public static class PlayerInfo{
public String id; public String id;
public String lastName = "<unknown>", lastIP = "<unknown>"; public String lastName = "<unknown>", lastIP = "<unknown>";
@@ -303,7 +305,7 @@ public class Administration{
this.id = id; this.id = id;
} }
private PlayerInfo(){ public PlayerInfo(){
} }
} }
@@ -3,6 +3,7 @@ package io.anuke.mindustry.ui.dialogs;
import com.badlogic.gdx.graphics.Color; import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.math.MathUtils; import com.badlogic.gdx.math.MathUtils;
import com.badlogic.gdx.utils.Array; import com.badlogic.gdx.utils.Array;
import io.anuke.annotations.Annotations.Serialize;
import io.anuke.mindustry.Vars; import io.anuke.mindustry.Vars;
import io.anuke.mindustry.core.Platform; import io.anuke.mindustry.core.Platform;
import io.anuke.mindustry.entities.Player; import io.anuke.mindustry.entities.Player;
@@ -326,22 +327,24 @@ public class JoinDialog extends FloatingDialog{
} }
private void loadServers(){ private void loadServers(){
servers = Settings.getJson("server-list", Array.class); servers = Settings.getBinary("server-list", Array.class, () -> new Array<>());
} }
private void saveServers(){ private void saveServers(){
Settings.putJson("server-list", servers); Settings.putBinary("server-list", servers);
Settings.save(); Settings.save();
} }
static class Server{ @Serialize
String ip; public static class Server{
int port; public String ip;
public int port;
transient Host host; transient Host host;
transient Table content; transient Table content;
void setIP(String ip){ void setIP(String ip){
//parse ip:port, if unsuccessful, use default values //parse ip:port, if unsuccessful, use default values
if(ip.lastIndexOf(':') != -1 && ip.lastIndexOf(':') != ip.length()-1){ if(ip.lastIndexOf(':') != -1 && ip.lastIndexOf(':') != ip.length()-1){
try{ try{
@@ -362,6 +365,6 @@ public class JoinDialog extends FloatingDialog{
return ip + (port != Vars.port ? ":" + port : ""); return ip + (port != Vars.port ? ":" + port : "");
} }
Server(){} public Server(){}
} }
} }