mirror of
https://github.com/Anuken/Mindustry.git
synced 2024-11-13 07:15:28 +03:00
More entity processor features
This commit is contained in:
parent
7ddfcbfabd
commit
acb3438cc8
@ -4,6 +4,15 @@ import java.lang.annotation.*;
|
||||
|
||||
public class Annotations{
|
||||
|
||||
//region entity interfaces
|
||||
|
||||
/** Indicates multiple inheritance on a component type. */
|
||||
@Target(ElementType.TYPE)
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
public @interface Depends{
|
||||
Class[] value();
|
||||
}
|
||||
|
||||
/** Indicates an entity definition. */
|
||||
@Target(ElementType.TYPE)
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
@ -17,11 +26,8 @@ public class Annotations{
|
||||
public @interface EntityInterface{
|
||||
}
|
||||
|
||||
/** Indicates that a component logic method should be merged. */
|
||||
@Target(ElementType.METHOD)
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
public @interface Merge{
|
||||
}
|
||||
//endregion
|
||||
//region misc. utility
|
||||
|
||||
@Target(ElementType.TYPE)
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
@ -48,6 +54,9 @@ public class Annotations{
|
||||
|
||||
}
|
||||
|
||||
//endregion
|
||||
//region struct
|
||||
|
||||
/** Marks a class as a special value type struct. Class name must end in 'Struct'. */
|
||||
@Target(ElementType.TYPE)
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
@ -63,6 +72,9 @@ public class Annotations{
|
||||
int value();
|
||||
}
|
||||
|
||||
//endregion
|
||||
//region remote
|
||||
|
||||
public enum PacketPriority{
|
||||
/** Gets put in a queue and processed if not connected. */
|
||||
normal,
|
||||
@ -157,4 +169,6 @@ public class Annotations{
|
||||
public @interface ReadClass{
|
||||
Class<?> value();
|
||||
}
|
||||
|
||||
//endregion
|
||||
}
|
||||
|
@ -12,7 +12,6 @@ import mindustry.annotations.util.*;
|
||||
import javax.annotation.processing.*;
|
||||
import javax.lang.model.element.*;
|
||||
import javax.lang.model.type.*;
|
||||
import java.util.*;
|
||||
|
||||
@SupportedAnnotationTypes({
|
||||
"mindustry.annotations.Annotations.EntityDef",
|
||||
@ -20,6 +19,8 @@ import java.util.*;
|
||||
})
|
||||
public class EntityProcess extends BaseProcessor{
|
||||
Array<Definition> definitions = new Array<>();
|
||||
ObjectMap<Stype, Array<Stype>> componentDependencies = new ObjectMap<>();
|
||||
ObjectMap<Stype, Array<Stype>> defComponents = new ObjectMap<>();
|
||||
|
||||
{
|
||||
rounds = 2;
|
||||
@ -43,7 +44,12 @@ public class EntityProcess extends BaseProcessor{
|
||||
for(Stype component : allComponents){
|
||||
TypeSpec.Builder inter = TypeSpec.interfaceBuilder(component.name() + "c").addModifiers(Modifier.PUBLIC).addAnnotation(EntityInterface.class);
|
||||
|
||||
for(Svar field : component.fields().select(e -> !e.is(Modifier.STATIC) && !e.is(Modifier.PRIVATE))){
|
||||
Array<Stype> depends = getDependencies(component);
|
||||
for(Stype type : depends){
|
||||
inter.addSuperinterface(ClassName.get(packageName, type.name() + "c"));
|
||||
}
|
||||
|
||||
for(Svar field : component.fields().select(e -> !e.is(Modifier.STATIC) && !e.is(Modifier.PRIVATE) && !e.is(Modifier.TRANSIENT))){
|
||||
String cname = Strings.capitalize(field.name());
|
||||
//getter
|
||||
inter.addMethod(MethodSpec.methodBuilder("get" + cname).addModifiers(Modifier.ABSTRACT, Modifier.PUBLIC).returns(field.tname()).build());
|
||||
@ -72,8 +78,8 @@ public class EntityProcess extends BaseProcessor{
|
||||
//add all components
|
||||
for(Stype comp : components){
|
||||
|
||||
//write fields
|
||||
Array<Svar> fields = comp.fields();
|
||||
//write fields to the class; ignoring transient ones
|
||||
Array<Svar> fields = comp.fields().select(f -> !f.is(Modifier.TRANSIENT));
|
||||
for(Svar f : fields){
|
||||
VariableTree tree = f.tree();
|
||||
FieldSpec.Builder fbuilder = FieldSpec.builder(f.tname(), f.name(), Modifier.PUBLIC);
|
||||
@ -96,7 +102,8 @@ public class EntityProcess extends BaseProcessor{
|
||||
Smethod first = entry.value.first();
|
||||
//build method using same params/returns
|
||||
MethodSpec.Builder mbuilder = MethodSpec.methodBuilder(first.name()).addModifiers(Modifier.PUBLIC, Modifier.FINAL);
|
||||
mbuilder.returns(TypeName.get(first.ret()));
|
||||
mbuilder.returns(first.retn());
|
||||
|
||||
for(Svar var : first.params()){
|
||||
mbuilder.addParameter(var.tname(), var.name());
|
||||
}
|
||||
@ -141,6 +148,8 @@ public class EntityProcess extends BaseProcessor{
|
||||
|
||||
//generate getter/setter for each method
|
||||
for(Smethod method : inter.methods()){
|
||||
if(method.name().length() == 3) continue;
|
||||
|
||||
String var = Strings.camelize(method.name().substring(3));
|
||||
if(method.name().startsWith("get")){
|
||||
def.builder.addMethod(MethodSpec.overriding(method.e).addStatement("return " + var).build());
|
||||
@ -157,16 +166,47 @@ public class EntityProcess extends BaseProcessor{
|
||||
|
||||
/** @return all components that a entity def has */
|
||||
Array<Stype> allComponents(Stype type){
|
||||
ObjectSet<TypeMirror> mirrors = ObjectSet.with(mirrors(type));
|
||||
for(TypeMirror curr : mirrors){
|
||||
List<? extends TypeMirror> sub = typeu.directSupertypes(curr);
|
||||
while(!sub.isEmpty() && !sub.get(0).toString().equals("java.lang.Object")){
|
||||
mirrors.add(sub.get(0));
|
||||
curr = sub.get(0);
|
||||
sub = typeu.directSupertypes(curr);
|
||||
if(!defComponents.containsKey(type)){
|
||||
//get base defs
|
||||
Array<Stype> components = Array.with(mirrors(type)).map(Stype::of);
|
||||
ObjectSet<Stype> out = new ObjectSet<>();
|
||||
for(Stype comp : components){
|
||||
//get dependencies for each def, add them
|
||||
out.add(comp);
|
||||
out.addAll(getDependencies(comp));
|
||||
}
|
||||
|
||||
defComponents.put(type, out.asArray());
|
||||
}
|
||||
return mirrors.asArray().map(m -> new Stype((TypeElement)typeu.asElement(m)));
|
||||
|
||||
return defComponents.get(type);
|
||||
}
|
||||
|
||||
Array<Stype> getDependencies(Stype component){
|
||||
if(!componentDependencies.containsKey(component)){
|
||||
ObjectSet<Stype> out = new ObjectSet<>();
|
||||
out.addAll(component.superclasses());
|
||||
|
||||
//get dependency classes
|
||||
if(component.annotation(Depends.class) != null){
|
||||
try{
|
||||
component.annotation(Depends.class).value();
|
||||
}catch(MirroredTypesException e){
|
||||
out.addAll(Array.with(e.getTypeMirrors()).map(Stype::of));
|
||||
}
|
||||
}
|
||||
|
||||
//out now contains the base dependencies; finish constructing the tree
|
||||
ObjectSet<Stype> result = new ObjectSet<>();
|
||||
for(Stype type : out){
|
||||
result.add(type);
|
||||
result.addAll(getDependencies(type));
|
||||
}
|
||||
|
||||
componentDependencies.put(component, result.asArray());
|
||||
}
|
||||
|
||||
return componentDependencies.get(component);
|
||||
}
|
||||
|
||||
TypeMirror[] mirrors(Stype type){
|
||||
|
@ -33,4 +33,14 @@ public class Selement<T extends Element>{
|
||||
public String toString(){
|
||||
return e.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode(){
|
||||
return e.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o){
|
||||
return o != null && o.getClass() == getClass() && ((Selement)o).e.equals(e);
|
||||
}
|
||||
}
|
||||
|
@ -13,12 +13,16 @@ public class Stype extends Selement<TypeElement>{
|
||||
super(typeElement);
|
||||
}
|
||||
|
||||
public static Stype of(TypeMirror mirror){
|
||||
return new Stype((TypeElement)BaseProcessor.typeu.asElement(mirror));
|
||||
}
|
||||
|
||||
public Array<Stype> superclasses(){
|
||||
Array<Stype> out = new Array<>();
|
||||
Stype sup = superclass();
|
||||
while(!sup.superclass().name().equals("java.lang.Object")){
|
||||
while(!sup.name().equals("Object")){
|
||||
out.add(sup);
|
||||
sup = superclass();
|
||||
sup = sup.superclass();
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
@ -8,9 +8,14 @@ import mindustry.net.*;
|
||||
|
||||
public class EntityDefs{
|
||||
|
||||
@EntityDef({Health.class, Vel.class, Status.class, Connection.class})
|
||||
@EntityDef({Unit.class, Connection.class})
|
||||
class PlayerDef{}
|
||||
|
||||
@Depends({Health.class, Vel.class, Status.class})
|
||||
class Unit{
|
||||
|
||||
}
|
||||
|
||||
class Health{
|
||||
float health, maxHealth;
|
||||
boolean dead;
|
||||
@ -24,7 +29,11 @@ public class EntityDefs{
|
||||
float x, y;
|
||||
}
|
||||
|
||||
class Vel extends Pos{
|
||||
@Depends(Pos.class)
|
||||
class Vel{
|
||||
//transient fields act as imports from any other clases; these are ignored by the generator
|
||||
transient float x, y;
|
||||
|
||||
final Vec2 vel = new Vec2();
|
||||
|
||||
void update(){
|
||||
@ -46,7 +55,7 @@ public class EntityDefs{
|
||||
NetConnection connection;
|
||||
}
|
||||
|
||||
static <T extends Connectionc & Velc & Healthc & Posc> void doSomethingWithAConnection(T value){
|
||||
static <T extends Connectionc & Unitc> void doSomethingWithAConnection(T value){
|
||||
value.setX(0);
|
||||
value.setY(0);
|
||||
value.getVel().set(100, 100f);
|
||||
|
Loading…
Reference in New Issue
Block a user