Skip to content

Commit

Permalink
Add alternative score displays
Browse files Browse the repository at this point in the history
Signed-off-by: Pablo Herrera <[email protected]>
  • Loading branch information
Pablete1234 committed Nov 23, 2024
1 parent f02940c commit 3a54971
Show file tree
Hide file tree
Showing 8 changed files with 202 additions and 211 deletions.
58 changes: 22 additions & 36 deletions core/src/main/java/tc/oc/pgm/score/ScoreBox.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,80 +2,66 @@

import static tc.oc.pgm.util.Assert.assertNotNull;

import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Maps;
import java.time.Duration;
import java.time.Instant;
import java.util.Map;
import java.util.UUID;
import org.jetbrains.annotations.Nullable;
import tc.oc.pgm.api.filter.Filter;
import tc.oc.pgm.api.player.MatchPlayerState;
import tc.oc.pgm.api.player.ParticipantState;
import tc.oc.pgm.api.player.MatchPlayer;
import tc.oc.pgm.api.region.Region;
import tc.oc.pgm.filters.query.PlayerStateQuery;
import tc.oc.pgm.util.material.MaterialMatcher;

public class ScoreBox {
private final Region region;
private final int score;
private final Filter trigger;
private final ImmutableMap<MaterialMatcher, Double> redeemables;
private final boolean silent;

private final Map<MatchPlayerState, Instant> lastScoreTime = Maps.newHashMap();

public ScoreBox(
Region region,
int score,
Filter filter,
ImmutableMap<MaterialMatcher, Double> redeemables,
boolean silent) {
this.region = assertNotNull(region, "region");
this.score = score;
this.trigger = assertNotNull(filter, "filter");
this.redeemables = redeemables;
this.silent = silent;
private static final Duration COOLDOWN = Duration.ofMillis(500);
private final ScoreBoxDefinition definition;

private final Map<UUID, Instant> lastScoreTime = Maps.newHashMap();

public ScoreBox(ScoreBoxDefinition definition) {
this.definition = definition;
}

public Region getRegion() {
return this.region;
return this.definition.region();
}

public int getScore() {
return this.score;
return this.definition.score();
}

public Filter getFilter() {
return this.trigger;
return this.definition.filter();
}

public Map<MaterialMatcher, Double> getRedeemables() {
return redeemables;
return this.definition.redeemables();
}

public boolean isSilent() {
return silent;
return this.definition.silent();
}

public @Nullable Instant getLastScoreTime(MatchPlayerState player) {
public @Nullable Instant getLastScoreTime(MatchPlayer player) {
assertNotNull(player, "player");

return this.lastScoreTime.get(player);
return this.lastScoreTime.get(player.getId());
}

public boolean canScore(ParticipantState player) {
return this.trigger.query(new PlayerStateQuery(null, player)).isAllowed();
public boolean canScore(MatchPlayer player) {
return this.definition.filter().query(player).isAllowed();
}

public boolean isCoolingDown(MatchPlayerState player) {
public boolean isCoolingDown(MatchPlayer player) {
Instant lastScore = this.getLastScoreTime(player);
return lastScore != null && lastScore.plus(Duration.ofSeconds(1)).isAfter(Instant.now());
return lastScore != null && Duration.between(lastScore, Instant.now()).compareTo(COOLDOWN) < 0;
}

public void setLastScoreTime(MatchPlayerState player, Instant time) {
public void setLastScoreTime(MatchPlayer player, Instant time) {
assertNotNull(player, "player");
assertNotNull(time, "time");

this.lastScoreTime.put(player, time);
this.lastScoreTime.put(player.getId(), time);
}
}
25 changes: 25 additions & 0 deletions core/src/main/java/tc/oc/pgm/score/ScoreBoxDefinition.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package tc.oc.pgm.score;

import static tc.oc.pgm.util.Assert.assertNotNull;

import com.google.common.collect.ImmutableMap;
import tc.oc.pgm.api.filter.Filter;
import tc.oc.pgm.api.match.Match;
import tc.oc.pgm.api.region.Region;
import tc.oc.pgm.util.material.MaterialMatcher;

public record ScoreBoxDefinition(
Region region,
int score,
Filter filter,
ImmutableMap<MaterialMatcher, Double> redeemables,
boolean silent) {
public ScoreBoxDefinition {
assertNotNull(region, "region");
assertNotNull(filter, "filter");
}

public ScoreBox createScoreBox(Match match) {
return new ScoreBox(this);
}
}
37 changes: 0 additions & 37 deletions core/src/main/java/tc/oc/pgm/score/ScoreBoxFactory.java

This file was deleted.

70 changes: 50 additions & 20 deletions core/src/main/java/tc/oc/pgm/score/ScoreConfig.java
Original file line number Diff line number Diff line change
@@ -1,27 +1,57 @@
package tc.oc.pgm.score;

import static net.kyori.adventure.text.Component.empty;
import static net.kyori.adventure.text.Component.space;
import static net.kyori.adventure.text.Component.text;

import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.NamedTextColor;
import tc.oc.pgm.api.filter.Filter;
import tc.oc.pgm.api.party.Competitor;
import tc.oc.pgm.util.named.NameStyle;

public record ScoreConfig(
int scoreLimit,
int deathScore,
int killScore,
int mercyLimit,
int mercyLimitMin,
Display display,
Filter scoreboardFilter) {

public enum Display {
NUMERICAL(null, Integer.MAX_VALUE) {
@Override
public Component format(Competitor competitor, int score, int limit) {
return text()
.append(text(score, NamedTextColor.WHITE))
.append(limit > 0 ? text("/", NamedTextColor.DARK_GRAY) : empty())
.append(limit > 0 ? text(limit, NamedTextColor.GRAY) : empty())
.append(space())
.append(competitor.getName(NameStyle.SIMPLE_COLOR))
.build();
}
},
CIRCLE("\u2B24", 16), // ⬤
SQUARE("\u2b1b", 16), // ⬛
PIPE("|", 24);

public final String symbol;
public final int max;

public class ScoreConfig {
public final int scoreLimit;
public final int deathScore;
public final int killScore;
public final int mercyLimit;
public final int mercyLimitMin;
public final Filter scoreboardFilter;
Display(String symbol, int max) {
this.symbol = symbol;
this.max = max;
}

public ScoreConfig(
int scoreLimit,
int deathScore,
int killScore,
int mercyLimit,
int mercyLimitMin,
Filter scoreboardFilter) {
this.scoreLimit = scoreLimit;
this.deathScore = deathScore;
this.killScore = killScore;
this.mercyLimit = mercyLimit;
this.mercyLimitMin = mercyLimitMin;
this.scoreboardFilter = scoreboardFilter;
public Component format(Competitor competitor, int score, int limit) {
if (score < 0 || score > max || limit > max)
return NUMERICAL.format(competitor, score, limit);
return text()
.append(text("\u2794 ", competitor.getTextColor())) // ➔
.append(text(symbol.repeat(score), competitor.getTextColor()))
.append(limit > score ? text(symbol.repeat(limit - score), NamedTextColor.GRAY) : empty())
.build();
}
}
}
44 changes: 21 additions & 23 deletions core/src/main/java/tc/oc/pgm/score/ScoreMatchModule.java
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@
import tc.oc.pgm.api.party.Competitor;
import tc.oc.pgm.api.party.event.CompetitorScoreChangeEvent;
import tc.oc.pgm.api.player.MatchPlayer;
import tc.oc.pgm.api.player.ParticipantState;
import tc.oc.pgm.api.player.event.MatchPlayerDeathEvent;
import tc.oc.pgm.events.ListenerScope;
import tc.oc.pgm.events.PlayerParticipationStartEvent;
Expand Down Expand Up @@ -61,9 +60,9 @@ public ScoreMatchModule(Match match, ScoreConfig config, Set<ScoreBox> scoreBoxe
this.scoreBoxes = scoreBoxes;
this.match.getCompetitors().forEach(competitor -> this.scores.put(competitor, 0.0));

if (this.config.mercyLimit > 0) {
if (this.config.mercyLimit() > 0) {
this.mercyRule =
new MercyRule(this, config.scoreLimit, config.mercyLimit, config.mercyLimitMin);
new MercyRule(this, config.scoreLimit(), config.mercyLimit(), config.mercyLimitMin());
}
}

Expand All @@ -72,16 +71,20 @@ public void load() {
match.addVictoryCondition(new ScoreVictoryCondition());
}

public ScoreConfig.Display getDisplay() {
return config.display();
}

public boolean hasScoreLimit() {
return this.config.scoreLimit > 0 || hasMercyRule();
return this.config.scoreLimit() > 0 || hasMercyRule();
}

public boolean hasMercyRule() {
return this.mercyRule != null;
}

public Filter getScoreboardFilter() {
return this.config.scoreboardFilter;
return this.config.scoreboardFilter();
}

public int getScoreLimit() {
Expand All @@ -91,7 +94,7 @@ public int getScoreLimit() {
return this.mercyRule.getScoreLimit();
}

return this.config.scoreLimit;
return this.config.scoreLimit();
}

public Map<Competitor, Double> getScores() {
Expand Down Expand Up @@ -148,8 +151,8 @@ public Component getScoreMessage(MatchPlayer matchPlayer) {
public Component getStatusMessage(MatchPlayer matchPlayer) {
Component message = this.getScoreMessage(matchPlayer);

if (this.config.scoreLimit > 0) {
message = message.append(text(" [" + this.config.scoreLimit + "]", NamedTextColor.GRAY));
if (this.config.scoreLimit() > 0) {
message = message.append(text(" [" + this.config.scoreLimit() + "]", NamedTextColor.GRAY));
}
return message;
}
Expand All @@ -161,10 +164,10 @@ public void incrementDeath(MatchPlayerDeathEvent event) {
// add +1 to killer's team if it was a kill, otherwise -1 to victim's team
if (event.isChallengeKill()) {
this.incrementScore(
event.getKiller().getId(), event.getKiller().getParty(), this.config.killScore);
event.getKiller().getId(), event.getKiller().getParty(), this.config.killScore());
} else {
this.incrementScore(
event.getVictim().getId(), event.getVictim().getCompetitor(), -this.config.deathScore);
event.getVictim().getId(), event.getVictim().getCompetitor(), -this.config.deathScore());
}
}

Expand Down Expand Up @@ -209,21 +212,16 @@ public void playerEnterBox(PlayerCoarseMoveEvent event) {
MatchPlayer player = this.match.getPlayer(event.getPlayer());
if (player == null || !player.canInteract() || player.getBukkit().isDead()) return;

ParticipantState playerState = player.getParticipantState();
Vector from = event.getBlockFrom().toVector();
Vector to = event.getBlockTo().toVector();

for (ScoreBox box : this.scoreBoxes) {
if (box.getRegion().enters(from, to) && box.canScore(playerState)) {
if (box.isCoolingDown(playerState)) {
if (box.getRegion().enters(from, to) && box.canScore(player)) {
if (box.isCoolingDown(player)) {
match
.getLogger()
.warning(playerState.getId()
+ " tried to score multiple times in one second (from="
+ from
+ " to="
+ to
+ ")");
.warning("%s tried to score multiple times in under a second (from=%s to=%s)"
.formatted(player.getId(), from, to));
} else {
this.playerScore(box, player, box.getScore() + redeemItems(box, player.getInventory()));
}
Expand All @@ -240,7 +238,7 @@ public void playerAcquireRedeemableInBox(final PlayerItemTransferEvent event) {
for (final ScoreBox box : this.scoreBoxes) {
if (!box.getRedeemables().isEmpty()
&& box.getRegion().contains(player.getBukkit())
&& box.canScore(player.getParticipantState())) {
&& box.canScore(player)) {
match.getExecutor(MatchScope.RUNNING).execute(() -> {
if (player.getBukkit().isOnline()) {
double points = redeemItems(box, player.getInventory());
Expand All @@ -265,7 +263,7 @@ private void playerScore(ScoreBox box, MatchPlayer player, double points) {
if (points == 0) return;

this.incrementScore(player.getId(), player.getCompetitor(), points);
box.setLastScoreTime(player.getState(), Instant.now());
box.setLastScoreTime(player, Instant.now());

int wholePoints = (int) points;
if (wholePoints < 1 || box.isSilent()) return;
Expand Down Expand Up @@ -313,8 +311,8 @@ public void incrementScore(Competitor competitor, double amount) {
}

private void setScore(Competitor competitor, double oldScore, double newScore) {
if (this.config.scoreLimit > 0 && newScore > this.config.scoreLimit) {
newScore = this.config.scoreLimit;
if (this.config.scoreLimit() > 0 && newScore > this.config.scoreLimit()) {
newScore = this.config.scoreLimit();
}

CompetitorScoreChangeEvent event =
Expand Down
Loading

0 comments on commit 3a54971

Please sign in to comment.