3030import me .chancesd .pvpmanager .setting .Permissions ;
3131import me .chancesd .pvpmanager .tasks .NewbieTask ;
3232import me .chancesd .pvpmanager .utils .CombatUtils ;
33+ import me .chancesd .sdutils .scheduler .SDTask ;
3334import me .chancesd .sdutils .scheduler .ScheduleUtils ;
3435import me .chancesd .sdutils .utils .Log ;
3536import me .chancesd .sdutils .utils .MCVersion ;
@@ -49,6 +50,7 @@ public class CombatPlayer extends EcoPlayer {
4950 private volatile long totalTagTime ;
5051 private long lastKillCommandTime ;
5152 private NewbieTask newbieTask ;
53+ private SDTask pendingUntagTask ;
5254 private CombatPlayer enemy ;
5355 private final Set <CombatPlayer > lastHitters = new HashSet <>();
5456 private final Map <String , Integer > victim = new HashMap <>();
@@ -151,7 +153,7 @@ public final void setNewbie(final boolean newbie, final long time) {
151153 * @param other The other player involved in the attack
152154 * @param timeMiliseconds How long the player should be tagged for
153155 */
154- public final void tag (final boolean isAttacker , final CombatPlayer other , final long timeMiliseconds ) {
156+ public final synchronized void tag (final boolean isAttacker , final CombatPlayer other , final long timeMiliseconds ) {
155157 if (hasPerm (Permissions .EXEMPT_COMBAT_TAG )) {
156158 Log .debug ("Not tagging " + getName () + " because player has permission: " + Permissions .EXEMPT_COMBAT_TAG );
157159 return ;
@@ -164,6 +166,13 @@ public final void tag(final boolean isAttacker, final CombatPlayer other, final
164166 return ;
165167 }
166168
169+ // Cancel any pending untag task
170+ if (pendingUntagTask != null && !pendingUntagTask .isCancelled ()) {
171+ pendingUntagTask .cancel ();
172+ Log .debug ("Cancelled stale untag task for " + getName ());
173+ pendingUntagTask = null ;
174+ }
175+
167176 this .totalTagTime = timeMiliseconds ;
168177
169178 final PlayerTagEvent event = new PlayerTagEvent (getPlayer (), this , isAttacker , other .getPlayer ());
@@ -207,17 +216,17 @@ public final void tag(final boolean isAttacker, final CombatPlayer other) {
207216 /**
208217 * Takes the player out of combat
209218 */
210- public final void untag (final UntagReason reason ) {
219+ public final synchronized void untag (final UntagReason reason ) {
211220 if (!isInCombat ()) {
212- Log .debug ("Not untagging " + getName () + " because player is not tagged." );
213221 return ;
214222 }
215223 final PlayerUntagEvent event = new PlayerUntagEvent (getPlayer (), this , reason );
216- ScheduleUtils .ensureMainThread (() -> {
224+ pendingUntagTask = ScheduleUtils .ensureMainThread (() -> {
217225 Bukkit .getPluginManager ().callEvent (event );
218226 if (Conf .DISABLE_FLY .asBool () && Conf .RESTORE_FLY .asBool () && getWasAllowedFlight ()) {
219227 getPlayer ().setAllowFlight (getWasAllowedFlight ()); // Sync because there's an async catcher on MC 1.8
220228 }
229+ pendingUntagTask = null ;
221230 }, getPlayer ());
222231
223232 if (Conf .GLOWING_IN_COMBAT .asBool () && MCVersion .isAtLeast (MCVersion .V1_9 )) {
@@ -423,7 +432,7 @@ private void initializeNameTag() {
423432 /**
424433 * Apply loaded player data to this CombatPlayer
425434 */
426- public void applyPlayerData (final PlayerData data ) {
435+ public synchronized void applyPlayerData (final PlayerData data ) {
427436 // Apply loaded data (overriding defaults)
428437 this .pvpState = data .isPvpEnabled ();
429438 this .toggleTime = data .getToggleTime ();
@@ -443,9 +452,7 @@ public void applyPlayerData(final PlayerData data) {
443452
444453 this .loaded = true ;
445454 // Wake up any threads waiting for data to load
446- synchronized (this ) {
447- notifyAll ();
448- }
455+ notifyAll ();
449456 Log .debug ("Finished loading data for " + this + (nametag != null ? " with " + nametag .getClass ().getSimpleName () : "" ));
450457 }
451458
0 commit comments