Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Prevent relogging to avoid respawn timers #1068

Merged
merged 1 commit into from
Oct 8, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
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