Merge branch 'master' of https://github.com/Anuken/Mindustry into v105

This commit is contained in:
Petr Gašparík
2020-07-13 10:42:30 +02:00
485 changed files with 11639 additions and 9071 deletions

View File

@@ -18,7 +18,7 @@ See [CONTRIBUTING](CONTRIBUTING.md).
Bleeding-edge live builds are generated automatically for every commit. You can see them [here](https://github.com/Anuken/MindustryBuilds/releases). Old builds might still be on [jenkins](https://jenkins.hellomouse.net/job/mindustry/). Bleeding-edge live builds are generated automatically for every commit. You can see them [here](https://github.com/Anuken/MindustryBuilds/releases). Old builds might still be on [jenkins](https://jenkins.hellomouse.net/job/mindustry/).
If you'd rather compile on your own, follow these instructions. If you'd rather compile on your own, follow these instructions.
First, make sure you have [JDK 8](https://adoptopenjdk.net/) installed. Open a terminal in the root directory, `cd` to the Mindustry folder and run the following commands: First, make sure you have [JDK 14](https://adoptopenjdk.net/) installed. Open a terminal in the root directory, `cd` to the Mindustry folder and run the following commands:
#### Windows #### Windows

View File

@@ -1,29 +0,0 @@
# To enable ProGuard in your project, edit project.properties
# to define the proguard.config property as described in that file.
#
# Add project specific ProGuard rules here.
# By default, the flags in this file are appended to flags specified
# in ${sdk.dir}/tools/proguard/proguard-android.txt
# You can edit the include path and order by changing the ProGuard
# include property in project.properties.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# Add any project specific keep options here:
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
-verbose
-verbose
-ignorewarnings
-keep class mindustry.game.Rules
-keep class mindustry.desktop.DesktopLauncher
-keepclasseswithmembers public class * {
public static void main(java.lang.String[]);
}

View File

@@ -1,13 +0,0 @@
# This file is automatically generated by Android Tools.
# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
#
# This file must be checked in Version Control Systems.
#
# To customize properties used by the Ant build system edit
# "ant.properties", and override values to adapt the script to your
# project structure.
#
# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
# Project target.
target=android-19

View File

@@ -27,7 +27,7 @@ public class Annotations{
boolean clamped() default false; boolean clamped() default false;
} }
/** Indicates that a field will not be read from the server when syncing. */ /** Indicates that a field will not be read from the server when syncing the local player state. */
@Target({ElementType.FIELD}) @Target({ElementType.FIELD})
@Retention(RetentionPolicy.SOURCE) @Retention(RetentionPolicy.SOURCE)
public @interface SyncLocal{ public @interface SyncLocal{
@@ -50,6 +50,9 @@ public class Annotations{
@Target(ElementType.TYPE) @Target(ElementType.TYPE)
@Retention(RetentionPolicy.SOURCE) @Retention(RetentionPolicy.SOURCE)
public @interface Component{ public @interface Component{
/** Whether to generate a base class for this components.
* An entity cannot have two base classes, so only one component can have base be true. */
boolean base() default false;
} }
/** Indicates that a method is implemented by the annotation processor. */ /** Indicates that a method is implemented by the annotation processor. */

View File

@@ -2,9 +2,9 @@ package mindustry.annotations;
import arc.files.*; import arc.files.*;
import arc.struct.*; import arc.struct.*;
import arc.util.*;
import arc.util.Log; import arc.util.Log;
import arc.util.Log.*; import arc.util.Log.*;
import arc.util.*;
import com.squareup.javapoet.*; import com.squareup.javapoet.*;
import com.sun.source.util.*; import com.sun.source.util.*;
import com.sun.tools.javac.model.*; import com.sun.tools.javac.model.*;
@@ -22,9 +22,8 @@ import javax.tools.Diagnostic.*;
import javax.tools.*; import javax.tools.*;
import java.io.*; import java.io.*;
import java.lang.annotation.*; import java.lang.annotation.*;
import java.lang.reflect.*;
import java.util.*;
import java.util.List; import java.util.List;
import java.util.*;
@SupportedSourceVersion(SourceVersion.RELEASE_8) @SupportedSourceVersion(SourceVersion.RELEASE_8)
public abstract class BaseProcessor extends AbstractProcessor{ public abstract class BaseProcessor extends AbstractProcessor{
@@ -100,10 +99,16 @@ public abstract class BaseProcessor extends AbstractProcessor{
return str.contains(".") ? str.substring(str.lastIndexOf('.') + 1) : str; return str.contains(".") ? str.substring(str.lastIndexOf('.') + 1) : str;
} }
public static TypeName tname(String name) throws Exception{ public static TypeName tname(String pack, String simple){
Constructor<TypeName> cons = TypeName.class.getDeclaredConstructor(String.class); return ClassName.get(pack, simple );
cons.setAccessible(true); }
return cons.newInstance(name);
public static TypeName tname(String name){
if(!name.contains(".")) return ClassName.get(packageName, name);
String pack = name.substring(0, name.lastIndexOf("."));
String simple = name.substring(name.lastIndexOf(".") + 1);
return ClassName.get(pack, simple);
} }
public static TypeName tname(Class<?> c){ public static TypeName tname(Class<?> c){

View File

@@ -32,7 +32,7 @@ public class EntityIO{
MethodSpec.Builder method; MethodSpec.Builder method;
ObjectSet<String> presentFields = new ObjectSet<>(); ObjectSet<String> presentFields = new ObjectSet<>();
EntityIO(String name, TypeSpec.Builder type, ClassSerializer serializer, Fi directory){ EntityIO(String name, TypeSpec.Builder type, Seq<FieldSpec> typeFields, ClassSerializer serializer, Fi directory){
this.directory = directory; this.directory = directory;
this.type = type; this.type = type;
this.serializer = serializer; this.serializer = serializer;
@@ -49,7 +49,7 @@ public class EntityIO{
int nextRevision = revisions.isEmpty() ? 0 : revisions.max(r -> r.version).version + 1; int nextRevision = revisions.isEmpty() ? 0 : revisions.max(r -> r.version).version + 1;
//resolve preferred field order based on fields that fit //resolve preferred field order based on fields that fit
Seq<FieldSpec> fields = Seq.with(type.fieldSpecs).select(spec -> Seq<FieldSpec> fields = typeFields.select(spec ->
!spec.hasModifier(Modifier.TRANSIENT) && !spec.hasModifier(Modifier.TRANSIENT) &&
!spec.hasModifier(Modifier.STATIC) && !spec.hasModifier(Modifier.STATIC) &&
!spec.hasModifier(Modifier.FINAL)/* && !spec.hasModifier(Modifier.FINAL)/* &&
@@ -142,7 +142,13 @@ public class EntityIO{
io(field.type, "this." + (sf ? field.name + targetSuf : field.name) + " = "); io(field.type, "this." + (sf ? field.name + targetSuf : field.name) + " = ");
if(sl) econt(); if(sl){
ncont("else" );
io(field.type, "");
econt();
}
} }
st("afterSync()"); st("afterSync()");
@@ -187,7 +193,7 @@ public class EntityIO{
st("$L = $L($T.$L($L, $L, alpha))", name, field.annotation(SyncField.class).clamped() ? "arc.math.Mathf.clamp" : "", Mathf.class, field.annotation(SyncField.class).value() ? "lerp" : "slerp", lastName, targetName); st("$L = $L($T.$L($L, $L, alpha))", name, field.annotation(SyncField.class).clamped() ? "arc.math.Mathf.clamp" : "", Mathf.class, field.annotation(SyncField.class).value() ? "lerp" : "slerp", lastName, targetName);
} }
ncont("else"); //no meaningful data has arrived yet ncont("else if(lastUpdated != 0)"); //check if no meaningful data has arrived yet
//write values directly to targets //write values directly to targets
for(Svar field : fields){ for(Svar field : fields){

View File

@@ -38,10 +38,12 @@ public class EntityProcess extends BaseProcessor{
ObjectMap<Selement, Seq<Stype>> defComponents = new ObjectMap<>(); ObjectMap<Selement, Seq<Stype>> defComponents = new ObjectMap<>();
ObjectMap<String, String> varInitializers = new ObjectMap<>(); ObjectMap<String, String> varInitializers = new ObjectMap<>();
ObjectMap<String, String> methodBlocks = new ObjectMap<>(); ObjectMap<String, String> methodBlocks = new ObjectMap<>();
ObjectMap<Stype, ObjectSet<Stype>> baseClassDeps = new ObjectMap<>();
ObjectSet<String> imports = new ObjectSet<>(); ObjectSet<String> imports = new ObjectSet<>();
Seq<Selement> allGroups = new Seq<>(); Seq<Selement> allGroups = new Seq<>();
Seq<Selement> allDefs = new Seq<>(); Seq<Selement> allDefs = new Seq<>();
Seq<Stype> allInterfaces = new Seq<>(); Seq<Stype> allInterfaces = new Seq<>();
Seq<TypeSpec.Builder> baseClasses = new Seq<>();
ClassSerializer serializer; ClassSerializer serializer;
{ {
@@ -151,12 +153,53 @@ public class EntityProcess extends BaseProcessor{
write(inter); write(inter);
//generate base class if necessary
//SPECIAL CASE: components with EntityDefs don't get a base class! the generated class becomes the base class itself
if(component.annotation(Component.class).base()){
Seq<Stype> deps = depends.copy().and(component);
baseClassDeps.get(component, ObjectSet::new).addAll(deps);
//do not generate base classes when the component will generate one itself
if(!component.has(EntityDef.class)){
TypeSpec.Builder base = TypeSpec.classBuilder(baseName(component)).addModifiers(Modifier.PUBLIC, Modifier.ABSTRACT);
//go through all the fields.
for(Stype type : deps){
//add public fields
for(Svar field : type.fields().select(e -> !e.is(Modifier.STATIC) && !e.is(Modifier.PRIVATE) && !e.has(Import.class) && !e.has(ReadOnly.class))){
FieldSpec.Builder builder = FieldSpec.builder(field.tname(),field.name(), Modifier.PUBLIC);
//keep transience
if(field.is(Modifier.TRANSIENT)) builder.addModifiers(Modifier.TRANSIENT);
//keep all annotations
builder.addAnnotations(field.annotations().map(AnnotationSpec::get));
//add initializer if it exists
if(varInitializers.containsKey(field.descString())){
builder.initializer(varInitializers.get(field.descString()));
}
base.addField(builder.build());
}
}
//add interfaces
for(Stype type : deps){
base.addSuperinterface(tname(packageName, interfaceName(type)));
}
//add to queue to be written later
baseClasses.add(base);
}
}
//LOGGING //LOGGING
Log.debug("&gGenerating interface for " + component.name()); Log.debug("&gGenerating interface for " + component.name());
for(TypeName tn : inter.superinterfaces){ for(TypeName tn : inter.superinterfaces){
Log.debug("&g> &lbextends @", simpleName(tn.toString())); Log.debug("&g> &lbimplements @", simpleName(tn.toString()));
} }
//log methods generated //log methods generated
@@ -173,10 +216,19 @@ public class EntityProcess extends BaseProcessor{
//this needs to be done before the entity interfaces are generated, as the entity classes need to know which groups to add themselves to //this needs to be done before the entity interfaces are generated, as the entity classes need to know which groups to add themselves to
for(Selement<?> group : allGroups){ for(Selement<?> group : allGroups){
GroupDef an = group.annotation(GroupDef.class); GroupDef an = group.annotation(GroupDef.class);
Seq<Stype> types = types(an, GroupDef::value).map(this::interfaceToComp); Seq<Stype> types = types(an, GroupDef::value).map(stype -> {
Stype result = interfaceToComp(stype);
if(result == null) throw new IllegalArgumentException("Interface " + stype + " does not have an associated component!");
return result;
});
//representative component type
Stype repr = types.first();
String groupType = repr.annotation(Component.class).base() ? baseName(repr) : interfaceName(repr);
boolean collides = an.collide(); boolean collides = an.collide();
groupDefs.add(new GroupDefinition(group.name().startsWith("g") ? group.name().substring(1) : group.name(), groupDefs.add(new GroupDefinition(group.name().startsWith("g") ? group.name().substring(1) : group.name(),
ClassName.bestGuess(packageName + "." + interfaceName(types.first())), types, an.spatial(), an.mapping(), collides)); ClassName.bestGuess(packageName + "." + groupType), types, an.spatial(), an.mapping(), collides));
} }
ObjectMap<String, Selement> usedNames = new ObjectMap<>(); ObjectMap<String, Selement> usedNames = new ObjectMap<>();
@@ -184,18 +236,41 @@ public class EntityProcess extends BaseProcessor{
//look at each definition //look at each definition
for(Selement<?> type : allDefs){ for(Selement<?> type : allDefs){
EntityDef ann = type.annotation(EntityDef.class); EntityDef ann = type.annotation(EntityDef.class);
boolean isFinal = ann.isFinal(); boolean isFinal = ann.isFinal();
//all component classes (not interfaces)
Seq<Stype> components = allComponents(type);
Seq<GroupDefinition> groups = groupDefs.select(g -> (!g.components.isEmpty() && !g.components.contains(s -> !components.contains(s))) || g.manualInclusions.contains(type));
ObjectMap<String, Seq<Smethod>> methods = new ObjectMap<>();
ObjectMap<FieldSpec, Svar> specVariables = new ObjectMap<>();
ObjectSet<String> usedFields = new ObjectSet<>();
//make sure there's less than 2 base classes
Seq<Stype> baseClasses = components.select(s -> s.annotation(Component.class).base());
if(baseClasses.size > 2){
err("No entity may have more than 2 base classes. Base classes: " + baseClasses, type);
}
//get base class type name for extension
Stype baseClassType = baseClasses.any() ? baseClasses.first() : null;
@Nullable TypeName baseClass = baseClasses.any() ? tname(packageName + "." + baseName(baseClassType)) : null;
//whether the main class is the base itself
boolean typeIsBase = baseClassType != null && type.has(Component.class) && type.annotation(Component.class).base();
if(type.isType() && (!type.name().endsWith("Def") && !type.name().endsWith("Comp"))){ if(type.isType() && (!type.name().endsWith("Def") && !type.name().endsWith("Comp"))){
err("All entity def names must end with 'Def'/'Comp'", type.e); err("All entity def names must end with 'Def'/'Comp'", type.e);
} }
String name = type.isType() ? String name = type.isType() ?
type.name().replace("Def", "Entity").replace("Comp", "Entity") : type.name().replace("Def", "").replace("Comp", "") :
createName(type); createName(type);
//check for type name conflicts
if(!typeIsBase && baseClass != null && name.equals(baseName(baseClassType))){
name += "Entity";
}
//skip double classes //skip double classes
if(usedNames.containsKey(name)){ if(usedNames.containsKey(name)){
extraNames.get(usedNames.get(name), ObjectSet::new).add(type.name()); extraNames.get(usedNames.get(name), ObjectSet::new).add(type.name());
@@ -209,31 +284,29 @@ public class EntityProcess extends BaseProcessor{
} }
TypeSpec.Builder builder = TypeSpec.classBuilder(name).addModifiers(Modifier.PUBLIC); TypeSpec.Builder builder = TypeSpec.classBuilder(name).addModifiers(Modifier.PUBLIC);
if(isFinal) builder.addModifiers(Modifier.FINAL);
Seq<Stype> components = allComponents(type); if(isFinal && !typeIsBase) builder.addModifiers(Modifier.FINAL);
Seq<GroupDefinition> groups = groupDefs.select(g -> (!g.components.isEmpty() && !g.components.contains(s -> !components.contains(s))) || g.manualInclusions.contains(type));
ObjectMap<String, Seq<Smethod>> methods = new ObjectMap<>();
ObjectMap<FieldSpec, Svar> specVariables = new ObjectMap<>();
ObjectSet<String> usedFields = new ObjectSet<>();
//add serialize() boolean //add serialize() boolean
builder.addMethod(MethodSpec.methodBuilder("serialize").addModifiers(Modifier.PUBLIC, Modifier.FINAL).returns(boolean.class).addStatement("return " + ann.serialize()).build()); builder.addMethod(MethodSpec.methodBuilder("serialize").addModifiers(Modifier.PUBLIC).returns(boolean.class).addStatement("return " + ann.serialize()).build());
//all SyncField fields //all SyncField fields
Seq<Svar> syncedFields = new Seq<>(); Seq<Svar> syncedFields = new Seq<>();
Seq<Svar> allFields = new Seq<>(); Seq<Svar> allFields = new Seq<>();
Seq<FieldSpec> allFieldSpecs = new Seq<>();
boolean isSync = components.contains(s -> s.name().contains("Sync")); boolean isSync = components.contains(s -> s.name().contains("Sync"));
//add all components //add all components
for(Stype comp : components){ for(Stype comp : components){
//whether this component's fields are defined in the base class
boolean isShadowed = baseClass != null && !typeIsBase && baseClassDeps.get(baseClassType).contains(comp);
//write fields to the class; ignoring transient/imported ones //write fields to the class; ignoring transient/imported ones
Seq<Svar> fields = comp.fields().select(f -> !f.has(Import.class)); Seq<Svar> fields = comp.fields().select(f -> !f.has(Import.class));
for(Svar f : fields){ for(Svar f : fields){
if(!usedFields.add(f.name())){ if(!usedFields.add(f.name())){
err("Field '" + f.name() + "' of component '" + comp.name() + "' re-defines a field in entity '" + type.name() + "'"); err("Field '" + f.name() + "' of component '" + comp.name() + "' redefines a field in entity '" + type.name() + "'");
continue; continue;
} }
@@ -255,9 +328,19 @@ public class EntityProcess extends BaseProcessor{
fbuilder.addModifiers(f.has(ReadOnly.class) ? Modifier.PROTECTED : Modifier.PUBLIC); fbuilder.addModifiers(f.has(ReadOnly.class) ? Modifier.PROTECTED : Modifier.PUBLIC);
fbuilder.addAnnotations(f.annotations().map(AnnotationSpec::get)); fbuilder.addAnnotations(f.annotations().map(AnnotationSpec::get));
builder.addField(fbuilder.build()); FieldSpec spec = fbuilder.build();
specVariables.put(builder.fieldSpecs.get(builder.fieldSpecs.size() - 1), f);
//whether this field would be added to the superclass
boolean isVisible = !f.is(Modifier.STATIC) && !f.is(Modifier.PRIVATE) && !f.has(ReadOnly.class);
//add the field only if it isn't visible or it wasn't implemented by the base class
if(!isShadowed || !isVisible){
builder.addField(spec);
}
specVariables.put(spec, f);
allFieldSpecs.add(spec);
allFields.add(f); allFields.add(f);
//add extra sync fields //add extra sync fields
@@ -294,7 +377,7 @@ public class EntityProcess extends BaseProcessor{
.addModifiers(Modifier.PUBLIC) .addModifiers(Modifier.PUBLIC)
.addStatement("return $S + $L", name + "#", "id").build()); .addStatement("return $S + $L", name + "#", "id").build());
EntityIO io = new EntityIO(type.name(), builder, serializer, rootDirectory.child("annotations/src/main/resources/revisions").child(name)); EntityIO io = new EntityIO(type.name(), builder, allFieldSpecs, serializer, rootDirectory.child("annotations/src/main/resources/revisions").child(name));
//entities with no sync comp and no serialization gen no code //entities with no sync comp and no serialization gen no code
boolean hasIO = ann.genio() && (components.contains(s -> s.name().contains("Sync")) || ann.serialize()); boolean hasIO = ann.genio() && (components.contains(s -> s.name().contains("Sync")) || ann.serialize());
@@ -327,7 +410,7 @@ public class EntityProcess extends BaseProcessor{
//build method using same params/returns //build method using same params/returns
MethodSpec.Builder mbuilder = MethodSpec.methodBuilder(first.name()).addModifiers(first.is(Modifier.PRIVATE) ? Modifier.PRIVATE : Modifier.PUBLIC); MethodSpec.Builder mbuilder = MethodSpec.methodBuilder(first.name()).addModifiers(first.is(Modifier.PRIVATE) ? Modifier.PRIVATE : Modifier.PUBLIC);
if(isFinal || entry.value.contains(s -> s.has(Final.class))) mbuilder.addModifiers(Modifier.FINAL); //if(isFinal || entry.value.contains(s -> s.has(Final.class))) mbuilder.addModifiers(Modifier.FINAL);
if(entry.value.contains(s -> s.has(CallSuper.class))) mbuilder.addAnnotation(CallSuper.class); //add callSuper here if necessary if(entry.value.contains(s -> s.has(CallSuper.class))) mbuilder.addAnnotation(CallSuper.class); //add callSuper here if necessary
if(first.is(Modifier.STATIC)) mbuilder.addModifiers(Modifier.STATIC); if(first.is(Modifier.STATIC)) mbuilder.addModifiers(Modifier.STATIC);
mbuilder.addTypeVariables(first.typeVariables().map(TypeVariableName::get)); mbuilder.addTypeVariables(first.typeVariables().map(TypeVariableName::get));
@@ -435,7 +518,7 @@ public class EntityProcess extends BaseProcessor{
builder.addSuperinterface(Poolable.class); builder.addSuperinterface(Poolable.class);
//implement reset() //implement reset()
MethodSpec.Builder resetBuilder = MethodSpec.methodBuilder("reset").addModifiers(Modifier.PUBLIC); MethodSpec.Builder resetBuilder = MethodSpec.methodBuilder("reset").addModifiers(Modifier.PUBLIC);
for(FieldSpec spec : builder.fieldSpecs){ for(FieldSpec spec : allFieldSpecs){
@Nullable Svar variable = specVariables.get(spec); @Nullable Svar variable = specVariables.get(spec);
if(variable != null && variable.isAny(Modifier.STATIC, Modifier.FINAL)) continue; if(variable != null && variable.isAny(Modifier.STATIC, Modifier.FINAL)) continue;
String desc = variable.descString(); String desc = variable.descString();
@@ -462,7 +545,7 @@ public class EntityProcess extends BaseProcessor{
.returns(tname(packageName + "." + name)) .returns(tname(packageName + "." + name))
.addStatement(ann.pooled() ? "return Pools.obtain($L.class, " +name +"::new)" : "return new $L()", name).build()); .addStatement(ann.pooled() ? "return Pools.obtain($L.class, " +name +"::new)" : "return new $L()", name).build());
definitions.add(new EntityDefinition(packageName + "." + name, builder, type, components, groups)); definitions.add(new EntityDefinition(packageName + "." + name, builder, type, typeIsBase ? null : baseClass, components, groups, allFieldSpecs));
} }
//generate groups //generate groups
@@ -483,6 +566,14 @@ public class EntityProcess extends BaseProcessor{
//write the groups //write the groups
groupsBuilder.addMethod(groupInit.build()); groupsBuilder.addMethod(groupInit.build());
MethodSpec.Builder groupClear = MethodSpec.methodBuilder("clear").addModifiers(Modifier.PUBLIC, Modifier.STATIC);
for(GroupDefinition group : groupDefs){
groupClear.addStatement("$L.clear()", group.name);
}
//write clear
groupsBuilder.addMethod(groupClear.build());
//add method for resizing all necessary groups //add method for resizing all necessary groups
MethodSpec.Builder groupResize = MethodSpec.methodBuilder("resize") MethodSpec.Builder groupResize = MethodSpec.methodBuilder("resize")
.addParameter(TypeName.FLOAT, "x").addParameter(TypeName.FLOAT, "y").addParameter(TypeName.FLOAT, "w").addParameter(TypeName.FLOAT, "h") .addParameter(TypeName.FLOAT, "x").addParameter(TypeName.FLOAT, "y").addParameter(TypeName.FLOAT, "w").addParameter(TypeName.FLOAT, "h")
@@ -522,9 +613,9 @@ public class EntityProcess extends BaseProcessor{
int maxID = max == null ? 0 : max + 1; int maxID = max == null ? 0 : max + 1;
//assign IDs //assign IDs
definitions.sort(Structs.comparing(t -> t.base.toString())); definitions.sort(Structs.comparing(t -> t.naming.toString()));
for(EntityDefinition def : definitions){ for(EntityDefinition def : definitions){
String name = def.base.fullName(); String name = def.naming.fullName();
if(map.containsKey(name)){ if(map.containsKey(name)){
def.classID = map.getInt(name); def.classID = map.getInt(name);
}else{ }else{
@@ -557,7 +648,7 @@ public class EntityProcess extends BaseProcessor{
for(EntityDefinition def : definitions){ for(EntityDefinition def : definitions){
//store mapping //store mapping
idStore.addStatement("idMap[$L] = $L::new", def.classID, def.name); idStore.addStatement("idMap[$L] = $L::new", def.classID, def.name);
extraNames.get(def.base).each(extra -> { extraNames.get(def.naming).each(extra -> {
idStore.addStatement("nameMap.put($S, $L::new)", extra, def.name); idStore.addStatement("nameMap.put($S, $L::new)", extra, def.name);
if(!Strings.camelToKebab(extra).equals(extra)){ if(!Strings.camelToKebab(extra).equals(extra)){
idStore.addStatement("nameMap.put($S, $L::new)", Strings.camelToKebab(extra), def.name); idStore.addStatement("nameMap.put($S, $L::new)", Strings.camelToKebab(extra), def.name);
@@ -576,11 +667,21 @@ public class EntityProcess extends BaseProcessor{
}else{ }else{
//round 3: generate actual classes and implement interfaces //round 3: generate actual classes and implement interfaces
//write base classes
for(TypeSpec.Builder b : baseClasses){
write(b, imports.asArray());
}
//implement each definition //implement each definition
for(EntityDefinition def : definitions){ for(EntityDefinition def : definitions){
ObjectSet<String> methodNames = def.components.flatMap(type -> type.methods().map(Smethod::simpleString)).<String>as().asSet(); ObjectSet<String> methodNames = def.components.flatMap(type -> type.methods().map(Smethod::simpleString)).<String>as().asSet();
//add base class extension if it exists
if(def.extend != null){
def.builder.superclass(def.extend);
}
//get interface for each component //get interface for each component
for(Stype comp : def.components){ for(Stype comp : def.components){
@@ -596,18 +697,18 @@ public class EntityProcess extends BaseProcessor{
//generate getter/setter for each method //generate getter/setter for each method
for(Smethod method : inter.methods()){ for(Smethod method : inter.methods()){
String var = method.name(); String var = method.name();
FieldSpec field = Seq.with(def.builder.fieldSpecs).find(f -> f.name.equals(var)); FieldSpec field = Seq.with(def.fieldSpecs).find(f -> f.name.equals(var));
//make sure it's a real variable AND that the component doesn't already implement it somewhere with custom logic //make sure it's a real variable AND that the component doesn't already implement it somewhere with custom logic
if(field == null || methodNames.contains(method.simpleString())) continue; if(field == null || methodNames.contains(method.simpleString())) continue;
//getter //getter
if(!method.isVoid()){ if(!method.isVoid()){
def.builder.addMethod(MethodSpec.overriding(method.e).addStatement("return " + var).addModifiers(Modifier.FINAL).build()); def.builder.addMethod(MethodSpec.overriding(method.e).addStatement("return " + var).build());
} }
//setter //setter
if(method.isVoid() && !Seq.with(field.annotations).contains(f -> f.type.toString().equals("@mindustry.annotations.Annotations.ReadOnly"))){ if(method.isVoid() && !Seq.with(field.annotations).contains(f -> f.type.toString().equals("@mindustry.annotations.Annotations.ReadOnly"))){
def.builder.addMethod(MethodSpec.overriding(method.e).addModifiers(Modifier.FINAL).addStatement("this." + var + " = " + var).build()); def.builder.addMethod(MethodSpec.overriding(method.e).addStatement("this." + var + " = " + var).build());
} }
} }
} }
@@ -625,6 +726,11 @@ public class EntityProcess extends BaseProcessor{
Seq<Smethod> methods = dependencies.flatMap(Stype::methods); Seq<Smethod> methods = dependencies.flatMap(Stype::methods);
methods.sortComparing(Object::toString); methods.sortComparing(Object::toString);
//optionally add superclass
Stype superclass = dependencies.map(this::interfaceToComp).find(s -> s != null && s.annotation(Component.class).base());
//use the base type when the interface being emulated has a base
TypeName type = superclass != null && interfaceToComp(interf).annotation(Component.class).base() ? tname(baseName(superclass)) : interf.tname();
//used method signatures //used method signatures
ObjectSet<String> signatures = new ObjectSet<>(); ObjectSet<String> signatures = new ObjectSet<>();
@@ -635,6 +741,7 @@ public class EntityProcess extends BaseProcessor{
.addModifiers(Modifier.FINAL); .addModifiers(Modifier.FINAL);
nullBuilder.addSuperinterface(interf.tname()); nullBuilder.addSuperinterface(interf.tname());
if(superclass != null) nullBuilder.superclass(tname(baseName(superclass)));
for(Smethod method : methods){ for(Smethod method : methods){
String signature = method.toString(); String signature = method.toString();
@@ -642,6 +749,7 @@ public class EntityProcess extends BaseProcessor{
Stype compType = interfaceToComp(method.type()); Stype compType = interfaceToComp(method.type());
MethodSpec.Builder builder = MethodSpec.overriding(method.e).addModifiers(Modifier.PUBLIC, Modifier.FINAL); MethodSpec.Builder builder = MethodSpec.overriding(method.e).addModifiers(Modifier.PUBLIC, Modifier.FINAL);
builder.addAnnotation(OverrideCallSuper.class); //just in case
if(!method.isVoid()){ if(!method.isVoid()){
if(method.name().equals("isNull")){ if(method.name().equals("isNull")){
@@ -665,7 +773,7 @@ public class EntityProcess extends BaseProcessor{
signatures.add(signature); signatures.add(signature);
} }
nullsBuilder.addField(FieldSpec.builder(interf.cname(), Strings.camelize(baseName)).initializer("new " + className + "()").addModifiers(Modifier.FINAL, Modifier.STATIC, Modifier.PUBLIC).build()); nullsBuilder.addField(FieldSpec.builder(type, Strings.camelize(baseName)).initializer("new " + className + "()").addModifiers(Modifier.FINAL, Modifier.STATIC, Modifier.PUBLIC).build());
write(nullBuilder); write(nullBuilder);
} }
@@ -681,12 +789,26 @@ public class EntityProcess extends BaseProcessor{
/** @return interface for a component type */ /** @return interface for a component type */
String interfaceName(Stype comp){ String interfaceName(Stype comp){
String suffix = "Comp"; String suffix = "Comp";
if(!comp.name().endsWith(suffix)){ if(!comp.name().endsWith(suffix)) err("All components must have names that end with 'Comp'", comp.e);
err("All components must have names that end with 'Comp'", comp.e);
} //example: BlockComp -> IBlock
return comp.name().substring(0, comp.name().length() - suffix.length()) + "c"; return comp.name().substring(0, comp.name().length() - suffix.length()) + "c";
} }
/** @return base class name for a component type */
String baseName(Stype comp){
String suffix = "Comp";
if(!comp.name().endsWith(suffix)) err("All components must have names that end with 'Comp'", comp.e);
return comp.name().substring(0, comp.name().length() - suffix.length());
}
@Nullable Stype interfaceToComp(Stype type){
//example: IBlock -> BlockComp
String name = type.name().substring(0, type.name().length() - 1) + "Comp";
return componentNames.get(name);
}
/** @return all components that a entity def has */ /** @return all components that a entity def has */
Seq<Stype> allComponents(Selement<?> type){ Seq<Stype> allComponents(Selement<?> type){
if(!defComponents.containsKey(type)){ if(!defComponents.containsKey(type)){
@@ -746,19 +868,10 @@ public class EntityProcess extends BaseProcessor{
return interfaceToComp(type) != null; return interfaceToComp(type) != null;
} }
@Nullable Stype interfaceToComp(Stype type){
String name = type.name().substring(0, type.name().length() - 1) + "Comp";
return componentNames.get(name);
}
String createName(Selement<?> elem){ String createName(Selement<?> elem){
Seq<Stype> comps = types(elem.annotation(EntityDef.class), EntityDef::value).map(this::interfaceToComp);; Seq<Stype> comps = types(elem.annotation(EntityDef.class), EntityDef::value).map(this::interfaceToComp);;
comps.sortComparing(Selement::name); comps.sortComparing(Selement::name);
return comps.toString("", s -> s.name().replace("Comp", "")) + "Entity"; return comps.toString("", s -> s.name().replace("Comp", ""));
}
boolean isComponent(Stype type){
return type.annotation(Component.class) != null;
} }
<T extends Annotation> Seq<Stype> types(T t, Cons<T> consumer){ <T extends Annotation> Seq<Stype> types(T t, Cons<T> consumer){
@@ -795,17 +908,21 @@ public class EntityProcess extends BaseProcessor{
class EntityDefinition{ class EntityDefinition{
final Seq<GroupDefinition> groups; final Seq<GroupDefinition> groups;
final Seq<Stype> components; final Seq<Stype> components;
final Seq<FieldSpec> fieldSpecs;
final TypeSpec.Builder builder; final TypeSpec.Builder builder;
final Selement base; final Selement naming;
final String name; final String name;
final @Nullable TypeName extend;
int classID; int classID;
public EntityDefinition(String name, Builder builder, Selement base, Seq<Stype> components, Seq<GroupDefinition> groups){ public EntityDefinition(String name, Builder builder, Selement naming, TypeName extend, Seq<Stype> components, Seq<GroupDefinition> groups, Seq<FieldSpec> fieldSpec){
this.builder = builder; this.builder = builder;
this.name = name; this.name = name;
this.base = base; this.naming = naming;
this.groups = groups; this.groups = groups;
this.components = components; this.components = components;
this.extend = extend;
this.fieldSpecs = fieldSpec;
} }
@Override @Override
@@ -813,7 +930,7 @@ public class EntityProcess extends BaseProcessor{
return "Definition{" + return "Definition{" +
"groups=" + groups + "groups=" + groups +
"components=" + components + "components=" + components +
", base=" + base + ", base=" + naming +
'}'; '}';
} }
} }

View File

@@ -1,17 +1,14 @@
package mindustry.annotations.impl; package mindustry.annotations.impl;
import arc.struct.*;
import com.squareup.javapoet.*; import com.squareup.javapoet.*;
import mindustry.annotations.Annotations.*;
import mindustry.annotations.*; import mindustry.annotations.*;
import mindustry.annotations.Annotations.Struct; import mindustry.annotations.util.*;
import mindustry.annotations.Annotations.StructField;
import javax.annotation.processing.*; import javax.annotation.processing.*;
import javax.lang.model.element.*; import javax.lang.model.element.*;
import javax.lang.model.type.TypeKind; import javax.lang.model.type.*;
import javax.lang.model.util.ElementFilter;
import javax.tools.Diagnostic.Kind;
import java.util.List;
import java.util.Set;
/** /**
* Generates ""value types"" classes that are packed into integer primitives of the most aproppriate size. * Generates ""value types"" classes that are packed into integer primitives of the most aproppriate size.
@@ -24,28 +21,28 @@ public class StructProcess extends BaseProcessor{
@Override @Override
public void process(RoundEnvironment env) throws Exception{ public void process(RoundEnvironment env) throws Exception{
Set<TypeElement> elements = ElementFilter.typesIn(env.getElementsAnnotatedWith(Struct.class)); Seq<Stype> elements = types(Struct.class);
for(TypeElement elem : elements){ for(Stype elem : elements){
if(!elem.getSimpleName().toString().endsWith("Struct")){ if(!elem.name().endsWith("Struct")){
BaseProcessor.err("All classes annotated with @Struct must have their class names end in 'Struct'.", elem); err("All classes annotated with @Struct must have their class names end in 'Struct'.", elem);
continue; continue;
} }
String structName = elem.getSimpleName().toString().substring(0, elem.getSimpleName().toString().length() - "Struct".length()); String structName = elem.name().substring(0, elem.name().length() - "Struct".length());
String structParam = structName.toLowerCase(); String structParam = structName.toLowerCase();
TypeSpec.Builder classBuilder = TypeSpec.classBuilder(structName) TypeSpec.Builder classBuilder = TypeSpec.classBuilder(structName)
.addModifiers(Modifier.FINAL, Modifier.PUBLIC); .addModifiers(Modifier.FINAL, Modifier.PUBLIC);
try{ try{
List<VariableElement> variables = ElementFilter.fieldsIn(elem.getEnclosedElements()); Seq<Svar> variables = elem.fields();
int structSize = variables.stream().mapToInt(StructProcess::varSize).sum(); int structSize = variables.mapInt(StructProcess::varSize).sum();
int structTotalSize = (structSize <= 8 ? 8 : structSize <= 16 ? 16 : structSize <= 32 ? 32 : 64); int structTotalSize = (structSize <= 8 ? 8 : structSize <= 16 ? 16 : structSize <= 32 ? 32 : 64);
if(variables.size() == 0){ if(variables.size == 0){
BaseProcessor.err("making a struct with no fields is utterly pointles.", elem); err("making a struct with no fields is utterly pointles.", elem);
continue; continue;
} }
@@ -62,21 +59,21 @@ public class StructProcess extends BaseProcessor{
doc.append("Bits used: ").append(structSize).append(" / ").append(structTotalSize).append("\n"); doc.append("Bits used: ").append(structSize).append(" / ").append(structTotalSize).append("\n");
int offset = 0; int offset = 0;
for(VariableElement var : variables){ for(Svar var : variables){
int size = varSize(var); int size = varSize(var);
TypeName varType = TypeName.get(var.asType()); TypeName varType = var.tname();
String varName = var.getSimpleName().toString(); String varName = var.name();
//add val param to constructor //add val param to constructor
constructor.addParameter(varType, varName); constructor.addParameter(varType, varName);
//[get] field(structType) : fieldType //[get] field(structType) : fieldType
MethodSpec.Builder getter = MethodSpec.methodBuilder(var.getSimpleName().toString()) MethodSpec.Builder getter = MethodSpec.methodBuilder(var.name().toString())
.addModifiers(Modifier.STATIC, Modifier.PUBLIC) .addModifiers(Modifier.STATIC, Modifier.PUBLIC)
.returns(varType) .returns(varType)
.addParameter(structType, structParam); .addParameter(structType, structParam);
//[set] field(structType, fieldType) : structType //[set] field(structType, fieldType) : structType
MethodSpec.Builder setter = MethodSpec.methodBuilder(var.getSimpleName().toString()) MethodSpec.Builder setter = MethodSpec.methodBuilder(var.name().toString())
.addModifiers(Modifier.STATIC, Modifier.PUBLIC) .addModifiers(Modifier.STATIC, Modifier.PUBLIC)
.returns(structType) .returns(structType)
.addParameter(structType, structParam).addParameter(varType, "value"); .addParameter(structType, structParam).addParameter(varType, "value");
@@ -133,7 +130,7 @@ public class StructProcess extends BaseProcessor{
JavaFile.builder(packageName, classBuilder.build()).build().writeTo(BaseProcessor.filer); JavaFile.builder(packageName, classBuilder.build()).build().writeTo(BaseProcessor.filer);
}catch(IllegalArgumentException e){ }catch(IllegalArgumentException e){
e.printStackTrace(); e.printStackTrace();
BaseProcessor.err(e.getMessage(), elem); err(e.getMessage(), elem);
} }
} }
@@ -154,21 +151,21 @@ public class StructProcess extends BaseProcessor{
return "0b" + builder.reverse().toString() + "L"; return "0b" + builder.reverse().toString() + "L";
} }
static int varSize(VariableElement var) throws IllegalArgumentException{ static int varSize(Svar var) throws IllegalArgumentException{
if(!var.asType().getKind().isPrimitive()){ if(!var.mirror().getKind().isPrimitive()){
throw new IllegalArgumentException("All struct fields must be primitives: " + var); throw new IllegalArgumentException("All struct fields must be primitives: " + var);
} }
StructField an = var.getAnnotation(StructField.class); StructField an = var.annotation(StructField.class);
if(var.asType().getKind() == TypeKind.BOOLEAN && an != null && an.value() != 1){ if(var.mirror().getKind() == TypeKind.BOOLEAN && an != null && an.value() != 1){
throw new IllegalArgumentException("Booleans can only be one bit long... why would you do this?"); throw new IllegalArgumentException("Booleans can only be one bit long... why would you do this?");
} }
if(var.asType().getKind() == TypeKind.FLOAT && an != null && an.value() != 32){ if(var.mirror().getKind() == TypeKind.FLOAT && an != null && an.value() != 32){
throw new IllegalArgumentException("Float size can't be changed. Very sad."); throw new IllegalArgumentException("Float size can't be changed. Very sad.");
} }
return an == null ? typeSize(var.asType().getKind()) : an.value(); return an == null ? typeSize(var.mirror().getKind()) : an.value();
} }
static Class<?> typeForSize(int size) throws IllegalArgumentException{ static Class<?> typeForSize(int size) throws IllegalArgumentException{

View File

@@ -1,15 +1,15 @@
package mindustry.annotations.remote; package mindustry.annotations.remote;
import arc.struct.*;
import com.squareup.javapoet.*; import com.squareup.javapoet.*;
import mindustry.annotations.*;
import mindustry.annotations.Annotations.*; import mindustry.annotations.Annotations.*;
import mindustry.annotations.*;
import mindustry.annotations.util.*; import mindustry.annotations.util.*;
import mindustry.annotations.util.TypeIOResolver.*; import mindustry.annotations.util.TypeIOResolver.*;
import javax.annotation.processing.*; import javax.annotation.processing.*;
import javax.lang.model.element.*; import javax.lang.model.element.*;
import java.util.*; import java.util.*;
import java.util.stream.*;
/** The annotation processor for generating remote method call code. */ /** The annotation processor for generating remote method call code. */
@@ -33,13 +33,13 @@ public class RemoteProcess extends BaseProcessor{
//class serializers //class serializers
private ClassSerializer serializer; private ClassSerializer serializer;
//all elements with the Remote annotation //all elements with the Remote annotation
private Set<? extends Element> elements; private Seq<Smethod> elements;
//map of all classes to generate by name //map of all classes to generate by name
private HashMap<String, ClassEntry> classMap; private HashMap<String, ClassEntry> classMap;
//list of all method entries //list of all method entries
private ArrayList<MethodEntry> methods; private Seq<MethodEntry> methods;
//list of all method entries //list of all method entries
private ArrayList<ClassEntry> classes; private Seq<ClassEntry> classes;
{ {
rounds = 2; rounds = 2;
@@ -54,23 +54,23 @@ public class RemoteProcess extends BaseProcessor{
//last method ID used //last method ID used
int lastMethodID = 0; int lastMethodID = 0;
//find all elements with the Remote annotation //find all elements with the Remote annotation
elements = roundEnv.getElementsAnnotatedWith(Remote.class); elements = methods(Remote.class);
//map of all classes to generate by name //map of all classes to generate by name
classMap = new HashMap<>(); classMap = new HashMap<>();
//list of all method entries //list of all method entries
methods = new ArrayList<>(); methods = new Seq<>();
//list of all method entries //list of all method entries
classes = new ArrayList<>(); classes = new Seq<>();
List<Element> orderedElements = new ArrayList<>(elements); Seq<Smethod> orderedElements = elements.copy();
orderedElements.sort(Comparator.comparing(Object::toString)); orderedElements.sortComparing(Object::toString);
//create methods //create methods
for(Element element : orderedElements){ for(Smethod element : orderedElements){
Remote annotation = element.getAnnotation(Remote.class); Remote annotation = element.annotation(Remote.class);
//check for static //check for static
if(!element.getModifiers().contains(Modifier.STATIC) || !element.getModifiers().contains(Modifier.PUBLIC)){ if(!element.is(Modifier.STATIC) || !element.is(Modifier.PUBLIC)){
err("All @Remote methods must be public and static: ", element); err("All @Remote methods must be public and static: ", element);
} }
@@ -89,8 +89,8 @@ public class RemoteProcess extends BaseProcessor{
ClassEntry entry = classMap.get(callLocation); ClassEntry entry = classMap.get(callLocation);
//create and add entry //create and add entry
MethodEntry method = new MethodEntry(entry.name, BaseProcessor.getMethodName(element), annotation.targets(), annotation.variants(), MethodEntry method = new MethodEntry(entry.name, BaseProcessor.getMethodName(element.e), annotation.targets(), annotation.variants(),
annotation.called(), annotation.unreliable(), annotation.forward(), lastMethodID++, (ExecutableElement)element, annotation.priority()); annotation.called(), annotation.unreliable(), annotation.forward(), lastMethodID++, element.e, annotation.priority());
entry.methods.add(method); entry.methods.add(method);
methods.add(method); methods.add(method);
@@ -105,15 +105,15 @@ public class RemoteProcess extends BaseProcessor{
RemoteReadGenerator readgen = new RemoteReadGenerator(serializer); RemoteReadGenerator readgen = new RemoteReadGenerator(serializer);
//generate server readers //generate server readers
readgen.generateFor(methods.stream().filter(method -> method.where.isClient).collect(Collectors.toList()), readServerName, packageName, true); readgen.generateFor(methods.select(method -> method.where.isClient), readServerName, packageName, true);
//generate client readers //generate client readers
readgen.generateFor(methods.stream().filter(method -> method.where.isServer).collect(Collectors.toList()), readClientName, packageName, false); readgen.generateFor(methods.select(method -> method.where.isServer), readClientName, packageName, false);
//create class for storing unique method hash //create class for storing unique method hash
TypeSpec.Builder hashBuilder = TypeSpec.classBuilder("MethodHash").addModifiers(Modifier.PUBLIC); TypeSpec.Builder hashBuilder = TypeSpec.classBuilder("MethodHash").addModifiers(Modifier.PUBLIC);
hashBuilder.addJavadoc(autogenWarning); hashBuilder.addJavadoc(autogenWarning);
hashBuilder.addField(FieldSpec.builder(int.class, "HASH", Modifier.STATIC, Modifier.PUBLIC, Modifier.FINAL) hashBuilder.addField(FieldSpec.builder(int.class, "HASH", Modifier.STATIC, Modifier.PUBLIC, Modifier.FINAL)
.initializer("$1L", Objects.hash(methods)).build()); .initializer("$1L", Arrays.hashCode(methods.map(m -> m.element).toArray())).build());
//build and write resulting hash class //build and write resulting hash class
TypeSpec spec = hashBuilder.build(); TypeSpec spec = hashBuilder.build();

View File

@@ -1,14 +1,12 @@
package mindustry.annotations.remote; package mindustry.annotations.remote;
import arc.struct.*;
import arc.util.io.*; import arc.util.io.*;
import com.squareup.javapoet.*; import com.squareup.javapoet.*;
import mindustry.annotations.*; import mindustry.annotations.*;
import mindustry.annotations.util.TypeIOResolver.*; import mindustry.annotations.util.TypeIOResolver.*;
import javax.lang.model.element.Modifier;
import javax.lang.model.element.*; import javax.lang.model.element.*;
import java.lang.reflect.*;
import java.util.*;
/** Generates code for reading remote invoke packets on the client and server. */ /** Generates code for reading remote invoke packets on the client and server. */
public class RemoteReadGenerator{ public class RemoteReadGenerator{
@@ -26,7 +24,7 @@ public class RemoteReadGenerator{
* @param packageName Full target package name. * @param packageName Full target package name.
* @param needsPlayer Whether this read method requires a reference to the player sender. * @param needsPlayer Whether this read method requires a reference to the player sender.
*/ */
public void generateFor(List<MethodEntry> entries, String className, String packageName, boolean needsPlayer) throws Exception{ public void generateFor(Seq<MethodEntry> entries, String className, String packageName, boolean needsPlayer) throws Exception{
TypeSpec.Builder classBuilder = TypeSpec.classBuilder(className).addModifiers(Modifier.PUBLIC); TypeSpec.Builder classBuilder = TypeSpec.classBuilder(className).addModifiers(Modifier.PUBLIC);
classBuilder.addJavadoc(RemoteProcess.autogenWarning); classBuilder.addJavadoc(RemoteProcess.autogenWarning);
@@ -39,14 +37,8 @@ public class RemoteReadGenerator{
.returns(void.class); .returns(void.class);
if(needsPlayer){ if(needsPlayer){
//since the player type isn't loaded yet, creating a type def is necessary
//this requires reflection since the TypeName constructor is private for some reason
Constructor<TypeName> cons = TypeName.class.getDeclaredConstructor(String.class);
cons.setAccessible(true);
TypeName playerType = cons.newInstance("mindustry.gen.Playerc");
//add player parameter //add player parameter
readMethod.addParameter(playerType, "player"); readMethod.addParameter(ClassName.get(packageName, "Player"), "player");
} }
CodeBlock.Builder readBlock = CodeBlock.builder(); //start building block of code inside read method CodeBlock.Builder readBlock = CodeBlock.builder(); //start building block of code inside read method
@@ -111,7 +103,7 @@ public class RemoteReadGenerator{
if(entry.forward && entry.where.isServer && needsPlayer){ if(entry.forward && entry.where.isServer && needsPlayer){
//call forwarded method //call forwarded method
readBlock.addStatement(packageName + "." + entry.className + "." + entry.element.getSimpleName() + readBlock.addStatement(packageName + "." + entry.className + "." + entry.element.getSimpleName() +
"__forward(player.con()" + (varResult.length() == 0 ? "" : ", ") + varResult.toString() + ")"); "__forward(player.con" + (varResult.length() == 0 ? "" : ", ") + varResult.toString() + ")");
} }
readBlock.nextControlFlow("catch (java.lang.Exception e)"); readBlock.nextControlFlow("catch (java.lang.Exception e)");

View File

@@ -9,7 +9,6 @@ import mindustry.annotations.util.TypeIOResolver.*;
import javax.lang.model.element.*; import javax.lang.model.element.*;
import java.io.*; import java.io.*;
import java.util.*;
/** Generates code for writing remote invoke packets on the client and server. */ /** Generates code for writing remote invoke packets on the client and server. */
public class RemoteWriteGenerator{ public class RemoteWriteGenerator{
@@ -21,7 +20,7 @@ public class RemoteWriteGenerator{
} }
/** Generates all classes in this list. */ /** Generates all classes in this list. */
public void generateFor(List<ClassEntry> entries, String packageName) throws IOException{ public void generateFor(Seq<ClassEntry> entries, String packageName) throws IOException{
for(ClassEntry entry : entries){ for(ClassEntry entry : entries){
//create builder //create builder
@@ -66,7 +65,7 @@ public class RemoteWriteGenerator{
//create builder //create builder
MethodSpec.Builder method = MethodSpec.methodBuilder(elem.getSimpleName().toString() + (forwarded ? "__forward" : "")) //add except suffix when forwarding MethodSpec.Builder method = MethodSpec.methodBuilder(elem.getSimpleName().toString() + (forwarded ? "__forward" : "")) //add except suffix when forwarding
.addModifiers(Modifier.STATIC, Modifier.SYNCHRONIZED) .addModifiers(Modifier.STATIC)
.returns(void.class); .returns(void.class);
//forwarded methods aren't intended for use, and are not public //forwarded methods aren't intended for use, and are not public
@@ -81,8 +80,8 @@ public class RemoteWriteGenerator{
return; return;
} }
if(!elem.getParameters().get(0).asType().toString().contains("Playerc")){ if(!elem.getParameters().get(0).asType().toString().contains("Player")){
BaseProcessor.err("Client invoke methods should have a first parameter of type Playerc", elem); BaseProcessor.err("Client invoke methods should have a first parameter of type Player", elem);
return; return;
} }
} }

View File

@@ -17,6 +17,6 @@ public class SerializerResolver{
} }
private static boolean isEntity(TypeMirror mirror){ private static boolean isEntity(TypeMirror mirror){
return !mirror.toString().contains(".") && mirror.toString().endsWith("c"); return !mirror.toString().contains(".") || mirror.toString().startsWith("mindustry.gen.") && !mirror.toString().startsWith("byte");
} }
} }

View File

@@ -29,7 +29,7 @@ public class TypeIOResolver{
}else if(params.size == 1 && params.first().tname().toString().equals("arc.util.io.Reads") && !meth.isVoid()){ }else if(params.size == 1 && params.first().tname().toString().equals("arc.util.io.Reads") && !meth.isVoid()){
//1 param, one is reader, returns type //1 param, one is reader, returns type
out.readers.put(fix(meth.retn().toString()), type.fullName() + "." + meth.name()); out.readers.put(fix(meth.retn().toString()), type.fullName() + "." + meth.name());
}else if(params.size == 2 && params.first().tname().toString().equals("arc.util.io.Reads") && !meth.isVoid() && meth.ret() == meth.params().get(1).mirror()){ }else if(params.size == 2 && params.first().tname().toString().equals("arc.util.io.Reads") && !meth.isVoid() && meth.ret().equals(meth.params().get(1).mirror())){
//2 params, one is reader, other is type, returns type - these are made to reduce garbage allocated //2 params, one is reader, other is type, returns type - these are made to reduce garbage allocated
out.mutatorReaders.put(fix(meth.retn().toString()), type.fullName() + "." + meth.name()); out.mutatorReaders.put(fix(meth.retn().toString()), type.fullName() + "." + meth.name());
} }

View File

@@ -1,23 +1,41 @@
#Maps entity names to IDs. Autogenerated. #Maps entity names to IDs. Autogenerated.
alpha=0 alpha=0
arkyid=37
atrax=38
block=1 block=1
cix=2 cix=2
draug=3 draug=3
flare=36
horizon=35
mace=4 mace=4
mindustry.entities.comp.BulletComp=5 mega=28
mindustry.entities.comp.BuildingComp=22
mindustry.entities.comp.Buildingomp=11
mindustry.entities.comp.BulletComp=24
mindustry.entities.comp.Bulletomp=5
mindustry.entities.comp.DecalComp=6 mindustry.entities.comp.DecalComp=6
mindustry.entities.comp.EffectComp=7 mindustry.entities.comp.EffectComp=7
mindustry.entities.comp.EffectInstanceComp=23
mindustry.entities.comp.EffectStateComp=25
mindustry.entities.comp.FireComp=8 mindustry.entities.comp.FireComp=8
mindustry.entities.comp.LaunchCoreComp=21 mindustry.entities.comp.LaunchCoreComp=21
mindustry.entities.comp.PlayerComp=9 mindustry.entities.comp.PlayerComp=9
mindustry.entities.comp.PuddleComp=10 mindustry.entities.comp.PuddleComp=10
mindustry.entities.comp.TileComp=11
mindustry.type.Weather.WeatherComp=12 mindustry.type.Weather.WeatherComp=12
mindustry.type.Weather.WeatherStateComp=26
mindustry.world.blocks.campaign.CoreLauncher.LaunchCoreComp=13 mindustry.world.blocks.campaign.CoreLauncher.LaunchCoreComp=13
mindustry.world.blocks.campaign.LaunchPad.LaunchPayloadComp=14 mindustry.world.blocks.campaign.LaunchPad.LaunchPayloadComp=14
mono=29
nova=30
oculon=15 oculon=15
phantom=16 phantom=16
poly=31
pulsar=34
quasar=32
risse=33
spirit=27
spiroct=39
tau=17 tau=17
trident=18 trident=18
vanguard=19 vanguard=19

View File

@@ -0,0 +1 @@
{fields:[{name:ammo,type:int,size:4},{name:armor,type:float,size:4},{name:controller,type:mindustry.entities.units.UnitController,size:-1},{name:elevation,type:float,size:4},{name:health,type:float,size:4},{name:isShooting,type:boolean,size:1},{name:mounts,type:"mindustry.entities.units.WeaponMount[]",size:-1},{name:rotation,type:float,size:4},{name:shield,type:float,size:4},{name:spawnedByCore,type:boolean,size:1},{name:stack,type:mindustry.type.ItemStack,size:-1},{name:statuses,type:arc.struct.Seq<mindustry.entities.units.StatusEntry>,size:-1},{name:team,type:mindustry.game.Team,size:-1},{name:type,type:mindustry.type.UnitType,size:-1},{name:x,type:float,size:4},{name:y,type:float,size:4}]}

View File

@@ -1 +0,0 @@
{fields:[{name:armor,type:float,size:4},{name:controller,type:mindustry.entities.units.UnitController,size:-1},{name:elevation,type:float,size:4},{name:health,type:float,size:4},{name:isShooting,type:boolean,size:1},{name:rotation,type:float,size:4},{name:shield,type:float,size:4},{name:spawnedByCore,type:boolean,size:1},{name:stack,type:mindustry.type.ItemStack,size:-1},{name:statuses,type:arc.struct.Seq<mindustry.entities.units.StatusEntry>,size:-1},{name:team,type:mindustry.game.Team,size:-1},{name:type,type:mindustry.type.UnitType,size:-1},{name:x,type:float,size:4},{name:y,type:float,size:4}]}

View File

@@ -1 +0,0 @@
{version:1,fields:[{name:ammo,type:int,size:4},{name:armor,type:float,size:4},{name:controller,type:mindustry.entities.units.UnitController,size:-1},{name:elevation,type:float,size:4},{name:health,type:float,size:4},{name:isShooting,type:boolean,size:1},{name:rotation,type:float,size:4},{name:shield,type:float,size:4},{name:spawnedByCore,type:boolean,size:1},{name:stack,type:mindustry.type.ItemStack,size:-1},{name:statuses,type:arc.struct.Seq<mindustry.entities.units.StatusEntry>,size:-1},{name:team,type:mindustry.game.Team,size:-1},{name:type,type:mindustry.type.UnitType,size:-1},{name:x,type:float,size:4},{name:y,type:float,size:4}]}

View File

@@ -0,0 +1 @@
{fields:[{name:ammo,type:int,size:4},{name:armor,type:float,size:4},{name:baseRotation,type:float,size:4},{name:controller,type:mindustry.entities.units.UnitController,size:-1},{name:elevation,type:float,size:4},{name:health,type:float,size:4},{name:isShooting,type:boolean,size:1},{name:mineTile,type:mindustry.world.Tile,size:-1},{name:mounts,type:"mindustry.entities.units.WeaponMount[]",size:-1},{name:plans,type:arc.struct.Queue<mindustry.entities.units.BuildPlan>,size:-1},{name:rotation,type:float,size:4},{name:shield,type:float,size:4},{name:spawnedByCore,type:boolean,size:1},{name:stack,type:mindustry.type.ItemStack,size:-1},{name:statuses,type:arc.struct.Seq<mindustry.entities.units.StatusEntry>,size:-1},{name:team,type:mindustry.game.Team,size:-1},{name:type,type:mindustry.type.UnitType,size:-1},{name:x,type:float,size:4},{name:y,type:float,size:4}]}

View File

@@ -1 +0,0 @@
{fields:[{name:armor,type:float,size:4},{name:baseRotation,type:float,size:4},{name:controller,type:mindustry.entities.units.UnitController,size:-1},{name:elevation,type:float,size:4},{name:health,type:float,size:4},{name:isShooting,type:boolean,size:1},{name:mineTile,type:mindustry.world.Tile,size:-1},{name:requests,type:arc.struct.Queue<mindustry.entities.units.BuildRequest>,size:-1},{name:rotation,type:float,size:4},{name:shield,type:float,size:4},{name:spawnedByCore,type:boolean,size:1},{name:stack,type:mindustry.type.ItemStack,size:-1},{name:statuses,type:arc.struct.Seq<mindustry.entities.units.StatusEntry>,size:-1},{name:team,type:mindustry.game.Team,size:-1},{name:type,type:mindustry.type.UnitType,size:-1},{name:x,type:float,size:4},{name:y,type:float,size:4}]}

View File

@@ -1 +0,0 @@
{version:1,fields:[{name:armor,type:float,size:4},{name:baseRotation,type:float,size:4},{name:controller,type:mindustry.entities.units.UnitController,size:-1},{name:elevation,type:float,size:4},{name:health,type:float,size:4},{name:isShooting,type:boolean,size:1},{name:mineTile,type:mindustry.world.Tile,size:-1},{name:plans,type:arc.struct.Queue<mindustry.entities.units.BuildPlan>,size:-1},{name:rotation,type:float,size:4},{name:shield,type:float,size:4},{name:spawnedByCore,type:boolean,size:1},{name:stack,type:mindustry.type.ItemStack,size:-1},{name:statuses,type:arc.struct.Seq<mindustry.entities.units.StatusEntry>,size:-1},{name:team,type:mindustry.game.Team,size:-1},{name:type,type:mindustry.type.UnitType,size:-1},{name:x,type:float,size:4},{name:y,type:float,size:4}]}

View File

@@ -1 +0,0 @@
{version:2,fields:[{name:ammo,type:int,size:4},{name:armor,type:float,size:4},{name:baseRotation,type:float,size:4},{name:controller,type:mindustry.entities.units.UnitController,size:-1},{name:elevation,type:float,size:4},{name:health,type:float,size:4},{name:isShooting,type:boolean,size:1},{name:mineTile,type:mindustry.world.Tile,size:-1},{name:plans,type:arc.struct.Queue<mindustry.entities.units.BuildPlan>,size:-1},{name:rotation,type:float,size:4},{name:shield,type:float,size:4},{name:spawnedByCore,type:boolean,size:1},{name:stack,type:mindustry.type.ItemStack,size:-1},{name:statuses,type:arc.struct.Seq<mindustry.entities.units.StatusEntry>,size:-1},{name:team,type:mindustry.game.Team,size:-1},{name:type,type:mindustry.type.UnitType,size:-1},{name:x,type:float,size:4},{name:y,type:float,size:4}]}

View File

@@ -0,0 +1 @@
{fields:[{name:ammo,type:int,size:4},{name:armor,type:float,size:4},{name:controller,type:mindustry.entities.units.UnitController,size:-1},{name:elevation,type:float,size:4},{name:health,type:float,size:4},{name:isShooting,type:boolean,size:1},{name:mounts,type:"mindustry.entities.units.WeaponMount[]",size:-1},{name:plans,type:arc.struct.Queue<mindustry.entities.units.BuildPlan>,size:-1},{name:rotation,type:float,size:4},{name:shield,type:float,size:4},{name:spawnedByCore,type:boolean,size:1},{name:stack,type:mindustry.type.ItemStack,size:-1},{name:statuses,type:arc.struct.Seq<mindustry.entities.units.StatusEntry>,size:-1},{name:team,type:mindustry.game.Team,size:-1},{name:type,type:mindustry.type.UnitType,size:-1},{name:x,type:float,size:4},{name:y,type:float,size:4}]}

View File

@@ -0,0 +1 @@
{fields:[{name:ammo,type:int,size:4},{name:armor,type:float,size:4},{name:baseRotation,type:float,size:4},{name:controller,type:mindustry.entities.units.UnitController,size:-1},{name:elevation,type:float,size:4},{name:health,type:float,size:4},{name:isShooting,type:boolean,size:1},{name:mounts,type:"mindustry.entities.units.WeaponMount[]",size:-1},{name:plans,type:arc.struct.Queue<mindustry.entities.units.BuildPlan>,size:-1},{name:rotation,type:float,size:4},{name:shield,type:float,size:4},{name:spawnedByCore,type:boolean,size:1},{name:stack,type:mindustry.type.ItemStack,size:-1},{name:statuses,type:arc.struct.Seq<mindustry.entities.units.StatusEntry>,size:-1},{name:team,type:mindustry.game.Team,size:-1},{name:type,type:mindustry.type.UnitType,size:-1},{name:x,type:float,size:4},{name:y,type:float,size:4}]}

View File

@@ -1 +0,0 @@
{fields:[{name:armor,type:float,size:4},{name:baseRotation,type:float,size:4},{name:controller,type:mindustry.entities.units.UnitController,size:-1},{name:elevation,type:float,size:4},{name:health,type:float,size:4},{name:isShooting,type:boolean,size:1},{name:requests,type:arc.struct.Queue<mindustry.entities.units.BuildRequest>,size:-1},{name:rotation,type:float,size:4},{name:shield,type:float,size:4},{name:spawnedByCore,type:boolean,size:1},{name:stack,type:mindustry.type.ItemStack,size:-1},{name:statuses,type:arc.struct.Seq<mindustry.entities.units.StatusEntry>,size:-1},{name:team,type:mindustry.game.Team,size:-1},{name:type,type:mindustry.type.UnitType,size:-1},{name:x,type:float,size:4},{name:y,type:float,size:4}]}

View File

@@ -1 +0,0 @@
{version:1,fields:[{name:armor,type:float,size:4},{name:baseRotation,type:float,size:4},{name:controller,type:mindustry.entities.units.UnitController,size:-1},{name:elevation,type:float,size:4},{name:health,type:float,size:4},{name:isShooting,type:boolean,size:1},{name:plans,type:arc.struct.Queue<mindustry.entities.units.BuildPlan>,size:-1},{name:rotation,type:float,size:4},{name:shield,type:float,size:4},{name:spawnedByCore,type:boolean,size:1},{name:stack,type:mindustry.type.ItemStack,size:-1},{name:statuses,type:arc.struct.Seq<mindustry.entities.units.StatusEntry>,size:-1},{name:team,type:mindustry.game.Team,size:-1},{name:type,type:mindustry.type.UnitType,size:-1},{name:x,type:float,size:4},{name:y,type:float,size:4}]}

View File

@@ -1 +0,0 @@
{version:2,fields:[{name:ammo,type:int,size:4},{name:armor,type:float,size:4},{name:baseRotation,type:float,size:4},{name:controller,type:mindustry.entities.units.UnitController,size:-1},{name:elevation,type:float,size:4},{name:health,type:float,size:4},{name:isShooting,type:boolean,size:1},{name:plans,type:arc.struct.Queue<mindustry.entities.units.BuildPlan>,size:-1},{name:rotation,type:float,size:4},{name:shield,type:float,size:4},{name:spawnedByCore,type:boolean,size:1},{name:stack,type:mindustry.type.ItemStack,size:-1},{name:statuses,type:arc.struct.Seq<mindustry.entities.units.StatusEntry>,size:-1},{name:team,type:mindustry.game.Team,size:-1},{name:type,type:mindustry.type.UnitType,size:-1},{name:x,type:float,size:4},{name:y,type:float,size:4}]}

View File

@@ -0,0 +1 @@
{fields:[{name:ammo,type:int,size:4},{name:armor,type:float,size:4},{name:controller,type:mindustry.entities.units.UnitController,size:-1},{name:elevation,type:float,size:4},{name:health,type:float,size:4},{name:isShooting,type:boolean,size:1},{name:mineTile,type:mindustry.world.Tile,size:-1},{name:mounts,type:"mindustry.entities.units.WeaponMount[]",size:-1},{name:payloads,type:arc.struct.Seq<mindustry.world.blocks.payloads.Payload>,size:-1},{name:plans,type:arc.struct.Queue<mindustry.entities.units.BuildPlan>,size:-1},{name:rotation,type:float,size:4},{name:shield,type:float,size:4},{name:spawnedByCore,type:boolean,size:1},{name:stack,type:mindustry.type.ItemStack,size:-1},{name:statuses,type:arc.struct.Seq<mindustry.entities.units.StatusEntry>,size:-1},{name:team,type:mindustry.game.Team,size:-1},{name:type,type:mindustry.type.UnitType,size:-1},{name:x,type:float,size:4},{name:y,type:float,size:4}]}

View File

@@ -1 +0,0 @@
{fields:[{name:armor,type:float,size:4},{name:controller,type:mindustry.entities.units.UnitController,size:-1},{name:elevation,type:float,size:4},{name:health,type:float,size:4},{name:isShooting,type:boolean,size:1},{name:mineTile,type:mindustry.world.Tile,size:-1},{name:payloads,type:arc.struct.Seq<mindustry.world.blocks.payloads.Payload>,size:-1},{name:requests,type:arc.struct.Queue<mindustry.entities.units.BuildRequest>,size:-1},{name:rotation,type:float,size:4},{name:shield,type:float,size:4},{name:spawnedByCore,type:boolean,size:1},{name:stack,type:mindustry.type.ItemStack,size:-1},{name:statuses,type:arc.struct.Seq<mindustry.entities.units.StatusEntry>,size:-1},{name:team,type:mindustry.game.Team,size:-1},{name:type,type:mindustry.type.UnitType,size:-1},{name:x,type:float,size:4},{name:y,type:float,size:4}]}

View File

@@ -1 +0,0 @@
{version:1,fields:[{name:armor,type:float,size:4},{name:controller,type:mindustry.entities.units.UnitController,size:-1},{name:elevation,type:float,size:4},{name:health,type:float,size:4},{name:isShooting,type:boolean,size:1},{name:mineTile,type:mindustry.world.Tile,size:-1},{name:payloads,type:arc.struct.Seq<mindustry.world.blocks.payloads.Payload>,size:-1},{name:plans,type:arc.struct.Queue<mindustry.entities.units.BuildPlan>,size:-1},{name:rotation,type:float,size:4},{name:shield,type:float,size:4},{name:spawnedByCore,type:boolean,size:1},{name:stack,type:mindustry.type.ItemStack,size:-1},{name:statuses,type:arc.struct.Seq<mindustry.entities.units.StatusEntry>,size:-1},{name:team,type:mindustry.game.Team,size:-1},{name:type,type:mindustry.type.UnitType,size:-1},{name:x,type:float,size:4},{name:y,type:float,size:4}]}

View File

@@ -1 +0,0 @@
{version:2,fields:[{name:ammo,type:int,size:4},{name:armor,type:float,size:4},{name:controller,type:mindustry.entities.units.UnitController,size:-1},{name:elevation,type:float,size:4},{name:health,type:float,size:4},{name:isShooting,type:boolean,size:1},{name:mineTile,type:mindustry.world.Tile,size:-1},{name:payloads,type:arc.struct.Seq<mindustry.world.blocks.payloads.Payload>,size:-1},{name:plans,type:arc.struct.Queue<mindustry.entities.units.BuildPlan>,size:-1},{name:rotation,type:float,size:4},{name:shield,type:float,size:4},{name:spawnedByCore,type:boolean,size:1},{name:stack,type:mindustry.type.ItemStack,size:-1},{name:statuses,type:arc.struct.Seq<mindustry.entities.units.StatusEntry>,size:-1},{name:team,type:mindustry.game.Team,size:-1},{name:type,type:mindustry.type.UnitType,size:-1},{name:x,type:float,size:4},{name:y,type:float,size:4}]}

View File

@@ -0,0 +1 @@
{fields:[{name:ammo,type:int,size:4},{name:armor,type:float,size:4},{name:controller,type:mindustry.entities.units.UnitController,size:-1},{name:elevation,type:float,size:4},{name:health,type:float,size:4},{name:isShooting,type:boolean,size:1},{name:mineTile,type:mindustry.world.Tile,size:-1},{name:mounts,type:"mindustry.entities.units.WeaponMount[]",size:-1},{name:plans,type:arc.struct.Queue<mindustry.entities.units.BuildPlan>,size:-1},{name:rotation,type:float,size:4},{name:shield,type:float,size:4},{name:spawnedByCore,type:boolean,size:1},{name:stack,type:mindustry.type.ItemStack,size:-1},{name:statuses,type:arc.struct.Seq<mindustry.entities.units.StatusEntry>,size:-1},{name:team,type:mindustry.game.Team,size:-1},{name:type,type:mindustry.type.UnitType,size:-1},{name:x,type:float,size:4},{name:y,type:float,size:4}]}

View File

@@ -0,0 +1 @@
{fields:[{name:ammo,type:int,size:4},{name:armor,type:float,size:4},{name:controller,type:mindustry.entities.units.UnitController,size:-1},{name:elevation,type:float,size:4},{name:health,type:float,size:4},{name:isShooting,type:boolean,size:1},{name:mineTile,type:mindustry.world.Tile,size:-1},{name:mounts,type:"mindustry.entities.units.WeaponMount[]",size:-1},{name:plans,type:arc.struct.Queue<mindustry.entities.units.BuildPlan>,size:-1},{name:rotation,type:float,size:4},{name:shield,type:float,size:4},{name:spawnedByCore,type:boolean,size:1},{name:stack,type:mindustry.type.ItemStack,size:-1},{name:statuses,type:arc.struct.Seq<mindustry.entities.units.StatusEntry>,size:-1},{name:team,type:mindustry.game.Team,size:-1},{name:type,type:mindustry.type.UnitType,size:-1},{name:x,type:float,size:4},{name:y,type:float,size:4}]}

View File

@@ -1 +0,0 @@
{fields:[{name:armor,type:float,size:4},{name:controller,type:mindustry.entities.units.UnitController,size:-1},{name:elevation,type:float,size:4},{name:health,type:float,size:4},{name:isShooting,type:boolean,size:1},{name:mineTile,type:mindustry.world.Tile,size:-1},{name:requests,type:arc.struct.Queue<mindustry.entities.units.BuildRequest>,size:-1},{name:rotation,type:float,size:4},{name:shield,type:float,size:4},{name:spawnedByCore,type:boolean,size:1},{name:stack,type:mindustry.type.ItemStack,size:-1},{name:statuses,type:arc.struct.Seq<mindustry.entities.units.StatusEntry>,size:-1},{name:team,type:mindustry.game.Team,size:-1},{name:type,type:mindustry.type.UnitType,size:-1},{name:x,type:float,size:4},{name:y,type:float,size:4}]}

View File

@@ -1 +0,0 @@
{version:1,fields:[{name:armor,type:float,size:4},{name:controller,type:mindustry.entities.units.UnitController,size:-1},{name:elevation,type:float,size:4},{name:health,type:float,size:4},{name:isShooting,type:boolean,size:1},{name:mineTile,type:mindustry.world.Tile,size:-1},{name:plans,type:arc.struct.Queue<mindustry.entities.units.BuildPlan>,size:-1},{name:rotation,type:float,size:4},{name:shield,type:float,size:4},{name:spawnedByCore,type:boolean,size:1},{name:stack,type:mindustry.type.ItemStack,size:-1},{name:statuses,type:arc.struct.Seq<mindustry.entities.units.StatusEntry>,size:-1},{name:team,type:mindustry.game.Team,size:-1},{name:type,type:mindustry.type.UnitType,size:-1},{name:x,type:float,size:4},{name:y,type:float,size:4}]}

View File

@@ -1 +0,0 @@
{version:2,fields:[{name:ammo,type:int,size:4},{name:armor,type:float,size:4},{name:controller,type:mindustry.entities.units.UnitController,size:-1},{name:elevation,type:float,size:4},{name:health,type:float,size:4},{name:isShooting,type:boolean,size:1},{name:mineTile,type:mindustry.world.Tile,size:-1},{name:plans,type:arc.struct.Queue<mindustry.entities.units.BuildPlan>,size:-1},{name:rotation,type:float,size:4},{name:shield,type:float,size:4},{name:spawnedByCore,type:boolean,size:1},{name:stack,type:mindustry.type.ItemStack,size:-1},{name:statuses,type:arc.struct.Seq<mindustry.entities.units.StatusEntry>,size:-1},{name:team,type:mindustry.game.Team,size:-1},{name:type,type:mindustry.type.UnitType,size:-1},{name:x,type:float,size:4},{name:y,type:float,size:4}]}

View File

@@ -0,0 +1 @@
{fields:[{name:ammo,type:int,size:4},{name:armor,type:float,size:4},{name:controller,type:mindustry.entities.units.UnitController,size:-1},{name:elevation,type:float,size:4},{name:health,type:float,size:4},{name:isShooting,type:boolean,size:1},{name:mounts,type:"mindustry.entities.units.WeaponMount[]",size:-1},{name:plans,type:arc.struct.Queue<mindustry.entities.units.BuildPlan>,size:-1},{name:rotation,type:float,size:4},{name:shield,type:float,size:4},{name:spawnedByCore,type:boolean,size:1},{name:stack,type:mindustry.type.ItemStack,size:-1},{name:statuses,type:arc.struct.Seq<mindustry.entities.units.StatusEntry>,size:-1},{name:team,type:mindustry.game.Team,size:-1},{name:type,type:mindustry.type.UnitType,size:-1},{name:x,type:float,size:4},{name:y,type:float,size:4}]}

View File

@@ -1 +0,0 @@
{fields:[{name:armor,type:float,size:4},{name:controller,type:mindustry.entities.units.UnitController,size:-1},{name:elevation,type:float,size:4},{name:health,type:float,size:4},{name:isShooting,type:boolean,size:1},{name:requests,type:arc.struct.Queue<mindustry.entities.units.BuildRequest>,size:-1},{name:rotation,type:float,size:4},{name:shield,type:float,size:4},{name:spawnedByCore,type:boolean,size:1},{name:stack,type:mindustry.type.ItemStack,size:-1},{name:statuses,type:arc.struct.Seq<mindustry.entities.units.StatusEntry>,size:-1},{name:team,type:mindustry.game.Team,size:-1},{name:type,type:mindustry.type.UnitType,size:-1},{name:x,type:float,size:4},{name:y,type:float,size:4}]}

View File

@@ -1 +0,0 @@
{version:1,fields:[{name:armor,type:float,size:4},{name:controller,type:mindustry.entities.units.UnitController,size:-1},{name:elevation,type:float,size:4},{name:health,type:float,size:4},{name:isShooting,type:boolean,size:1},{name:plans,type:arc.struct.Queue<mindustry.entities.units.BuildPlan>,size:-1},{name:rotation,type:float,size:4},{name:shield,type:float,size:4},{name:spawnedByCore,type:boolean,size:1},{name:stack,type:mindustry.type.ItemStack,size:-1},{name:statuses,type:arc.struct.Seq<mindustry.entities.units.StatusEntry>,size:-1},{name:team,type:mindustry.game.Team,size:-1},{name:type,type:mindustry.type.UnitType,size:-1},{name:x,type:float,size:4},{name:y,type:float,size:4}]}

View File

@@ -1 +0,0 @@
{version:2,fields:[{name:ammo,type:int,size:4},{name:armor,type:float,size:4},{name:controller,type:mindustry.entities.units.UnitController,size:-1},{name:elevation,type:float,size:4},{name:health,type:float,size:4},{name:isShooting,type:boolean,size:1},{name:plans,type:arc.struct.Queue<mindustry.entities.units.BuildPlan>,size:-1},{name:rotation,type:float,size:4},{name:shield,type:float,size:4},{name:spawnedByCore,type:boolean,size:1},{name:stack,type:mindustry.type.ItemStack,size:-1},{name:statuses,type:arc.struct.Seq<mindustry.entities.units.StatusEntry>,size:-1},{name:team,type:mindustry.game.Team,size:-1},{name:type,type:mindustry.type.UnitType,size:-1},{name:x,type:float,size:4},{name:y,type:float,size:4}]}

View File

@@ -0,0 +1 @@
{fields:[{name:collided,type:arc.struct.IntSeq,size:-1},{name:damage,type:float,size:4},{name:data,type:java.lang.Object,size:-1},{name:lifetime,type:float,size:4},{name:owner,type:mindustry.gen.Entityc,size:-1},{name:team,type:mindustry.game.Team,size:-1},{name:time,type:float,size:4},{name:type,type:mindustry.entities.bullet.BulletType,size:-1},{name:x,type:float,size:4},{name:y,type:float,size:4}]}

View File

@@ -1 +0,0 @@
{fields:[{name:collided,type:arc.struct.IntSeq,size:-1},{name:damage,type:float,size:4},{name:data,type:java.lang.Object,size:-1},{name:lifetime,type:float,size:4},{name:owner,type:Entityc,size:-1},{name:team,type:mindustry.game.Team,size:-1},{name:time,type:float,size:4},{name:type,type:mindustry.entities.bullet.BulletType,size:-1},{name:x,type:float,size:4},{name:y,type:float,size:4}]}

View File

@@ -0,0 +1 @@
{fields:[{name:ammo,type:int,size:4},{name:armor,type:float,size:4},{name:controller,type:mindustry.entities.units.UnitController,size:-1},{name:elevation,type:float,size:4},{name:health,type:float,size:4},{name:isShooting,type:boolean,size:1},{name:mounts,type:"mindustry.entities.units.WeaponMount[]",size:-1},{name:rotation,type:float,size:4},{name:shield,type:float,size:4},{name:spawnedByCore,type:boolean,size:1},{name:stack,type:mindustry.type.ItemStack,size:-1},{name:statuses,type:arc.struct.Seq<mindustry.entities.units.StatusEntry>,size:-1},{name:team,type:mindustry.game.Team,size:-1},{name:type,type:mindustry.type.UnitType,size:-1},{name:x,type:float,size:4},{name:y,type:float,size:4}]}

View File

@@ -1 +0,0 @@
{fields:[{name:armor,type:float,size:4},{name:controller,type:mindustry.entities.units.UnitController,size:-1},{name:elevation,type:float,size:4},{name:health,type:float,size:4},{name:isShooting,type:boolean,size:1},{name:rotation,type:float,size:4},{name:shield,type:float,size:4},{name:spawnedByCore,type:boolean,size:1},{name:stack,type:mindustry.type.ItemStack,size:-1},{name:statuses,type:arc.struct.Seq<mindustry.entities.units.StatusEntry>,size:-1},{name:team,type:mindustry.game.Team,size:-1},{name:type,type:mindustry.type.UnitType,size:-1},{name:x,type:float,size:4},{name:y,type:float,size:4}]}

View File

@@ -1 +0,0 @@
{version:1,fields:[{name:ammo,type:int,size:4},{name:armor,type:float,size:4},{name:controller,type:mindustry.entities.units.UnitController,size:-1},{name:elevation,type:float,size:4},{name:health,type:float,size:4},{name:isShooting,type:boolean,size:1},{name:rotation,type:float,size:4},{name:shield,type:float,size:4},{name:spawnedByCore,type:boolean,size:1},{name:stack,type:mindustry.type.ItemStack,size:-1},{name:statuses,type:arc.struct.Seq<mindustry.entities.units.StatusEntry>,size:-1},{name:team,type:mindustry.game.Team,size:-1},{name:type,type:mindustry.type.UnitType,size:-1},{name:x,type:float,size:4},{name:y,type:float,size:4}]}

View File

@@ -1 +1 @@
{fields:[{name:color,type:arc.graphics.Color,size:-1},{name:data,type:java.lang.Object,size:-1},{name:effect,type:mindustry.entities.Effect,size:-1},{name:lifetime,type:float,size:4},{name:offsetX,type:float,size:4},{name:offsetY,type:float,size:4},{name:parent,type:Posc,size:-1},{name:rotation,type:float,size:4},{name:time,type:float,size:4},{name:x,type:float,size:4},{name:y,type:float,size:4}]} {fields:[{name:color,type:arc.graphics.Color,size:-1},{name:data,type:java.lang.Object,size:-1},{name:effect,type:mindustry.entities.Effect,size:-1},{name:lifetime,type:float,size:4},{name:offsetX,type:float,size:4},{name:offsetY,type:float,size:4},{name:parent,type:mindustry.gen.Posc,size:-1},{name:rotation,type:float,size:4},{name:time,type:float,size:4},{name:x,type:float,size:4},{name:y,type:float,size:4}]}

View File

@@ -0,0 +1 @@
{fields:[{name:ammo,type:int,size:4},{name:armor,type:float,size:4},{name:controller,type:mindustry.entities.units.UnitController,size:-1},{name:elevation,type:float,size:4},{name:health,type:float,size:4},{name:isShooting,type:boolean,size:1},{name:mounts,type:"mindustry.entities.units.WeaponMount[]",size:-1},{name:rotation,type:float,size:4},{name:shield,type:float,size:4},{name:spawnedByCore,type:boolean,size:1},{name:stack,type:mindustry.type.ItemStack,size:-1},{name:statuses,type:arc.struct.Seq<mindustry.entities.units.StatusEntry>,size:-1},{name:team,type:mindustry.game.Team,size:-1},{name:type,type:mindustry.type.UnitType,size:-1},{name:x,type:float,size:4},{name:y,type:float,size:4}]}

View File

@@ -1 +0,0 @@
{fields:[{name:armor,type:float,size:4},{name:controller,type:mindustry.entities.units.UnitController,size:-1},{name:elevation,type:float,size:4},{name:health,type:float,size:4},{name:isShooting,type:boolean,size:1},{name:rotation,type:float,size:4},{name:shield,type:float,size:4},{name:spawnedByCore,type:boolean,size:1},{name:stack,type:mindustry.type.ItemStack,size:-1},{name:statuses,type:arc.struct.Seq<mindustry.entities.units.StatusEntry>,size:-1},{name:team,type:mindustry.game.Team,size:-1},{name:type,type:mindustry.type.UnitType,size:-1},{name:x,type:float,size:4},{name:y,type:float,size:4}]}

View File

@@ -1 +0,0 @@
{version:1,fields:[{name:ammo,type:int,size:4},{name:armor,type:float,size:4},{name:controller,type:mindustry.entities.units.UnitController,size:-1},{name:elevation,type:float,size:4},{name:health,type:float,size:4},{name:isShooting,type:boolean,size:1},{name:rotation,type:float,size:4},{name:shield,type:float,size:4},{name:spawnedByCore,type:boolean,size:1},{name:stack,type:mindustry.type.ItemStack,size:-1},{name:statuses,type:arc.struct.Seq<mindustry.entities.units.StatusEntry>,size:-1},{name:team,type:mindustry.game.Team,size:-1},{name:type,type:mindustry.type.UnitType,size:-1},{name:x,type:float,size:4},{name:y,type:float,size:4}]}

View File

@@ -0,0 +1 @@
{fields:[{name:ammo,type:int,size:4},{name:armor,type:float,size:4},{name:baseRotation,type:float,size:4},{name:controller,type:mindustry.entities.units.UnitController,size:-1},{name:elevation,type:float,size:4},{name:health,type:float,size:4},{name:isShooting,type:boolean,size:1},{name:mounts,type:"mindustry.entities.units.WeaponMount[]",size:-1},{name:rotation,type:float,size:4},{name:shield,type:float,size:4},{name:spawnedByCore,type:boolean,size:1},{name:stack,type:mindustry.type.ItemStack,size:-1},{name:statuses,type:arc.struct.Seq<mindustry.entities.units.StatusEntry>,size:-1},{name:team,type:mindustry.game.Team,size:-1},{name:type,type:mindustry.type.UnitType,size:-1},{name:x,type:float,size:4},{name:y,type:float,size:4}]}

View File

@@ -1 +0,0 @@
{fields:[{name:armor,type:float,size:4},{name:baseRotation,type:float,size:4},{name:controller,type:mindustry.entities.units.UnitController,size:-1},{name:elevation,type:float,size:4},{name:health,type:float,size:4},{name:isShooting,type:boolean,size:1},{name:rotation,type:float,size:4},{name:shield,type:float,size:4},{name:spawnedByCore,type:boolean,size:1},{name:stack,type:mindustry.type.ItemStack,size:-1},{name:statuses,type:arc.struct.Seq<mindustry.entities.units.StatusEntry>,size:-1},{name:team,type:mindustry.game.Team,size:-1},{name:type,type:mindustry.type.UnitType,size:-1},{name:x,type:float,size:4},{name:y,type:float,size:4}]}

View File

@@ -1 +0,0 @@
{version:1,fields:[{name:ammo,type:int,size:4},{name:armor,type:float,size:4},{name:baseRotation,type:float,size:4},{name:controller,type:mindustry.entities.units.UnitController,size:-1},{name:elevation,type:float,size:4},{name:health,type:float,size:4},{name:isShooting,type:boolean,size:1},{name:rotation,type:float,size:4},{name:shield,type:float,size:4},{name:spawnedByCore,type:boolean,size:1},{name:stack,type:mindustry.type.ItemStack,size:-1},{name:statuses,type:arc.struct.Seq<mindustry.entities.units.StatusEntry>,size:-1},{name:team,type:mindustry.game.Team,size:-1},{name:type,type:mindustry.type.UnitType,size:-1},{name:x,type:float,size:4},{name:y,type:float,size:4}]}

View File

@@ -0,0 +1 @@
{fields:[{name:ammo,type:int,size:4},{name:armor,type:float,size:4},{name:controller,type:mindustry.entities.units.UnitController,size:-1},{name:elevation,type:float,size:4},{name:health,type:float,size:4},{name:isShooting,type:boolean,size:1},{name:mineTile,type:mindustry.world.Tile,size:-1},{name:mounts,type:"mindustry.entities.units.WeaponMount[]",size:-1},{name:rotation,type:float,size:4},{name:shield,type:float,size:4},{name:spawnedByCore,type:boolean,size:1},{name:stack,type:mindustry.type.ItemStack,size:-1},{name:statuses,type:arc.struct.Seq<mindustry.entities.units.StatusEntry>,size:-1},{name:team,type:mindustry.game.Team,size:-1},{name:type,type:mindustry.type.UnitType,size:-1},{name:x,type:float,size:4},{name:y,type:float,size:4}]}

View File

@@ -1 +0,0 @@
{fields:[{name:armor,type:float,size:4},{name:controller,type:mindustry.entities.units.UnitController,size:-1},{name:elevation,type:float,size:4},{name:health,type:float,size:4},{name:isShooting,type:boolean,size:1},{name:mineTile,type:mindustry.world.Tile,size:-1},{name:rotation,type:float,size:4},{name:shield,type:float,size:4},{name:spawnedByCore,type:boolean,size:1},{name:stack,type:mindustry.type.ItemStack,size:-1},{name:statuses,type:arc.struct.Seq<mindustry.entities.units.StatusEntry>,size:-1},{name:team,type:mindustry.game.Team,size:-1},{name:type,type:mindustry.type.UnitType,size:-1},{name:x,type:float,size:4},{name:y,type:float,size:4}]}

View File

@@ -1 +0,0 @@
{version:1,fields:[{name:ammo,type:int,size:4},{name:armor,type:float,size:4},{name:controller,type:mindustry.entities.units.UnitController,size:-1},{name:elevation,type:float,size:4},{name:health,type:float,size:4},{name:isShooting,type:boolean,size:1},{name:mineTile,type:mindustry.world.Tile,size:-1},{name:rotation,type:float,size:4},{name:shield,type:float,size:4},{name:spawnedByCore,type:boolean,size:1},{name:stack,type:mindustry.type.ItemStack,size:-1},{name:statuses,type:arc.struct.Seq<mindustry.entities.units.StatusEntry>,size:-1},{name:team,type:mindustry.game.Team,size:-1},{name:type,type:mindustry.type.UnitType,size:-1},{name:x,type:float,size:4},{name:y,type:float,size:4}]}

View File

@@ -1 +1 @@
{fields:[{name:admin,type:boolean,size:1},{name:boosting,type:boolean,size:1},{name:color,type:arc.graphics.Color,size:-1},{name:mouseX,type:float,size:4},{name:mouseY,type:float,size:4},{name:name,type:java.lang.String,size:-1},{name:shooting,type:boolean,size:1},{name:team,type:mindustry.game.Team,size:-1},{name:typing,type:boolean,size:1},{name:unit,type:Unitc,size:-1},{name:x,type:float,size:4},{name:y,type:float,size:4}]} {fields:[{name:admin,type:boolean,size:1},{name:boosting,type:boolean,size:1},{name:color,type:arc.graphics.Color,size:-1},{name:mouseX,type:float,size:4},{name:mouseY,type:float,size:4},{name:name,type:java.lang.String,size:-1},{name:shooting,type:boolean,size:1},{name:team,type:mindustry.game.Team,size:-1},{name:typing,type:boolean,size:1},{name:unit,type:Unit,size:-1},{name:x,type:float,size:4},{name:y,type:float,size:4}]}

View File

@@ -1 +1 @@
{fields:[{name:armor,type:float,size:4},{name:controller,type:mindustry.entities.units.UnitController,size:-1},{name:elevation,type:float,size:4},{name:health,type:float,size:4},{name:isShooting,type:boolean,size:1},{name:rotation,type:float,size:4},{name:shield,type:float,size:4},{name:spawnedByCore,type:boolean,size:1},{name:stack,type:mindustry.type.ItemStack,size:-1},{name:statuses,type:arc.struct.Seq<mindustry.entities.units.StatusEntry>,size:-1},{name:team,type:mindustry.game.Team,size:-1},{name:type,type:mindustry.type.UnitType,size:-1},{name:x,type:float,size:4},{name:y,type:float,size:4}]} {fields:[{name:ammo,type:int,size:4},{name:armor,type:float,size:4},{name:controller,type:mindustry.entities.units.UnitController,size:-1},{name:elevation,type:float,size:4},{name:health,type:float,size:4},{name:isShooting,type:boolean,size:1},{name:mounts,type:"mindustry.entities.units.WeaponMount[]",size:-1},{name:rotation,type:float,size:4},{name:shield,type:float,size:4},{name:spawnedByCore,type:boolean,size:1},{name:stack,type:mindustry.type.ItemStack,size:-1},{name:statuses,type:arc.struct.Seq<mindustry.entities.units.StatusEntry>,size:-1},{name:team,type:mindustry.game.Team,size:-1},{name:type,type:mindustry.type.UnitType,size:-1},{name:x,type:float,size:4},{name:y,type:float,size:4}]}

View File

@@ -1 +0,0 @@
{version:1,fields:[{name:ammo,type:int,size:4},{name:armor,type:float,size:4},{name:controller,type:mindustry.entities.units.UnitController,size:-1},{name:elevation,type:float,size:4},{name:health,type:float,size:4},{name:isShooting,type:boolean,size:1},{name:rotation,type:float,size:4},{name:shield,type:float,size:4},{name:spawnedByCore,type:boolean,size:1},{name:stack,type:mindustry.type.ItemStack,size:-1},{name:statuses,type:arc.struct.Seq<mindustry.entities.units.StatusEntry>,size:-1},{name:team,type:mindustry.game.Team,size:-1},{name:type,type:mindustry.type.UnitType,size:-1},{name:x,type:float,size:4},{name:y,type:float,size:4}]}

View File

@@ -176,6 +176,7 @@ allprojects{
sourceCompatibility = 1.8 sourceCompatibility = 1.8
targetCompatibility = 1.8 targetCompatibility = 1.8
options.encoding = "UTF-8" options.encoding = "UTF-8"
options.compilerArgs += ["-Xlint:deprecation"]
} }
} }
@@ -183,7 +184,6 @@ project(":desktop"){
apply plugin: "java" apply plugin: "java"
compileJava.options.fork = true compileJava.options.fork = true
compileJava.options.compilerArgs += ["-XDignore.symbol.file"]
dependencies{ dependencies{
implementation project(":core") implementation project(":core")
@@ -325,7 +325,7 @@ project(":tools"){
implementation arcModule("natives:natives-box2d-desktop") implementation arcModule("natives:natives-box2d-desktop")
implementation arcModule("backends:backend-headless") implementation arcModule("backends:backend-headless")
implementation "org.reflections:reflections:0.9.12" implementation "org.reflections:reflections:0.9.11"
} }
} }

Binary file not shown.

After

Width:  |  Height:  |  Size: 758 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 852 B

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 874 B

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 177 B

After

Width:  |  Height:  |  Size: 237 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 831 B

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 979 B

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 614 B

After

Width:  |  Height:  |  Size: 929 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 209 B

After

Width:  |  Height:  |  Size: 356 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 211 B

After

Width:  |  Height:  |  Size: 366 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 400 B

After

Width:  |  Height:  |  Size: 316 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 413 B

After

Width:  |  Height:  |  Size: 321 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 376 B

After

Width:  |  Height:  |  Size: 311 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 415 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 111 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 209 B

After

Width:  |  Height:  |  Size: 313 B

View File

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

Before

Width:  |  Height:  |  Size: 7.4 KiB

After

Width:  |  Height:  |  Size: 7.4 KiB

View File

Before

Width:  |  Height:  |  Size: 359 B

After

Width:  |  Height:  |  Size: 359 B

View File

Before

Width:  |  Height:  |  Size: 624 B

After

Width:  |  Height:  |  Size: 624 B

View File

Before

Width:  |  Height:  |  Size: 592 B

After

Width:  |  Height:  |  Size: 592 B

View File

Before

Width:  |  Height:  |  Size: 553 B

After

Width:  |  Height:  |  Size: 553 B

View File

Before

Width:  |  Height:  |  Size: 618 B

After

Width:  |  Height:  |  Size: 618 B

View File

Before

Width:  |  Height:  |  Size: 2.0 KiB

After

Width:  |  Height:  |  Size: 2.0 KiB

View File

Before

Width:  |  Height:  |  Size: 304 B

After

Width:  |  Height:  |  Size: 304 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 455 B

View File

Before

Width:  |  Height:  |  Size: 359 B

After

Width:  |  Height:  |  Size: 359 B

View File

Before

Width:  |  Height:  |  Size: 230 B

After

Width:  |  Height:  |  Size: 230 B

View File

Before

Width:  |  Height:  |  Size: 273 B

After

Width:  |  Height:  |  Size: 273 B

View File

Before

Width:  |  Height:  |  Size: 400 B

After

Width:  |  Height:  |  Size: 400 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 279 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 890 B

Some files were not shown because too many files have changed in this diff Show More