From 069d572a97997c664b1c550f61348f7e2a6638ab Mon Sep 17 00:00:00 2001 From: Anuken Date: Sat, 2 May 2020 11:47:27 -0400 Subject: [PATCH] New region loading system for blocks --- .../mindustry/annotations/Annotations.java | 8 ++ .../annotations/misc/LoadRegionProcessor.java | 128 ++++++++++++++++++ .../java/mindustry/annotations/util/Svar.java | 4 + core/src/mindustry/world/Block.java | 3 + 4 files changed, 143 insertions(+) create mode 100644 annotations/src/main/java/mindustry/annotations/misc/LoadRegionProcessor.java diff --git a/annotations/src/main/java/mindustry/annotations/Annotations.java b/annotations/src/main/java/mindustry/annotations/Annotations.java index 38b48a25a7..bd3385df9b 100644 --- a/annotations/src/main/java/mindustry/annotations/Annotations.java +++ b/annotations/src/main/java/mindustry/annotations/Annotations.java @@ -87,6 +87,14 @@ public class Annotations{ //endregion //region misc. utility + @Target(ElementType.FIELD) + @Retention(RetentionPolicy.SOURCE) + public @interface LoadRegion{ + String value(); + int length() default 1; + int[] lengths() default {}; + } + @Target(ElementType.TYPE) @Retention(RetentionPolicy.SOURCE) public @interface StyleDefaults{ diff --git a/annotations/src/main/java/mindustry/annotations/misc/LoadRegionProcessor.java b/annotations/src/main/java/mindustry/annotations/misc/LoadRegionProcessor.java new file mode 100644 index 0000000000..f7c3112faf --- /dev/null +++ b/annotations/src/main/java/mindustry/annotations/misc/LoadRegionProcessor.java @@ -0,0 +1,128 @@ +package mindustry.annotations.misc; + +import arc.*; +import arc.graphics.g2d.*; +import arc.struct.*; +import arc.struct.ObjectMap.*; +import com.squareup.javapoet.*; +import mindustry.annotations.Annotations.*; +import mindustry.annotations.*; +import mindustry.annotations.util.*; + +import javax.annotation.processing.*; +import javax.lang.model.element.*; + +@SupportedAnnotationTypes({"mindustry.annotations.Annotations.LoadRegion",}) +public class LoadRegionProcessor extends BaseProcessor{ + + @Override + public void process(RoundEnvironment env) throws Exception{ + TypeSpec.Builder regionClass = TypeSpec.classBuilder("ContentRegions") + .addModifiers(Modifier.PUBLIC); + MethodSpec.Builder method = MethodSpec.methodBuilder("loadRegions") + .addParameter(tname("mindustry.ctype.MappableContent"), "content") + .addModifiers(Modifier.STATIC, Modifier.PUBLIC); + + ObjectMap> fieldMap = new ObjectMap<>(); + + for(Svar field : fields(LoadRegion.class)){ + if(!field.is(Modifier.PUBLIC)){ + err("@LoadRegion field must be public", field); + } + + fieldMap.getOr(field.enclosingType(), Array::new).add(field); + } + + int index = 0; + + for(Entry> entry : fieldMap){ + if(index == 0){ + method.beginControlFlow("if(content instanceof $T)", entry.key.tname()); + }else{ + method.nextControlFlow("else if(content instanceof $T)", entry.key.tname()); + } + + //go through each supertype + for(Stype stype : entry.key.superclasses().and(entry.key)){ + if(fieldMap.containsKey(stype)){ + for(Svar field : fieldMap.get(stype)){ + LoadRegion an = field.annotation(LoadRegion.class); + //get # of array dimensions + int dims = count(field.mirror().toString(), "[]"); + + //not an array + if(dims == 0){ + method.addStatement("(($T)content).$L = $T.atlas.find($L)", entry.key.tname(), field.name(), Core.class, parse(an.value())); + }else{ + //is an array, create length string + int[] lengths = an.lengths(); + if(lengths.length == 0) lengths = new int[]{an.length()}; + + if(dims != lengths.length){ + err("Length dimensions must match array dimensions: " + dims + " != " + lengths.length, field); + } + + StringBuilder lengthString = new StringBuilder(); + for(int value : lengths) lengthString.append("[").append(value).append("]"); + + method.addStatement("(($T)content).$L = new $T$L", entry.key.tname(), field.name(), TextureRegion.class, lengthString.toString()); + + for(int i = 0; i < dims; i++){ + int length = lengths[0]; + + method.beginControlFlow("for(int INDEX$L = 0; INDEX$L < $L; INDEX$L ++)", i, i, length, i); + } + + StringBuilder indexString = new StringBuilder(); + for(int i = 0; i < dims; i++){ + indexString.append("[INDEX").append(i).append("]"); + } + + method.addStatement("(($T)content).$L$L = $T.atlas.find($L)", entry.key.tname(), field.name(), indexString.toString(), Core.class, parse(an.value())); + + for(int i = 0; i < dims; i++){ + method.endControlFlow(); + } + } + } + } + } + + index ++; + } + + if(index > 0){ + method.endControlFlow(); + } + + regionClass.addMethod(method.build()); + + write(regionClass); + } + + private static int count(String str, String substring){ + int lastIndex = 0; + int count = 0; + + while(lastIndex != -1){ + + lastIndex = str.indexOf(substring, lastIndex); + + if(lastIndex != -1){ + count ++; + lastIndex += substring.length(); + } + } + return count; + } + + private String parse(String value){ + value = '"' + value + '"'; + value = value.replace("@", "\" + content.name + \""); + value = value.replace("#1", "\" + INDEX0 + \""); + value = value.replace("#2", "\" + INDEX1 + \""); + value = value.replace("#", "\" + INDEX0 + \""); + return value; + } + +} diff --git a/annotations/src/main/java/mindustry/annotations/util/Svar.java b/annotations/src/main/java/mindustry/annotations/util/Svar.java index 6f307e8bc9..daee29106b 100644 --- a/annotations/src/main/java/mindustry/annotations/util/Svar.java +++ b/annotations/src/main/java/mindustry/annotations/util/Svar.java @@ -11,6 +11,10 @@ public class Svar extends Selement{ super(e); } + public Stype enclosingType(){ + return new Stype((TypeElement)up()); + } + public boolean isAny(Modifier... mods){ for(Modifier m : mods){ if(is(m)) return true; diff --git a/core/src/mindustry/world/Block.java b/core/src/mindustry/world/Block.java index d0a97050b4..74b20cbc59 100644 --- a/core/src/mindustry/world/Block.java +++ b/core/src/mindustry/world/Block.java @@ -586,6 +586,7 @@ public class Block extends UnlockableContent{ } } + @CallSuper @Override public void load(){ region = Core.atlas.find(name); @@ -603,6 +604,8 @@ public class Block extends UnlockableContent{ } } } + + ContentRegions.loadRegions(this); } @Override