1
0
mirror of https://github.com/Anuken/Mindustry.git synced 2024-09-11 08:15:35 +03:00

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

2
.gitignore vendored
View File

@ -21,7 +21,7 @@
/android/assets/mindustry-saves/
/core/assets/gifexport/
/core/assets/version.properties
/core/assets/locales.json
/core/assets/locales
/ios/src/io/anuke/mindustry/gen/
*.gif

View File

@ -11,6 +11,13 @@ import java.lang.annotation.Target;
*/
public class Annotations{
/** Marks a class as serializable.*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.CLASS)
public @interface Serialize{
}
public enum PacketPriority{
/** Gets put in a queue and processed if not connected. */
normal,

View File

@ -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);
}
}
}

View File

@ -27,7 +27,7 @@ allprojects {
appName = 'Mindustry'
gdxVersion = '1.9.8'
roboVMVersion = '2.3.0'
uCoreVersion = '7aa05daa277ffb67cda3d2d047c37b2f441e4e4e'
uCoreVersion = '7fafee20b6bf5615e009d2be20d1c1331d1e66c1'
getVersionString = {
String buildVersion = getBuildVersion()
@ -44,14 +44,13 @@ allprojects {
}
generateLocales = {
def output = '["en",'
def output = 'en\n'
def bundles = new File(project(':core').projectDir, 'assets/bundles/')
bundles.listFiles().each { other ->
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.json').text = output;
new File(project(':core').projectDir, 'assets/locales').text = output;
}
writeVersion = {
@ -118,9 +117,6 @@ project(":html") {
compile "com.badlogicgames.gdx:gdx-controllers-gwt:$gdxVersion:sources"
}
compileJava.options.compilerArgs = [
"-processor", "io.anuke.annotations.RemoteMethodAnnotationProcessor"
]
}
project(":ios") {
@ -185,7 +181,7 @@ project(":core") {
}
compileJava.options.compilerArgs = [
"-processor", "io.anuke.annotations.RemoteMethodAnnotationProcessor"
"-processor", "io.anuke.annotations.RemoteMethodAnnotationProcessor,io.anuke.annotations.SerializeAnnotationProcessor"
]
}

View File

@ -4,7 +4,6 @@ import com.badlogic.gdx.Application.ApplicationType;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.files.FileHandle;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.utils.Json;
import io.anuke.mindustry.core.*;
import io.anuke.mindustry.entities.Player;
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.game.Team;
import io.anuke.mindustry.game.Version;
import io.anuke.mindustry.gen.Serialization;
import io.anuke.mindustry.net.Net;
import io.anuke.mindustry.world.blocks.defense.ForceProjector.ShieldEntity;
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 void init(){
Serialization.init();
//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];
for(int i = 0; i < locales.length; i++){
String code = stra[i];

View File

@ -51,6 +51,7 @@ public class Control extends Module{
private Throwable error;
public Control(){
saves = new Saves();
db = new ContentDatabase();

View File

@ -68,7 +68,7 @@ public class ContentDatabase{
}
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()){
ObjectSet<String> set = new ObjectSet<>();
@ -87,7 +87,7 @@ public class ContentDatabase{
write.put(entry.key, entry.value.iterator().toArray());
}
Settings.putJson("content-database", write);
Settings.putBinary("content-database", write);
Settings.save();
dirty = false;
}

View File

@ -2,6 +2,7 @@ package io.anuke.mindustry.game;
import com.badlogic.gdx.files.FileHandle;
import com.badlogic.gdx.utils.Array;
import com.badlogic.gdx.utils.IntArray;
import com.badlogic.gdx.utils.IntMap;
import com.badlogic.gdx.utils.TimeUtils;
import io.anuke.mindustry.core.GameState.State;
@ -44,9 +45,10 @@ public class Saves{
public void load(){
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)){
SaveSlot slot = new SaveSlot(index);
saves.add(slot);
@ -138,11 +140,10 @@ public class Saves{
}
private void saveSlots(){
int[] result = new int[saves.size];
for(int i = 0; i < result.length; i++){
result[i] = saves.get(i).index;
}
Settings.putJson("save-slots", result);
IntArray result = new IntArray(saves.size);
for(int i = 0; i < saves.size; i++) result.add(saves.get(i).index);
Settings.putBinary("save-slots", result);
Settings.save();
}

View File

@ -90,7 +90,7 @@ public class Maps implements Disposable{
Settings.putString("map-data-" + name, new String(Base64Coder.encode(stream.toByteArray())));
if(!customMapNames.contains(name, false)){
customMapNames.add(name);
Settings.putJson("custom-maps", customMapNames);
Settings.putBinary("custom-maps", customMapNames);
}
Settings.save();
}
@ -130,7 +130,7 @@ public class Maps implements Disposable{
} else {
customMapNames.removeValue(map.name, false);
Settings.putString("map-data-" + map.name, "");
Settings.putJson("custom-maps", customMapNames);
Settings.putBinary("custom-maps", customMapNames);
Settings.save();
}
}
@ -163,7 +163,7 @@ public class Maps implements Disposable{
}
}else{
customMapNames = Settings.getJson("custom-maps", Array.class);
customMapNames = Settings.getBinary("custom-maps", Array.class, () -> new Array<>());
for(String name : customMapNames){
try{

View File

@ -2,6 +2,7 @@ package io.anuke.mindustry.maps;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.utils.Array;
import io.anuke.annotations.Annotations.Serialize;
import io.anuke.mindustry.game.Difficulty;
import io.anuke.mindustry.game.Saves.SaveSlot;
import io.anuke.mindustry.game.SpawnGroup;
@ -12,6 +13,7 @@ import io.anuke.ucore.util.Bits;
import static io.anuke.mindustry.Vars.control;
@Serialize
public class Sector{
/**Position on the map, can be positive or negative.*/
public short x, y;

View File

@ -29,10 +29,6 @@ public class Sectors{
private GridMap<Sector> grid = new GridMap<>();
public Sectors(){
Settings.json().addClassTag("Sector", Sector.class);
}
public void playSector(Sector sector){
if(sector.hasSave() && SaveIO.breakingVersions.contains(sector.getSave().getBuild())){
sector.getSave().delete();
@ -117,7 +113,7 @@ public class Sectors{
}
grid.clear();
Array<Sector> out = Settings.getJson("sectors", Array.class);
Array<Sector> out = Settings.getBinary("sectors", Array.class, () -> new Array<>());
for(Sector sector : out){
createTexture(sector);
@ -141,7 +137,7 @@ public class Sectors{
out.add(sector);
}
Settings.putJson("sectors", out);
Settings.putBinary("sectors", out);
Settings.save();
}

View File

@ -3,6 +3,7 @@ package io.anuke.mindustry.net;
import com.badlogic.gdx.utils.Array;
import com.badlogic.gdx.utils.IntMap;
import com.badlogic.gdx.utils.ObjectMap;
import io.anuke.annotations.Annotations.Serialize;
import io.anuke.ucore.core.Settings;
import static io.anuke.mindustry.Vars.headless;
@ -276,16 +277,17 @@ public class Administration{
}
public void save(){
Settings.putJson("player-info", playerInfo);
Settings.putJson("banned-ips", bannedIPs);
Settings.putBinary("player-info", playerInfo);
Settings.putBinary("banned-ips", bannedIPs);
Settings.save();
}
private void load(){
playerInfo = Settings.getJson("player-info", ObjectMap.class);
bannedIPs = Settings.getJson("banned-ips", Array.class);
playerInfo = Settings.getBinary("player-info", ObjectMap.class, () -> new ObjectMap<>());
bannedIPs = Settings.getBinary("banned-ips", Array.class, () -> new Array<>());
}
@Serialize
public static class PlayerInfo{
public String id;
public String lastName = "<unknown>", lastIP = "<unknown>";
@ -303,7 +305,7 @@ public class Administration{
this.id = id;
}
private PlayerInfo(){
public PlayerInfo(){
}
}

View File

@ -3,6 +3,7 @@ package io.anuke.mindustry.ui.dialogs;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.math.MathUtils;
import com.badlogic.gdx.utils.Array;
import io.anuke.annotations.Annotations.Serialize;
import io.anuke.mindustry.Vars;
import io.anuke.mindustry.core.Platform;
import io.anuke.mindustry.entities.Player;
@ -326,22 +327,24 @@ public class JoinDialog extends FloatingDialog{
}
private void loadServers(){
servers = Settings.getJson("server-list", Array.class);
servers = Settings.getBinary("server-list", Array.class, () -> new Array<>());
}
private void saveServers(){
Settings.putJson("server-list", servers);
Settings.putBinary("server-list", servers);
Settings.save();
}
static class Server{
String ip;
int port;
@Serialize
public static class Server{
public String ip;
public int port;
transient Host host;
transient Table content;
void setIP(String ip){
//parse ip:port, if unsuccessful, use default values
if(ip.lastIndexOf(':') != -1 && ip.lastIndexOf(':') != ip.length()-1){
try{
@ -362,6 +365,6 @@ public class JoinDialog extends FloatingDialog{
return ip + (port != Vars.port ? ":" + port : "");
}
Server(){}
public Server(){}
}
}