More multiplayer bugfixes

This commit is contained in:
Anuken
2020-06-23 22:46:28 -04:00
parent db2f61ec29
commit 843be42568
14 changed files with 75 additions and 16 deletions

View File

@@ -27,7 +27,7 @@ public class Annotations{
boolean clamped() default false; boolean clamped() default false;
} }
/** Indicates that a field will not be read from the server when syncing. */ /** Indicates that a field will not be read from the server when syncing the local player state. */
@Target({ElementType.FIELD}) @Target({ElementType.FIELD})
@Retention(RetentionPolicy.SOURCE) @Retention(RetentionPolicy.SOURCE)
public @interface SyncLocal{ public @interface SyncLocal{

View File

@@ -145,7 +145,7 @@ public class EntityIO{
if(sl){ if(sl){
ncont("else" ); ncont("else" );
st("read.f()"); io(field.type, "");
econt(); econt();
} }

View File

@@ -29,7 +29,7 @@ public class TypeIOResolver{
}else if(params.size == 1 && params.first().tname().toString().equals("arc.util.io.Reads") && !meth.isVoid()){ }else if(params.size == 1 && params.first().tname().toString().equals("arc.util.io.Reads") && !meth.isVoid()){
//1 param, one is reader, returns type //1 param, one is reader, returns type
out.readers.put(fix(meth.retn().toString()), type.fullName() + "." + meth.name()); out.readers.put(fix(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()){ }else if(params.size == 2 && params.first().tname().toString().equals("arc.util.io.Reads") && !meth.isVoid() && meth.ret().equals(meth.params().get(1).mirror())){
//2 params, one is reader, other is type, returns type - these are made to reduce garbage allocated //2 params, one is reader, other is type, returns type - these are made to reduce garbage allocated
out.mutatorReaders.put(fix(meth.retn().toString()), type.fullName() + "." + meth.name()); out.mutatorReaders.put(fix(meth.retn().toString()), type.fullName() + "." + meth.name());
} }

View File

@@ -15,7 +15,7 @@ import static mindustry.Vars.*;
public class BuilderAI extends AIController{ public class BuilderAI extends AIController{
@Override @Override
public void update(){ public void updateUnit(){
Builderc builder = (Builderc)unit; Builderc builder = (Builderc)unit;
if(builder.moving()){ if(builder.moving()){

View File

@@ -10,7 +10,7 @@ import mindustry.world.meta.*;
public class FlyingAI extends AIController{ public class FlyingAI extends AIController{
@Override @Override
public void update(){ public void updateUnit(){
if(unit.moving()){ if(unit.moving()){
unit.rotation(unit.vel().angle()); unit.rotation(unit.vel().angle());
} }

View File

@@ -24,7 +24,7 @@ public class FormationAI extends AIController implements FormationMember{
} }
@Override @Override
public void update(){ public void updateUnit(){
if(leader.dead()){ if(leader.dead()){
unit.resetController(); unit.resetController();
return; return;

View File

@@ -12,7 +12,7 @@ import static mindustry.Vars.pathfinder;
public class GroundAI extends AIController{ public class GroundAI extends AIController{
@Override @Override
public void update(){ public void updateUnit(){
if(Units.invalidateTarget(target, unit.team(), unit.x(), unit.y(), Float.MAX_VALUE)){ if(Units.invalidateTarget(target, unit.team(), unit.x(), unit.y(), Float.MAX_VALUE)){
target = null; target = null;

View File

@@ -10,7 +10,7 @@ public class SuicideAI extends GroundAI{
static boolean blockedByBlock; static boolean blockedByBlock;
@Override @Override
public void update(){ public void updateUnit(){
if(Units.invalidateTarget(target, unit.team(), unit.x(), unit.y(), Float.MAX_VALUE)){ if(Units.invalidateTarget(target, unit.team(), unit.x(), unit.y(), Float.MAX_VALUE)){
target = null; target = null;

View File

@@ -2,6 +2,7 @@ package mindustry.entities;
import arc.func.*; import arc.func.*;
import arc.math.geom.*; import arc.math.geom.*;
import mindustry.annotations.Annotations.*;
import mindustry.game.*; import mindustry.game.*;
import mindustry.gen.*; import mindustry.gen.*;
import mindustry.world.*; import mindustry.world.*;
@@ -15,6 +16,11 @@ public class Units{
private static float cdist; private static float cdist;
private static boolean boolResult; private static boolean boolResult;
@Remote(called = Loc.server)
public static void onUnitDeath(Unitc unit){
unit.killed();
}
/** @return whether a new instance of a unit of this team can be created. */ /** @return whether a new instance of a unit of this team can be created. */
public static boolean canCreate(Team team){ public static boolean canCreate(Team team){
return teamIndex.count(team) < getCap(team); return teamIndex.count(team) < getCap(team);

View File

@@ -29,8 +29,8 @@ abstract class BlockUnitComp implements Unitc{
} }
} }
@Replace @Override
public void kill(){ public void killed(){
tile.kill(); tile.kill();
} }

View File

@@ -23,7 +23,8 @@ import static mindustry.Vars.*;
@Component @Component
abstract class UnitComp implements Healthc, Physicsc, Hitboxc, Statusc, Teamc, Itemsc, Rotc, Unitc, Weaponsc, Drawc, Boundedc, Syncc, Shieldc, Displayable{ abstract class UnitComp implements Healthc, Physicsc, Hitboxc, Statusc, Teamc, Itemsc, Rotc, Unitc, Weaponsc, Drawc, Boundedc, Syncc, Shieldc, Displayable{
@Import float x, y, rotation, elevation, maxHealth, drag, armor, hitSize; @Import float x, y, rotation, elevation, maxHealth, drag, armor, hitSize, health;
@Import boolean dead;
private UnitController controller; private UnitController controller;
private UnitType type; private UnitType type;
@@ -191,7 +192,10 @@ abstract class UnitComp implements Healthc, Physicsc, Hitboxc, Statusc, Teamc, I
} }
} }
controller.update(); //AI only updates on the server
if(!net.client()){
controller.updateUnit();
}
//remove units spawned by the core //remove units spawned by the core
if(spawnedByCore && !isPlayer()){ if(spawnedByCore && !isPlayer()){
@@ -227,6 +231,9 @@ abstract class UnitComp implements Healthc, Physicsc, Hitboxc, Statusc, Teamc, I
@Override @Override
public void killed(){ public void killed(){
health = 0;
dead = true;
float explosiveness = 2f + item().explosiveness * stack().amount; float explosiveness = 2f + item().explosiveness * stack().amount;
float flammability = item().flammability * stack().amount; float flammability = item().flammability * stack().amount;
Damage.dynamicExplosion(x, y, flammability, explosiveness, 0f, bounds() / 2f, Pal.darkFlame); Damage.dynamicExplosion(x, y, flammability, explosiveness, 0f, bounds() / 2f, Pal.darkFlame);
@@ -241,6 +248,17 @@ abstract class UnitComp implements Healthc, Physicsc, Hitboxc, Statusc, Teamc, I
if(explosiveness > 7f && isLocal()){ if(explosiveness > 7f && isLocal()){
Events.fire(Trigger.suicideBomb); Events.fire(Trigger.suicideBomb);
} }
remove();
}
@Override
@Replace
public void kill(){
if(dead || net.client()) return;
//deaths are synced; this calls killed()
Call.onUnitDeath(this);
} }
@Override @Override

View File

@@ -22,7 +22,7 @@ abstract class WeaponsComp implements Teamc, Posc, Rotc{
static int sequenceNum = 0; static int sequenceNum = 0;
/** weapon mount array, never null */ /** weapon mount array, never null */
@ReadOnly transient WeaponMount[] mounts = {}; @ReadOnly @SyncLocal WeaponMount[] mounts = {};
@ReadOnly transient float range, aimX, aimY; @ReadOnly transient float range, aimX, aimY;
@ReadOnly transient boolean isRotate; @ReadOnly transient boolean isRotate;
boolean isShooting; boolean isShooting;

View File

@@ -10,7 +10,7 @@ public interface UnitController{
} }
default void update(){ default void updateUnit(){
} }

View File

@@ -104,7 +104,42 @@ public class TypeIO{
return Payload.read(read); return Payload.read(read);
} }
//only for players! public static void writeMounts(Writes writes, WeaponMount[] mounts){
writes.b(mounts.length);
for(WeaponMount m : mounts){
writes.b((m.shoot ? 1 : 0) | (m.rotate ? 2 : 0));
writes.f(m.aimX);
writes.f(m.aimY);
}
}
public static WeaponMount[] readMounts(Reads read, WeaponMount[] mounts){
byte len = read.b();
for(int i = 0; i < len; i++){
byte state = read.b();
float ax = read.f(), ay = read.f();
if(i <= mounts.length - 1){
WeaponMount m = mounts[i];
m.aimX = ax;
m.aimY = ay;
m.shoot = (state & 1) != 0;
m.rotate = (state & 2) != 0;
}
}
return mounts;
}
//this is irrelevant.
static final WeaponMount[] noMounts = {};
public static WeaponMount[] readMounts(Reads read){
read.skip(read.b() * (1 + 4 + 4));
return noMounts;
}
public static void writeUnit(Writes write, Unitc unit){ public static void writeUnit(Writes write, Unitc unit){
write.b(unit.isNull() ? 0 : unit instanceof BlockUnitc ? 1 : 2); write.b(unit.isNull() ? 0 : unit instanceof BlockUnitc ? 1 : 2);
//block units are special //block units are special
@@ -255,7 +290,7 @@ public class TypeIO{
//there are two cases here: //there are two cases here:
//1: prev controller was not a player, carry on //1: prev controller was not a player, carry on
//2: prev controller was a player, so replace this controller with *anything else* //2: prev controller was a player, so replace this controller with *anything else*
//...since AI doesn't update clientside it doesn't matter what //...since AI doesn't update clientside it doesn't matter
return (!(prev instanceof AIController) || (prev instanceof FormationAI)) ? new GroundAI() : prev; return (!(prev instanceof AIController) || (prev instanceof FormationAI)) ? new GroundAI() : prev;
} }
} }