Skip to content

Commit

Permalink
Add auto cancel with series based bans
Browse files Browse the repository at this point in the history
  • Loading branch information
Pugzy committed Apr 8, 2022
1 parent 30c691d commit eb79608
Show file tree
Hide file tree
Showing 7 changed files with 254 additions and 40 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,14 @@
public class Punishment {

private final UUID target;
private Integer seriesId;

private UUID issuer;
private String reason;

public Punishment(UUID target) {
public Punishment(UUID target, Integer seriesId) {
this.target = target;
this.seriesId = seriesId;
}

public Punishment(UUID target, @Nullable CommandSender issuer, @Nullable String reason) {
Expand All @@ -28,6 +31,10 @@ public UUID getTarget() {
return target;
}

public Integer getSeriesId() {
return seriesId;
}

public UUID getIssuer() {
return issuer;
}
Expand Down
11 changes: 10 additions & 1 deletion src/main/java/rip/bolt/ingame/api/definitions/Series.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,20 @@
@JsonIgnoreProperties(ignoreUnknown = true)
public class Series {

private Integer id;
private String name;
private Boolean hideObservers = false;

public Series() {}

public Integer getId() {
return id;
}

public void setId(Integer id) {
this.id = id;
}

public String getName() {
return name;
}
Expand All @@ -28,6 +37,6 @@ public void setHideObservers(boolean hideObservers) {

@Override
public String toString() {
return "Series{" + "name='" + name + '\'' + ", hideObservers=" + hideObservers + '}';
return name + " (" + id + "): hideObservers=" + hideObservers;
}
}
8 changes: 8 additions & 0 deletions src/main/java/rip/bolt/ingame/config/AppData.java
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,14 @@ public static Duration forfeitAfter() {
return parseDuration(Ingame.get().getConfig().getString("forfeit.after", "300s"));
}

public static Duration autoCancelBefore() {
return parseDuration(Ingame.get().getConfig().getString("auto-cancel.before", "60s"));
}

public static Duration autoCancelCountdown() {
return parseDuration(Ingame.get().getConfig().getString("auto-cancel.countdown", "10s"));
}

public static Duration matchStartDuration() {
return parseDuration(Ingame.get().getConfig().getString("match-start-duration", "180s"));
}
Expand Down
121 changes: 121 additions & 0 deletions src/main/java/rip/bolt/ingame/ranked/CancelManager.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
package rip.bolt.ingame.ranked;

import static tc.oc.pgm.lib.net.kyori.adventure.text.Component.text;

import com.google.common.collect.Ordering;
import java.time.Duration;
import java.util.Comparator;
import java.util.UUID;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import rip.bolt.ingame.Ingame;
import rip.bolt.ingame.config.AppData;
import tc.oc.pgm.api.match.Match;
import tc.oc.pgm.api.match.MatchScope;
import tc.oc.pgm.api.player.MatchPlayer;
import tc.oc.pgm.lib.net.kyori.adventure.text.format.NamedTextColor;

public class CancelManager {

public static final Duration CANCEL_TIME_LIMIT = AppData.autoCancelBefore();
public static final Duration CANCEL_ABSENCE_LENGTH = AppData.autoCancelCountdown();

private final PlayerWatcher playerWatcher;
private LeaverCountdown countdown = null;

public CancelManager(PlayerWatcher playerWatcher) {
this.playerWatcher = playerWatcher;
}

public void clearCountdown() {
if (countdown != null) countdown.cancelCountdown();
this.countdown = null;
}

public void playerJoined(MatchPlayer player) {
if (countdown != null && countdown.player.equals(player.getId())) clearCountdown();
if (canCancel(player.getMatch())) startCountdownIfRequired(player.getMatch());
}

public void startCountdownIfRequired(Match match) {
// Check if countdown required for any participants
PlayerWatcher.MatchParticipation participation =
playerWatcher.getParticipations().values().stream()
.filter(
matchParticipation ->
match.getPlayer(matchParticipation.getUUID()) == null
&& matchParticipation.hasJoined())
.max(Comparator.comparing(PlayerWatcher.MatchParticipation::currentAbsentDuration))
.orElse(null);

if (participation == null || (countdown != null && countdown.player == participation.getUUID()))
return;

// Cancel and clear existing countdown
clearCountdown();

Duration duration =
Ordering.natural()
.max(CANCEL_ABSENCE_LENGTH.minus(participation.absentDuration()), Duration.ZERO);

countdown = new LeaverCountdown(match, participation.getUUID(), duration);
}

public void playerLeft(MatchPlayer player) {
Match match = player.getMatch();
if (canCancel(match)) {
startCountdownIfRequired(match);
}
}

private boolean canCancel(Match match) {
return (match.getDuration().compareTo(CANCEL_TIME_LIMIT) < 0);
}

public static class LeaverCountdown {

private final Match match;
private final UUID player;
private long duration;

private final ScheduledFuture<?> scheduledFuture;

public LeaverCountdown(Match match, UUID player, Duration duration) {
this.match = match;
this.player = player;
this.duration = (duration.toMillis() + 999) / 1000;

scheduledFuture =
match
.getExecutor(MatchScope.RUNNING)
.scheduleAtFixedRate(this::tick, 0, 1, TimeUnit.SECONDS);
}

private void broadcast() {
match.sendWarning(
text("Cancelling match in ")
.append(text(duration, NamedTextColor.YELLOW))
.append(text((duration == 1) ? " second" : " seconds")));
}

private void tick() {
if (duration <= 0) {
// Cancel match
Ingame.get().getRankedManager().getPlayerWatcher().cancelMatch(match);
// Cancel scheduler
cancelCountdown();
} else if (duration % 5 == 0 || duration <= 3) broadcast();

duration--;
}

public void cancelCountdown() {
this.scheduledFuture.cancel(false);
}

@Override
public String toString() {
return "LeaverCountdown{" + "player=" + player + ", duration=" + duration + '}';
}
}
}
Loading

0 comments on commit eb79608

Please sign in to comment.