From e16aa5a74ac1a29d2e612e52758aa51b3e01f657 Mon Sep 17 00:00:00 2001 From: Anuken Date: Sun, 24 May 2020 15:38:40 -0400 Subject: [PATCH] Sync progress --- .../mindustry/annotations/Annotations.java | 6 +- .../annotations/entity/EntityIO.java | 4 + .../annotations/entity/EntityProcess.java | 15 ++-- .../annotations/util/TypeIOResolver.java | 14 ++-- .../revisions/BlockUnitUnitEntity/0.json | 2 +- .../revisions/BuilderLegsUnitEntity/0.json | 2 +- .../revisions/BuilderMinerUnitEntity/0.json | 2 +- .../revisions/BuilderUnitEntity/0.json | 2 +- .../resources/revisions/BulletEntity/0.json | 1 + .../CommanderUnitWaterMoveEntity/0.json | 2 +- .../resources/revisions/DecalEntity/0.json | 1 + .../resources/revisions/EffectEntity/0.json | 1 + .../resources/revisions/LegsUnitEntity/0.json | 2 +- .../revisions/MinerUnitEntity/0.json | 2 +- .../resources/revisions/PlayerEntity/0.json | 1 + .../resources/revisions/TileEntity/0.json | 1 + .../resources/revisions/UnitEntity/0.json | 2 +- core/src/mindustry/core/NetClient.java | 2 +- core/src/mindustry/core/NetServer.java | 1 + .../mindustry/entities/comp/PlayerComp.java | 22 +++-- .../src/mindustry/entities/comp/SyncComp.java | 1 + .../mindustry/entities/comp/TimerComp.java | 2 +- .../src/mindustry/entities/comp/UnitComp.java | 2 +- .../mindustry/entities/comp/WeaponsComp.java | 3 +- core/src/mindustry/io/TypeIO.java | 82 +++++++++++++++++-- core/src/mindustry/type/ItemStack.java | 6 ++ gradle.properties | 2 +- 27 files changed, 139 insertions(+), 44 deletions(-) create mode 100644 annotations/src/main/resources/revisions/BulletEntity/0.json create mode 100644 annotations/src/main/resources/revisions/DecalEntity/0.json create mode 100644 annotations/src/main/resources/revisions/EffectEntity/0.json create mode 100644 annotations/src/main/resources/revisions/PlayerEntity/0.json create mode 100644 annotations/src/main/resources/revisions/TileEntity/0.json diff --git a/annotations/src/main/java/mindustry/annotations/Annotations.java b/annotations/src/main/java/mindustry/annotations/Annotations.java index 37c1ee2929..fbc5845a18 100644 --- a/annotations/src/main/java/mindustry/annotations/Annotations.java +++ b/annotations/src/main/java/mindustry/annotations/Annotations.java @@ -80,9 +80,11 @@ public class Annotations{ boolean isFinal() default true; /** If true, entities are recycled. */ boolean pooled() default false; - /** Whether to serialize (makes the serialize method return this value) */ + /** Whether to serialize (makes the serialize method return this value). + * If true, this entity is automatically put into save files. + * If false, no serialization code is generated at all. */ boolean serialize() default true; - /** Whether to generate IO code */ + /** Whether to generate IO code. This is for advanced usage only. */ boolean genio() default true; } diff --git a/annotations/src/main/java/mindustry/annotations/entity/EntityIO.java b/annotations/src/main/java/mindustry/annotations/entity/EntityIO.java index f9a5bb50da..853a96b162 100644 --- a/annotations/src/main/java/mindustry/annotations/entity/EntityIO.java +++ b/annotations/src/main/java/mindustry/annotations/entity/EntityIO.java @@ -133,6 +133,8 @@ public class EntityIO{ io(field.type, "this." + (sf != null ? field.name + targetSuf : field.name) + " = "); } + + st("afterSync()"); } } @@ -196,6 +198,8 @@ public class EntityIO{ } }else if(serializer.writers.containsKey(type) && write){ st("$L(write, $L)", serializer.writers.get(type), field); + }else if(serializer.mutatorReaders.containsKey(type) && !write && !field.replace(" = ", "").contains(" ")){ + st("$L$L(read, $L)", field, serializer.mutatorReaders.get(type), field.replace(" = ", "")); }else if(serializer.readers.containsKey(type) && !write){ st("$L$L(read)", field, serializer.readers.get(type)); }else if(type.endsWith("[]")){ //it's a 1D array diff --git a/annotations/src/main/java/mindustry/annotations/entity/EntityProcess.java b/annotations/src/main/java/mindustry/annotations/entity/EntityProcess.java index da68df755b..1800b3c311 100644 --- a/annotations/src/main/java/mindustry/annotations/entity/EntityProcess.java +++ b/annotations/src/main/java/mindustry/annotations/entity/EntityProcess.java @@ -287,8 +287,9 @@ public class EntityProcess extends BaseProcessor{ .addModifiers(Modifier.PUBLIC) .addStatement("return $S + $L", name + "#", "id").build()); - EntityIO io = ann.serialize() ? new EntityIO(type.name(), builder, serializer, rootDirectory.child("annotations/src/main/resources/revisions").child(name)) : null; - boolean hasIO = ann.genio() && ann.serialize(); + EntityIO io = new EntityIO(type.name(), builder, serializer, rootDirectory.child("annotations/src/main/resources/revisions").child(name)); + //entities with no sync comp and no serialization gen no code + boolean hasIO = ann.genio() && (components.contains(s -> s.name().contains("Sync")) || ann.serialize()); //add all methods from components for(ObjectMap.Entry> entry : methods){ @@ -347,20 +348,20 @@ public class EntityProcess extends BaseProcessor{ } } - if(io != null){ + if(hasIO){ //SPECIAL CASE: I/O code //note that serialization is generated even for non-serializing entities for manual usage - if((first.name().equals("read") || first.name().equals("write")) && hasIO){ + if((first.name().equals("read") || first.name().equals("write"))){ io.write(mbuilder, first.name().equals("write")); } //SPECIAL CASE: sync I/O code - if((first.name().equals("readSync") || first.name().equals("writeSync")) && hasIO){ + if((first.name().equals("readSync") || first.name().equals("writeSync"))){ io.writeSync(mbuilder, first.name().equals("writeSync"), syncedFields); } //SPECIAL CASE: sync I/O code for writing to/from a manual buffer - if((first.name().equals("readSyncManual") || first.name().equals("writeSyncManual")) && hasIO){ + if((first.name().equals("readSyncManual") || first.name().equals("writeSyncManual"))){ io.writeSyncManual(mbuilder, first.name().equals("writeSyncManual"), syncedFields); } @@ -369,7 +370,7 @@ public class EntityProcess extends BaseProcessor{ io.writeInterpolate(mbuilder, syncedFields); } - //snap to target position + //SPECIAL CASE: method to snap to target position after being read for the first time if(first.name().equals("snapSync")){ mbuilder.addStatement("updateSpacing = 16"); mbuilder.addStatement("lastUpdated = $T.millis()", Time.class); diff --git a/annotations/src/main/java/mindustry/annotations/util/TypeIOResolver.java b/annotations/src/main/java/mindustry/annotations/util/TypeIOResolver.java index d0359ba51c..9c4d0e9139 100644 --- a/annotations/src/main/java/mindustry/annotations/util/TypeIOResolver.java +++ b/annotations/src/main/java/mindustry/annotations/util/TypeIOResolver.java @@ -16,7 +16,7 @@ public class TypeIOResolver{ * Maps fully qualified class names to their serializers. */ public static ClassSerializer resolve(BaseProcessor processor){ - ClassSerializer out = new ClassSerializer(new ObjectMap<>(), new ObjectMap<>()); + ClassSerializer out = new ClassSerializer(new ObjectMap<>(), new ObjectMap<>(), new ObjectMap<>()); for(Stype type : processor.types(TypeIOHandler.class)){ //look at all TypeIOHandler methods Array methods = type.methods(); @@ -29,6 +29,9 @@ public class TypeIOResolver{ }else if(params.size == 1 && params.first().tname().toString().equals("arc.util.io.Reads") && !meth.isVoid()){ //1 param, one is reader, returns type out.readers.put(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()){ + //2 params, one is reader, other is type, returns type - these are made to reduce garbage allocated + out.mutatorReaders.put(meth.retn().toString(), type.fullName() + "." + meth.name()); } } } @@ -39,15 +42,12 @@ public class TypeIOResolver{ /** Information about read/write methods for class types. */ public static class ClassSerializer{ - public final ObjectMap writers, readers; + public final ObjectMap writers, readers, mutatorReaders; - public ClassSerializer(ObjectMap writers, ObjectMap readers){ + public ClassSerializer(ObjectMap writers, ObjectMap readers, ObjectMap mutatorReaders){ this.writers = writers; this.readers = readers; - } - - public boolean has(String type){ - return writers.containsKey(type) && readers.containsKey(type); + this.mutatorReaders = mutatorReaders; } } } diff --git a/annotations/src/main/resources/revisions/BlockUnitUnitEntity/0.json b/annotations/src/main/resources/revisions/BlockUnitUnitEntity/0.json index 56bbd65f1b..46ca7005e0 100644 --- a/annotations/src/main/resources/revisions/BlockUnitUnitEntity/0.json +++ b/annotations/src/main/resources/revisions/BlockUnitUnitEntity/0.json @@ -1 +1 @@ -{fields:[{name:armor,type:float,size:4},{name:elevation,type:float,size:4},{name:health,type:float,size:4},{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.Array,size:-1},{name:team,type:mindustry.game.Team,size:-1},{name:tile,type:Tilec,size:-1},{name:type,type:mindustry.type.UnitType,size:-1},{name:vel,type:arc.math.geom.Vec2,size:-1},{name:x,type:float,size:4},{name:y,type:float,size:4}]} \ No newline at end of file +{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.Array,size:-1},{name:team,type:mindustry.game.Team,size:-1},{name:tile,type:Tilec,size:-1},{name:type,type:mindustry.type.UnitType,size:-1},{name:vel,type:arc.math.geom.Vec2,size:-1},{name:x,type:float,size:4},{name:y,type:float,size:4}]} \ No newline at end of file diff --git a/annotations/src/main/resources/revisions/BuilderLegsUnitEntity/0.json b/annotations/src/main/resources/revisions/BuilderLegsUnitEntity/0.json index 4cf7451425..cb7a5d3e05 100644 --- a/annotations/src/main/resources/revisions/BuilderLegsUnitEntity/0.json +++ b/annotations/src/main/resources/revisions/BuilderLegsUnitEntity/0.json @@ -1 +1 @@ -{fields:[{name:armor,type:float,size:4},{name:baseRotation,type:float,size:4},{name:elevation,type:float,size:4},{name:health,type:float,size:4},{name:requests,type:arc.struct.Queue,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.Array,size:-1},{name:team,type:mindustry.game.Team,size:-1},{name:type,type:mindustry.type.UnitType,size:-1},{name:vel,type:arc.math.geom.Vec2,size:-1},{name:x,type:float,size:4},{name:y,type:float,size:4}]} \ No newline at end of file +{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,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.Array,size:-1},{name:team,type:mindustry.game.Team,size:-1},{name:type,type:mindustry.type.UnitType,size:-1},{name:vel,type:arc.math.geom.Vec2,size:-1},{name:x,type:float,size:4},{name:y,type:float,size:4}]} \ No newline at end of file diff --git a/annotations/src/main/resources/revisions/BuilderMinerUnitEntity/0.json b/annotations/src/main/resources/revisions/BuilderMinerUnitEntity/0.json index 68b44ba7f5..7cad47e786 100644 --- a/annotations/src/main/resources/revisions/BuilderMinerUnitEntity/0.json +++ b/annotations/src/main/resources/revisions/BuilderMinerUnitEntity/0.json @@ -1 +1 @@ -{fields:[{name:armor,type:float,size:4},{name:elevation,type:float,size:4},{name:health,type:float,size:4},{name:mineTile,type:mindustry.world.Tile,size:-1},{name:requests,type:arc.struct.Queue,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.Array,size:-1},{name:team,type:mindustry.game.Team,size:-1},{name:type,type:mindustry.type.UnitType,size:-1},{name:vel,type:arc.math.geom.Vec2,size:-1},{name:x,type:float,size:4},{name:y,type:float,size:4}]} \ No newline at end of file +{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,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.Array,size:-1},{name:team,type:mindustry.game.Team,size:-1},{name:type,type:mindustry.type.UnitType,size:-1},{name:vel,type:arc.math.geom.Vec2,size:-1},{name:x,type:float,size:4},{name:y,type:float,size:4}]} \ No newline at end of file diff --git a/annotations/src/main/resources/revisions/BuilderUnitEntity/0.json b/annotations/src/main/resources/revisions/BuilderUnitEntity/0.json index 7ccda37017..6d45f92336 100644 --- a/annotations/src/main/resources/revisions/BuilderUnitEntity/0.json +++ b/annotations/src/main/resources/revisions/BuilderUnitEntity/0.json @@ -1 +1 @@ -{fields:[{name:armor,type:float,size:4},{name:elevation,type:float,size:4},{name:health,type:float,size:4},{name:requests,type:arc.struct.Queue,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.Array,size:-1},{name:team,type:mindustry.game.Team,size:-1},{name:type,type:mindustry.type.UnitType,size:-1},{name:vel,type:arc.math.geom.Vec2,size:-1},{name:x,type:float,size:4},{name:y,type:float,size:4}]} \ No newline at end of file +{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,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.Array,size:-1},{name:team,type:mindustry.game.Team,size:-1},{name:type,type:mindustry.type.UnitType,size:-1},{name:vel,type:arc.math.geom.Vec2,size:-1},{name:x,type:float,size:4},{name:y,type:float,size:4}]} \ No newline at end of file diff --git a/annotations/src/main/resources/revisions/BulletEntity/0.json b/annotations/src/main/resources/revisions/BulletEntity/0.json new file mode 100644 index 0000000000..c9efe77456 --- /dev/null +++ b/annotations/src/main/resources/revisions/BulletEntity/0.json @@ -0,0 +1 @@ +{fields:[{name:collided,type:arc.struct.IntArray,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:vel,type:arc.math.geom.Vec2,size:-1},{name:x,type:float,size:4},{name:y,type:float,size:4}]} \ No newline at end of file diff --git a/annotations/src/main/resources/revisions/CommanderUnitWaterMoveEntity/0.json b/annotations/src/main/resources/revisions/CommanderUnitWaterMoveEntity/0.json index 3256d7ddb6..d1cff2a24e 100644 --- a/annotations/src/main/resources/revisions/CommanderUnitWaterMoveEntity/0.json +++ b/annotations/src/main/resources/revisions/CommanderUnitWaterMoveEntity/0.json @@ -1 +1 @@ -{fields:[{name:armor,type:float,size:4},{name:elevation,type:float,size:4},{name:health,type:float,size:4},{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.Array,size:-1},{name:team,type:mindustry.game.Team,size:-1},{name:type,type:mindustry.type.UnitType,size:-1},{name:vel,type:arc.math.geom.Vec2,size:-1},{name:x,type:float,size:4},{name:y,type:float,size:4}]} \ No newline at end of file +{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.Array,size:-1},{name:team,type:mindustry.game.Team,size:-1},{name:type,type:mindustry.type.UnitType,size:-1},{name:vel,type:arc.math.geom.Vec2,size:-1},{name:x,type:float,size:4},{name:y,type:float,size:4}]} \ No newline at end of file diff --git a/annotations/src/main/resources/revisions/DecalEntity/0.json b/annotations/src/main/resources/revisions/DecalEntity/0.json new file mode 100644 index 0000000000..df78246160 --- /dev/null +++ b/annotations/src/main/resources/revisions/DecalEntity/0.json @@ -0,0 +1 @@ +{fields:[{name:color,type:arc.graphics.Color,size:-1},{name:lifetime,type:float,size:4},{name:region,type:arc.graphics.g2d.TextureRegion,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}]} \ No newline at end of file diff --git a/annotations/src/main/resources/revisions/EffectEntity/0.json b/annotations/src/main/resources/revisions/EffectEntity/0.json new file mode 100644 index 0000000000..5ce16bf09c --- /dev/null +++ b/annotations/src/main/resources/revisions/EffectEntity/0.json @@ -0,0 +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}]} \ No newline at end of file diff --git a/annotations/src/main/resources/revisions/LegsUnitEntity/0.json b/annotations/src/main/resources/revisions/LegsUnitEntity/0.json index f08cc037f0..9eccbed4da 100644 --- a/annotations/src/main/resources/revisions/LegsUnitEntity/0.json +++ b/annotations/src/main/resources/revisions/LegsUnitEntity/0.json @@ -1 +1 @@ -{fields:[{name:armor,type:float,size:4},{name:baseRotation,type:float,size:4},{name:elevation,type:float,size:4},{name:health,type:float,size:4},{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.Array,size:-1},{name:team,type:mindustry.game.Team,size:-1},{name:type,type:mindustry.type.UnitType,size:-1},{name:vel,type:arc.math.geom.Vec2,size:-1},{name:x,type:float,size:4},{name:y,type:float,size:4}]} \ No newline at end of file +{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.Array,size:-1},{name:team,type:mindustry.game.Team,size:-1},{name:type,type:mindustry.type.UnitType,size:-1},{name:vel,type:arc.math.geom.Vec2,size:-1},{name:x,type:float,size:4},{name:y,type:float,size:4}]} \ No newline at end of file diff --git a/annotations/src/main/resources/revisions/MinerUnitEntity/0.json b/annotations/src/main/resources/revisions/MinerUnitEntity/0.json index 4c7131be5a..8f5ad7a649 100644 --- a/annotations/src/main/resources/revisions/MinerUnitEntity/0.json +++ b/annotations/src/main/resources/revisions/MinerUnitEntity/0.json @@ -1 +1 @@ -{fields:[{name:armor,type:float,size:4},{name:elevation,type:float,size:4},{name:health,type:float,size:4},{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.Array,size:-1},{name:team,type:mindustry.game.Team,size:-1},{name:type,type:mindustry.type.UnitType,size:-1},{name:vel,type:arc.math.geom.Vec2,size:-1},{name:x,type:float,size:4},{name:y,type:float,size:4}]} \ No newline at end of file +{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.Array,size:-1},{name:team,type:mindustry.game.Team,size:-1},{name:type,type:mindustry.type.UnitType,size:-1},{name:vel,type:arc.math.geom.Vec2,size:-1},{name:x,type:float,size:4},{name:y,type:float,size:4}]} \ No newline at end of file diff --git a/annotations/src/main/resources/revisions/PlayerEntity/0.json b/annotations/src/main/resources/revisions/PlayerEntity/0.json new file mode 100644 index 0000000000..95165898b4 --- /dev/null +++ b/annotations/src/main/resources/revisions/PlayerEntity/0.json @@ -0,0 +1 @@ +{fields:[{name:admin,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}]} \ No newline at end of file diff --git a/annotations/src/main/resources/revisions/TileEntity/0.json b/annotations/src/main/resources/revisions/TileEntity/0.json new file mode 100644 index 0000000000..c3a6d143c5 --- /dev/null +++ b/annotations/src/main/resources/revisions/TileEntity/0.json @@ -0,0 +1 @@ +{fields:[{name:cons,type:mindustry.world.modules.ConsumeModule,size:-1},{name:health,type:float,size:4},{name:items,type:mindustry.world.modules.ItemModule,size:-1},{name:liquids,type:mindustry.world.modules.LiquidModule,size:-1},{name:power,type:mindustry.world.modules.PowerModule,size:-1},{name:team,type:mindustry.game.Team,size:-1},{name:x,type:float,size:4},{name:y,type:float,size:4}]} \ No newline at end of file diff --git a/annotations/src/main/resources/revisions/UnitEntity/0.json b/annotations/src/main/resources/revisions/UnitEntity/0.json index 3256d7ddb6..d1cff2a24e 100644 --- a/annotations/src/main/resources/revisions/UnitEntity/0.json +++ b/annotations/src/main/resources/revisions/UnitEntity/0.json @@ -1 +1 @@ -{fields:[{name:armor,type:float,size:4},{name:elevation,type:float,size:4},{name:health,type:float,size:4},{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.Array,size:-1},{name:team,type:mindustry.game.Team,size:-1},{name:type,type:mindustry.type.UnitType,size:-1},{name:vel,type:arc.math.geom.Vec2,size:-1},{name:x,type:float,size:4},{name:y,type:float,size:4}]} \ No newline at end of file +{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.Array,size:-1},{name:team,type:mindustry.game.Team,size:-1},{name:type,type:mindustry.type.UnitType,size:-1},{name:vel,type:arc.math.geom.Vec2,size:-1},{name:x,type:float,size:4},{name:y,type:float,size:4}]} \ No newline at end of file diff --git a/core/src/mindustry/core/NetClient.java b/core/src/mindustry/core/NetClient.java index 4949b8bdd4..ec9ff4da09 100644 --- a/core/src/mindustry/core/NetClient.java +++ b/core/src/mindustry/core/NetClient.java @@ -567,7 +567,7 @@ public class NetClient implements ApplicationListener{ Call.onClientShapshot(lastSent++, unit.x(), unit.y(), - player.mouseX(), player.mouseY(), + player.unit().aimX(), player.unit().aimY(), unit.rotation(), unit instanceof Legsc ? ((Legsc)unit).baseRotation() : 0, unit.vel().x, unit.vel().y, diff --git a/core/src/mindustry/core/NetServer.java b/core/src/mindustry/core/NetServer.java index 056580c750..10ded99a92 100644 --- a/core/src/mindustry/core/NetServer.java +++ b/core/src/mindustry/core/NetServer.java @@ -551,6 +551,7 @@ public class NetServer implements ApplicationListener{ player.mouseX(pointerX); player.mouseY(pointerY); player.typing(chatting); + player.shooting(shooting); player.unit().controlWeapons(shooting, shooting); player.unit().aim(pointerX, pointerY); diff --git a/core/src/mindustry/entities/comp/PlayerComp.java b/core/src/mindustry/entities/comp/PlayerComp.java index 51e28f069c..7f956ded9b 100644 --- a/core/src/mindustry/entities/comp/PlayerComp.java +++ b/core/src/mindustry/entities/comp/PlayerComp.java @@ -28,17 +28,17 @@ abstract class PlayerComp implements UnitController, Entityc, Syncc, Timerc, Dra static final float deathDelay = 30f; @NonNull @ReadOnly Unitc unit = Nulls.unit; + transient @Nullable NetConnection con; @ReadOnly Team team = Team.sharded; String name = "noname"; - @Nullable NetConnection con; - boolean admin, typing; + boolean admin, typing, shooting; Color color = new Color(); float mouseX, mouseY; - float deathTimer; - String lastText = ""; - float textFadeTime; + transient float deathTimer; + transient String lastText = ""; + transient float textFadeTime; public boolean isBuilder(){ return unit instanceof Builderc; @@ -64,7 +64,16 @@ abstract class PlayerComp implements UnitController, Entityc, Syncc, Timerc, Dra @Replace public float clipSize(){ - return 20; + return unit.isNull() ? 20 : unit.type().hitsize * 2f; + } + + @Override + public void afterSync(){ + unit.aim(mouseX, mouseY); + //this is only necessary when the thing being controlled isn't synced + unit.isShooting(shooting); + //extra precaution, necessary for non-synced things + unit.controller(this); } @Override @@ -113,6 +122,7 @@ abstract class PlayerComp implements UnitController, Entityc, Syncc, Timerc, Dra public void unit(Unitc unit){ if(unit == null) throw new IllegalArgumentException("Unit cannot be null. Use clearUnit() instead."); + if(this.unit == unit) return; if(this.unit != Nulls.unit){ //un-control the old unit this.unit.controller(this.unit.type().createController()); diff --git a/core/src/mindustry/entities/comp/SyncComp.java b/core/src/mindustry/entities/comp/SyncComp.java index 2b341a0014..550c2e8363 100644 --- a/core/src/mindustry/entities/comp/SyncComp.java +++ b/core/src/mindustry/entities/comp/SyncComp.java @@ -17,6 +17,7 @@ abstract class SyncComp implements Entityc{ void writeSync(Writes write){} void readSyncManual(FloatBuffer buffer){} void writeSyncManual(FloatBuffer buffer){} + void afterSync(){} void interpolate(){} @Override diff --git a/core/src/mindustry/entities/comp/TimerComp.java b/core/src/mindustry/entities/comp/TimerComp.java index b17c84a150..26c76646d0 100644 --- a/core/src/mindustry/entities/comp/TimerComp.java +++ b/core/src/mindustry/entities/comp/TimerComp.java @@ -5,7 +5,7 @@ import mindustry.annotations.Annotations.*; @Component abstract class TimerComp{ - Interval timer = new Interval(6); + transient Interval timer = new Interval(6); public boolean timer(int index, float time){ return timer.get(index, time); diff --git a/core/src/mindustry/entities/comp/UnitComp.java b/core/src/mindustry/entities/comp/UnitComp.java index c9053593f2..22429d0767 100644 --- a/core/src/mindustry/entities/comp/UnitComp.java +++ b/core/src/mindustry/entities/comp/UnitComp.java @@ -23,7 +23,7 @@ abstract class UnitComp implements Healthc, Physicsc, Hitboxc, Statusc, Teamc, I @Import float x, y, rotation, elevation, maxHealth; - private transient UnitController controller; + private UnitController controller; private UnitType type; boolean spawnedByCore; diff --git a/core/src/mindustry/entities/comp/WeaponsComp.java b/core/src/mindustry/entities/comp/WeaponsComp.java index 427439e8ba..217f16505d 100644 --- a/core/src/mindustry/entities/comp/WeaponsComp.java +++ b/core/src/mindustry/entities/comp/WeaponsComp.java @@ -22,7 +22,8 @@ abstract class WeaponsComp implements Teamc, Posc, Rotc{ /** weapon mount array, never null */ @ReadOnly transient WeaponMount[] mounts = {}; @ReadOnly transient float range, aimX, aimY; - @ReadOnly transient boolean isRotate, isShooting; + @ReadOnly transient boolean isRotate; + boolean isShooting; void setWeaponRotation(float rotation){ for(WeaponMount mount : mounts){ diff --git a/core/src/mindustry/io/TypeIO.java b/core/src/mindustry/io/TypeIO.java index 43db19626e..51617b642a 100644 --- a/core/src/mindustry/io/TypeIO.java +++ b/core/src/mindustry/io/TypeIO.java @@ -5,6 +5,7 @@ import arc.math.geom.*; import arc.struct.*; import arc.util.io.*; import arc.util.pooling.*; +import mindustry.ai.types.*; import mindustry.annotations.Annotations.*; import mindustry.ctype.*; import mindustry.entities.bullet.*; @@ -15,6 +16,7 @@ import mindustry.net.Administration.*; import mindustry.net.Packets.*; import mindustry.type.*; import mindustry.world.*; +import mindustry.world.blocks.*; import java.io.*; import java.nio.*; @@ -26,8 +28,6 @@ import static mindustry.Vars.*; @TypeIOHandler public class TypeIO{ - //TODO read/write enums like commands! - public static void writeObject(Writes write, Object object){ if(object == null){ write.b((byte)0); @@ -87,6 +87,32 @@ public class TypeIO{ } } + //only for players! + public static void writeUnit(Writes write, Unitc unit){ + write.b(unit.isNull() ? 0 : unit instanceof BlockUnitc ? 1 : 2); + //block units are special + if(unit instanceof BlockUnitc){ + write.i(((BlockUnitc)unit).tile().pos()); + }else{ + write.i(unit.id()); + } + } + + public static Unitc readUnit(Reads read){ + byte type = read.b(); + int id = read.i(); + //nothing + if(type == 0) return Nulls.unit; + if(type == 2){ //standard unit + Unitc unit = Groups.unit.getByID(id); + return unit == null ? Nulls.unit : unit; + }else if(type == 1){ //block + Tilec tile = world.ent(id); + return tile instanceof ControlBlock ? ((ControlBlock)tile).unit() : Nulls.unit; + } + return Nulls.unit; + } + public static void writeEntity(Writes write, Entityc entity){ write.i(entity == null ? -1 : entity.id()); } @@ -184,6 +210,33 @@ public class TypeIO{ return reqs; } + public static void writeController(Writes write, UnitController control){ + //no real unit controller state is written, only the type + if(control instanceof Playerc){ + write.b(0); + write.i(((Playerc)control).id()); + }else{ + write.b(1); + } + } + + public static UnitController readController(Reads read, UnitController prev){ + byte type = read.b(); + if(type == 0){ //is player + int id = read.i(); + Playerc player = Groups.player.getByID(id); + //local players will cause problems if assigned, since they may not know they are controlling the unit + if(player == null || player.isLocal()) return prev; + return player; + }else{ + //there are two cases here: + //1: prev controller was not a player, carry on + //2: prev controller was a player, so replace this controller with *anything else* + //...since AI doesn't update clientside it doesn't matter what + return prev instanceof Playerc ? new GroundAI() : prev; + } + } + public static void writeKick(Writes write, KickReason reason){ write.b((byte)reason.ordinal()); } @@ -215,6 +268,10 @@ public class TypeIO{ } } + public static Vec2 readVec2(Reads read, Vec2 base){ + return base.set(read.f(), read.f()); + } + public static Vec2 readVec2(Reads read){ return new Vec2(read.f(), read.f()); } @@ -233,6 +290,10 @@ public class TypeIO{ write.i(stack.amount); } + public static ItemStack readItems(Reads read, ItemStack stack){ + return stack.set(readItem(read), read.i()); + } + public static ItemStack readItems(Reads read){ return new ItemStack(readItem(read), read.i()); } @@ -277,6 +338,10 @@ public class TypeIO{ return new Color(read.i()); } + public static Color readColor(Reads read, Color color){ + return color.set(read.i()); + } + public static void writeLiquid(Writes write, Liquid liquid){ write.s(liquid == null ? -1 : liquid.id); } @@ -314,18 +379,17 @@ public class TypeIO{ public static void writeString(Writes write, String string){ if(string != null){ - byte[] bytes = string.getBytes(charset); - write.s((short)bytes.length); - write.b(bytes); + write.b(1); + write.str(string); }else{ - write.s((short)-1); + write.b(0); } } public static String readString(Reads read){ - short slength = read.s(); - if(slength != -1){ - return new String(read.b(new byte[slength]), charset); + byte exists = read.b(); + if(exists != 0){ + return read.str(); }else{ return null; } diff --git a/core/src/mindustry/type/ItemStack.java b/core/src/mindustry/type/ItemStack.java index a794444204..99957c6fcb 100644 --- a/core/src/mindustry/type/ItemStack.java +++ b/core/src/mindustry/type/ItemStack.java @@ -21,6 +21,12 @@ public class ItemStack implements Comparable{ item = Items.copper; } + public ItemStack set(Item item, int amount){ + this.item = item; + this.amount = amount; + return this; + } + public ItemStack copy(){ return new ItemStack(item, amount); } diff --git a/gradle.properties b/gradle.properties index f6bced3e19..e2d47ecbd3 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,3 +1,3 @@ org.gradle.daemon=true org.gradle.jvmargs=-Xms256m -Xmx1024m -archash=88bbf067bd128651ebfa797ba64425658258e2c7 +archash=ca7245cbd7cd13b4343da2f2b105d4fc44058df2