From c0202b4b2f29be0156b3df0541377efdc9e77372 Mon Sep 17 00:00:00 2001 From: ShinyDialga Date: Tue, 16 May 2017 01:11:48 -0500 Subject: [PATCH] Add MVP module --- .../main/i18n/templates/pgm/PGMUI.properties | 2 + .../java/tc/oc/pgm/PGMModulesManifest.java | 2 + .../oc/pgm/events/MatchScoreChangeEvent.java | 11 +- .../oc/pgm/highlights/HighlightListener.java | 82 ++++++++++++ .../oc/pgm/highlights/HighlightManifest.java | 16 +++ .../tc/oc/pgm/playerstats/StatsUserFacet.java | 119 +++++++++++++++++- .../java/tc/oc/pgm/score/ScoreBoxFactory.java | 3 +- .../tc/oc/pgm/score/ScoreMatchModule.java | 12 +- 8 files changed, 237 insertions(+), 10 deletions(-) create mode 100644 PGM/src/main/java/tc/oc/pgm/highlights/HighlightListener.java create mode 100644 PGM/src/main/java/tc/oc/pgm/highlights/HighlightManifest.java diff --git a/Commons/core/src/main/i18n/templates/pgm/PGMUI.properties b/Commons/core/src/main/i18n/templates/pgm/PGMUI.properties index 30afe03..52dc285 100644 --- a/Commons/core/src/main/i18n/templates/pgm/PGMUI.properties +++ b/Commons/core/src/main/i18n/templates/pgm/PGMUI.properties @@ -157,6 +157,8 @@ broadcast.gameOver.gameOverText = Game over! broadcast.gameOver.teamWon = Your team won! broadcast.gameOver.teamLost = Your team lost +broadcast.gameOver.mvp = MVP + # {0} = singular / plural substitution broadcast.score.limitReached = Score limit of {0} reached diff --git a/PGM/src/main/java/tc/oc/pgm/PGMModulesManifest.java b/PGM/src/main/java/tc/oc/pgm/PGMModulesManifest.java index 0f324f4..ba95b3e 100644 --- a/PGM/src/main/java/tc/oc/pgm/PGMModulesManifest.java +++ b/PGM/src/main/java/tc/oc/pgm/PGMModulesManifest.java @@ -10,6 +10,7 @@ import tc.oc.pgm.damage.DamageManifest; import tc.oc.pgm.destroyable.DestroyableManifest; import tc.oc.pgm.filters.FilterManifest; import tc.oc.pgm.flag.FlagManifest; +import tc.oc.pgm.highlights.HighlightManifest; import tc.oc.pgm.itemkeep.ItemKeepManifest; import tc.oc.pgm.kits.KitManifest; import tc.oc.pgm.lane.LaneManifest; @@ -68,5 +69,6 @@ public class PGMModulesManifest extends HybridManifest { install(new TokenManifest()); install(new ObjectiveModeManifest()); install(new BlitzManifest()); + install(new HighlightManifest()); } } diff --git a/PGM/src/main/java/tc/oc/pgm/events/MatchScoreChangeEvent.java b/PGM/src/main/java/tc/oc/pgm/events/MatchScoreChangeEvent.java index 2fc2b44..7cce1de 100644 --- a/PGM/src/main/java/tc/oc/pgm/events/MatchScoreChangeEvent.java +++ b/PGM/src/main/java/tc/oc/pgm/events/MatchScoreChangeEvent.java @@ -4,17 +4,22 @@ import org.bukkit.event.HandlerList; import tc.oc.pgm.match.Match; import tc.oc.pgm.match.Competitor; +import tc.oc.pgm.match.MatchPlayer; + +import java.util.Optional; public class MatchScoreChangeEvent extends MatchEvent { private static final HandlerList handlers = new HandlerList(); private final Competitor competitor; + private final Optional player; private final double oldScore; private final double newScore; - public MatchScoreChangeEvent(Match match, Competitor competitor, double oldScore, double newScore) { + public MatchScoreChangeEvent(Match match, Competitor competitor, Optional player, double oldScore, double newScore) { super(match); this.competitor = competitor; + this.player = player; this.oldScore = oldScore; this.newScore = newScore; } @@ -23,6 +28,10 @@ public class MatchScoreChangeEvent extends MatchEvent { return this.competitor; } + public Optional getPlayer() { + return player; + } + public double getOldScore() { return this.oldScore; } diff --git a/PGM/src/main/java/tc/oc/pgm/highlights/HighlightListener.java b/PGM/src/main/java/tc/oc/pgm/highlights/HighlightListener.java new file mode 100644 index 0000000..0bd6f89 --- /dev/null +++ b/PGM/src/main/java/tc/oc/pgm/highlights/HighlightListener.java @@ -0,0 +1,82 @@ +package tc.oc.pgm.highlights; + +import net.md_5.bungee.api.ChatColor; +import net.md_5.bungee.api.chat.BaseComponent; +import net.md_5.bungee.api.chat.TranslatableComponent; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import tc.oc.commons.core.chat.Component; +import tc.oc.pgm.destroyable.DestroyableContribution; +import tc.oc.pgm.events.MatchEndEvent; +import tc.oc.pgm.match.MatchPlayer; +import tc.oc.pgm.match.MatchScheduler; +import tc.oc.pgm.playerstats.StatsUserFacet; + +import javax.inject.Inject; + +public class HighlightListener implements Listener { + + private final MatchScheduler scheduler; + + @Inject + HighlightListener(MatchScheduler scheduler) { + this.scheduler = scheduler; + } + + @EventHandler + public void matchEnd(MatchEndEvent event) { + StatsUserFacet bestPlayerStats = null; + MatchPlayer bestPlayer = null; + int bestPlayerPoints = 0; + + if (event.getMatch().getParticipatingPlayers().size() < 10) { + return; + } + + for (MatchPlayer player : event.getMatch().getParticipatingPlayers()) { + StatsUserFacet facet = player.getUserContext().facet(StatsUserFacet.class); + + int points = 0; + points += facet.matchKills() * 2; + points -= facet.deaths(); + for (long wool : facet.getWoolCaptureTimes()) { + int woolPoints = (int)((wool * 2) - 2); + points += Math.min(Math.max(woolPoints, 0), 120); + } + + for (long core : facet.getCoreLeakTimes()) { + int corePoints = (int)((core * 2) - 2); + points += Math.min(Math.max(corePoints, 0), 120); + } + + for (DestroyableContribution destroyable : facet.getDestroyableDestroyTimes().keySet()) { + int destroyablePoints = (int)((facet.getDestroyableDestroyTimes().get(destroyable) * 2 * destroyable.getPercentage()) - 2); + points += Math.min(Math.max(destroyablePoints, 0), 120); + } + + for (long flag : facet.getFlagCaptureTimes()) { + int flagPoints = (int)(flag / 2); + points += Math.min(Math.max(flagPoints, 0), 120); + } + + points += (facet.getBlocksBroken() / 20); + + if (bestPlayerStats == null || points > bestPlayerPoints) { + bestPlayerStats = facet; + bestPlayer = player; + bestPlayerPoints = points; + } + } + + if (bestPlayer != null) { + final BaseComponent title = new Component(new TranslatableComponent("broadcast.gameOver.mvp"), ChatColor.AQUA, ChatColor.BOLD); + Component subtitle = new Component(bestPlayer.getDisplayName()); + + for(MatchPlayer viewer : event.getMatch().getPlayers()) { + scheduler.createDelayedTask(100L, () -> { + viewer.showTitle(title, subtitle, 0, 60, 60); + }); + } + } + } +} diff --git a/PGM/src/main/java/tc/oc/pgm/highlights/HighlightManifest.java b/PGM/src/main/java/tc/oc/pgm/highlights/HighlightManifest.java new file mode 100644 index 0000000..ab67fec --- /dev/null +++ b/PGM/src/main/java/tc/oc/pgm/highlights/HighlightManifest.java @@ -0,0 +1,16 @@ +package tc.oc.pgm.highlights; + +import tc.oc.commons.core.inject.HybridManifest; +import tc.oc.pgm.map.inject.MapBinders; +import tc.oc.pgm.match.MatchScope; +import tc.oc.pgm.match.inject.MatchBinders; +import tc.oc.pgm.match.inject.MatchScoped; + +public class HighlightManifest extends HybridManifest implements MapBinders, MatchBinders { + @Override + protected void configure() { + bind(HighlightListener.class).in(MatchScoped.class); + matchListener(HighlightListener.class, MatchScope.LOADED); + } +} + diff --git a/PGM/src/main/java/tc/oc/pgm/playerstats/StatsUserFacet.java b/PGM/src/main/java/tc/oc/pgm/playerstats/StatsUserFacet.java index 47517c3..91c56ed 100644 --- a/PGM/src/main/java/tc/oc/pgm/playerstats/StatsUserFacet.java +++ b/PGM/src/main/java/tc/oc/pgm/playerstats/StatsUserFacet.java @@ -1,25 +1,50 @@ package tc.oc.pgm.playerstats; -import java.util.UUID; -import javax.inject.Inject; - +import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; import org.bukkit.event.Listener; +import org.bukkit.event.block.BlockBreakEvent; import tc.oc.commons.bukkit.event.targeted.TargetedEventHandler; +import tc.oc.pgm.core.Core; +import tc.oc.pgm.core.CoreBlockBreakEvent; +import tc.oc.pgm.core.CoreLeakEvent; +import tc.oc.pgm.destroyable.Destroyable; +import tc.oc.pgm.destroyable.DestroyableContribution; +import tc.oc.pgm.destroyable.DestroyableDestroyedEvent; import tc.oc.pgm.events.MatchPlayerDeathEvent; +import tc.oc.pgm.events.MatchScoreChangeEvent; import tc.oc.pgm.events.PlayerPartyChangeEvent; +import tc.oc.pgm.flag.event.FlagCaptureEvent; import tc.oc.pgm.match.MatchUserFacet; import tc.oc.pgm.match.ParticipantState; import tc.oc.pgm.match.inject.ForMatchUser; import tc.oc.pgm.spawns.events.ParticipantSpawnEvent; +import tc.oc.pgm.wool.PlayerWoolPlaceEvent; + +import javax.inject.Inject; +import java.util.*; public class StatsUserFacet implements MatchUserFacet, Listener { private final UUID player; private int lifeKills, teamKills, matchKills, deaths; + private List woolCaptureTimes; + private Map coreTouchTimes; + private List coreLeakTimes; + private List flagCaptureTimes; + private double pointsScored; + private HashMap destroyableDestroyTimes; + private int blocksBroken; @Inject public StatsUserFacet(@ForMatchUser UUID player) { this.player = player; + woolCaptureTimes = new ArrayList<>(); + coreTouchTimes = new HashMap<>(); + coreLeakTimes = new ArrayList<>(); + flagCaptureTimes = new ArrayList<>(); + pointsScored = 0; + destroyableDestroyTimes = new HashMap<>(); + blocksBroken = 0; } /** @@ -50,6 +75,32 @@ public class StatsUserFacet implements MatchUserFacet, Listener { return deaths; } + public List getWoolCaptureTimes() { return woolCaptureTimes; } + + public Map getCoreTouchTimes() { + return coreTouchTimes; + } + + public List getCoreLeakTimes() { + return coreLeakTimes; + } + + public List getFlagCaptureTimes() { + return flagCaptureTimes; + } + + public double getPointsScored() { + return pointsScored; + } + + public HashMap getDestroyableDestroyTimes() { + return destroyableDestroyTimes; + } + + public int getBlocksBroken() { + return blocksBroken; + } + @TargetedEventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) public void onKill(final MatchPlayerDeathEvent event) { ParticipantState killer = event.getKiller(); @@ -62,6 +113,61 @@ public class StatsUserFacet implements MatchUserFacet, Listener { } } + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) + public void onWoolPlace(final PlayerWoolPlaceEvent event) { + if (event.getWool().isVisible() && event.getPlayer().getUniqueId().equals(player)) { + woolCaptureTimes.add(event.getMatch().runningTime().toMinutes()); + } + } + + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) + public void onFlagCapture(final FlagCaptureEvent event) { + if (event.getGoal().isVisible() && event.getCarrier().getUniqueId().equals(player)) { + flagCaptureTimes.add(event.getMatch().runningTime().toMinutes()); + } + } + + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) + public void onDestroyableDestroyed(final DestroyableDestroyedEvent event) { + Destroyable destroyable = event.getDestroyable(); + + if (destroyable.isVisible()) { + for (DestroyableContribution entry : event.getDestroyable().getContributions()) { + if (entry.getPlayerState().getUniqueId().equals(player)) { + destroyableDestroyTimes.put(entry, event.getMatch().runningTime().toMinutes()); + } + } + } + } + + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) + public void onCoreBlockBreak(final CoreBlockBreakEvent event) { + if (event.getCore().isVisible() && event.getPlayer().getUniqueId().equals(player)) { + coreTouchTimes.put(event.getCore(), event.getMatch().runningTime().toMinutes()); + } + } + + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) + public void onCoreLeak(final CoreLeakEvent event) { + if (event.getCore().isVisible() && coreTouchTimes.containsKey(event.getCore())) { + coreLeakTimes.add(coreTouchTimes.get(event.getCore())); + } + } + + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) + public void onScoreEvent(final MatchScoreChangeEvent event) { + if (event.getPlayer().isPresent() && event.getPlayer().get().getUniqueId().equals(player)) { + pointsScored += event.getNewScore() - event.getOldScore(); + } + } + + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) + public void onScoreEvent(final BlockBreakEvent event) { + if (event.getPlayer().getUniqueId().equals(player)) { + ++blocksBroken; + } + } + @TargetedEventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) public void onSpawn(final ParticipantSpawnEvent event) { lifeKills = 0; @@ -71,5 +177,12 @@ public class StatsUserFacet implements MatchUserFacet, Listener { public void onPartyChange(final PlayerPartyChangeEvent event) { lifeKills = 0; teamKills = 0; + woolCaptureTimes.clear(); + coreTouchTimes.clear(); + coreLeakTimes.clear(); + flagCaptureTimes.clear(); + pointsScored = 0; + destroyableDestroyTimes.clear(); + blocksBroken = 0; } } diff --git a/PGM/src/main/java/tc/oc/pgm/score/ScoreBoxFactory.java b/PGM/src/main/java/tc/oc/pgm/score/ScoreBoxFactory.java index f6e9f9c..7d90e31 100644 --- a/PGM/src/main/java/tc/oc/pgm/score/ScoreBoxFactory.java +++ b/PGM/src/main/java/tc/oc/pgm/score/ScoreBoxFactory.java @@ -1,6 +1,7 @@ package tc.oc.pgm.score; import java.util.Map; +import java.util.Optional; import com.google.common.base.Preconditions; import com.google.common.collect.ImmutableMap; @@ -153,7 +154,7 @@ class ScoreBoxFactoryImpl extends FeatureDefinition.Impl implements ScoreBoxFact ); } - smm.incrementScore(player.getCompetitor(), points); + smm.incrementScore(player.getCompetitor(), points, Optional.of(player)); } } } diff --git a/PGM/src/main/java/tc/oc/pgm/score/ScoreMatchModule.java b/PGM/src/main/java/tc/oc/pgm/score/ScoreMatchModule.java index 48c6121..68f352b 100644 --- a/PGM/src/main/java/tc/oc/pgm/score/ScoreMatchModule.java +++ b/PGM/src/main/java/tc/oc/pgm/score/ScoreMatchModule.java @@ -2,6 +2,7 @@ package tc.oc.pgm.score; import java.util.HashMap; import java.util.Map; +import java.util.Optional; import java.util.stream.Collectors; import net.md_5.bungee.api.ChatColor; @@ -15,10 +16,7 @@ import tc.oc.commons.core.util.DefaultMapAdapter; import tc.oc.pgm.events.ListenerScope; import tc.oc.pgm.events.MatchPlayerDeathEvent; import tc.oc.pgm.events.MatchScoreChangeEvent; -import tc.oc.pgm.match.Competitor; -import tc.oc.pgm.match.Match; -import tc.oc.pgm.match.MatchModule; -import tc.oc.pgm.match.MatchScope; +import tc.oc.pgm.match.*; import tc.oc.pgm.victory.VictoryMatchModule; import static com.google.common.base.Preconditions.checkState; @@ -86,6 +84,10 @@ public class ScoreMatchModule extends MatchModule implements Listener { } public void incrementScore(Competitor competitor, double amount) { + this.incrementScore(competitor, amount, null); + } + + public void incrementScore(Competitor competitor, double amount, Optional player) { double oldScore = this.scores.get(competitor); double newScore = oldScore + amount; @@ -93,7 +95,7 @@ public class ScoreMatchModule extends MatchModule implements Listener { newScore = this.config.scoreLimit.get(); } - MatchScoreChangeEvent event = new MatchScoreChangeEvent(competitor.getMatch(), competitor, oldScore, newScore); + MatchScoreChangeEvent event = new MatchScoreChangeEvent(competitor.getMatch(), competitor, player, oldScore, newScore); this.match.getServer().getPluginManager().callEvent(event); this.scores.put(competitor, event.getNewScore());