Skip to content

Commit

Permalink
Prevent relogging to avoid respawn timers (#1068)
Browse files Browse the repository at this point in the history
Signed-off-by: Pugzy <[email protected]>
  • Loading branch information
Pugzy authored Oct 8, 2022
1 parent 23102e4 commit 0f62502
Show file tree
Hide file tree
Showing 6 changed files with 70 additions and 68 deletions.
30 changes: 29 additions & 1 deletion core/src/main/java/tc/oc/pgm/spawns/SpawnMatchModule.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package tc.oc.pgm.spawns;

import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import java.util.ArrayList;
Expand All @@ -8,6 +10,8 @@
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import javax.annotation.Nullable;
import org.bukkit.Location;
Expand Down Expand Up @@ -45,16 +49,21 @@
import tc.oc.pgm.util.event.PlayerItemTransferEvent;
import tc.oc.pgm.util.event.player.PlayerAttackEntityEvent;

@SuppressWarnings("UnstableApiUsage")
@ListenerScope(MatchScope.LOADED)
public class SpawnMatchModule implements MatchModule, Listener, Tickable {

private static final long PREDICTED_EXTRA_TICKS = 10 * 20;

private final Match match;
private final SpawnModule module;
private final Map<MatchPlayer, State> states = new HashMap<>();
private final Set<MatchPlayer> transitioningPlayers = new HashSet<>();
private final Map<Competitor, Spawn> unique = new HashMap<>();
private final Set<Spawn> failed = new HashSet<>();
private final ObserverToolFactory observerToolFactory;
private final Cache<UUID, Long> deathTicks =
CacheBuilder.newBuilder().expireAfterWrite(60, TimeUnit.SECONDS).build();

public SpawnMatchModule(Match match, SpawnModule module) {
this.match = match;
Expand Down Expand Up @@ -169,12 +178,20 @@ public void reportFailedSpawn(Spawn spawn, MatchPlayer player) {
}
}

public long getDeathTick(MatchPlayer player) {
Long deathTick = deathTicks.getIfPresent(player.getId());
return deathTick != null ? deathTick : 0;
}

@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void onPartyChange(final PlayerPartyChangeEvent event) {
if (event.getOldParty() == null) {
// Join match
if (event.getNewParty().isParticipating()) {
transition(event.getPlayer(), null, new Joining(this, event.getPlayer()));
transition(
event.getPlayer(),
null,
new Joining(this, event.getPlayer(), getDeathTick(event.getPlayer())));
} else {
transition(event.getPlayer(), null, new Observing(this, event.getPlayer(), true, true));
}
Expand Down Expand Up @@ -306,6 +323,17 @@ public void onCompetitorRemove(CompetitorRemoveEvent event) {
}
}

@EventHandler(ignoreCancelled = true)
public void onPlayerDeath(MatchPlayerDeathEvent event) {
long tick = event.getMatch().getTick().tick;

if (event.isPredicted()) {
tick = tick + PREDICTED_EXTRA_TICKS;
}

deathTicks.put(event.getPlayer().getId(), tick);
}

@Override
public void tick(Match match, Tick tick) {
// Copy states so they can transition without concurrent modification
Expand Down
58 changes: 2 additions & 56 deletions core/src/main/java/tc/oc/pgm/spawns/states/Dead.java
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
package tc.oc.pgm.spawns.states;

import static net.kyori.adventure.text.Component.text;
import static net.kyori.adventure.text.Component.translatable;
import static tc.oc.pgm.util.text.PlayerComponent.player;

import java.util.List;
import javax.annotation.Nullable;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.NamedTextColor;
import org.bukkit.event.Event;
Expand All @@ -17,7 +15,6 @@
import tc.oc.pgm.api.party.Competitor;
import tc.oc.pgm.api.player.MatchPlayer;
import tc.oc.pgm.events.PlayerJoinPartyEvent;
import tc.oc.pgm.spawns.Spawn;
import tc.oc.pgm.spawns.SpawnMatchModule;
import tc.oc.pgm.spawns.SpawnModule;
import tc.oc.pgm.spawns.events.DeathKitApplyEvent;
Expand All @@ -36,16 +33,14 @@ public class Dead extends Spawning {
private static final PotionEffect BLINDNESS_LONG =
new PotionEffect(PotionEffectType.BLINDNESS, Integer.MAX_VALUE, 0, true, false);

private final long deathTick;
private boolean kitted, rotted;

public Dead(SpawnMatchModule smm, MatchPlayer player) {
this(smm, player, player.getMatch().getTick().tick);
}

public Dead(SpawnMatchModule smm, MatchPlayer player, long deathTick) {
super(smm, player);
this.deathTick = deathTick;
super(smm, player, deathTick);
}

@Override
Expand Down Expand Up @@ -88,10 +83,6 @@ public void leaveState(List<Event> events) {
super.leaveState(events);
}

protected long age() {
return player.getMatch().getTick().tick - deathTick;
}

@Override
public void tick() {
long age = age();
Expand Down Expand Up @@ -121,22 +112,8 @@ public void onEvent(PlayerJoinPartyEvent event) {
}
}

protected long ticksUntilRespawn() {
return Math.max(0, options.delayTicks - age());
}

@Override
public @Nullable Spawn chooseSpawn() {
if (ticksUntilRespawn() > 0) {
return null;
} else {
return super.chooseSpawn();
}
}

public void requestSpawn() {
if (player.getMatch().getTick().tick - deathTick
>= TimeUtils.toTicks(SpawnModule.IGNORE_CLICKS_DELAY)) {
if (age() >= TimeUtils.toTicks(SpawnModule.IGNORE_CLICKS_DELAY)) {
super.requestSpawn();
}
}
Expand All @@ -149,21 +126,6 @@ protected Component getTitle(boolean spectator) {
player(this.player.getId(), NameStyle.SIMPLE_COLOR));
}

@Override
protected Component getSubtitle(boolean spectator) {
long ticks = ticksUntilRespawn();
if (ticks > 0) {
return translatable(
spawnRequested
? "death.respawn.confirmed.time"
: "death.respawn.unconfirmed.time" + (spectator ? ".spectator" : ""),
NamedTextColor.GREEN,
text(String.format("%.1f", (ticks / (float) 20)), NamedTextColor.AQUA));
} else {
return super.getSubtitle(spectator);
}
}

@Override
public void onEvent(InventoryClickEvent event) {
super.onEvent(event);
Expand All @@ -175,20 +137,4 @@ public void onEvent(EntityDamageEvent event) {
super.onEvent(event);
event.setCancelled(true);
}

@Override
public void sendMessage() {
long ticks = options.delayTicks - age();
if (ticks % (ticks > 0 ? 20 : 100) == 0) {
player.sendMessage(
(ticks > 0
? translatable(
spawnRequested
? "death.respawn.confirmed.time"
: "death.respawn.unconfirmed.time",
text((int) (ticks / (float) 20), NamedTextColor.AQUA))
: super.getSubtitle(false))
.color(NamedTextColor.GREEN));
}
}
}
6 changes: 5 additions & 1 deletion core/src/main/java/tc/oc/pgm/spawns/states/Joining.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,11 @@
public class Joining extends Spawning {

public Joining(SpawnMatchModule smm, MatchPlayer player) {
super(smm, player);
this(smm, player, 0);
}

public Joining(SpawnMatchModule smm, MatchPlayer player, long deathTick) {
super(smm, player, deathTick);
this.spawnRequested = true;
}

Expand Down
2 changes: 1 addition & 1 deletion core/src/main/java/tc/oc/pgm/spawns/states/Observing.java
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ public void onEvent(MatchStartEvent event) {
@Override
public void onEvent(PlayerJoinPartyEvent event) {
if (event.getNewParty() instanceof Competitor && event.getMatch().isRunning()) {
transition(new Joining(smm, player));
transition(new Joining(smm, player, smm.getDeathTick(event.getPlayer())));
}
}

Expand Down
39 changes: 33 additions & 6 deletions core/src/main/java/tc/oc/pgm/spawns/states/Spawning.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package tc.oc.pgm.spawns.states;

import static net.kyori.adventure.text.Component.text;
import static net.kyori.adventure.text.Component.translatable;
import static net.kyori.adventure.title.Title.title;
import static tc.oc.pgm.util.TimeUtils.fromTicks;
Expand All @@ -13,6 +14,7 @@
import org.bukkit.event.entity.EntityDamageEvent;
import tc.oc.pgm.api.player.MatchPlayer;
import tc.oc.pgm.api.player.event.ObserverInteractEvent;
import tc.oc.pgm.spawns.RespawnOptions;
import tc.oc.pgm.spawns.Spawn;
import tc.oc.pgm.spawns.SpawnMatchModule;
import tc.oc.pgm.util.event.PlayerItemTransferEvent;
Expand All @@ -21,11 +23,15 @@
/** Player is waiting to spawn as a participant */
public abstract class Spawning extends Participating {

protected final RespawnOptions options;
protected boolean spawnRequested;
protected final long deathTick;

public Spawning(SpawnMatchModule smm, MatchPlayer player) {
public Spawning(SpawnMatchModule smm, MatchPlayer player, long deathTick) {
super(smm, player);
this.options = smm.getRespawnOptions(player);
this.spawnRequested = options.auto;
this.deathTick = deathTick;
}

@Override
Expand Down Expand Up @@ -66,6 +72,10 @@ public void onEvent(EntityDamageEvent event) {
event.setCancelled(true);
}

protected long age() {
return player.getMatch().getTick().tick - deathTick;
}

@Override
public void tick() {
if (!trySpawn()) {
Expand All @@ -89,16 +99,18 @@ protected boolean trySpawn() {
return true;
}

protected long ticksUntilRespawn() {
return Math.max(0, options.delayTicks - age());
}

public @Nullable Spawn chooseSpawn() {
if (spawnRequested) {
if (ticksUntilRespawn() <= 0 && spawnRequested) {
return smm.chooseSpawn(player);
} else {
return null;
}
}

public void sendMessage() {}

public void updateTitle() {
Title.Times times = Title.Times.of(Duration.ZERO, fromTicks(3), fromTicks(3));

Expand All @@ -111,15 +123,30 @@ public void updateTitle() {
protected abstract Component getTitle(boolean spectator);

protected Component getSubtitle(boolean spectator) {
if (!spawnRequested) {
long ticks = ticksUntilRespawn();
if (ticks > 0) {
return translatable(
spawnRequested
? "death.respawn.confirmed.time"
: "death.respawn.unconfirmed.time" + (spectator ? ".spectator" : ""),
NamedTextColor.GREEN,
text(String.format("%.1f", (ticks / (float) 20)), NamedTextColor.AQUA));
} else if (!spawnRequested) {
return translatable(
"death.respawn.unconfirmed" + (spectator ? ".spectator" : ""), NamedTextColor.GREEN);
} else if (options.message != null) {
return options.message;
return options.message.colorIfAbsent(NamedTextColor.GREEN);
} else {
return translatable(
"death.respawn.confirmed.waiting" + (spectator ? ".spectator" : ""),
NamedTextColor.GREEN);
}
}

public void sendMessage() {
long ticks = options.delayTicks - age();
if (ticks % (ticks > 0 ? 20 : 100) == 0) {
player.sendMessage(getSubtitle(false));
}
}
}
3 changes: 0 additions & 3 deletions core/src/main/java/tc/oc/pgm/spawns/states/State.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,13 @@
import tc.oc.pgm.api.player.event.MatchPlayerDeathEvent;
import tc.oc.pgm.api.player.event.ObserverInteractEvent;
import tc.oc.pgm.events.PlayerJoinPartyEvent;
import tc.oc.pgm.spawns.RespawnOptions;
import tc.oc.pgm.spawns.SpawnMatchModule;
import tc.oc.pgm.util.event.PlayerItemTransferEvent;
import tc.oc.pgm.util.event.player.PlayerAttackEntityEvent;

public abstract class State {

protected final SpawnMatchModule smm;
protected final RespawnOptions options;
protected final MatchPlayer player;
protected final Player bukkit;

Expand All @@ -30,7 +28,6 @@ public State(SpawnMatchModule smm, MatchPlayer player) {
this.smm = smm;
this.player = player;
this.bukkit = player.getBukkit();
this.options = smm.getRespawnOptions(player);
}

public boolean isCurrent() {
Expand Down

0 comments on commit 0f62502

Please sign in to comment.