Skip to content

Commit

Permalink
Add Match History feature
Browse files Browse the repository at this point in the history
Signed-off-by: applenick <[email protected]>
  • Loading branch information
applenick committed Aug 27, 2024
1 parent 9eeb3b6 commit 7e1126c
Show file tree
Hide file tree
Showing 9 changed files with 312 additions and 0 deletions.
3 changes: 3 additions & 0 deletions src/main/java/dev/pgm/community/CommunityPermissions.java
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,9 @@ public interface CommunityPermissions {
String FREEZE_EXEMPT = FREEZE + ".exempt";
String FREEZE_FORCE = FREEZE + ".force";

// Match History
String MATCH_HISTORY = ROOT + ".match-history";

// Mutations
String MUTATION = ROOT + ".mutation"; // Access to /mutate

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import dev.pgm.community.commands.providers.TargetPlayerParser;
import dev.pgm.community.freeze.FreezeCommand;
import dev.pgm.community.friends.commands.FriendshipCommand;
import dev.pgm.community.history.MatchHistoryCommand;
import dev.pgm.community.mobs.MobCommand;
import dev.pgm.community.moderation.commands.BanCommand;
import dev.pgm.community.moderation.commands.KickCommand;
Expand Down Expand Up @@ -118,6 +119,9 @@ protected void registerCommands() {
// Friends
register(new FriendshipCommand());

// History
register(new MatchHistoryCommand());

// Mobs
register(new MobCommand());

Expand Down
10 changes: 10 additions & 0 deletions src/main/java/dev/pgm/community/feature/FeatureManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import dev.pgm.community.freeze.FreezeFeature;
import dev.pgm.community.friends.feature.FriendshipFeature;
import dev.pgm.community.friends.feature.types.SQLFriendshipFeature;
import dev.pgm.community.history.MatchHistoryFeature;
import dev.pgm.community.info.InfoCommandsFeature;
import dev.pgm.community.mobs.MobFeature;
import dev.pgm.community.moderation.feature.ModerationFeature;
Expand Down Expand Up @@ -58,6 +59,7 @@ public class FeatureManager {
private final MapPartyFeature party;
private final PollFeature polls;
private final SquadFeature squads;
private final MatchHistoryFeature history;

public FeatureManager(
Configuration config,
Expand Down Expand Up @@ -94,6 +96,7 @@ public FeatureManager(
this.party = new MapPartyFeature(config, logger);
this.polls = new PollFeature(config, logger);
this.squads = new SquadFeature(config, logger);
this.history = new MatchHistoryFeature(config, logger);
}

public AssistanceFeature getReports() {
Expand Down Expand Up @@ -172,6 +175,10 @@ public SquadFeature getSquads() {
return squads;
}

public MatchHistoryFeature getHistory() {
return history;
}

public void reloadConfig(Configuration config) {
// Reload all config values here
getReports().getConfig().reload(config);
Expand All @@ -192,6 +199,8 @@ public void reloadConfig(Configuration config) {
getParty().getConfig().reload(config);
getPolls().getConfig().reload(config);
getSquads().getConfig().reload(config);
getHistory().getConfig().reload(config);

// TODO: Look into maybe unregister commands for features that have been disabled
// commands#unregisterCommand
// Will need to check isEnabled
Expand All @@ -216,5 +225,6 @@ public void disable() {
if (getParty().isEnabled()) getParty().disable();
if (getPolls().isEnabled()) getPolls().disable();
if (getSquads().isEnabled()) getSquads().disable();
if (getHistory().isEnabled()) getHistory().disable();
}
}
40 changes: 40 additions & 0 deletions src/main/java/dev/pgm/community/history/MatchHistoryCommand.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package dev.pgm.community.history;

import static tc.oc.pgm.util.text.TextException.exception;

import co.aikar.commands.annotation.CommandPermission;
import dev.pgm.community.Community;
import dev.pgm.community.CommunityPermissions;
import dev.pgm.community.utils.CommandAudience;
import tc.oc.pgm.lib.org.incendo.cloud.annotations.Argument;
import tc.oc.pgm.lib.org.incendo.cloud.annotations.Command;
import tc.oc.pgm.lib.org.incendo.cloud.annotations.CommandDescription;
import tc.oc.pgm.lib.org.incendo.cloud.annotations.Default;
import tc.oc.pgm.lib.org.incendo.cloud.annotations.Flag;

@Command("matchhistory|mh")
public class MatchHistoryCommand {

private final MatchHistoryFeature manager;

public MatchHistoryCommand() {
this.manager = Community.get().getFeatures().getHistory();
}

@Command("[page]")
@CommandDescription("Display match history")
@CommandPermission(CommunityPermissions.MATCH_HISTORY)
public void sendHistory(
CommandAudience sender,
@Argument("page") @Default("1") int page,
@Flag(value = "verbose", aliases = "v") boolean verbose) {
checkEnabled();
manager.sendHistory(sender, page, verbose);
}

private void checkEnabled() {
if (!manager.isEnabled()) {
throw exception("Match History is not enabled");
}
}
}
13 changes: 13 additions & 0 deletions src/main/java/dev/pgm/community/history/MatchHistoryConfig.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package dev.pgm.community.history;

import dev.pgm.community.feature.config.FeatureConfigImpl;
import org.bukkit.configuration.Configuration;

public class MatchHistoryConfig extends FeatureConfigImpl {

private static final String KEY = "history";

public MatchHistoryConfig(Configuration config) {
super(KEY, config);
}
}
156 changes: 156 additions & 0 deletions src/main/java/dev/pgm/community/history/MatchHistoryEntry.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
package dev.pgm.community.history;

import static net.kyori.adventure.text.Component.text;
import static tc.oc.pgm.util.text.TemporalComponent.duration;
import static tc.oc.pgm.util.text.TemporalComponent.relativePastApproximate;

import dev.pgm.community.CommunityPermissions;
import dev.pgm.community.utils.PGMUtils;
import java.time.Duration;
import java.time.Instant;
import java.util.List;
import java.util.stream.Collectors;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.event.HoverEvent;
import net.kyori.adventure.text.format.NamedTextColor;
import tc.oc.pgm.api.match.Match;
import tc.oc.pgm.util.text.TextFormatter;

public class MatchHistoryEntry implements Comparable<MatchHistoryEntry> {

private final String matchID;
private final int totalParticipants;
private final int observeringPlayers;
private final int staffCount;
private final String mapName;
private final Duration finalDuration;
private final Instant endTime;

private List<Component> staff;

public MatchHistoryEntry(Match match) {
this.matchID = match.getId();
this.totalParticipants = match.getParticipants().size();
this.observeringPlayers = match.getObservers().size();
this.staffCount = PGMUtils.getPlayers(CommunityPermissions.STAFF).size();
this.mapName = match.getMap().getName();
this.finalDuration = match.getDuration();
this.staff = PGMUtils.getPlayers(CommunityPermissions.STAFF).stream()
.map(mp -> text(mp.getNameLegacy()))
.collect(Collectors.toList());
this.endTime = Instant.now();
}

public String getMatchID() {
return matchID;
}

public int getTotalParticipants() {
return totalParticipants;
}

public int getObserveringPlayers() {
return observeringPlayers;
}

public int getStaffCount() {
return staffCount;
}

public String getMapName() {
return mapName;
}

public Duration getFinalDuration() {
return finalDuration;
}

public List<Component> getStaff() {
return staff;
}

public Instant getEndTime() {
return endTime;
}

public Component format(boolean verbose) {
Component staffList = TextFormatter.list(getStaff(), NamedTextColor.GRAY);

Component matchLength = text()
.append(text("(", NamedTextColor.GRAY))
.append(duration(getFinalDuration(), NamedTextColor.DARK_AQUA).color(NamedTextColor.GRAY))
.append(text(")", NamedTextColor.GRAY))
.hoverEvent(HoverEvent.showText(text("Final length of match", NamedTextColor.GRAY)))
.build();

Component timeSince = text()
.append(text("(", NamedTextColor.GRAY))
.append(relativePastApproximate(getEndTime()).color(NamedTextColor.DARK_GREEN))
.append(text(")", NamedTextColor.GRAY))
.hoverEvent(HoverEvent.showText(text()
.append(text("This match ended at ", NamedTextColor.GRAY))
.append(text(getEndTime().toString(), NamedTextColor.DARK_GREEN))))
.build();

Component top = text()
.append(text("#", NamedTextColor.YELLOW))
.append(text(getMatchID(), NamedTextColor.YELLOW))
.appendSpace()
.append(text(getMapName(), NamedTextColor.GOLD))
.appendSpace()
.append(matchLength)
.appendSpace()
.append(timeSince)
.build();

Component playersComponent = text()
.append(text("(", NamedTextColor.GRAY))
.append(text(getTotalParticipants(), NamedTextColor.GREEN))
.append(text(" player" + (getTotalParticipants() != 1 ? "s" : ""), NamedTextColor.GRAY))
.append(text(")", NamedTextColor.GRAY))
.build();

Component obsComponent = text()
.append(text("(", NamedTextColor.GRAY))
.append(text(getObserveringPlayers(), NamedTextColor.AQUA))
.append(text(" observer" + (getObserveringPlayers() != 1 ? "s" : ""), NamedTextColor.GRAY))
.append(text(")", NamedTextColor.GRAY))
.build();

Component staffComponent = text()
.append(text("(", NamedTextColor.GRAY))
.append(text(getStaffCount(), NamedTextColor.RED))
.append(text(" staff", NamedTextColor.GRAY))
.append(text(")", NamedTextColor.GRAY))
.hoverEvent(HoverEvent.showText(staffList))
.build();

Component spacer = text(" - ");

Component counts = text()
.append(playersComponent)
.append(spacer)
.append(obsComponent)
.append(spacer)
.append(staffComponent)
.build();

if (verbose) {
return text()
.append(top)
.appendNewline()
.append(text(" "))
.append(counts)
.build();
}

return top;
}

@Override
public int compareTo(MatchHistoryEntry other) {
long thisMatchID = Long.parseLong(this.matchID);
long otherMatchID = Long.parseLong(other.matchID);
return Long.compare(otherMatchID, thisMatchID);
}
}
73 changes: 73 additions & 0 deletions src/main/java/dev/pgm/community/history/MatchHistoryFeature.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
package dev.pgm.community.history;

import static dev.pgm.community.utils.PGMUtils.isPGMEnabled;
import static net.kyori.adventure.text.Component.text;
import static net.kyori.adventure.text.Component.translatable;

import com.google.common.collect.Lists;
import dev.pgm.community.feature.FeatureBase;
import dev.pgm.community.utils.CommandAudience;
import dev.pgm.community.utils.PaginatedComponentResults;
import java.util.List;
import java.util.logging.Logger;
import java.util.stream.Collectors;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.NamedTextColor;
import org.bukkit.configuration.Configuration;
import org.bukkit.event.EventHandler;
import tc.oc.pgm.api.match.event.MatchFinishEvent;
import tc.oc.pgm.util.text.TextFormatter;

public class MatchHistoryFeature extends FeatureBase {

private final List<MatchHistoryEntry> entries = Lists.newArrayList();

public MatchHistoryFeature(Configuration config, Logger logger) {
super(new MatchHistoryConfig(config), logger, "Match History (PGM)");

if (getConfig().isEnabled() && isPGMEnabled()) {
enable();
}
}

@EventHandler
public void onMatchEnd(MatchFinishEvent event) {
entries.add(new MatchHistoryEntry(event.getMatch()));
}

public void sendHistory(CommandAudience sender, int page, boolean verbose) {
Component headerResultCount = text(Long.toString(entries.size()), NamedTextColor.DARK_GREEN);

int perPage = 7;
int pages = (entries.size() + perPage - 1) / perPage;
page = Math.max(1, Math.min(page, pages));

Component pageNum = translatable(
"command.simplePageHeader",
NamedTextColor.GRAY,
text(Integer.toString(page), NamedTextColor.YELLOW),
text(Integer.toString(pages), NamedTextColor.YELLOW));

Component header = text()
.append(text("Match History", NamedTextColor.GREEN))
.append(text(" (", NamedTextColor.GRAY))
.append(headerResultCount)
.append(text(") » ", NamedTextColor.GRAY))
.append(pageNum)
.build();

Component formattedHeader =
TextFormatter.horizontalLineHeading(sender.getSender(), header, NamedTextColor.DARK_GRAY);
new PaginatedComponentResults<MatchHistoryEntry>(formattedHeader, perPage) {
@Override
public Component format(MatchHistoryEntry data, int index) {
return data.format(verbose);
}

@Override
public Component formatEmpty() {
return text("No recent matches found", NamedTextColor.RED);
}
}.display(sender.getAudience(), entries.stream().sorted().collect(Collectors.toList()), page);
}
}
8 changes: 8 additions & 0 deletions src/main/java/dev/pgm/community/utils/PGMUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import tc.oc.pgm.api.map.MapInfo;
import tc.oc.pgm.api.match.Match;
import tc.oc.pgm.api.match.MatchPhase;
import tc.oc.pgm.api.player.MatchPlayer;
import tc.oc.pgm.blitz.BlitzMatchModule;
import tc.oc.pgm.rotation.MapPoolManager;
import tc.oc.pgm.rotation.pools.MapPool;
Expand Down Expand Up @@ -173,4 +174,11 @@ public static Optional<MapPool> getMapPool(String name) {
}
return Optional.empty();
}

public static List<MatchPlayer> getPlayers(String permissionFilter) {
if (!isPGMEnabled()) return Lists.newArrayList();
return getMatch().getPlayers().stream()
.filter(mp -> mp.getBukkit().hasPermission(permissionFilter))
.collect(Collectors.toList());
}
}
5 changes: 5 additions & 0 deletions src/main/resources/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -327,6 +327,11 @@ polls:
squads:
# Set to true to enable squads, false to disable.
enabled: true

# Match History - Feature that tracks completed PGM matches for easy lookup via command.
history:
# Set to true to enable match history, false to disable.
enabled: true

# Network - Features which assist in running Community on multiple servers
network:
Expand Down

0 comments on commit 7e1126c

Please sign in to comment.