From 1a55f19ab2d1915d2588029efbe551344a373b37 Mon Sep 17 00:00:00 2001 From: Anuken Date: Mon, 16 Aug 2021 10:34:48 -0400 Subject: [PATCH] Fixed #5774 --- core/src/mindustry/entities/comp/PlayerComp.java | 7 +++++++ core/src/mindustry/input/InputHandler.java | 12 +++--------- core/src/mindustry/mod/ContentParser.java | 7 ++++--- server/src/mindustry/server/ServerControl.java | 1 - 4 files changed, 14 insertions(+), 13 deletions(-) diff --git a/core/src/mindustry/entities/comp/PlayerComp.java b/core/src/mindustry/entities/comp/PlayerComp.java index 057687ada8..07a80b1e30 100644 --- a/core/src/mindustry/entities/comp/PlayerComp.java +++ b/core/src/mindustry/entities/comp/PlayerComp.java @@ -45,6 +45,7 @@ abstract class PlayerComp implements UnitController, Entityc, Syncc, Timerc, Dra transient String lastText = ""; transient float textFadeTime; transient private Unit lastReadUnit = Nulls.unit; + transient private int wrongReadUnits; transient @Nullable Unit justSwitchFrom, justSwitchTo; public boolean isBuilder(){ @@ -104,9 +105,15 @@ abstract class PlayerComp implements UnitController, Entityc, Syncc, Timerc, Dra //reason: we know the server is lying here, essentially skip the unit snapshot because we know the client's information is more recent if(isLocal() && unit == justSwitchFrom && justSwitchFrom != null && justSwitchTo != null){ unit = justSwitchTo; + //if several snapshots have passed and this unit is still incorrect, something's wrong + if(++wrongReadUnits >= 2){ + justSwitchFrom = null; + wrongReadUnits = 0; + } }else{ justSwitchFrom = null; justSwitchTo = null; + wrongReadUnits = 0; } //simulate a unit change after sync diff --git a/core/src/mindustry/input/InputHandler.java b/core/src/mindustry/input/InputHandler.java index fdaa0e335e..4e3c58e5c0 100644 --- a/core/src/mindustry/input/InputHandler.java +++ b/core/src/mindustry/input/InputHandler.java @@ -379,15 +379,6 @@ public abstract class InputHandler implements InputProcessor, GestureListener{ throw new ValidateException(player, "Player cannot control a unit."); } - //TODO problem: - //1. server send snapshot - //2. client requests to control unit, becomes unit locally - //3. snapshot arrives, client now thinks they're in the old unit (!!!) - //4. server gets packet that player is in the right unit - //5. server sends snapshot - //6. client gets snapshot, realizes that they are actually in the unit they selected - //7. client gets switched to new unit -> rubberbanding (!!!) - //clear player unit when they possess a core if(unit == null){ //just clear the unit (is this used?) player.clearUnit(); @@ -404,6 +395,9 @@ public abstract class InputHandler implements InputProcessor, GestureListener{ if(!player.dead()){ Fx.unitSpirit.at(player.x, player.y, 0f, unit); } + }else if(net.server()){ + //reject forwarding the packet if the unit was dead, AI or team + throw new ValidateException(player, "Player attempted to control invalid unit."); } Events.fire(new UnitControlEvent(player, unit)); diff --git a/core/src/mindustry/mod/ContentParser.java b/core/src/mindustry/mod/ContentParser.java index 68f829bac7..3644b3ad5b 100644 --- a/core/src/mindustry/mod/ContentParser.java +++ b/core/src/mindustry/mod/ContentParser.java @@ -77,9 +77,10 @@ public class ContentParser{ } }); put(StatusEffect.class, (type, data) -> { - Object result = fieldOpt(StatusEffects.class, data); - if(result != null){ - return result; + if(data.isString()){ + StatusEffect result = locate(ContentType.status, data.asString()); + if(result != null) return result; + throw new IllegalArgumentException("Unknown status effect: '" + data.asString() + "'"); } StatusEffect effect = new StatusEffect(currentMod.name + "-" + data.getString("name")); readFields(effect, data); diff --git a/server/src/mindustry/server/ServerControl.java b/server/src/mindustry/server/ServerControl.java index 3d378f4d25..3af40c0c78 100644 --- a/server/src/mindustry/server/ServerControl.java +++ b/server/src/mindustry/server/ServerControl.java @@ -287,7 +287,6 @@ public class ServerControl implements ApplicationListener{ Core.app.exit(); }); - handler.register("stop", "Stop hosting the server.", arg -> { net.closeServer(); if(lastTask != null) lastTask.cancel();