Better entity code generation + minor refactoring
This commit is contained in:
@@ -10,6 +10,8 @@ import javax.lang.model.*;
|
|||||||
import javax.lang.model.element.*;
|
import javax.lang.model.element.*;
|
||||||
import javax.lang.model.util.*;
|
import javax.lang.model.util.*;
|
||||||
import javax.tools.Diagnostic.*;
|
import javax.tools.Diagnostic.*;
|
||||||
|
import javax.tools.*;
|
||||||
|
import java.io.*;
|
||||||
import java.lang.annotation.*;
|
import java.lang.annotation.*;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
@@ -38,7 +40,33 @@ public abstract class BaseProcessor extends AbstractProcessor{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static void write(TypeSpec.Builder builder) throws Exception{
|
public static void write(TypeSpec.Builder builder) throws Exception{
|
||||||
JavaFile.builder(packageName, builder.build()).build().writeTo(BaseProcessor.filer);
|
write(builder, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void write(TypeSpec.Builder builder, Array<String> imports) throws Exception{
|
||||||
|
JavaFile file = JavaFile.builder(packageName, builder.build()).skipJavaLangImports(true).build();
|
||||||
|
|
||||||
|
if(imports != null){
|
||||||
|
String rawSource = file.toString();
|
||||||
|
Array<String> result = new Array<>();
|
||||||
|
for (String s : rawSource.split("\n", -1)) {
|
||||||
|
result.add(s);
|
||||||
|
if (s.startsWith("package ")) {
|
||||||
|
result.add("");
|
||||||
|
for (String i : imports) {
|
||||||
|
result.add(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
String out = result.toString("\n");
|
||||||
|
JavaFileObject object = filer.createSourceFile(file.packageName + "." + file.typeSpec.name, file.typeSpec.originatingElements.toArray(new Element[0]));
|
||||||
|
OutputStream stream = object.openOutputStream();
|
||||||
|
stream.write(out.getBytes());
|
||||||
|
stream.close();
|
||||||
|
}else{
|
||||||
|
file.writeTo(filer);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Array<Stype> types(Class<? extends Annotation> type){
|
public Array<Stype> types(Class<? extends Annotation> type){
|
||||||
|
|||||||
@@ -122,6 +122,7 @@ public class CallSuperProcess extends AbstractProcessor{
|
|||||||
}
|
}
|
||||||
|
|
||||||
for(Symbol s : it){
|
for(Symbol s : it){
|
||||||
|
|
||||||
if(s instanceof MethodSymbol){
|
if(s instanceof MethodSymbol){
|
||||||
MethodSymbol ms = (MethodSymbol)s;
|
MethodSymbol ms = (MethodSymbol)s;
|
||||||
|
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ public class EntityProcess extends BaseProcessor{
|
|||||||
Array<Stype> baseComponents;
|
Array<Stype> baseComponents;
|
||||||
ObjectMap<Stype, Array<Stype>> componentDependencies = new ObjectMap<>();
|
ObjectMap<Stype, Array<Stype>> componentDependencies = new ObjectMap<>();
|
||||||
ObjectMap<Stype, Array<Stype>> defComponents = new ObjectMap<>();
|
ObjectMap<Stype, Array<Stype>> defComponents = new ObjectMap<>();
|
||||||
|
ObjectSet<String> imports = new ObjectSet<>();
|
||||||
|
|
||||||
{
|
{
|
||||||
rounds = 2;
|
rounds = 2;
|
||||||
@@ -40,6 +41,7 @@ public class EntityProcess extends BaseProcessor{
|
|||||||
|
|
||||||
//find all components used...
|
//find all components used...
|
||||||
for(Stype type : allDefs){
|
for(Stype type : allDefs){
|
||||||
|
imports.addAll(getImports(type.e));
|
||||||
allComponents.addAll(allComponents(type));
|
allComponents.addAll(allComponents(type));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -70,6 +72,7 @@ public class EntityProcess extends BaseProcessor{
|
|||||||
//add utility methods to interface
|
//add utility methods to interface
|
||||||
for(Smethod method : component.methods()){
|
for(Smethod method : component.methods()){
|
||||||
inter.addMethod(MethodSpec.methodBuilder(method.name())
|
inter.addMethod(MethodSpec.methodBuilder(method.name())
|
||||||
|
.addExceptions(method.thrownt())
|
||||||
.addTypeVariables(method.typeVariables().map(TypeVariableName::get))
|
.addTypeVariables(method.typeVariables().map(TypeVariableName::get))
|
||||||
.returns(method.ret().toString().equals("void") ? TypeName.VOID : method.retn())
|
.returns(method.ret().toString().equals("void") ? TypeName.VOID : method.retn())
|
||||||
.addParameters(method.params().map(v -> ParameterSpec.builder(v.tname(), v.name())
|
.addParameters(method.params().map(v -> ParameterSpec.builder(v.tname(), v.name())
|
||||||
@@ -119,6 +122,7 @@ public class EntityProcess extends BaseProcessor{
|
|||||||
MethodSpec.Builder mbuilder = MethodSpec.methodBuilder(first.name()).addModifiers(Modifier.PUBLIC, Modifier.FINAL);
|
MethodSpec.Builder mbuilder = MethodSpec.methodBuilder(first.name()).addModifiers(Modifier.PUBLIC, Modifier.FINAL);
|
||||||
mbuilder.addTypeVariables(first.typeVariables().map(TypeVariableName::get));
|
mbuilder.addTypeVariables(first.typeVariables().map(TypeVariableName::get));
|
||||||
mbuilder.returns(first.retn());
|
mbuilder.returns(first.retn());
|
||||||
|
mbuilder.addExceptions(first.thrownt());
|
||||||
|
|
||||||
for(Svar var : first.params()){
|
for(Svar var : first.params()){
|
||||||
mbuilder.addParameter(var.tname(), var.name());
|
mbuilder.addParameter(var.tname(), var.name());
|
||||||
@@ -127,19 +131,25 @@ public class EntityProcess extends BaseProcessor{
|
|||||||
boolean returns = !first.ret().toString().equals("void");
|
boolean returns = !first.ret().toString().equals("void");
|
||||||
|
|
||||||
for(Smethod elem : entry.value){
|
for(Smethod elem : entry.value){
|
||||||
//wrap scope to prevent variable leakage
|
|
||||||
if(!returns) mbuilder.beginControlFlow("");
|
|
||||||
|
|
||||||
//get all statements in the method, copy them over
|
//get all statements in the method, copy them over
|
||||||
MethodTree methodTree = elem.tree();
|
MethodTree methodTree = elem.tree();
|
||||||
BlockTree blockTree = methodTree.getBody();
|
BlockTree blockTree = methodTree.getBody();
|
||||||
for(StatementTree st : blockTree.getStatements()){
|
String str = blockTree.toString();
|
||||||
String state = st.toString();
|
String blockName = elem.up().getSimpleName().toString().toLowerCase().replace("comp", "");
|
||||||
mbuilder.addStatement(state.substring(0, state.length() - 1));
|
|
||||||
|
//skip empty blocks
|
||||||
|
if(str.replace("{", "").replace("\n", "").replace("}", "").replace("\t", "").replace(" ", "").isEmpty()){
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//wrap scope to prevent variable leakage
|
||||||
|
if(!returns) mbuilder.addCode(blockName + ": {\n");
|
||||||
|
|
||||||
|
//make sure to remove braces here
|
||||||
|
mbuilder.addCode(str.substring(2, str.length() - 1).replace("return;", "break " + blockName + ";"));
|
||||||
|
|
||||||
//end scope
|
//end scope
|
||||||
if(!returns) mbuilder.endControlFlow();
|
if(!returns) mbuilder.addCode("}\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
builder.addMethod(mbuilder.build());
|
builder.addMethod(mbuilder.build());
|
||||||
@@ -167,6 +177,9 @@ public class EntityProcess extends BaseProcessor{
|
|||||||
if(method.name().length() <= 3) continue;
|
if(method.name().length() <= 3) continue;
|
||||||
|
|
||||||
String var = Strings.camelize(method.name().substring(3));
|
String var = Strings.camelize(method.name().substring(3));
|
||||||
|
//make sure it's a real variable
|
||||||
|
if(!Array.with(def.builder.fieldSpecs).contains(f -> f.name.equals(var))) continue;
|
||||||
|
|
||||||
if(method.name().startsWith("get")){
|
if(method.name().startsWith("get")){
|
||||||
def.builder.addMethod(MethodSpec.overriding(method.e).addStatement("return " + var).build());
|
def.builder.addMethod(MethodSpec.overriding(method.e).addStatement("return " + var).build());
|
||||||
}else if(method.name().startsWith("set")){
|
}else if(method.name().startsWith("set")){
|
||||||
@@ -175,11 +188,16 @@ public class EntityProcess extends BaseProcessor{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
write(def.builder);
|
write(def.builder, imports.asArray());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Array<String> getImports(Element elem){
|
||||||
|
return Array.with(trees.getPath(elem).getCompilationUnit().getImports()).map(t -> t.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @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)){
|
||||||
|
|||||||
@@ -13,6 +13,10 @@ public class Selement<T extends Element>{
|
|||||||
this.e = e;
|
this.e = e;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Element up(){
|
||||||
|
return e.getEnclosingElement();
|
||||||
|
}
|
||||||
|
|
||||||
public TypeMirror mirror(){
|
public TypeMirror mirror(){
|
||||||
return e.asType();
|
return e.asType();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,6 +14,14 @@ public class Smethod extends Selement<ExecutableElement>{
|
|||||||
super(executableElement);
|
super(executableElement);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Array<TypeMirror> thrown(){
|
||||||
|
return Array.with(e.getThrownTypes()).as(TypeMirror.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Array<TypeName> thrownt(){
|
||||||
|
return Array.with(e.getThrownTypes()).map(TypeName::get);
|
||||||
|
}
|
||||||
|
|
||||||
public Array<TypeParameterElement> typeVariables(){
|
public Array<TypeParameterElement> typeVariables(){
|
||||||
return Array.with(e.getTypeParameters()).as(TypeParameterElement.class);
|
return Array.with(e.getTypeParameters()).as(TypeParameterElement.class);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,23 @@
|
|||||||
package mindustry.entities.def;
|
package mindustry.entities.def;
|
||||||
|
|
||||||
|
import arc.graphics.*;
|
||||||
import arc.math.geom.*;
|
import arc.math.geom.*;
|
||||||
|
import arc.struct.Bits;
|
||||||
|
import arc.struct.*;
|
||||||
|
import arc.util.*;
|
||||||
|
import arc.util.pooling.*;
|
||||||
import mindustry.annotations.Annotations.*;
|
import mindustry.annotations.Annotations.*;
|
||||||
|
import mindustry.content.*;
|
||||||
|
import mindustry.ctype.*;
|
||||||
import mindustry.entities.bullet.*;
|
import mindustry.entities.bullet.*;
|
||||||
import mindustry.entities.units.*;
|
import mindustry.entities.units.*;
|
||||||
import mindustry.gen.*;
|
import mindustry.gen.*;
|
||||||
import mindustry.net.*;
|
import mindustry.net.*;
|
||||||
|
import mindustry.type.*;
|
||||||
|
|
||||||
|
import java.io.*;
|
||||||
|
|
||||||
|
import static mindustry.Vars.content;
|
||||||
|
|
||||||
class EntityDefs{
|
class EntityDefs{
|
||||||
|
|
||||||
@@ -64,11 +76,117 @@ class EntityDefs{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Depends(PosComp.class)
|
||||||
class StatusComp{
|
class StatusComp{
|
||||||
final Statuses statuses = new Statuses();
|
private Array<StatusEntry> statuses = new Array<>();
|
||||||
|
private Bits applied = new Bits(content.getBy(ContentType.status).size);
|
||||||
|
|
||||||
|
private float speedMultiplier;
|
||||||
|
private float damageMultiplier;
|
||||||
|
private float armorMultiplier;
|
||||||
|
|
||||||
|
void apply(StatusEffect effect, float duration){
|
||||||
|
if(effect == StatusEffects.none || effect == null || isImmune(effect)) return; //don't apply empty or immune effects
|
||||||
|
|
||||||
|
if(statuses.size > 0){
|
||||||
|
//check for opposite effects
|
||||||
|
for(StatusEntry entry : statuses){
|
||||||
|
//extend effect
|
||||||
|
if(entry.effect == effect){
|
||||||
|
entry.time = Math.max(entry.time, duration);
|
||||||
|
return;
|
||||||
|
}else if(entry.effect.reactsWith(effect)){ //find opposite
|
||||||
|
StatusEntry.tmp.effect = entry.effect;
|
||||||
|
//TODO unit cannot be null here
|
||||||
|
entry.effect.getTransition(null, effect, entry.time, duration, StatusEntry.tmp);
|
||||||
|
entry.time = StatusEntry.tmp.time;
|
||||||
|
|
||||||
|
if(StatusEntry.tmp.effect != entry.effect){
|
||||||
|
entry.effect = StatusEntry.tmp.effect;
|
||||||
|
}
|
||||||
|
|
||||||
|
//stop looking when one is found
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//otherwise, no opposites found, add direct effect
|
||||||
|
StatusEntry entry = Pools.obtain(StatusEntry.class, StatusEntry::new);
|
||||||
|
entry.set(effect, duration);
|
||||||
|
statuses.add(entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean isImmune(StatusEffect effect){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Color getStatusColor(){
|
||||||
|
if(statuses.size == 0){
|
||||||
|
return Tmp.c1.set(Color.white);
|
||||||
|
}
|
||||||
|
|
||||||
|
float r = 0f, g = 0f, b = 0f;
|
||||||
|
for(StatusEntry entry : statuses){
|
||||||
|
r += entry.effect.color.r;
|
||||||
|
g += entry.effect.color.g;
|
||||||
|
b += entry.effect.color.b;
|
||||||
|
}
|
||||||
|
return Tmp.c1.set(r / statuses.size, g / statuses.size, b / statuses.size, 1f);
|
||||||
|
}
|
||||||
|
|
||||||
void update(){
|
void update(){
|
||||||
statuses.update(null);
|
applied.clear();
|
||||||
|
speedMultiplier = damageMultiplier = armorMultiplier = 1f;
|
||||||
|
|
||||||
|
if(statuses.isEmpty()) return;
|
||||||
|
|
||||||
|
statuses.eachFilter(entry -> {
|
||||||
|
entry.time = Math.max(entry.time - Time.delta(), 0);
|
||||||
|
applied.set(entry.effect.id);
|
||||||
|
|
||||||
|
if(entry.time <= 0){
|
||||||
|
Pools.free(entry);
|
||||||
|
return true;
|
||||||
|
}else{
|
||||||
|
speedMultiplier *= entry.effect.speedMultiplier;
|
||||||
|
armorMultiplier *= entry.effect.armorMultiplier;
|
||||||
|
damageMultiplier *= entry.effect.damageMultiplier;
|
||||||
|
//TODO unit can't be null
|
||||||
|
entry.effect.update(null, entry.time);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean hasEffect(StatusEffect effect){
|
||||||
|
return applied.get(effect.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
void writeSave(DataOutput stream) throws IOException{
|
||||||
|
stream.writeByte(statuses.size);
|
||||||
|
for(StatusEntry entry : statuses){
|
||||||
|
stream.writeByte(entry.effect.id);
|
||||||
|
stream.writeFloat(entry.time);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void readSave(DataInput stream, byte version) throws IOException{
|
||||||
|
for(StatusEntry effect : statuses){
|
||||||
|
Pools.free(effect);
|
||||||
|
}
|
||||||
|
|
||||||
|
statuses.clear();
|
||||||
|
|
||||||
|
byte amount = stream.readByte();
|
||||||
|
for(int i = 0; i < amount; i++){
|
||||||
|
byte id = stream.readByte();
|
||||||
|
float time = stream.readFloat();
|
||||||
|
StatusEntry entry = Pools.obtain(StatusEntry.class, StatusEntry::new);
|
||||||
|
entry.set(content.getByID(ContentType.status, id), time);
|
||||||
|
statuses.add(entry);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,16 @@
|
|||||||
|
package mindustry.entities.units;
|
||||||
|
|
||||||
|
import mindustry.type.*;
|
||||||
|
|
||||||
|
public class StatusEntry{
|
||||||
|
public static final StatusEntry tmp = new StatusEntry();
|
||||||
|
|
||||||
|
public StatusEffect effect;
|
||||||
|
public float time;
|
||||||
|
|
||||||
|
public StatusEntry set(StatusEffect effect, float time){
|
||||||
|
this.effect = effect;
|
||||||
|
this.time = time;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -147,14 +147,4 @@ public class Statuses implements Saveable{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class StatusEntry{
|
|
||||||
public StatusEffect effect;
|
|
||||||
public float time;
|
|
||||||
|
|
||||||
public StatusEntry set(StatusEffect effect, float time){
|
|
||||||
this.effect = effect;
|
|
||||||
this.time = time;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import mindustry.ctype.ContentType;
|
|||||||
import mindustry.entities.*;
|
import mindustry.entities.*;
|
||||||
import mindustry.entities.Effects.*;
|
import mindustry.entities.Effects.*;
|
||||||
import mindustry.entities.type.*;
|
import mindustry.entities.type.*;
|
||||||
import mindustry.entities.units.Statuses.*;
|
import mindustry.entities.units.*;
|
||||||
|
|
||||||
public class StatusEffect extends MappableContent{
|
public class StatusEffect extends MappableContent{
|
||||||
/** Damage dealt by the unit with the effect. */
|
/** Damage dealt by the unit with the effect. */
|
||||||
|
|||||||
+1
-1
@@ -1,3 +1,3 @@
|
|||||||
org.gradle.daemon=true
|
org.gradle.daemon=true
|
||||||
org.gradle.jvmargs=-Xms256m -Xmx1024m
|
org.gradle.jvmargs=-Xms256m -Xmx1024m
|
||||||
archash=8c7b7cbef40a0cc546cace77364c88f3f6ee5ed7
|
archash=45ffc0ea35fa7c282538259daf247eabfc987acf
|
||||||
|
|||||||
Reference in New Issue
Block a user