From 7c06ba94c13fb01ddbde4c67fa4fa592d0ebbbfc Mon Sep 17 00:00:00 2001 From: Anuken Date: Sun, 24 May 2020 14:00:53 -0400 Subject: [PATCH] Autogenerated interpolation --- .../mindustry/annotations/Annotations.java | 10 ++- .../annotations/entity/EntityIO.java | 81 +++++++++++++++++++ .../annotations/entity/EntityProcess.java | 69 ++++++++++++++-- .../src/main/resources/classids.properties | 34 ++++---- .../revisions/BlockUnitUnitEntity/0.json | 1 + .../revisions/BuilderUnitEntity/0.json | 2 +- .../revisions/BuilderUnitEntity/1.json | 1 - .../revisions/BuilderUnitEntity/2.json | 1 - .../CommanderUnitWaterMoveEntity/0.json | 2 +- .../CommanderUnitWaterMoveEntity/1.json | 1 - .../CommanderUnitWaterMoveEntity/2.json | 1 - .../resources/revisions/LegsUnitEntity/0.json | 2 +- .../resources/revisions/LegsUnitEntity/1.json | 1 - .../resources/revisions/LegsUnitEntity/2.json | 1 - .../revisions/MinerUnitEntity/0.json | 2 +- .../revisions/MinerUnitEntity/1.json | 1 - .../revisions/MinerUnitEntity/2.json | 1 - .../resources/revisions/UnitEntity/0.json | 2 +- .../resources/revisions/UnitEntity/1.json | 1 - .../resources/revisions/UnitEntity/2.json | 1 - core/src/mindustry/content/UnitTypes.java | 13 --- core/src/mindustry/core/NetClient.java | 8 +- core/src/mindustry/core/NetServer.java | 42 +++++++--- .../src/mindustry/entities/comp/LegsComp.java | 4 +- .../mindustry/entities/comp/PhysicsComp.java | 14 +++- core/src/mindustry/entities/comp/PosComp.java | 2 +- core/src/mindustry/entities/comp/RotComp.java | 10 +-- .../src/mindustry/entities/comp/SyncComp.java | 33 +++----- core/src/mindustry/game/GlobalData.java | 10 +-- core/src/mindustry/input/InputHandler.java | 5 ++ core/src/mindustry/net/Interpolator.java | 66 --------------- core/src/mindustry/net/NetConnection.java | 3 + core/src/mindustry/type/UnitType.java | 2 +- .../blocks/distribution/OverflowGate.java | 2 - .../world/blocks/units/UnitBlock.java | 2 +- .../world/blocks/units/UnitFactory.java | 4 +- 36 files changed, 252 insertions(+), 183 deletions(-) create mode 100644 annotations/src/main/resources/revisions/BlockUnitUnitEntity/0.json delete mode 100644 annotations/src/main/resources/revisions/BuilderUnitEntity/1.json delete mode 100644 annotations/src/main/resources/revisions/BuilderUnitEntity/2.json delete mode 100644 annotations/src/main/resources/revisions/CommanderUnitWaterMoveEntity/1.json delete mode 100644 annotations/src/main/resources/revisions/CommanderUnitWaterMoveEntity/2.json delete mode 100644 annotations/src/main/resources/revisions/LegsUnitEntity/1.json delete mode 100644 annotations/src/main/resources/revisions/LegsUnitEntity/2.json delete mode 100644 annotations/src/main/resources/revisions/MinerUnitEntity/1.json delete mode 100644 annotations/src/main/resources/revisions/MinerUnitEntity/2.json delete mode 100644 annotations/src/main/resources/revisions/UnitEntity/1.json delete mode 100644 annotations/src/main/resources/revisions/UnitEntity/2.json delete mode 100644 core/src/mindustry/net/Interpolator.java diff --git a/annotations/src/main/java/mindustry/annotations/Annotations.java b/annotations/src/main/java/mindustry/annotations/Annotations.java index 5884f3f8f1..37c1ee2929 100644 --- a/annotations/src/main/java/mindustry/annotations/Annotations.java +++ b/annotations/src/main/java/mindustry/annotations/Annotations.java @@ -17,7 +17,15 @@ public class Annotations{ public @interface Final{ } - /** Indicates that a component field is imported from other components. */ + /** Indicates that a field will be interpolated when synced. */ + @Target({ElementType.FIELD}) + @Retention(RetentionPolicy.SOURCE) + public @interface SyncField{ + /** If true, the field will be linearly interpolated. If false, it will be interpolated as an angle. */ + boolean value(); + } + + /** Indicates that a component field is imported from other components. This means it doesn't actually exist. */ @Target({ElementType.FIELD}) @Retention(RetentionPolicy.SOURCE) public @interface Import{ diff --git a/annotations/src/main/java/mindustry/annotations/entity/EntityIO.java b/annotations/src/main/java/mindustry/annotations/entity/EntityIO.java index a9fe41a701..f9a5bb50da 100644 --- a/annotations/src/main/java/mindustry/annotations/entity/EntityIO.java +++ b/annotations/src/main/java/mindustry/annotations/entity/EntityIO.java @@ -1,12 +1,14 @@ package mindustry.annotations.entity; import arc.files.*; +import arc.math.*; import arc.struct.*; import arc.util.*; import arc.util.serialization.*; import com.squareup.javapoet.*; import mindustry.annotations.Annotations.*; import mindustry.annotations.*; +import mindustry.annotations.util.*; import mindustry.annotations.util.TypeIOResolver.*; import javax.lang.model.element.*; @@ -15,6 +17,8 @@ import static mindustry.annotations.BaseProcessor.instanceOf; public class EntityIO{ final static Json json = new Json(); + //suffixes for sync fields + final static String targetSuf = "_TARGET_", lastSuf = "_LAST_"; final ClassSerializer serializer; final String name; @@ -104,6 +108,83 @@ public class EntityIO{ } } + void writeSync(MethodSpec.Builder method, boolean write, Array syncFields) throws Exception{ + this.method = method; + this.write = write; + + if(write){ + //write uses most recent revision + for(RevisionField field : revisions.peek().fields){ + io(field.type, "this." + field.name); + } + }else{ + Revision rev = revisions.peek(); + + //base read code + st("if(lastUpdated != 0) updateSpacing = $T.timeSinceMillis(lastUpdated)", Time.class); + st("lastUpdated = $T.millis()", Time.class); + + //add code for reading revision + for(RevisionField field : rev.fields){ + Svar sf = syncFields.find(s -> s.name().equals(field.name)); + if(sf != null){ + st(field.name + lastSuf + " = this." + field.name); + } + + io(field.type, "this." + (sf != null ? field.name + targetSuf : field.name) + " = "); + } + } + } + + void writeSyncManual(MethodSpec.Builder method, boolean write, Array syncFields) throws Exception{ + this.method = method; + this.write = write; + + if(write){ + for(Svar field : syncFields){ + st("buffer.put(this.$L)", field.name()); + } + }else{ + //base read code + st("if(lastUpdated != 0) updateSpacing = $T.timeSinceMillis(lastUpdated)", Time.class); + st("lastUpdated = $T.millis()", Time.class); + + //just read the field + for(Svar field : syncFields){ + //last + st("this.$L = this.$L", field.name() + lastSuf, field.name()); + //assign target + st("this.$L = buffer.get()", field.name() + targetSuf); + } + } + } + + void writeInterpolate(MethodSpec.Builder method, Array fields) throws Exception{ + this.method = method; + + cont("if(lastUpdated != 0 && updateSpacing != 0)"); + + //base calculations + st("float timeSinceUpdate = Time.timeSinceMillis(lastUpdated)"); + st("float alpha = Math.min(timeSinceUpdate / updateSpacing, 2f)"); + + //write interpolated data, using slerp / lerp + for(Svar field : fields){ + String name = field.name(), targetName = name + targetSuf, lastName = name + lastSuf; + st("$L = $T.$L($L, $L, alpha)", name, Mathf.class, field.annotation(SyncField.class).value() ? "lerp" : "slerp", lastName, targetName); + } + + ncont("else"); //no meaningful data has arrived yet + + //write values directly to targets + for(Svar field : fields){ + String name = field.name(), targetName = name + targetSuf; + st("$L = $L", name, targetName); + } + + econt(); + } + private void io(String type, String field) throws Exception{ if(BaseProcessor.isPrimitive(type)){ s(type.equals("boolean") ? "bool" : type.charAt(0) + "", field); diff --git a/annotations/src/main/java/mindustry/annotations/entity/EntityProcess.java b/annotations/src/main/java/mindustry/annotations/entity/EntityProcess.java index 1219236d3d..da68df755b 100644 --- a/annotations/src/main/java/mindustry/annotations/entity/EntityProcess.java +++ b/annotations/src/main/java/mindustry/annotations/entity/EntityProcess.java @@ -218,10 +218,13 @@ public class EntityProcess extends BaseProcessor{ //add serialize() boolean builder.addMethod(MethodSpec.methodBuilder("serialize").addModifiers(Modifier.PUBLIC, Modifier.FINAL).returns(boolean.class).addStatement("return " + ann.serialize()).build()); + //all SyncField fields + Array syncedFields = new Array<>(); + //add all components for(Stype comp : components){ - //write fields to the class; ignoring transient ones + //write fields to the class; ignoring transient/imported ones Array fields = comp.fields().select(f -> !f.has(Import.class)); for(Svar f : fields){ if(!usedFields.add(f.name())){ @@ -239,6 +242,7 @@ public class EntityProcess extends BaseProcessor{ if(f.is(Modifier.TRANSIENT)){ fbuilder.addModifiers(Modifier.TRANSIENT); } + //add initializer if it exists if(varInitializers.containsKey(f)){ fbuilder.initializer(varInitializers.get(f)); @@ -248,6 +252,24 @@ public class EntityProcess extends BaseProcessor{ fbuilder.addAnnotations(f.annotations().map(AnnotationSpec::get)); builder.addField(fbuilder.build()); specVariables.put(builder.fieldSpecs.get(builder.fieldSpecs.size() - 1), f); + + //add extra sync fields + if(f.has(SyncField.class)){ + if(!f.tname().toString().equals("float")) err("All SyncFields must be of type float", f); + + syncedFields.add(f); + + //a synced field has 3 values: + //- target state + //- last state + //- current state (the field itself, will be written to) + + //target + builder.addField(FieldSpec.builder(float.class, f.name() + EntityIO.targetSuf).addModifiers(Modifier.TRANSIENT, Modifier.PRIVATE).build()); + + //last + builder.addField(FieldSpec.builder(float.class, f.name() + EntityIO.lastSuf).addModifiers(Modifier.TRANSIENT, Modifier.PRIVATE).build()); + } } //get all utility methods from components @@ -256,6 +278,8 @@ public class EntityProcess extends BaseProcessor{ } } + syncedFields.sortComparing(Selement::name); + //override toString method builder.addMethod(MethodSpec.methodBuilder("toString") .addAnnotation(Override.class) @@ -264,6 +288,7 @@ public class EntityProcess extends BaseProcessor{ .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(); //add all methods from components for(ObjectMap.Entry> entry : methods){ @@ -322,10 +347,38 @@ public class EntityProcess extends BaseProcessor{ } } - //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")) && ann.genio() && ann.serialize()){ - io.write(mbuilder, first.name().equals("write")); + if(io != null){ + //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){ + io.write(mbuilder, first.name().equals("write")); + } + + //SPECIAL CASE: sync I/O code + if((first.name().equals("readSync") || first.name().equals("writeSync")) && hasIO){ + 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){ + io.writeSyncManual(mbuilder, first.name().equals("writeSyncManual"), syncedFields); + } + + //SPECIAL CASE: interpolate method implementation + if(first.name().equals("interpolate")){ + io.writeInterpolate(mbuilder, syncedFields); + } + + //snap to target position + if(first.name().equals("snapSync")){ + mbuilder.addStatement("updateSpacing = 16"); + mbuilder.addStatement("lastUpdated = $T.millis()", Time.class); + for(Svar field : syncedFields){ + //reset last+current state to target position + mbuilder.addStatement("$L = $L", field.name() + EntityIO.lastSuf, field.name() + EntityIO.targetSuf); + mbuilder.addStatement("$L = $L", field.name(), field.name() + EntityIO.targetSuf); + } + } } for(Smethod elem : entry.value){ @@ -373,12 +426,12 @@ public class EntityProcess extends BaseProcessor{ //implement reset() MethodSpec.Builder resetBuilder = MethodSpec.methodBuilder("reset").addModifiers(Modifier.PUBLIC); for(FieldSpec spec : builder.fieldSpecs){ - Svar variable = specVariables.get(spec); - if(variable.isAny(Modifier.STATIC, Modifier.FINAL)) continue; + @Nullable Svar variable = specVariables.get(spec); + if(variable != null && variable.isAny(Modifier.STATIC, Modifier.FINAL)) continue; if(spec.type.isPrimitive()){ //set to primitive default - resetBuilder.addStatement("$L = $L", spec.name, varInitializers.containsKey(variable) ? varInitializers.get(variable) : getDefault(spec.type.toString())); + resetBuilder.addStatement("$L = $L", spec.name, variable != null && varInitializers.containsKey(variable) ? varInitializers.get(variable) : getDefault(spec.type.toString())); }else{ //set to default null if(!varInitializers.containsKey(variable)){ diff --git a/annotations/src/main/resources/classids.properties b/annotations/src/main/resources/classids.properties index 68da37f11c..42faa6493f 100644 --- a/annotations/src/main/resources/classids.properties +++ b/annotations/src/main/resources/classids.properties @@ -1,19 +1,19 @@ #Maps entity names to IDs. Autogenerated. -alpha=14 -dart=15 -draug=0 -mindustry.entities.comp.BulletComp=1 -mindustry.entities.comp.DecalComp=2 -mindustry.entities.comp.EffectComp=3 -mindustry.entities.comp.FireComp=4 -mindustry.entities.comp.PlayerComp=5 -mindustry.entities.comp.PuddleComp=6 -mindustry.entities.comp.TileComp=7 -mindustry.type.Weather.WeatherComp=8 -mindustry.world.blocks.storage.LaunchPad.LaunchPayloadComp=9 -oculon=16 -phantom=10 -titan=11 -vanguard=12 -wraith=13 \ No newline at end of file +alpha=0 +block=1 +draug=2 +mindustry.entities.comp.BulletComp=3 +mindustry.entities.comp.DecalComp=4 +mindustry.entities.comp.EffectComp=5 +mindustry.entities.comp.FireComp=6 +mindustry.entities.comp.PlayerComp=7 +mindustry.entities.comp.PuddleComp=8 +mindustry.entities.comp.TileComp=9 +mindustry.type.Weather.WeatherComp=10 +mindustry.world.blocks.storage.LaunchPad.LaunchPayloadComp=11 +oculon=12 +phantom=13 +titan=14 +vanguard=15 +wraith=16 \ No newline at end of file diff --git a/annotations/src/main/resources/revisions/BlockUnitUnitEntity/0.json b/annotations/src/main/resources/revisions/BlockUnitUnitEntity/0.json new file mode 100644 index 0000000000..56bbd65f1b --- /dev/null +++ b/annotations/src/main/resources/revisions/BlockUnitUnitEntity/0.json @@ -0,0 +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 diff --git a/annotations/src/main/resources/revisions/BuilderUnitEntity/0.json b/annotations/src/main/resources/revisions/BuilderUnitEntity/0.json index 2b9663c159..7ccda37017 100644 --- a/annotations/src/main/resources/revisions/BuilderUnitEntity/0.json +++ b/annotations/src/main/resources/revisions/BuilderUnitEntity/0.json @@ -1 +1 @@ -{fields:[{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: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: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 diff --git a/annotations/src/main/resources/revisions/BuilderUnitEntity/1.json b/annotations/src/main/resources/revisions/BuilderUnitEntity/1.json deleted file mode 100644 index b63cb9ce23..0000000000 --- a/annotations/src/main/resources/revisions/BuilderUnitEntity/1.json +++ /dev/null @@ -1 +0,0 @@ -{version: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: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/2.json b/annotations/src/main/resources/revisions/BuilderUnitEntity/2.json deleted file mode 100644 index d694b5ff50..0000000000 --- a/annotations/src/main/resources/revisions/BuilderUnitEntity/2.json +++ /dev/null @@ -1 +0,0 @@ -{version:2,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 diff --git a/annotations/src/main/resources/revisions/CommanderUnitWaterMoveEntity/0.json b/annotations/src/main/resources/revisions/CommanderUnitWaterMoveEntity/0.json index 25aa74f6fe..3256d7ddb6 100644 --- a/annotations/src/main/resources/revisions/CommanderUnitWaterMoveEntity/0.json +++ b/annotations/src/main/resources/revisions/CommanderUnitWaterMoveEntity/0.json @@ -1 +1 @@ -{fields:[{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: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: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 diff --git a/annotations/src/main/resources/revisions/CommanderUnitWaterMoveEntity/1.json b/annotations/src/main/resources/revisions/CommanderUnitWaterMoveEntity/1.json deleted file mode 100644 index ad4b4e1eba..0000000000 --- a/annotations/src/main/resources/revisions/CommanderUnitWaterMoveEntity/1.json +++ /dev/null @@ -1 +0,0 @@ -{version: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: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/CommanderUnitWaterMoveEntity/2.json b/annotations/src/main/resources/revisions/CommanderUnitWaterMoveEntity/2.json deleted file mode 100644 index 7d12703388..0000000000 --- a/annotations/src/main/resources/revisions/CommanderUnitWaterMoveEntity/2.json +++ /dev/null @@ -1 +0,0 @@ -{version:2,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 diff --git a/annotations/src/main/resources/revisions/LegsUnitEntity/0.json b/annotations/src/main/resources/revisions/LegsUnitEntity/0.json index 1351f965a9..f08cc037f0 100644 --- a/annotations/src/main/resources/revisions/LegsUnitEntity/0.json +++ b/annotations/src/main/resources/revisions/LegsUnitEntity/0.json @@ -1 +1 @@ -{fields:[{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: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: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 diff --git a/annotations/src/main/resources/revisions/LegsUnitEntity/1.json b/annotations/src/main/resources/revisions/LegsUnitEntity/1.json deleted file mode 100644 index 1b95d1e8c9..0000000000 --- a/annotations/src/main/resources/revisions/LegsUnitEntity/1.json +++ /dev/null @@ -1 +0,0 @@ -{version: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: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/LegsUnitEntity/2.json b/annotations/src/main/resources/revisions/LegsUnitEntity/2.json deleted file mode 100644 index 9867109097..0000000000 --- a/annotations/src/main/resources/revisions/LegsUnitEntity/2.json +++ /dev/null @@ -1 +0,0 @@ -{version:2,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 diff --git a/annotations/src/main/resources/revisions/MinerUnitEntity/0.json b/annotations/src/main/resources/revisions/MinerUnitEntity/0.json index d9c2fbd34f..4c7131be5a 100644 --- a/annotations/src/main/resources/revisions/MinerUnitEntity/0.json +++ b/annotations/src/main/resources/revisions/MinerUnitEntity/0.json @@ -1 +1 @@ -{fields:[{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: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: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 diff --git a/annotations/src/main/resources/revisions/MinerUnitEntity/1.json b/annotations/src/main/resources/revisions/MinerUnitEntity/1.json deleted file mode 100644 index ba7c2381df..0000000000 --- a/annotations/src/main/resources/revisions/MinerUnitEntity/1.json +++ /dev/null @@ -1 +0,0 @@ -{version: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: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/2.json b/annotations/src/main/resources/revisions/MinerUnitEntity/2.json deleted file mode 100644 index 4a3d8a6706..0000000000 --- a/annotations/src/main/resources/revisions/MinerUnitEntity/2.json +++ /dev/null @@ -1 +0,0 @@ -{version:2,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 diff --git a/annotations/src/main/resources/revisions/UnitEntity/0.json b/annotations/src/main/resources/revisions/UnitEntity/0.json index 25aa74f6fe..3256d7ddb6 100644 --- a/annotations/src/main/resources/revisions/UnitEntity/0.json +++ b/annotations/src/main/resources/revisions/UnitEntity/0.json @@ -1 +1 @@ -{fields:[{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: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: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 diff --git a/annotations/src/main/resources/revisions/UnitEntity/1.json b/annotations/src/main/resources/revisions/UnitEntity/1.json deleted file mode 100644 index ad4b4e1eba..0000000000 --- a/annotations/src/main/resources/revisions/UnitEntity/1.json +++ /dev/null @@ -1 +0,0 @@ -{version: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: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/UnitEntity/2.json b/annotations/src/main/resources/revisions/UnitEntity/2.json deleted file mode 100644 index 7d12703388..0000000000 --- a/annotations/src/main/resources/revisions/UnitEntity/2.json +++ /dev/null @@ -1 +0,0 @@ -{version:2,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 diff --git a/core/src/mindustry/content/UnitTypes.java b/core/src/mindustry/content/UnitTypes.java index c192adcaf2..624dfc3f0a 100644 --- a/core/src/mindustry/content/UnitTypes.java +++ b/core/src/mindustry/content/UnitTypes.java @@ -48,7 +48,6 @@ public class UnitTypes implements ContentList{ dagger = new UnitType("dagger"){{ speed = 0.5f; hitsize = 8f; - mass = 1.75f; health = 130; weapons.add(new Weapon("large-weapon"){{ reload = 14f; @@ -64,7 +63,6 @@ public class UnitTypes implements ContentList{ tier = 2; speed = 0.4f; - mass = 3.5f; hitsize = 9f; range = 10f; health = 460; @@ -85,7 +83,6 @@ public class UnitTypes implements ContentList{ crawler = new UnitType("crawler"){{ speed = 0.65f; hitsize = 8f; - mass = 1.75f; health = 120; sway = 0.25f; weapons.add(new Weapon(){{ @@ -160,7 +157,6 @@ public class UnitTypes implements ContentList{ tier = 3; speed = 0.38f; - mass = 5f; hitsize = 13f; rotateSpeed = 3f; targetAir = false; @@ -184,7 +180,6 @@ public class UnitTypes implements ContentList{ speed = 0.4f; drag = 0.4f; - mass = 5f; hitsize = 10f; rotateSpeed = 3f; targetAir = false; @@ -206,7 +201,6 @@ public class UnitTypes implements ContentList{ speed = 3f; accel = 0.08f; drag = 0.01f; - mass = 1.5f; flying = true; health = 75; faceTarget = false; @@ -229,7 +223,6 @@ public class UnitTypes implements ContentList{ health = 220; speed = 2f; - mass = 3f; accel = 0.08f; drag = 0.016f; flying = true; @@ -255,7 +248,6 @@ public class UnitTypes implements ContentList{ speed = 1.1f; accel = 0.02f; drag = 0.05f; - mass = 30f; rotateSpeed = 0.5f; flying = true; lowAltitude = true; @@ -279,7 +271,6 @@ public class UnitTypes implements ContentList{ speed = 1.3f; drag = 0.1f; hitsize = 8f; - mass = 1.75f; health = 130; immunities = ObjectSet.with(StatusEffects.wet); weapons.add(new Weapon("mount-weapon"){{ @@ -331,7 +322,6 @@ public class UnitTypes implements ContentList{ mineSpeed = 2f; buildSpeed = 0.5f; drag = 0.05f; - mass = 2f; speed = 2.4f; rotateSpeed = 15f; accel = 0.1f; @@ -356,7 +346,6 @@ public class UnitTypes implements ContentList{ phantom = new UnitType("phantom"){{ flying = true; drag = 0.05f; - mass = 2f; speed = 3f; rotateSpeed = 15f; accel = 0.3f; @@ -374,10 +363,8 @@ public class UnitTypes implements ContentList{ drillTier = -1; speed = 0.6f; hitsize = 9f; - mass = 1.75f; boostMultiplier = 2f; itemCapacity = 15; - mass = 0.9f; health = 160f; buildSpeed = 0.9f; canBoost = true; diff --git a/core/src/mindustry/core/NetClient.java b/core/src/mindustry/core/NetClient.java index c4604f93d6..4949b8bdd4 100644 --- a/core/src/mindustry/core/NetClient.java +++ b/core/src/mindustry/core/NetClient.java @@ -399,11 +399,11 @@ public class NetClient implements ApplicationListener{ } //read the entity - entity.read(Reads.get(input)); + entity.readSync(Reads.get(input)); - if(created && entity.interpolator().target != null){ - //set initial starting position - entity.setNet(entity.interpolator().target.x, entity.interpolator().target.y); + if(created){ + //snap initial starting position + entity.snapSync(); } if(add){ diff --git a/core/src/mindustry/core/NetServer.java b/core/src/mindustry/core/NetServer.java index 1f300b015b..056580c750 100644 --- a/core/src/mindustry/core/NetServer.java +++ b/core/src/mindustry/core/NetServer.java @@ -36,6 +36,7 @@ import static mindustry.Vars.*; public class NetServer implements ApplicationListener{ private final static int maxSnapshotSize = 430, timerBlockSync = 0; private final static float serverSyncTime = 12, blockSyncTime = 60 * 8; + private final static FloatBuffer fbuffer = FloatBuffer.allocate(20); private final static Vec2 vector = new Vec2(); private final static Rect viewport = new Rect(); /** If a player goes away of their server-side coordinates by this distance, they get teleported back. */ @@ -598,34 +599,53 @@ public class NetServer implements ApplicationListener{ float maxSpeed = player.dead() ? Float.MAX_VALUE : player.unit().type().speed; float maxMove = elapsed / 1000f * 60f * maxSpeed * 1.1f; - vector.set(x - unit.interpolator().target.x, y - unit.interpolator().target.y); + if(connection.lastUnit != unit && !player.dead()){ + connection.lastUnit = unit; + connection.lastPosition.set(unit); + } + + vector.set(x, y).sub(connection.lastPosition); vector.limit(maxMove); float prevx = unit.x(), prevy = unit.y(); - unit.set(unit.interpolator().target.x, unit.interpolator().target.y); + unit.set(connection.lastPosition); if(!unit.isFlying()){ unit.move(vector.x, vector.y); }else{ unit.trns(vector.x, vector.y); } + + //set last position after movement + connection.lastPosition.set(unit); float newx = unit.x(), newy = unit.y(); if(!verifyPosition){ - unit.x(prevx); - unit.y(prevy); + unit.set(prevx, prevy); newx = x; newy = y; - }else if(Mathf.dst(x, y, newx, newy) > correctDist){ + }else if(!Mathf.within(x, y, newx, newy, correctDist)){ Call.onPositionSet(player.con(), newx, newy); //teleport and correct position when necessary } //reset player to previous synced position so it gets interpolated - unit.x(prevx); - unit.y(prevy); + unit.set(prevx, prevy); - //set interpolator target to *new* position so it moves toward it - unit.interpolator().read(unit.x(), unit.y(), newx, newy, rotation, baseRotation); - unit.vel().set(xVelocity, yVelocity); //only for visual calculation purposes, doesn't actually update the player + //write sync data to the buffer + fbuffer.limit(20); + fbuffer.position(0); + + //now, put the new position, rotation and baserotation into the buffer so it can be read + if(unit instanceof Legsc) fbuffer.put(baseRotation); //base rotation is optional + fbuffer.put(rotation); //rotation is always there + fbuffer.put(newx); + fbuffer.put(newy); + fbuffer.flip(); + + //read sync data so it can be used for interpolation for the server + unit.readSyncManual(fbuffer); + + //TODO fix + unit.vel().set(xVelocity, yVelocity); //only for visual calculation purposes, doesn't actually update the player (TODO or does it?) }else{ player.x(x); player.y(y); @@ -795,7 +815,7 @@ public class NetServer implements ApplicationListener{ //write all entities now dataStream.writeInt(entity.id()); //write id dataStream.writeByte(entity.classId()); //write type ID - entity.write(Writes.get(dataStream)); //write entity + entity.writeSync(Writes.get(dataStream)); //write entity sent++; diff --git a/core/src/mindustry/entities/comp/LegsComp.java b/core/src/mindustry/entities/comp/LegsComp.java index e4dc746371..d8afd9a2aa 100644 --- a/core/src/mindustry/entities/comp/LegsComp.java +++ b/core/src/mindustry/entities/comp/LegsComp.java @@ -7,9 +7,7 @@ import mindustry.gen.*; @Component abstract class LegsComp implements Posc, Flyingc, Hitboxc, Unitc, Legsc, ElevationMovec{ - @Import float x, y; - - float baseRotation; + @SyncField(false) float baseRotation; transient float walkTime; @Override diff --git a/core/src/mindustry/entities/comp/PhysicsComp.java b/core/src/mindustry/entities/comp/PhysicsComp.java index a2c44116c8..8db4ab12ff 100644 --- a/core/src/mindustry/entities/comp/PhysicsComp.java +++ b/core/src/mindustry/entities/comp/PhysicsComp.java @@ -1,5 +1,6 @@ package mindustry.entities.comp; +import arc.math.*; import mindustry.annotations.Annotations.*; import mindustry.async.PhysicsProcess.*; import mindustry.gen.*; @@ -9,10 +10,17 @@ import mindustry.gen.*; * Has mass.*/ @Component abstract class PhysicsComp implements Velc, Hitboxc, Flyingc{ - transient PhysicRef physref; - transient float mass = 1f; + @Import float hitSize; - public void impulse(float x, float y){ + transient PhysicRef physref; + + //mass is simply the area of this object + float mass(){ + return hitSize * hitSize * Mathf.pi; + } + + void impulse(float x, float y){ + float mass = mass(); vel().add(x / mass, y / mass); } } diff --git a/core/src/mindustry/entities/comp/PosComp.java b/core/src/mindustry/entities/comp/PosComp.java index df114ae81f..6fb2b08d98 100644 --- a/core/src/mindustry/entities/comp/PosComp.java +++ b/core/src/mindustry/entities/comp/PosComp.java @@ -12,7 +12,7 @@ import static mindustry.Vars.world; @Component abstract class PosComp implements Position{ - float x, y; + @SyncField(true) float x, y; void set(float x, float y){ this.x = x; diff --git a/core/src/mindustry/entities/comp/RotComp.java b/core/src/mindustry/entities/comp/RotComp.java index 548db46730..427bee4c95 100644 --- a/core/src/mindustry/entities/comp/RotComp.java +++ b/core/src/mindustry/entities/comp/RotComp.java @@ -5,13 +5,5 @@ import mindustry.gen.*; @Component abstract class RotComp implements Entityc{ - float rotation; - - void interpolate(){ - Syncc sync = as(Syncc.class); - - if(sync.interpolator().values.length > 0){ - rotation = sync.interpolator().values[0]; - } - } + @SyncField(false) float rotation; } diff --git a/core/src/mindustry/entities/comp/SyncComp.java b/core/src/mindustry/entities/comp/SyncComp.java index 0e36ebd682..2b341a0014 100644 --- a/core/src/mindustry/entities/comp/SyncComp.java +++ b/core/src/mindustry/entities/comp/SyncComp.java @@ -1,26 +1,23 @@ package mindustry.entities.comp; +import arc.util.io.*; import mindustry.*; import mindustry.annotations.Annotations.*; import mindustry.gen.*; -import mindustry.net.*; + +import java.nio.*; @Component -abstract class SyncComp implements Posc{ - @Import float x, y; +abstract class SyncComp implements Entityc{ + transient long lastUpdated, updateSpacing; - transient Interpolator interpolator = new Interpolator(); - - void setNet(float x, float y){ - set(x, y); - - //TODO change interpolator API - interpolator.target.set(x, y); - interpolator.last.set(x, y); - interpolator.pos.set(0, 0); - interpolator.updateSpacing = 16; - interpolator.lastUpdated = 0; - } + //all these method bodies are internally generated + void snapSync(){} + void readSync(Reads read){} + void writeSync(Writes write){} + void readSyncManual(FloatBuffer buffer){} + void writeSyncManual(FloatBuffer buffer){} + void interpolate(){} @Override public void update(){ @@ -28,10 +25,4 @@ abstract class SyncComp implements Posc{ interpolate(); } } - - void interpolate(){ - interpolator.update(); - x = interpolator.pos.x; - y = interpolator.pos.y; - } } diff --git a/core/src/mindustry/game/GlobalData.java b/core/src/mindustry/game/GlobalData.java index accdca9e77..f20e46a2f4 100644 --- a/core/src/mindustry/game/GlobalData.java +++ b/core/src/mindustry/game/GlobalData.java @@ -18,7 +18,7 @@ import static mindustry.Vars.*; /** Stores player unlocks. Clientside only. */ public class GlobalData{ - private ObjectMap> unlocked = new ObjectMap<>(); + private ObjectSet unlocked = new ObjectSet<>(); private ObjectIntMap items = new ObjectIntMap<>(); private boolean modified; @@ -128,7 +128,7 @@ public class GlobalData{ /** Returns whether or not this piece of content is unlocked yet. */ public boolean isUnlocked(UnlockableContent content){ - return content.alwaysUnlocked() || unlocked.getOr(content.getContentType(), ObjectSet::new).contains(content.name); + return content.alwaysUnlocked() || unlocked.contains(content.name); } /** @@ -140,7 +140,7 @@ public class GlobalData{ if(content.alwaysUnlocked()) return; //fire unlock event so other classes can use it - if(unlocked.getOr(content.getContentType(), ObjectSet::new).add(content.name)){ + if(unlocked.add(content.name)){ modified = true; content.onUnlock(); Events.fire(new UnlockEvent(content)); @@ -162,7 +162,7 @@ public class GlobalData{ @SuppressWarnings("unchecked") public void load(){ items.clear(); - unlocked = Core.settings.getJson("unlocks", ObjectMap.class, ObjectMap::new); + unlocked = Core.settings.getJson("unlocked-content", ObjectSet.class, ObjectSet::new); for(Item item : Vars.content.items()){ items.put(item, Core.settings.getInt("item-" + item.name, 0)); } @@ -174,7 +174,7 @@ public class GlobalData{ } public void save(){ - Core.settings.putJson("unlocks", unlocked); + Core.settings.putJson("unlocked-content", String.class, unlocked); for(Item item : Vars.content.items()){ Core.settings.put("item-" + item.name, items.get(item, 0)); } diff --git a/core/src/mindustry/input/InputHandler.java b/core/src/mindustry/input/InputHandler.java index bd5c15581d..495edda0e9 100644 --- a/core/src/mindustry/input/InputHandler.java +++ b/core/src/mindustry/input/InputHandler.java @@ -209,6 +209,7 @@ public abstract class InputHandler implements InputProcessor, GestureListener{ if(controlledType != null && player.dead()){ Unitc unit = Units.closest(player.team(), player.x(), player.y(), u -> !u.isPlayer() && u.type() == controlledType); + if(unit != null){ Call.onUnitControl(player, unit); } @@ -218,6 +219,10 @@ public abstract class InputHandler implements InputProcessor, GestureListener{ public void checkUnit(){ if(controlledType != null){ Unitc unit = Units.closest(player.team(), player.x(), player.y(), u -> !u.isPlayer() && u.type() == controlledType); + if(unit == null && controlledType == UnitTypes.block){ + unit = world.entWorld(player.x(), player.y()) instanceof ControlBlock ? ((ControlBlock)world.entWorld(player.x(), player.y())).unit() : null; + } + if(unit != null){ if(net.client()){ Call.onUnitControl(player, unit); diff --git a/core/src/mindustry/net/Interpolator.java b/core/src/mindustry/net/Interpolator.java deleted file mode 100644 index 7be5d327b3..0000000000 --- a/core/src/mindustry/net/Interpolator.java +++ /dev/null @@ -1,66 +0,0 @@ -package mindustry.net; - -import arc.math.*; -import arc.math.geom.*; -import arc.util.*; - -public class Interpolator{ - //used for movement - public Vec2 target = new Vec2(); - public Vec2 last = new Vec2(); - public float[] targets = {}; - public float[] lasts = {}; - public long lastUpdated, updateSpacing; - - //current state - public Vec2 pos = new Vec2(); - public float[] values = {}; - - public void read(float cx, float cy, float x, float y, float... target1ds){ - if(lastUpdated != 0) updateSpacing = Time.timeSinceMillis(lastUpdated); - - lastUpdated = Time.millis(); - - targets = target1ds; - if(lasts.length != values.length){ - lasts = new float[values.length]; - } - System.arraycopy(values, 0, lasts, 0, values.length); - last.set(cx, cy); - target.set(x, y); - } - - public void reset(){ - values = new float[0]; - targets = new float[0]; - target.setZero(); - last.setZero(); - lastUpdated = 0; - updateSpacing = 16; //1 frame - pos.setZero(); - } - - public void update(){ - if(lastUpdated != 0 && updateSpacing != 0){ - float timeSinceUpdate = Time.timeSinceMillis(lastUpdated); - float alpha = Math.min(timeSinceUpdate / updateSpacing, 2f); - - pos.set(last).lerpPast(target, alpha); - - if(values.length != targets.length){ - values = new float[targets.length]; - } - - if(lasts.length != targets.length){ - lasts = new float[targets.length]; - } - - for(int i = 0; i < values.length; i++){ - values[i] = Mathf.slerp(lasts[i], targets[i], alpha); - } - }else{ - pos.set(target); - } - - } -} diff --git a/core/src/mindustry/net/NetConnection.java b/core/src/mindustry/net/NetConnection.java index cd18e558ee..a6c5266fc7 100644 --- a/core/src/mindustry/net/NetConnection.java +++ b/core/src/mindustry/net/NetConnection.java @@ -1,5 +1,6 @@ package mindustry.net; +import arc.math.geom.*; import arc.struct.*; import arc.util.ArcAnnotate.*; import arc.util.*; @@ -18,6 +19,8 @@ public abstract class NetConnection{ public String uuid = "AAAAAAAA", usid = uuid; public boolean mobile, modclient; public @Nullable Playerc player; + public @Nullable Unitc lastUnit; + public Vec2 lastPosition = new Vec2(); /** ID of last recieved client snapshot. */ public int lastRecievedClientSnapshot = -1; diff --git a/core/src/mindustry/type/UnitType.java b/core/src/mindustry/type/UnitType.java index 77f21a55f1..e195962238 100644 --- a/core/src/mindustry/type/UnitType.java +++ b/core/src/mindustry/type/UnitType.java @@ -33,7 +33,7 @@ public class UnitType extends UnlockableContent{ public @Nullable UnitType upgrade; public int tier = 1; public float speed = 1.1f, boostMultiplier = 1f, rotateSpeed = 5f, baseRotateSpeed = 5f; - public float drag = 0.3f, mass = 1f, accel = 0.5f, landShake = 0f; + public float drag = 0.3f, accel = 0.5f, landShake = 0f; public float health = 200f, range = -1, armor = 0f; public boolean targetAir = true, targetGround = true; public boolean faceTarget = true, isCounted = true, lowAltitude = false; diff --git a/core/src/mindustry/world/blocks/distribution/OverflowGate.java b/core/src/mindustry/world/blocks/distribution/OverflowGate.java index 891a37b0df..a054e53627 100644 --- a/core/src/mindustry/world/blocks/distribution/OverflowGate.java +++ b/core/src/mindustry/world/blocks/distribution/OverflowGate.java @@ -84,8 +84,6 @@ public class OverflowGate extends Block{ lastItem = item; time = 0f; lastInput = source.tile(); - - updateTile(); } public @Nullable Tilec getTileTarget(Item item, Tile src, boolean flip){ diff --git a/core/src/mindustry/world/blocks/units/UnitBlock.java b/core/src/mindustry/world/blocks/units/UnitBlock.java index 72949789bc..2067a66ef5 100644 --- a/core/src/mindustry/world/blocks/units/UnitBlock.java +++ b/core/src/mindustry/world/blocks/units/UnitBlock.java @@ -43,7 +43,7 @@ public class UnitBlock extends PayloadAcceptor{ Unitc unit = payload.unit; unit.set(x, y); unit.rotation(rotdeg()); - unit.vel().trns(rotdeg(), payloadSpeed * 2f).add(Mathf.range(0.1f), Mathf.range(0.1f)); + unit.vel().trns(rotdeg(), payloadSpeed * 2f).add(Mathf.range(0.3f), Mathf.range(0.3f)); unit.trns(Tmp.v1.trns(rotdeg(), size * tilesize/2f)); unit.trns(unit.vel()); unit.add(); diff --git a/core/src/mindustry/world/blocks/units/UnitFactory.java b/core/src/mindustry/world/blocks/units/UnitFactory.java index 0436fba58f..8f8248a36c 100644 --- a/core/src/mindustry/world/blocks/units/UnitFactory.java +++ b/core/src/mindustry/world/blocks/units/UnitFactory.java @@ -35,8 +35,8 @@ public class UnitFactory extends UnitBlock{ hasPower = true; hasItems = true; solid = true; - flags = EnumSet.of(BlockFlag.producer, BlockFlag.unitModifier); - unitCapModifier = 4; + //flags = EnumSet.of(BlockFlag.producer, BlockFlag.unitModifier); + //unitCapModifier = 2; configurable = true; outputsPayload = true; rotate = true;