Automatic assignment of entities

This commit is contained in:
Anuken
2020-04-27 01:31:41 -04:00
parent 2f3c098b50
commit a4d49f5d17
11 changed files with 102 additions and 29 deletions

View File

@@ -173,7 +173,8 @@ public class EntityProcess extends BaseProcessor{
GroupDef an = group.annotation(GroupDef.class); GroupDef an = group.annotation(GroupDef.class);
Array<Stype> types = types(an, GroupDef::value).map(this::interfaceToComp); Array<Stype> types = types(an, GroupDef::value).map(this::interfaceToComp);
Array<Stype> collides = types(an, GroupDef::collide); Array<Stype> 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<String, Selement> usedNames = new ObjectMap<>(); ObjectMap<String, Selement> usedNames = new ObjectMap<>();
@@ -436,7 +437,7 @@ public class EntityProcess extends BaseProcessor{
for(GroupDefinition group : groupDefs){ for(GroupDefinition group : groupDefs){
for(Stype collide : group.collides){ 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());
} }
} }

View File

@@ -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}]}

View File

@@ -54,7 +54,7 @@ public class Fx{
reset(); reset();
}), }),
unitSpirit = new Effect(20f, e -> { unitSpirit = new Effect(17f, e -> {
if(!(e.data instanceof Position)) return; if(!(e.data instanceof Position)) return;
Position to = e.data(); Position to = e.data();

View File

@@ -5,6 +5,7 @@ import arc.assets.*;
import arc.audio.*; import arc.audio.*;
import arc.graphics.g2d.*; import arc.graphics.g2d.*;
import arc.input.*; import arc.input.*;
import arc.math.*;
import arc.scene.ui.*; import arc.scene.ui.*;
import arc.struct.*; import arc.struct.*;
import arc.util.*; import arc.util.*;
@@ -68,14 +69,19 @@ public class Control implements ApplicationListener, Loadable{
}); });
Events.on(WorldLoadEvent.class, event -> { Events.on(WorldLoadEvent.class, event -> {
//TODO test this if(Mathf.zero(player.x()) && Mathf.zero(player.y())){
app.post(() -> app.post(() -> {
//TODO 0,0 seems like a bad choice?
Tilec core = state.teams.closestCore(0, 0, player.team()); Tilec core = state.teams.closestCore(0, 0, player.team());
if(core != null){ if(core != null){
player.set(core);
camera.position.set(core); camera.position.set(core);
} }
})); }else{
camera.position.set(player);
}
});
Events.on(SaveLoadEvent.class, event -> {
input.checkUnit();
}); });
Events.on(ResetEvent.class, event -> { Events.on(ResetEvent.class, event -> {

View File

@@ -6,37 +6,37 @@ import mindustry.gen.*;
class AllDefs{ class AllDefs{
@GroupDef(value = Entityc.class, mapping = true) @GroupDef(value = Entityc.class, mapping = true)
class all{ class gall{
} }
@GroupDef(value = Playerc.class, mapping = true) @GroupDef(value = Playerc.class, mapping = true)
class player{ class gplayer{
} }
@GroupDef(value = Bulletc.class, spatial = true, collide = {unit.class}) @GroupDef(value = Bulletc.class, spatial = true, collide = {gunit.class})
class bullet{ class gbullet{
} }
@GroupDef(value = Unitc.class, spatial = true, collide = {unit.class}, mapping = true) @GroupDef(value = Unitc.class, spatial = true, collide = {gunit.class}, mapping = true)
class unit{ class gunit{
} }
@GroupDef(Tilec.class) @GroupDef(Tilec.class)
class tile{ class gtile{
} }
@GroupDef(value = Syncc.class, mapping = true) @GroupDef(value = Syncc.class, mapping = true)
class sync{ class gsync{
} }
@GroupDef(Drawc.class) @GroupDef(Drawc.class)
class draw{ class gdraw{
} }
} }

View File

@@ -126,6 +126,24 @@ public class Units{
return result; 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<Unitc> 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. */ /** Returns the closest ally of this team. Filter by predicate. */
public static Unitc closest(Team team, float x, float y, float range, Boolf<Unitc> predicate){ public static Unitc closest(Team team, float x, float y, float range, Boolf<Unitc> predicate){
result = null; result = null;

View File

@@ -25,6 +25,8 @@ import static mindustry.Vars.*;
@EntityDef(value = {Playerc.class}, serialize = false) @EntityDef(value = {Playerc.class}, serialize = false)
@Component @Component
abstract class PlayerComp implements UnitController, Entityc, Syncc, Timerc, Drawc{ abstract class PlayerComp implements UnitController, Entityc, Syncc, Timerc, Drawc{
static final float deathDelay = 30f;
@NonNull @ReadOnly Unitc unit = Nulls.unit; @NonNull @ReadOnly Unitc unit = Nulls.unit;
@ReadOnly Team team = Team.sharded; @ReadOnly Team team = Team.sharded;
@@ -33,6 +35,7 @@ abstract class PlayerComp implements UnitController, Entityc, Syncc, Timerc, Dra
boolean admin, typing; boolean admin, typing;
Color color = new Color(); Color color = new Color();
float mouseX, mouseY; float mouseX, mouseY;
float deathTimer;
String lastText = ""; String lastText = "";
float textFadeTime; float textFadeTime;
@@ -76,8 +79,12 @@ abstract class PlayerComp implements UnitController, Entityc, Syncc, Timerc, Dra
x(unit.x()); x(unit.x());
y(unit.y()); y(unit.y());
unit.team(team); unit.team(team);
deathTimer = 0;
}else if(core != null){ }else if(core != null){
core.requestSpawn((Playerc)this); deathTimer += Time.delta();
if(deathTimer >= deathDelay){
core.requestSpawn((Playerc)this);
}
} }
textFadeTime -= Time.delta() / (60 * 5); textFadeTime -= Time.delta() / (60 * 5);

View File

@@ -91,6 +91,10 @@ public class EventType{
} }
} }
public static class SaveLoadEvent{
}
public static class ClientCreateEvent{ public static class ClientCreateEvent{
} }

View File

@@ -55,6 +55,7 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
public boolean droppingItem; public boolean droppingItem;
public Group uiGroup; public Group uiGroup;
public boolean isShooting, isBuilding = true, buildWasAutoPaused = false; public boolean isShooting, isBuilding = true, buildWasAutoPaused = false;
public UnitType controlledType;
protected @Nullable Schematic lastSchematic; protected @Nullable Schematic lastSchematic;
protected GestureDetector detector; protected GestureDetector detector;
@@ -174,9 +175,7 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
player.clearUnit(); player.clearUnit();
//make sure it's AI controlled, so players can't overwrite each other //make sure it's AI controlled, so players can't overwrite each other
}else if(unit.isAI() && unit.team() == player.team()){ }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)); Time.run(Fx.unitSpirit.lifetime, () -> Fx.unitControl.at(unit.x(), unit.y(), 0f, unit));
if(!player.dead()){ if(!player.dead()){
Fx.unitSpirit.at(player.x(), player.y(), 0f, unit); Fx.unitSpirit.at(player.x(), player.y(), 0f, unit);
@@ -198,6 +197,30 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
public void update(){ public void update(){
player.typing(ui.chatfrag.shown()); 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(){ public float getMouseX(){

View File

@@ -1,17 +1,18 @@
package mindustry.io; package mindustry.io;
import arc.*;
import arc.files.*;
import arc.struct.*; import arc.struct.*;
import arc.files.Fi; import arc.util.io.*;
import arc.util.io.CounterInputStream; import mindustry.*;
import arc.util.io.FastDeflaterOutputStream; import mindustry.game.EventType.*;
import mindustry.Vars;
import mindustry.io.legacy.*; import mindustry.io.legacy.*;
import mindustry.io.versions.*; import mindustry.io.versions.*;
import mindustry.world.WorldContext; import mindustry.world.*;
import java.io.*; import java.io.*;
import java.util.Arrays; import java.util.*;
import java.util.zip.InflaterInputStream; import java.util.zip.*;
import static mindustry.Vars.*; import static mindustry.Vars.*;
@@ -151,6 +152,7 @@ public class SaveIO{
SaveVersion ver = versions.get(version); SaveVersion ver = versions.get(version);
ver.read(stream, counter, context); ver.read(stream, counter, context);
Events.fire(new SaveLoadEvent());
}catch(Exception e){ }catch(Exception e){
throw new SaveException(e); throw new SaveException(e);
}finally{ }finally{

View File

@@ -1,5 +1,7 @@
package mindustry.io; package mindustry.io;
import arc.*;
import arc.math.geom.*;
import arc.struct.*; import arc.struct.*;
import arc.util.*; import arc.util.*;
import arc.util.io.*; import arc.util.io.*;
@@ -69,7 +71,9 @@ public abstract class SaveVersion extends SaveFileReader{
"rules", JsonIO.write(state.rules), "rules", JsonIO.write(state.rules),
"mods", JsonIO.write(mods.getModStrings().toArray(String.class)), "mods", JsonIO.write(mods.getModStrings().toArray(String.class)),
"width", world.width(), "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)); ).merge(tags));
} }
@@ -83,6 +87,14 @@ public abstract class SaveVersion extends SaveFileReader{
if(state.rules.spawns.isEmpty()) state.rules.spawns = defaultWaves.get(); if(state.rules.spawns.isEmpty()) state.rules.spawns = defaultWaves.get();
lastReadBuild = map.getInt("build", -1); 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", "\\\\\\")); Map worldmap = maps.byName(map.get("mapname", "\\\\\\"));
state.map = worldmap == null ? new Map(StringMap.of( state.map = worldmap == null ? new Map(StringMap.of(
"name", map.get("mapname", "Unknown"), "name", map.get("mapname", "Unknown"),
@@ -184,7 +196,6 @@ public abstract class SaveVersion extends SaveFileReader{
//read blocks //read blocks
for(int i = 0; i < width * height; i++){ for(int i = 0; i < width * height; i++){
int x = i % width, y = i / width;
Block block = content.block(stream.readShort()); Block block = content.block(stream.readShort());
Tile tile = context.tile(i); Tile tile = context.tile(i);
if(block == null) block = Blocks.air; if(block == null) block = Blocks.air;