From a4d49f5d174c8bffffeb32586ec9a5ec594726e3 Mon Sep 17 00:00:00 2001 From: Anuken Date: Mon, 27 Apr 2020 01:31:41 -0400 Subject: [PATCH] Automatic assignment of entities --- .../annotations/entity/EntityProcess.java | 5 ++-- .../resources/revisions/PlayerEntity/1.json | 1 + core/src/mindustry/content/Fx.java | 2 +- core/src/mindustry/core/Control.java | 14 ++++++--- core/src/mindustry/entities/AllDefs.java | 18 ++++++------ core/src/mindustry/entities/Units.java | 18 ++++++++++++ .../mindustry/entities/def/PlayerComp.java | 9 +++++- core/src/mindustry/game/EventType.java | 4 +++ core/src/mindustry/input/InputHandler.java | 29 +++++++++++++++++-- core/src/mindustry/io/SaveIO.java | 16 +++++----- core/src/mindustry/io/SaveVersion.java | 15 ++++++++-- 11 files changed, 102 insertions(+), 29 deletions(-) create mode 100644 annotations/src/main/resources/revisions/PlayerEntity/1.json diff --git a/annotations/src/main/java/mindustry/annotations/entity/EntityProcess.java b/annotations/src/main/java/mindustry/annotations/entity/EntityProcess.java index 4b146c2cb3..e0cc24ebf6 100644 --- a/annotations/src/main/java/mindustry/annotations/entity/EntityProcess.java +++ b/annotations/src/main/java/mindustry/annotations/entity/EntityProcess.java @@ -173,7 +173,8 @@ public class EntityProcess extends BaseProcessor{ GroupDef an = group.annotation(GroupDef.class); Array types = types(an, GroupDef::value).map(this::interfaceToComp); Array collides = types(an, GroupDef::collide); - groupDefs.add(new GroupDefinition(group.name(), ClassName.bestGuess(packageName + "." + interfaceName(types.first())), types, an.spatial(), an.mapping(), collides)); + groupDefs.add(new GroupDefinition(group.name().startsWith("g") ? group.name().substring(1) : group.name(), + ClassName.bestGuess(packageName + "." + interfaceName(types.first())), types, an.spatial(), an.mapping(), collides)); } ObjectMap usedNames = new ObjectMap<>(); @@ -436,7 +437,7 @@ public class EntityProcess extends BaseProcessor{ for(GroupDefinition group : groupDefs){ for(Stype collide : group.collides){ - groupUpdate.addStatement("$L.collide($L)", group.name, collide.name()); + groupUpdate.addStatement("$L.collide($L)", group.name, collide.name().startsWith("g") ? collide.name().substring(1) : collide.name()); } } diff --git a/annotations/src/main/resources/revisions/PlayerEntity/1.json b/annotations/src/main/resources/revisions/PlayerEntity/1.json new file mode 100644 index 0000000000..ed43d8146e --- /dev/null +++ b/annotations/src/main/resources/revisions/PlayerEntity/1.json @@ -0,0 +1 @@ +{version:1,fields:[{name:admin,type:boolean,size:1},{name:color,type:arc.graphics.Color,size:-1},{name:deathTimer,type:float,size:4},{name:lastText,type:java.lang.String,size:-1},{name:mouseX,type:float,size:4},{name:mouseY,type:float,size:4},{name:name,type:java.lang.String,size:-1},{name:team,type:mindustry.game.Team,size:-1},{name:textFadeTime,type:float,size:4},{name:typing,type:boolean,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/Fx.java b/core/src/mindustry/content/Fx.java index 82d456bae5..a0f2bc11b7 100644 --- a/core/src/mindustry/content/Fx.java +++ b/core/src/mindustry/content/Fx.java @@ -54,7 +54,7 @@ public class Fx{ reset(); }), - unitSpirit = new Effect(20f, e -> { + unitSpirit = new Effect(17f, e -> { if(!(e.data instanceof Position)) return; Position to = e.data(); diff --git a/core/src/mindustry/core/Control.java b/core/src/mindustry/core/Control.java index 5f1ce60fe2..ce48eb26bb 100644 --- a/core/src/mindustry/core/Control.java +++ b/core/src/mindustry/core/Control.java @@ -5,6 +5,7 @@ import arc.assets.*; import arc.audio.*; import arc.graphics.g2d.*; import arc.input.*; +import arc.math.*; import arc.scene.ui.*; import arc.struct.*; import arc.util.*; @@ -68,14 +69,19 @@ public class Control implements ApplicationListener, Loadable{ }); Events.on(WorldLoadEvent.class, event -> { - //TODO test this - app.post(() -> app.post(() -> { - //TODO 0,0 seems like a bad choice? + if(Mathf.zero(player.x()) && Mathf.zero(player.y())){ Tilec core = state.teams.closestCore(0, 0, player.team()); if(core != null){ + player.set(core); camera.position.set(core); } - })); + }else{ + camera.position.set(player); + } + }); + + Events.on(SaveLoadEvent.class, event -> { + input.checkUnit(); }); Events.on(ResetEvent.class, event -> { diff --git a/core/src/mindustry/entities/AllDefs.java b/core/src/mindustry/entities/AllDefs.java index 318b1b0b85..ca88a8b688 100644 --- a/core/src/mindustry/entities/AllDefs.java +++ b/core/src/mindustry/entities/AllDefs.java @@ -6,37 +6,37 @@ import mindustry.gen.*; class AllDefs{ @GroupDef(value = Entityc.class, mapping = true) - class all{ + class gall{ } @GroupDef(value = Playerc.class, mapping = true) - class player{ + class gplayer{ } - @GroupDef(value = Bulletc.class, spatial = true, collide = {unit.class}) - class bullet{ + @GroupDef(value = Bulletc.class, spatial = true, collide = {gunit.class}) + class gbullet{ } - @GroupDef(value = Unitc.class, spatial = true, collide = {unit.class}, mapping = true) - class unit{ + @GroupDef(value = Unitc.class, spatial = true, collide = {gunit.class}, mapping = true) + class gunit{ } @GroupDef(Tilec.class) - class tile{ + class gtile{ } @GroupDef(value = Syncc.class, mapping = true) - class sync{ + class gsync{ } @GroupDef(Drawc.class) - class draw{ + class gdraw{ } } diff --git a/core/src/mindustry/entities/Units.java b/core/src/mindustry/entities/Units.java index ada57972ad..354efb576a 100644 --- a/core/src/mindustry/entities/Units.java +++ b/core/src/mindustry/entities/Units.java @@ -126,6 +126,24 @@ public class Units{ return result; } + /** Returns the closest ally of this team. Filter by predicate. No range. */ + public static Unitc closest(Team team, float x, float y, Boolf predicate){ + result = null; + cdist = 0f; + + for(Unitc e : Groups.unit){ + if(!predicate.get(e) || e.team() != team) continue; + + float dist = e.dst2(x, y); + if(result == null || dist < cdist){ + result = e; + cdist = dist; + } + } + + return result; + } + /** Returns the closest ally of this team. Filter by predicate. */ public static Unitc closest(Team team, float x, float y, float range, Boolf predicate){ result = null; diff --git a/core/src/mindustry/entities/def/PlayerComp.java b/core/src/mindustry/entities/def/PlayerComp.java index 68504de501..f3bbb2fd3f 100644 --- a/core/src/mindustry/entities/def/PlayerComp.java +++ b/core/src/mindustry/entities/def/PlayerComp.java @@ -25,6 +25,8 @@ import static mindustry.Vars.*; @EntityDef(value = {Playerc.class}, serialize = false) @Component abstract class PlayerComp implements UnitController, Entityc, Syncc, Timerc, Drawc{ + static final float deathDelay = 30f; + @NonNull @ReadOnly Unitc unit = Nulls.unit; @ReadOnly Team team = Team.sharded; @@ -33,6 +35,7 @@ abstract class PlayerComp implements UnitController, Entityc, Syncc, Timerc, Dra boolean admin, typing; Color color = new Color(); float mouseX, mouseY; + float deathTimer; String lastText = ""; float textFadeTime; @@ -76,8 +79,12 @@ abstract class PlayerComp implements UnitController, Entityc, Syncc, Timerc, Dra x(unit.x()); y(unit.y()); unit.team(team); + deathTimer = 0; }else if(core != null){ - core.requestSpawn((Playerc)this); + deathTimer += Time.delta(); + if(deathTimer >= deathDelay){ + core.requestSpawn((Playerc)this); + } } textFadeTime -= Time.delta() / (60 * 5); diff --git a/core/src/mindustry/game/EventType.java b/core/src/mindustry/game/EventType.java index 590b9e6f1c..036a7417e2 100644 --- a/core/src/mindustry/game/EventType.java +++ b/core/src/mindustry/game/EventType.java @@ -91,6 +91,10 @@ public class EventType{ } } + public static class SaveLoadEvent{ + + } + public static class ClientCreateEvent{ } diff --git a/core/src/mindustry/input/InputHandler.java b/core/src/mindustry/input/InputHandler.java index 24819ea5cd..a34471f956 100644 --- a/core/src/mindustry/input/InputHandler.java +++ b/core/src/mindustry/input/InputHandler.java @@ -55,6 +55,7 @@ public abstract class InputHandler implements InputProcessor, GestureListener{ public boolean droppingItem; public Group uiGroup; public boolean isShooting, isBuilding = true, buildWasAutoPaused = false; + public UnitType controlledType; protected @Nullable Schematic lastSchematic; protected GestureDetector detector; @@ -174,9 +175,7 @@ public abstract class InputHandler implements InputProcessor, GestureListener{ player.clearUnit(); //make sure it's AI controlled, so players can't overwrite each other }else if(unit.isAI() && unit.team() == player.team()){ - Time.runTask(Fx.unitSpirit.lifetime * 0.87f, () -> { - player.unit(unit); - }); + player.unit(unit); Time.run(Fx.unitSpirit.lifetime, () -> Fx.unitControl.at(unit.x(), unit.y(), 0f, unit)); if(!player.dead()){ Fx.unitSpirit.at(player.x(), player.y(), 0f, unit); @@ -198,6 +197,30 @@ public abstract class InputHandler implements InputProcessor, GestureListener{ public void update(){ player.typing(ui.chatfrag.shown()); + + if(!player.dead()){ + controlledType = player.unit().type(); + } + + 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); + } + } + } + + 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){ + if(net.client()){ + Call.onUnitControl(player, unit); + }else{ + unit.controller(player); + } + } + } } public float getMouseX(){ diff --git a/core/src/mindustry/io/SaveIO.java b/core/src/mindustry/io/SaveIO.java index a728e6c0c2..9f637224d9 100644 --- a/core/src/mindustry/io/SaveIO.java +++ b/core/src/mindustry/io/SaveIO.java @@ -1,17 +1,18 @@ package mindustry.io; +import arc.*; +import arc.files.*; import arc.struct.*; -import arc.files.Fi; -import arc.util.io.CounterInputStream; -import arc.util.io.FastDeflaterOutputStream; -import mindustry.Vars; +import arc.util.io.*; +import mindustry.*; +import mindustry.game.EventType.*; import mindustry.io.legacy.*; import mindustry.io.versions.*; -import mindustry.world.WorldContext; +import mindustry.world.*; import java.io.*; -import java.util.Arrays; -import java.util.zip.InflaterInputStream; +import java.util.*; +import java.util.zip.*; import static mindustry.Vars.*; @@ -151,6 +152,7 @@ public class SaveIO{ SaveVersion ver = versions.get(version); ver.read(stream, counter, context); + Events.fire(new SaveLoadEvent()); }catch(Exception e){ throw new SaveException(e); }finally{ diff --git a/core/src/mindustry/io/SaveVersion.java b/core/src/mindustry/io/SaveVersion.java index 8ff67ee747..7f1aad622d 100644 --- a/core/src/mindustry/io/SaveVersion.java +++ b/core/src/mindustry/io/SaveVersion.java @@ -1,5 +1,7 @@ package mindustry.io; +import arc.*; +import arc.math.geom.*; import arc.struct.*; import arc.util.*; import arc.util.io.*; @@ -69,7 +71,9 @@ public abstract class SaveVersion extends SaveFileReader{ "rules", JsonIO.write(state.rules), "mods", JsonIO.write(mods.getModStrings().toArray(String.class)), "width", world.width(), - "height", world.height() + "height", world.height(), + "viewpos", Tmp.v1.set(player == null ? Vec2.ZERO : player).toString(), + "controlledType", headless || control.input.controlledType == null ? "null" : control.input.controlledType.name ).merge(tags)); } @@ -83,6 +87,14 @@ public abstract class SaveVersion extends SaveFileReader{ if(state.rules.spawns.isEmpty()) state.rules.spawns = defaultWaves.get(); lastReadBuild = map.getInt("build", -1); + if(!headless){ + Tmp.v1.tryFromString(map.get("viewpos")); + Core.camera.position.set(Tmp.v1); + player.set(Tmp.v1); + + control.input.controlledType = content.getByName(ContentType.unit, map.get("controlledType")); + } + Map worldmap = maps.byName(map.get("mapname", "\\\\\\")); state.map = worldmap == null ? new Map(StringMap.of( "name", map.get("mapname", "Unknown"), @@ -184,7 +196,6 @@ public abstract class SaveVersion extends SaveFileReader{ //read blocks for(int i = 0; i < width * height; i++){ - int x = i % width, y = i / width; Block block = content.block(stream.readShort()); Tile tile = context.tile(i); if(block == null) block = Blocks.air;