diff --git a/annotations/src/main/java/mindustry/annotations/Annotations.java b/annotations/src/main/java/mindustry/annotations/Annotations.java index 4cb52fe87a..c0723057a5 100644 --- a/annotations/src/main/java/mindustry/annotations/Annotations.java +++ b/annotations/src/main/java/mindustry/annotations/Annotations.java @@ -17,6 +17,12 @@ public class Annotations{ public @interface Component{ } + /** Indicates that a method is implemented by the annotation processor. */ + @Target(ElementType.METHOD) + @Retention(RetentionPolicy.SOURCE) + public @interface InternalImpl{ + } + /** Indicates priority of a method in an entity. Methods with higher priority are done last. */ @Target(ElementType.METHOD) @Retention(RetentionPolicy.SOURCE) diff --git a/annotations/src/main/java/mindustry/annotations/BaseProcessor.java b/annotations/src/main/java/mindustry/annotations/BaseProcessor.java index db998ea889..99beedfdb5 100644 --- a/annotations/src/main/java/mindustry/annotations/BaseProcessor.java +++ b/annotations/src/main/java/mindustry/annotations/BaseProcessor.java @@ -1,5 +1,6 @@ package mindustry.annotations; +import arc.files.*; import arc.struct.*; import arc.util.*; import com.squareup.javapoet.*; @@ -30,6 +31,7 @@ public abstract class BaseProcessor extends AbstractProcessor{ protected int round; protected int rounds = 1; protected RoundEnvironment env; + protected Fi rootDirectory; public static String getMethodName(Element element){ return ((TypeElement)element.getEnclosingElement()).getQualifiedName().toString() + "." + element.getSimpleName(); @@ -113,6 +115,17 @@ public abstract class BaseProcessor extends AbstractProcessor{ @Override public boolean process(Set annotations, RoundEnvironment roundEnv){ if(round++ >= rounds) return false; //only process 1 round + if(rootDirectory == null){ + try{ + String path = Fi.get(filer.getResource(StandardLocation.CLASS_OUTPUT, "no", "no") + .toUri().toURL().toString().substring(System.getProperty("os.name").contains("Windows") ? 6 : "file:".length())) + .parent().parent().parent().parent().parent().parent().parent().toString().replace("%20", " "); + rootDirectory = Fi.get(path); + }catch(IOException e){ + throw new RuntimeException(e); + } + } + this.env = roundEnv; try{ process(roundEnv); diff --git a/annotations/src/main/java/mindustry/annotations/impl/AssetsProcess.java b/annotations/src/main/java/mindustry/annotations/impl/AssetsProcess.java index 10e258959c..46244c921f 100644 --- a/annotations/src/main/java/mindustry/annotations/impl/AssetsProcess.java +++ b/annotations/src/main/java/mindustry/annotations/impl/AssetsProcess.java @@ -5,29 +5,22 @@ import arc.scene.style.*; import arc.struct.*; import arc.util.serialization.*; import com.squareup.javapoet.*; -import mindustry.annotations.*; import mindustry.annotations.Annotations.*; +import mindustry.annotations.*; import javax.annotation.processing.*; import javax.lang.model.*; import javax.lang.model.element.*; import javax.tools.Diagnostic.*; -import javax.tools.*; import java.util.*; @SupportedAnnotationTypes("mindustry.annotations.Annotations.StyleDefaults") public class AssetsProcess extends BaseProcessor{ - private String path; @Override public void process(RoundEnvironment env) throws Exception{ - path = Fi.get(BaseProcessor.filer.createResource(StandardLocation.CLASS_OUTPUT, "no", "no") - .toUri().toURL().toString().substring(System.getProperty("os.name").contains("Windows") ? 6 : "file:".length())) - .parent().parent().parent().parent().parent().parent().toString(); - path = path.replace("%20", " "); - - processSounds("Sounds", path + "/assets/sounds", "arc.audio.Sound"); - processSounds("Musics", path + "/assets/music", "arc.audio.Music"); + processSounds("Sounds", rootDirectory + "/core/assets/sounds", "arc.audio.Sound"); + processSounds("Musics", rootDirectory + "/core/assets/music", "arc.audio.Music"); processUI(env.getElementsAnnotatedWith(StyleDefaults.class)); } @@ -38,8 +31,8 @@ public class AssetsProcess extends BaseProcessor{ MethodSpec.Builder load = MethodSpec.methodBuilder("load").addModifiers(Modifier.PUBLIC, Modifier.STATIC); MethodSpec.Builder loadStyles = MethodSpec.methodBuilder("loadStyles").addModifiers(Modifier.PUBLIC, Modifier.STATIC); MethodSpec.Builder icload = MethodSpec.methodBuilder("load").addModifiers(Modifier.PUBLIC, Modifier.STATIC); - String resources = path + "/assets-raw/sprites/ui"; - Jval icons = Jval.read(Fi.get(path + "/assets-raw/fontgen/config.json").readString()); + String resources = rootDirectory + "/core/assets-raw/sprites/ui"; + Jval icons = Jval.read(Fi.get(rootDirectory + "/core/assets-raw/fontgen/config.json").readString()); ictype.addField(FieldSpec.builder(ParameterizedTypeName.get(ObjectMap.class, String.class, TextureRegionDrawable.class), "icons", Modifier.PUBLIC, Modifier.STATIC, Modifier.FINAL).initializer("new ObjectMap<>()").build()); diff --git a/annotations/src/main/java/mindustry/annotations/impl/EntityProcess.java b/annotations/src/main/java/mindustry/annotations/impl/EntityProcess.java index 05eefc1645..6768fb906d 100644 --- a/annotations/src/main/java/mindustry/annotations/impl/EntityProcess.java +++ b/annotations/src/main/java/mindustry/annotations/impl/EntityProcess.java @@ -1,8 +1,10 @@ package mindustry.annotations.impl; +import arc.files.*; import arc.func.*; import arc.struct.*; import arc.util.*; +import arc.util.io.*; import com.squareup.javapoet.*; import com.squareup.javapoet.TypeSpec.*; import com.sun.source.tree.*; @@ -21,7 +23,7 @@ import java.lang.annotation.*; "mindustry.annotations.Annotations.BaseComponent" }) public class EntityProcess extends BaseProcessor{ - Array definitions = new Array<>(); + Array definitions = new Array<>(); Array groupDefs = new Array<>(); Array baseComponents; ObjectMap componentNames = new ObjectMap<>(); @@ -161,7 +163,7 @@ public class EntityProcess extends BaseProcessor{ //only write the block if it's a void method with several entries boolean writeBlock = first.ret().toString().equals("void") && entry.value.size > 1; - if((entry.value.first().is(Modifier.ABSTRACT) || entry.value.first().is(Modifier.NATIVE)) && entry.value.size == 1){ + if((entry.value.first().is(Modifier.ABSTRACT) || entry.value.first().is(Modifier.NATIVE)) && entry.value.size == 1 && !entry.value.first().has(InternalImpl.class)){ err(entry.value.first().up().getSimpleName() + "#" + entry.value.first() + " is an abstract method and must be implemented in some component", type); } @@ -208,7 +210,7 @@ public class EntityProcess extends BaseProcessor{ builder.addMethod(mbuilder.build()); } - definitions.add(new Definition(builder, type, components, groups)); + definitions.add(new EntityDefinition("mindustry.gen." + name, builder, type, components, groups)); } //generate groups @@ -216,6 +218,7 @@ public class EntityProcess extends BaseProcessor{ MethodSpec.Builder groupInit = MethodSpec.methodBuilder("init").addModifiers(Modifier.PUBLIC, Modifier.STATIC); for(GroupDefinition group : groupDefs){ Stype ctype = group.components.first(); + //class names for interface/group ClassName itype = ClassName.bestGuess("mindustry.gen." + interfaceName(ctype)); ClassName groupc = ClassName.bestGuess("mindustry.entities.EntityGroup"); @@ -226,16 +229,61 @@ public class EntityProcess extends BaseProcessor{ groupInit.addStatement("$L = new $T<>($L, $L)", group.name, groupc, group.def.spatial(), group.def.mapping()); } + //write the groups groupsBuilder.addMethod(groupInit.build()); write(groupsBuilder); + //load map of sync IDs + StringMap map = new StringMap(); + Fi idProps = rootDirectory.child("annotations/src/main/resources/classids.properties"); + if(!idProps.exists()) idProps.writeString(""); + PropertiesUtils.load(map, idProps.reader()); + //next ID to be used in generation + Integer max = map.values().toArray().map(Integer::parseInt).max(i -> i); + int maxID = max == null ? 0 : max + 1; + + //assign IDs + definitions.sort(Structs.comparing(t -> t.base.toString())); + for(EntityDefinition def : definitions){ + String name = def.base.fullName(); + if(map.containsKey(name)){ + def.classID = map.getInt(name); + }else{ + def.classID = maxID++; + map.put(name, def.classID + ""); + } + } + + //write assigned IDs + PropertiesUtils.store(map, idProps.writer(false), "Maps entity names to IDs. Autogenerated."); + + //build mapping class for sync IDs + TypeSpec.Builder idBuilder = TypeSpec.classBuilder("ClassMapping").addModifiers(Modifier.PUBLIC) + .addField(FieldSpec.builder(TypeName.get(Prov[].class), "mapping", Modifier.PRIVATE, Modifier.STATIC).initializer("new Prov[256]").build()) + .addMethod(MethodSpec.methodBuilder("map").addModifiers(Modifier.PUBLIC, Modifier.STATIC) + .returns(TypeName.get(Prov.class)).addParameter(int.class, "id").addStatement("return mapping[id]").build()); + + CodeBlock.Builder idStore = CodeBlock.builder(); + + //store the mappings + for(EntityDefinition def : definitions){ + //store mapping + idStore.addStatement("mapping[$L] = $L::new", def.classID, def.name); + //return mapping + def.builder.addMethod(MethodSpec.methodBuilder("classId").addAnnotation(Override.class) + .returns(int.class).addModifiers(Modifier.PUBLIC).addStatement("return " + def.classID).build()); + } + + idBuilder.addStaticBlock(idStore.build()); + + write(idBuilder); }else{ //round 2: generate actual classes and implement interfaces Array interfaces = types(EntityInterface.class); //implement each definition - for(Definition def : definitions){ + for(EntityDefinition def : definitions){ //get interface for each component for(Stype comp : def.components){ @@ -369,14 +417,17 @@ public class EntityProcess extends BaseProcessor{ } } - class Definition{ + class EntityDefinition{ final Array groups; final Array components; final TypeSpec.Builder builder; final Stype base; + final String name; + int classID; - public Definition(Builder builder, Stype base, Array components, Array groups){ + public EntityDefinition(String name, Builder builder, Stype base, Array components, Array groups){ this.builder = builder; + this.name = name; this.base = base; this.groups = groups; this.components = components; diff --git a/annotations/src/main/java/mindustry/annotations/util/Stype.java b/annotations/src/main/java/mindustry/annotations/util/Stype.java index abb6792f14..21d49c5c6a 100644 --- a/annotations/src/main/java/mindustry/annotations/util/Stype.java +++ b/annotations/src/main/java/mindustry/annotations/util/Stype.java @@ -16,6 +16,10 @@ public class Stype extends Selement{ return new Stype((TypeElement)BaseProcessor.typeu.asElement(mirror)); } + public String fullName(){ + return mirror().toString(); + } + public Array interfaces(){ return Array.with(e.getInterfaces()).map(Stype::of); } diff --git a/annotations/src/main/resources/classids.properties b/annotations/src/main/resources/classids.properties new file mode 100644 index 0000000000..c1984fdd69 --- /dev/null +++ b/annotations/src/main/resources/classids.properties @@ -0,0 +1,7 @@ +#Maps entity names to IDs. Autogenerated. +#Tue Feb 04 13:56:56 EST 2020 + +mindustry.entities.def.EntityDefs.DecalDef=1 +mindustry.entities.def.EntityDefs.EffectDef=2 +mindustry.entities.def.EntityDefs.TileDef=3 +mindustry.entities.def.EntityDefs.BulletDef=0 \ No newline at end of file diff --git a/core/src/mindustry/content/TypeIDs.java b/core/src/mindustry/content/TypeIDs.java deleted file mode 100644 index b99e321e98..0000000000 --- a/core/src/mindustry/content/TypeIDs.java +++ /dev/null @@ -1,18 +0,0 @@ -package mindustry.content; - -import mindustry.entities.effect.Fire; -import mindustry.entities.effect.Puddle; -import mindustry.entities.type.Player; -import mindustry.ctype.ContentList; -import mindustry.type.TypeID; - -public class TypeIDs implements ContentList{ - public static TypeID fire, puddle, player; - - @Override - public void load(){ - fire = new TypeID("fire", Fire::new); - puddle = new TypeID("puddle", Puddle::new); - player = new TypeID("player", Player::new); - } -} diff --git a/core/src/mindustry/core/ContentLoader.java b/core/src/mindustry/core/ContentLoader.java index 0a1d9c1db2..a2c54d9051 100644 --- a/core/src/mindustry/core/ContentLoader.java +++ b/core/src/mindustry/core/ContentLoader.java @@ -42,7 +42,6 @@ public class ContentLoader{ new Weathers(), new Planets(), new Zones(), - new TypeIDs(), //these are not really content classes, but this makes initialization easier new LegacyColorMapper(), diff --git a/core/src/mindustry/core/NetServer.java b/core/src/mindustry/core/NetServer.java index b5b2b00f9b..ec4217bb1b 100644 --- a/core/src/mindustry/core/NetServer.java +++ b/core/src/mindustry/core/NetServer.java @@ -12,7 +12,6 @@ import mindustry.annotations.Annotations.*; import mindustry.content.*; import mindustry.core.GameState.*; import mindustry.entities.*; -import mindustry.entities.traits.*; import mindustry.entities.type.*; import mindustry.gen.*; import mindustry.entities.units.*; diff --git a/core/src/mindustry/entities/Predict.java b/core/src/mindustry/entities/Predict.java index 32a812ac8f..db63c504c3 100644 --- a/core/src/mindustry/entities/Predict.java +++ b/core/src/mindustry/entities/Predict.java @@ -3,8 +3,6 @@ package mindustry.entities; import arc.math.*; import arc.math.geom.*; import arc.util.*; -import mindustry.entities.traits.*; - /** * Class for predicting shoot angles based on velocities of targets. */ diff --git a/core/src/mindustry/entities/def/EntityComps.java b/core/src/mindustry/entities/def/EntityComps.java index 6d0c8690f3..ba7d3d8182 100644 --- a/core/src/mindustry/entities/def/EntityComps.java +++ b/core/src/mindustry/entities/def/EntityComps.java @@ -55,7 +55,7 @@ public class EntityComps{ @Override public void controller(UnitController controller){ this.controller = controller; - controller.set(this); + controller.unit(this); } @Override @@ -1291,7 +1291,7 @@ public class EntityComps{ } @Component - abstract class ShielderComp implements Damagec{ + abstract class ShielderComp implements Damagec, Teamc, Posc{ void absorb(){ @@ -1536,7 +1536,7 @@ public class EntityComps{ @Component @BaseComponent - class EntityComp{ + abstract class EntityComp{ private boolean added; int id; @@ -1563,5 +1563,8 @@ public class EntityComps{ T as(Class type){ return (T)this; } + + @InternalImpl + abstract int classId(); } } diff --git a/core/src/mindustry/entities/effect/Lightning.java b/core/src/mindustry/entities/effect/Lightning.java index 33ed6dc42f..58049df9ca 100644 --- a/core/src/mindustry/entities/effect/Lightning.java +++ b/core/src/mindustry/entities/effect/Lightning.java @@ -9,7 +9,6 @@ import arc.util.pooling.*; import mindustry.annotations.Annotations.*; import mindustry.content.*; import mindustry.entities.*; -import mindustry.entities.traits.*; import mindustry.entities.type.*; import mindustry.game.*; import mindustry.gen.*; diff --git a/core/src/mindustry/entities/type/Player.java b/core/src/mindustry/entities/type/Player.java index b7a6bc847b..2fc06012df 100644 --- a/core/src/mindustry/entities/type/Player.java +++ b/core/src/mindustry/entities/type/Player.java @@ -17,7 +17,6 @@ import mindustry.content.*; import mindustry.core.*; import mindustry.ctype.ContentType; import mindustry.entities.*; -import mindustry.entities.traits.*; import mindustry.entities.units.*; import mindustry.game.*; import mindustry.gen.*; diff --git a/core/src/mindustry/entities/type/base/BuilderDrone.java b/core/src/mindustry/entities/type/base/BuilderDrone.java index 4a35328797..886ecc02f2 100644 --- a/core/src/mindustry/entities/type/base/BuilderDrone.java +++ b/core/src/mindustry/entities/type/base/BuilderDrone.java @@ -5,7 +5,6 @@ import arc.math.*; import arc.struct.*; import arc.util.*; import mindustry.entities.*; -import mindustry.entities.traits.*; import mindustry.entities.type.*; import mindustry.entities.units.*; import mindustry.game.EventType.*; diff --git a/core/src/mindustry/entities/units/UnitController.java b/core/src/mindustry/entities/units/UnitController.java index de87597c82..0c0bfd4832 100644 --- a/core/src/mindustry/entities/units/UnitController.java +++ b/core/src/mindustry/entities/units/UnitController.java @@ -3,10 +3,7 @@ package mindustry.entities.units; import mindustry.gen.*; //TODO rename -public abstract class UnitController{ - protected Unitc unit; - - public void set(Unitc unit){ - this.unit = unit; - } +public interface UnitController{ + void unit(Unitc unit); + Unitc unit(); } diff --git a/core/src/mindustry/type/TypeID.java b/core/src/mindustry/type/TypeID.java index 8630dfa219..23cff352d0 100644 --- a/core/src/mindustry/type/TypeID.java +++ b/core/src/mindustry/type/TypeID.java @@ -3,8 +3,6 @@ package mindustry.type; import arc.func.*; import mindustry.ctype.*; import mindustry.ctype.ContentType; -import mindustry.entities.traits.*; - public class TypeID extends MappableContent{ public final Prov constructor; diff --git a/core/src/mindustry/type/Weapon.java b/core/src/mindustry/type/Weapon.java index 940675784a..dc90314be9 100644 --- a/core/src/mindustry/type/Weapon.java +++ b/core/src/mindustry/type/Weapon.java @@ -7,7 +7,6 @@ import arc.util.ArcAnnotate.*; import mindustry.content.*; import mindustry.entities.*; import mindustry.entities.bullet.*; -import mindustry.entities.traits.*; import mindustry.gen.*; public class Weapon{ diff --git a/core/src/mindustry/type/Weather.java b/core/src/mindustry/type/Weather.java index b83be04262..eb0d9a9bda 100644 --- a/core/src/mindustry/type/Weather.java +++ b/core/src/mindustry/type/Weather.java @@ -4,7 +4,6 @@ import arc.util.ArcAnnotate.*; import mindustry.annotations.Annotations.*; import mindustry.ctype.*; import mindustry.entities.*; -import mindustry.entities.traits.*; import mindustry.entities.type.*; import mindustry.type.Weather.*; diff --git a/core/src/mindustry/world/blocks/defense/ForceProjector.java b/core/src/mindustry/world/blocks/defense/ForceProjector.java index 06bd20dfbb..8cc2348ad9 100644 --- a/core/src/mindustry/world/blocks/defense/ForceProjector.java +++ b/core/src/mindustry/world/blocks/defense/ForceProjector.java @@ -9,7 +9,7 @@ import arc.math.geom.*; import arc.util.*; import mindustry.content.*; import mindustry.entities.*; -import mindustry.entities.type.*; +import mindustry.gen.*; import mindustry.graphics.*; import mindustry.world.*; import mindustry.world.consumers.*; @@ -17,7 +17,7 @@ import mindustry.world.meta.*; import java.io.*; -import static mindustry.Vars.*; +import static mindustry.Vars.tilesize; public class ForceProjector extends Block{ public final int timerUse = timers++; @@ -35,12 +35,12 @@ public class ForceProjector extends Block{ private static Tile paramTile; private static ForceProjector paramBlock; private static ForceEntity paramEntity; - private static Cons shieldConsumer = trait -> { - if(trait.canBeAbsorbed() && trait.getTeam() != paramTile.getTeam() && Intersector.isInsideHexagon(trait.getX(), trait.getY(), paramBlock.realRadius(paramEntity) * 2f, paramTile.drawx(), paramTile.drawy())){ + private static Cons shieldConsumer = trait -> { + if(trait.team() != paramTile.getTeam() && Intersector.isInsideHexagon(trait.x(), trait.y(), paramBlock.realRadius(paramEntity) * 2f, paramTile.drawx(), paramTile.drawy())){ trait.absorb(); Fx.absorb.at(trait); paramEntity.hit = 1f; - paramEntity.buildup += trait.getShieldDamage() * paramEntity.warmup; + paramEntity.buildup += trait.damage() * paramEntity.warmup; } }; diff --git a/core/src/mindustry/world/blocks/storage/CoreBlock.java b/core/src/mindustry/world/blocks/storage/CoreBlock.java index 59454a4b78..a9b1bd41b8 100644 --- a/core/src/mindustry/world/blocks/storage/CoreBlock.java +++ b/core/src/mindustry/world/blocks/storage/CoreBlock.java @@ -8,7 +8,6 @@ import arc.graphics.g2d.*; import arc.math.*; import arc.math.geom.*; import mindustry.content.*; -import mindustry.entities.traits.*; import mindustry.entities.type.*; import mindustry.gen.*; import mindustry.game.EventType.*; diff --git a/core/src/mindustry/world/blocks/units/MechPad.java b/core/src/mindustry/world/blocks/units/MechPad.java index 871d3b6c65..557cd4387d 100644 --- a/core/src/mindustry/world/blocks/units/MechPad.java +++ b/core/src/mindustry/world/blocks/units/MechPad.java @@ -9,7 +9,6 @@ import arc.math.geom.*; import arc.util.*; import arc.util.ArcAnnotate.*; import mindustry.content.*; -import mindustry.entities.traits.*; import mindustry.entities.type.*; import mindustry.gen.*; import mindustry.game.EventType.*;