diff --git a/README.md b/README.md
index f56c00d..012bc01 100644
--- a/README.md
+++ b/README.md
@@ -52,8 +52,8 @@ players:
| `` | Uses the result from a round with a matching id - useful to stop repeating veto deciders | `id="map-name"` | N/A |
| `` | Represents a veto round | `id="veto"` | **Required:** ``, ``, `` |
| `` | Which team vetoes first | N/A | A round |
-| `` | What vetos should there be | `name` on the child element - what name should be displayed in the veto | Round(s) |
-| `` | The veto order (ban, pick, etc.). The last element is enacted by the system (not by a team and so should not have the who attribute). | `ban-until="3"` (ban until 3 maps are left), `starting-team="2"` (the team who lost the decider starts), `time="30"` - the time in seconds that each team has to veto | If no attributes are present, `` and `` |
+| `` | What vetos should there be | `name` on the child element - what name should be displayed in the veto | At least 2 rounds |
+| `` | The veto order (ban, pick, etc.), with one element per option and at least one pick. The last element is enacted by the system (not by a team and so should not have a `team` attribute). | `ban-until="3"` (ban until 3 maps are left), `starting-team="2"` (the team who lost the decider starts), `time="30"` - the time in seconds that each team has to veto | If no attributes are present, `` and `` |
| `` | A pick in the veto | `team="0"` - the team that gets to pick a map (zero is random map picked), `insert="back"` - whether the map should be added to the front or back of the maps to be played | N/A |
| `` | A ban in the veto | `team="0"` - the team that gets to ban a map (zero is random map banned), `insert="back"` - whether the map should be added to the front or back of the maps to be played | N/A |
diff --git a/build.gradle.kts b/build.gradle.kts
index 64612df..4d210a9 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -51,7 +51,7 @@ tasks {
expand(
mapOf(
"description" to description,
- "apiVersion" to "1.21.11",
+ "apiVersion" to "26.2",
"mainClass" to "dev.pgm.events.EventsPlugin",
"version" to version,
"commitHash" to commitHash.get(),
diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts
index bf1de44..7d98320 100644
--- a/buildSrc/build.gradle.kts
+++ b/buildSrc/build.gradle.kts
@@ -9,7 +9,7 @@ repositories {
}
dependencies {
- implementation("com.gradleup.shadow:com.gradleup.shadow.gradle.plugin:9.4.2")
- implementation("com.diffplug.gradle.spotless:com.diffplug.gradle.spotless.gradle.plugin:8.6.0")
- implementation("de.skuzzle.restrictimports:de.skuzzle.restrictimports.gradle.plugin:3.0.0")
+ implementation("com.gradleup.shadow:com.gradleup.shadow.gradle.plugin:9.6.1")
+ implementation("com.diffplug.spotless:com.diffplug.spotless.gradle.plugin:8.10.4")
+ implementation("de.skuzzle.restrictimports:de.skuzzle.restrictimports.gradle.plugin:3.0.2")
}
\ No newline at end of file
diff --git a/buildSrc/src/main/kotlin/buildlogic.java-conventions.gradle.kts b/buildSrc/src/main/kotlin/buildlogic.java-conventions.gradle.kts
index 5d41cc5..1fa574d 100644
--- a/buildSrc/src/main/kotlin/buildlogic.java-conventions.gradle.kts
+++ b/buildSrc/src/main/kotlin/buildlogic.java-conventions.gradle.kts
@@ -1,3 +1,5 @@
+import de.skuzzle.restrictimports.gradle.RestrictImports
+
plugins {
`java-library`
id("com.diffplug.spotless")
@@ -6,7 +8,7 @@ plugins {
java {
toolchain {
- languageVersion = JavaLanguageVersion.of(21)
+ languageVersion = JavaLanguageVersion.of(25)
}
}
@@ -21,14 +23,14 @@ repositories {
dependencies {
// Annotations
- api("org.jspecify:jspecify:1.0.0")
+ api("org.jspecify:jspecify:1.0.1")
compileOnly("org.jetbrains:annotations:26.1.0")
compileOnly("org.incendo:cloud-annotations:2.0.0")
// Provided dependencies
- compileOnly("dev.pgm.paper:paper-api:1.8_1.21.11-SNAPSHOT")
+ compileOnly("dev.pgm.paper:paper-api:1.8_26.2-SNAPSHOT")
compileOnly("tc.oc.pgm:core:0.16-SNAPSHOT") { isTransitive = false }
- compileOnly("net.kyori:adventure-api:4.26.1")
+ compileOnly("net.kyori:adventure-api:5.2.0")
compileOnly("com.google.guava:guava:17.0")
}
@@ -50,17 +52,24 @@ spotless {
removeUnusedImports()
trimTrailingWhitespace()
formatAnnotations()
- palantirJavaFormat("2.93.0").style("GOOGLE").formatJavadoc(true)
+ palantirJavaFormat("2.102.0").style("GOOGLE").formatJavadoc(true)
}
}
-restrictImports {
- group {
+tasks {
+ // Bypass inability to have two groups with same base packages inside the import restriction plugin
+ val restrictJavaxAnnotations = register("restrictJavaxAnnotations") {
+ group = "verification"
reason = "Use org.jspecify.annotations to add annotations, or org.jetbrains.annotations if needed"
bannedImports = listOf("javax.annotation.**")
}
- group {
+ val restrictAsserts = register("restrictAsserts") {
+ group = "verification"
reason = "Use tc.oc.pgm.util.Assert to add assertions"
bannedImports = listOf("com.google.common.base.Preconditions.**", "java.util.Objects.requireNonNull")
}
+ // Enforce the import restrictions
+ check {
+ dependsOn(restrictJavaxAnnotations, restrictAsserts)
+ }
}
\ No newline at end of file
diff --git a/gradle.properties b/gradle.properties
index c978528..68f8053 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -1 +1,2 @@
-//org.gradle.configuration-cache=true
+# https://github.com/diffplug/spotless/issues/2850
+org.gradle.configuration-cache=false
diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar
index b1b8ef5..9fa7f28 100644
Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index df6a6ad..2e7bb9f 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-9.5.1-bin.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-9.8.1-bin.zip
networkTimeout=10000
retries=0
retryBackOffMs=500
diff --git a/gradlew b/gradlew
index b9bb139..249efbb 100755
--- a/gradlew
+++ b/gradlew
@@ -20,7 +20,7 @@
##############################################################################
#
-# Gradle start up script for POSIX generated by Gradle.
+# gradlew start up script for POSIX generated by Gradle.
#
# Important for running:
#
@@ -29,7 +29,7 @@
# bash, then to run this script, type that shell name before the whole
# command line, like:
#
-# ksh Gradle
+# ksh gradlew
#
# Busybox and similar reduced shells will NOT work, because this script
# requires all of these POSIX shell features:
diff --git a/gradlew.bat b/gradlew.bat
index 24c62d5..3185a43 100644
--- a/gradlew.bat
+++ b/gradlew.bat
@@ -19,13 +19,40 @@
@if "%DEBUG%"=="" @echo off
@rem ##########################################################################
@rem
-@rem Gradle startup script for Windows
+@rem gradlew startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables, and ensure extensions are enabled
setlocal EnableExtensions
+@rem Catch executions from older scripts and ensure they exit cleanly.
+@rem This can be removed once we can be reasonably confident that few people
+@rem will be migrating directly to this new wrapper.
+goto afterSafetyNet
+::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
+::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
+::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
+::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
+::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
+::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
+::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
+::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
+::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
+::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
+::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
+::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
+::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
+::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
+::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
+::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
+::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
+::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
+::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
+::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
+goto exitWithErrorLevel
+:afterSafetyNet
+
set DIRNAME=%~dp0
if "%DIRNAME%"=="" set DIRNAME=.
@rem This is normally unused
@@ -45,13 +72,14 @@ set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if %ERRORLEVEL% equ 0 goto execute
-echo. 1>&2
-echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
-echo. 1>&2
-echo Please set the JAVA_HOME variable in your environment to match the 1>&2
-echo location of your Java installation. 1>&2
+1>&2 echo.
+1>&2 echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+1>&2 echo.
+1>&2 echo Please set the JAVA_HOME variable in your environment to match the
+1>&2 echo location of your Java installation.
"%COMSPEC%" /c exit 1
+goto exitWithErrorLevel
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
@@ -59,24 +87,26 @@ set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto execute
-echo. 1>&2
-echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
-echo. 1>&2
-echo Please set the JAVA_HOME variable in your environment to match the 1>&2
-echo location of your Java installation. 1>&2
+1>&2 echo.
+1>&2 echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+1>&2 echo.
+1>&2 echo Please set the JAVA_HOME variable in your environment to match the
+1>&2 echo location of your Java installation.
"%COMSPEC%" /c exit 1
+goto exitWithErrorLevel
:execute
@rem Setup the command line
-@rem Execute Gradle
+@rem Execute gradlew
@rem endlocal doesn't take effect until after the line is parsed and variables are expanded
@rem which allows us to clear the local environment before executing the java command
-endlocal & "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* & call :exitWithErrorLevel
+endlocal & "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* & call :exitWithErrorLevel & goto exitWithErrorLevel
+@rem This label must not be changed. We rely on old scripts being able to jump to this point.
:exitWithErrorLevel
@rem Use "%COMSPEC%" /c exit to allow operators to work properly in scripts
"%COMSPEC%" /c exit %ERRORLEVEL%
diff --git a/samples/formats/bo3.xml b/samples/formats/bo3.xml
index b6a85a1..7c07de9 100644
--- a/samples/formats/bo3.xml
+++ b/samples/formats/bo3.xml
@@ -10,6 +10,7 @@
Limbo II
Golden Drought II
+
Boom
diff --git a/samples/formats/group.xml b/samples/formats/group.xml
index e606abb..2589f64 100644
--- a/samples/formats/group.xml
+++ b/samples/formats/group.xml
@@ -34,6 +34,7 @@
Facility TE
Dwyer Hill
+
Boom
diff --git a/src/main/java/dev/pgm/events/api/events/TournamentEvent.java b/src/main/java/dev/pgm/events/api/events/TournamentEvent.java
index c130eeb..328e217 100644
--- a/src/main/java/dev/pgm/events/api/events/TournamentEvent.java
+++ b/src/main/java/dev/pgm/events/api/events/TournamentEvent.java
@@ -2,11 +2,9 @@
import dev.pgm.events.format.TournamentFormat;
import org.bukkit.event.Event;
-import org.bukkit.event.HandlerList;
-public class TournamentEvent extends Event {
+public abstract class TournamentEvent extends Event {
- private static final HandlerList handlers = new HandlerList();
private final TournamentFormat tournamentFormat;
public TournamentEvent(TournamentFormat tournamentFormat) {
@@ -16,13 +14,4 @@ public TournamentEvent(TournamentFormat tournamentFormat) {
public TournamentFormat format() {
return tournamentFormat;
}
-
- public static HandlerList getHandlerList() {
- return handlers;
- }
-
- @Override
- public HandlerList getHandlers() {
- return handlers;
- }
}
diff --git a/src/main/java/dev/pgm/events/api/events/TournamentFinishedEvent.java b/src/main/java/dev/pgm/events/api/events/TournamentFinishedEvent.java
index 904016a..d574061 100644
--- a/src/main/java/dev/pgm/events/api/events/TournamentFinishedEvent.java
+++ b/src/main/java/dev/pgm/events/api/events/TournamentFinishedEvent.java
@@ -3,18 +3,33 @@
import dev.pgm.events.format.TournamentFormat;
import dev.pgm.events.team.TournamentTeam;
import java.util.Optional;
+import org.bukkit.event.HandlerList;
+import org.jspecify.annotations.NullMarked;
+import org.jspecify.annotations.Nullable;
+@NullMarked
public class TournamentFinishedEvent extends TournamentEvent {
- private final Optional winningTeam;
+ private static final HandlerList HANDLER_LIST = new HandlerList();
+
+ private final @Nullable TournamentTeam winningTeam;
public TournamentFinishedEvent(
- TournamentFormat tournamentFormat, Optional winningTeam) {
+ TournamentFormat tournamentFormat, @Nullable TournamentTeam winningTeam) {
super(tournamentFormat);
this.winningTeam = winningTeam;
}
public Optional winningTeam() {
- return winningTeam;
+ return Optional.ofNullable(winningTeam);
+ }
+
+ @Override
+ public HandlerList getHandlers() {
+ return HANDLER_LIST;
+ }
+
+ public static HandlerList getHandlerList() {
+ return HANDLER_LIST;
}
}
diff --git a/src/main/java/dev/pgm/events/api/events/TournamentStartEvent.java b/src/main/java/dev/pgm/events/api/events/TournamentStartEvent.java
index 37eeac5..533a29b 100644
--- a/src/main/java/dev/pgm/events/api/events/TournamentStartEvent.java
+++ b/src/main/java/dev/pgm/events/api/events/TournamentStartEvent.java
@@ -1,10 +1,24 @@
package dev.pgm.events.api.events;
import dev.pgm.events.format.TournamentFormat;
+import org.bukkit.event.HandlerList;
+import org.jspecify.annotations.NullMarked;
+@NullMarked
public class TournamentStartEvent extends TournamentEvent {
+ private static final HandlerList HANDLER_LIST = new HandlerList();
+
public TournamentStartEvent(TournamentFormat tournamentFormat) {
super(tournamentFormat);
}
+
+ @Override
+ public HandlerList getHandlers() {
+ return HANDLER_LIST;
+ }
+
+ public static HandlerList getHandlerList() {
+ return HANDLER_LIST;
+ }
}
diff --git a/src/main/java/dev/pgm/events/api/teams/DefaultTeamRegistry.java b/src/main/java/dev/pgm/events/api/teams/DefaultTeamRegistry.java
index 0052ec0..52936e8 100644
--- a/src/main/java/dev/pgm/events/api/teams/DefaultTeamRegistry.java
+++ b/src/main/java/dev/pgm/events/api/teams/DefaultTeamRegistry.java
@@ -1,12 +1,13 @@
package dev.pgm.events.api.teams;
+import static net.kyori.adventure.text.Component.text;
+
import com.google.common.collect.Maps;
import dev.pgm.events.EventsPlugin;
import dev.pgm.events.team.TournamentTeam;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
-import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.NamedTextColor;
import org.bukkit.Bukkit;
import tc.oc.pgm.util.Audience;
@@ -55,8 +56,8 @@ public void reload() {
teams.forEach(x -> teamMap.put(x.getName(), x));
Bukkit.getOnlinePlayers().stream()
.filter(x -> x.hasPermission("events.staff"))
- .forEach(x -> Audience.get(x)
- .sendMessage(Component.text("Teams reloaded!", NamedTextColor.AQUA)));
+ .forEach(
+ x -> Audience.get(x).sendMessage(text("Teams reloaded!", NamedTextColor.AQUA)));
});
});
}
diff --git a/src/main/java/dev/pgm/events/commands/TournamentAdminCommands.java b/src/main/java/dev/pgm/events/commands/TournamentAdminCommands.java
index 4b52df5..98b9ded 100644
--- a/src/main/java/dev/pgm/events/commands/TournamentAdminCommands.java
+++ b/src/main/java/dev/pgm/events/commands/TournamentAdminCommands.java
@@ -1,12 +1,14 @@
package dev.pgm.events.commands;
+import static net.kyori.adventure.text.Component.text;
+
import dev.pgm.events.TournamentManager;
import dev.pgm.events.api.teams.TournamentTeamRegistry;
+import dev.pgm.events.format.TournamentFormat;
import dev.pgm.events.team.TournamentPlayer;
import dev.pgm.events.team.TournamentTeam;
import dev.pgm.events.team.TournamentTeamManager;
import dev.pgm.events.xml.MapFormatXMLParser;
-import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.NamedTextColor;
import org.bukkit.Bukkit;
import org.bukkit.OfflinePlayer;
@@ -35,8 +37,14 @@ public void tourney(
TournamentManager manager,
Match match,
@Argument("format") @Greedy String pool) {
- manager.createTournament(match, MapFormatXMLParser.parse(pool));
- Audience.get(sender).sendMessage(Component.text("Starting tournament.", NamedTextColor.GOLD));
+ TournamentFormat format;
+ try {
+ format = MapFormatXMLParser.parse(pool);
+ } catch (IllegalArgumentException e) {
+ throw new CommandException(e.getMessage());
+ }
+ manager.createTournament(match, format);
+ Audience.get(sender).sendMessage(text("Starting tournament.", NamedTextColor.GOLD));
}
@Command("register ")
@@ -62,7 +70,7 @@ public void register(
teamManager.addTeam(team);
Audience.get(sender)
- .sendMessage(Component.text("Added team " + team.getName() + "!", NamedTextColor.YELLOW));
+ .sendMessage(text("Added team " + team.getName() + "!", NamedTextColor.YELLOW));
}
@Command("list")
@@ -70,14 +78,13 @@ public void register(
@Permission("events.staff")
public void list(CommandSender sender, TournamentTeamRegistry registry) {
Audience audience = Audience.get(sender);
- audience.sendMessage(Component.text("------- ", NamedTextColor.GOLD)
- .append(Component.text("Registered Teams", NamedTextColor.AQUA))
- .append(Component.text(" -------", NamedTextColor.GOLD)));
+ audience.sendMessage(text("------- ", NamedTextColor.GOLD)
+ .append(text("Registered Teams", NamedTextColor.AQUA))
+ .append(text(" -------", NamedTextColor.GOLD)));
for (TournamentTeam team : registry.getTeams())
- audience.sendMessage(
- Component.text("- ", NamedTextColor.AQUA).append(Component.text(team.getName())));
+ audience.sendMessage(text("- ", NamedTextColor.AQUA).append(text(team.getName())));
audience.sendMessage(
- Component.text("Run /tourney info to see player roster!", NamedTextColor.YELLOW));
+ text("Run /tourney info to see player roster!", NamedTextColor.YELLOW));
}
@Command("info ")
@@ -91,16 +98,15 @@ public void info(
if (team == null) throw new CommandException("Team not found!");
Audience audience = Audience.get(sender);
- audience.sendMessage(Component.text("------- ", NamedTextColor.GOLD)
- .append(Component.text(team.getName(), NamedTextColor.AQUA))
- .append(Component.text(" -------", NamedTextColor.GOLD)));
+ audience.sendMessage(text("------- ", NamedTextColor.GOLD)
+ .append(text(team.getName(), NamedTextColor.AQUA))
+ .append(text(" -------", NamedTextColor.GOLD)));
for (TournamentPlayer player : team.getPlayers()) {
String playerName = player.getUUID().toString() + " (player hasn't logged on)";
OfflinePlayer offline = Bukkit.getOfflinePlayer(player.getUUID());
if (offline.getName() != null) playerName = offline.getName();
- audience.sendMessage(
- Component.text("- ", NamedTextColor.AQUA).append(Component.text(playerName)));
+ audience.sendMessage(text("- ", NamedTextColor.AQUA).append(text(playerName)));
}
}
@@ -109,7 +115,6 @@ public void info(
@Permission("events.staff")
public void clear(CommandSender sender, TournamentTeamManager teamManager) {
teamManager.clear();
- Audience.get(sender)
- .sendMessage(Component.text("Unregistered all teams!", NamedTextColor.YELLOW));
+ Audience.get(sender).sendMessage(text("Unregistered all teams!", NamedTextColor.YELLOW));
}
}
diff --git a/src/main/java/dev/pgm/events/commands/TournamentUserCommands.java b/src/main/java/dev/pgm/events/commands/TournamentUserCommands.java
index 7d2064e..72f0dc6 100644
--- a/src/main/java/dev/pgm/events/commands/TournamentUserCommands.java
+++ b/src/main/java/dev/pgm/events/commands/TournamentUserCommands.java
@@ -1,11 +1,12 @@
package dev.pgm.events.commands;
+import static net.kyori.adventure.text.Component.text;
+
import dev.pgm.events.EventsPlugin;
import dev.pgm.events.format.TournamentFormat;
import dev.pgm.events.format.rounds.RoundDescription;
import dev.pgm.events.format.rounds.format.FormatTournamentImpl;
import java.util.Optional;
-import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.NamedTextColor;
import org.bukkit.command.CommandSender;
import tc.oc.pgm.lib.org.incendo.cloud.annotations.Command;
@@ -22,14 +23,14 @@ public void currentScore(CommandSender sender, TournamentFormat format) {
if (format instanceof FormatTournamentImpl) {
String formatName =
((FormatTournamentImpl) format).getFormatRound().settings().name();
- audience.sendMessage(Component.text("For " + formatName + ":", NamedTextColor.YELLOW));
+ audience.sendMessage(text("For " + formatName + ":", NamedTextColor.YELLOW));
audience.sendMessage(format.currentScore().condensed());
Optional parentOptional =
EventsPlugin.get().getTournamentManager().currentTournament();
if (parentOptional.isPresent()) {
audience.sendMessage(
- Component.text("Overall score (excluding " + formatName + "):", NamedTextColor.YELLOW));
+ text("Overall score (excluding " + formatName + "):", NamedTextColor.YELLOW));
audience.sendMessage(parentOptional.get().currentScore().condensed());
}
} else {
@@ -46,14 +47,14 @@ public void rounds(CommandSender sender, TournamentFormat format) {
" (" + ((FormatTournamentImpl) format).getFormatRound().settings().name() + ")";
Audience audience = Audience.get(sender);
- audience.sendMessage(Component.text("------- ", NamedTextColor.GOLD)
- .append(Component.text(header, NamedTextColor.AQUA))
- .append(Component.text(" -------", NamedTextColor.GOLD)));
+ audience.sendMessage(text("------- ", NamedTextColor.GOLD)
+ .append(text(header, NamedTextColor.AQUA))
+ .append(text(" -------", NamedTextColor.GOLD)));
int round = 1;
for (RoundDescription roundDescription : format.roundsInformation()) {
audience.sendMessage(
- Component.text(round + ". ", NamedTextColor.GOLD).append(roundDescription.roundInfo()));
+ text(round + ". ", NamedTextColor.GOLD).append(roundDescription.roundInfo()));
round++;
}
}
diff --git a/src/main/java/dev/pgm/events/commands/providers/TournamentProvider.java b/src/main/java/dev/pgm/events/commands/providers/TournamentProvider.java
index c694141..a188f24 100644
--- a/src/main/java/dev/pgm/events/commands/providers/TournamentProvider.java
+++ b/src/main/java/dev/pgm/events/commands/providers/TournamentProvider.java
@@ -6,7 +6,7 @@
import dev.pgm.events.format.rounds.format.FormatRound;
import java.util.Optional;
import org.bukkit.command.CommandSender;
-import org.jetbrains.annotations.NotNull;
+import org.jspecify.annotations.NonNull;
import org.jspecify.annotations.Nullable;
import tc.oc.pgm.lib.org.incendo.cloud.context.CommandContext;
import tc.oc.pgm.lib.org.incendo.cloud.exception.CommandExecutionException;
@@ -23,8 +23,8 @@ public TournamentProvider(TournamentManager tournamentManager) {
@Override
public @Nullable TournamentFormat create(
- @NotNull CommandContext context,
- @NotNull AnnotationAccessor annotationAccessor) {
+ @NonNull CommandContext context,
+ @NonNull AnnotationAccessor annotationAccessor) {
Optional tournamentFormat = tournamentManager.currentTournament();
if (tournamentFormat.isPresent()) {
TournamentFormat format = tournamentFormat.get();
diff --git a/src/main/java/dev/pgm/events/format/RoundHolder.java b/src/main/java/dev/pgm/events/format/RoundHolder.java
index 07f46b5..7841ccf 100644
--- a/src/main/java/dev/pgm/events/format/RoundHolder.java
+++ b/src/main/java/dev/pgm/events/format/RoundHolder.java
@@ -12,7 +12,6 @@
import java.util.List;
import java.util.Map;
import java.util.Optional;
-import java.util.stream.Collectors;
import tc.oc.pgm.api.match.Match;
class RoundHolder {
@@ -55,7 +54,7 @@ public List roundDescriptions(Context context) {
return rounds.stream()
.filter(x -> x.shouldShowInHistory() || context == Context.DEBUG)
.map(TournamentRound::describe)
- .collect(Collectors.toList());
+ .toList();
}
public Scores scores(TournamentTeamManager teamManager) {
diff --git a/src/main/java/dev/pgm/events/format/TournamentFormatImpl.java b/src/main/java/dev/pgm/events/format/TournamentFormatImpl.java
index fc5bd31..ee73dfa 100644
--- a/src/main/java/dev/pgm/events/format/TournamentFormatImpl.java
+++ b/src/main/java/dev/pgm/events/format/TournamentFormatImpl.java
@@ -1,5 +1,7 @@
package dev.pgm.events.format;
+import static net.kyori.adventure.text.Component.text;
+
import dev.pgm.events.EventsPlugin;
import dev.pgm.events.api.events.TournamentFinishedEvent;
import dev.pgm.events.config.Context;
@@ -12,13 +14,12 @@
import dev.pgm.events.team.TournamentTeamManager;
import java.util.ArrayList;
import java.util.List;
-import java.util.Optional;
-import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.NamedTextColor;
import org.bukkit.Bukkit;
import org.bukkit.event.EventPriority;
import org.bukkit.event.HandlerList;
import org.bukkit.event.Listener;
+import org.jspecify.annotations.Nullable;
import tc.oc.pgm.api.PGM;
import tc.oc.pgm.api.match.Match;
import tc.oc.pgm.util.Audience;
@@ -87,14 +88,14 @@ else if (state == TournamentState.FINISHED) // if finished we outta here
broadcastScore();
// todo: Check phase of previous round?
- Optional winner = roundHolder.calculateWinner(teamManager);
- if (winner.isPresent() || !hasNextRound()) {
+ TournamentTeam winner = roundHolder.calculateWinner(teamManager).orElse(null);
+ if (winner != null || !hasNextRound()) {
unregisterAll();
// there's a winner, return and announce them
state = TournamentState.FINISHED;
- // if this doesn't call it just call it all normal like
- onEnd(match, winner);
+ // fire before onEnd, which may synchronously advance a parent tournament
Events.callEvent(new TournamentFinishedEvent(this, winner), EventPriority.NORMAL);
+ onEnd(match, winner);
return;
}
@@ -160,14 +161,14 @@ private void broadcastScore() {
3 * 20);
}
- public void onEnd(Match match, Optional winner) {
+ public void onEnd(Match match, @Nullable TournamentTeam winner) {
if (tournamentRoundOptions.shouldAnnounceWinner()) {
- if (winner.isPresent()) {
+ if (winner != null) {
match.sendMessage(teamManager
- .formattedName(winner.get())
- .append(Component.text(" wins this round!", NamedTextColor.GOLD)));
+ .formattedName(winner)
+ .append(text(" wins this round!", NamedTextColor.GOLD)));
} else {
- match.sendMessage(Component.text("This round has ended in a draw!", NamedTextColor.GRAY));
+ match.sendMessage(text("This round has ended in a draw!", NamedTextColor.GRAY));
}
}
diff --git a/src/main/java/dev/pgm/events/format/rounds/format/FormatRound.java b/src/main/java/dev/pgm/events/format/rounds/format/FormatRound.java
index 9275a09..93108f8 100644
--- a/src/main/java/dev/pgm/events/format/rounds/format/FormatRound.java
+++ b/src/main/java/dev/pgm/events/format/rounds/format/FormatRound.java
@@ -11,12 +11,13 @@
import dev.pgm.events.team.TournamentTeam;
import java.util.HashMap;
import java.util.Map;
+import org.jspecify.annotations.Nullable;
import tc.oc.pgm.api.match.Match;
public class FormatRound extends AbstractRound {
private FormatTournamentImpl formatTournament;
- private TournamentTeam winner;
+ private @Nullable TournamentTeam winner;
private TournamentTeam selectingTeam;
@@ -63,7 +64,7 @@ public Map scores() {
return scores;
}
- public void setWinner(Match match, TournamentTeam winner) {
+ public void setWinner(Match match, @Nullable TournamentTeam winner) {
this.winner = winner;
tournament().nextRound(match);
}
diff --git a/src/main/java/dev/pgm/events/format/rounds/format/FormatRoundDescription.java b/src/main/java/dev/pgm/events/format/rounds/format/FormatRoundDescription.java
index 548cba2..2e4a9ea 100644
--- a/src/main/java/dev/pgm/events/format/rounds/format/FormatRoundDescription.java
+++ b/src/main/java/dev/pgm/events/format/rounds/format/FormatRoundDescription.java
@@ -1,8 +1,10 @@
package dev.pgm.events.format.rounds.format;
+import static net.kyori.adventure.text.Component.text;
+import static net.kyori.adventure.text.event.HoverEvent.showText;
+
import dev.pgm.events.format.rounds.RoundDescription;
import net.kyori.adventure.text.Component;
-import net.kyori.adventure.text.event.HoverEvent;
import net.kyori.adventure.text.format.NamedTextColor;
public class FormatRoundDescription implements RoundDescription {
@@ -15,13 +17,12 @@ public FormatRoundDescription(FormatRound formatRound) {
@Override
public Component roundInfo() {
- Component base = Component.text(
+ Component base = text(
formatRound.settings().name() + " - Best of " + formatRound.settings().bestOf());
if (formatRound.formatTournament() != null) {
- return base.hoverEvent(HoverEvent.showText(formatRound.formattedScore().condensed()));
+ return base.hoverEvent(showText(formatRound.formattedScore().condensed()));
} else {
- return base.hoverEvent(
- HoverEvent.showText(Component.text("Loading...", NamedTextColor.YELLOW)));
+ return base.hoverEvent(showText(text("Loading...", NamedTextColor.YELLOW)));
}
}
diff --git a/src/main/java/dev/pgm/events/format/rounds/format/FormatTournamentImpl.java b/src/main/java/dev/pgm/events/format/rounds/format/FormatTournamentImpl.java
index 504a4d0..db987db 100644
--- a/src/main/java/dev/pgm/events/format/rounds/format/FormatTournamentImpl.java
+++ b/src/main/java/dev/pgm/events/format/rounds/format/FormatTournamentImpl.java
@@ -7,7 +7,7 @@
import dev.pgm.events.team.TournamentTeam;
import dev.pgm.events.team.TournamentTeamManager;
import java.time.Duration;
-import java.util.Optional;
+import org.jspecify.annotations.Nullable;
import tc.oc.pgm.api.match.Match;
public class FormatTournamentImpl extends TournamentFormatImpl {
@@ -31,8 +31,8 @@ public FormatTournamentImpl(
}
@Override
- public void onEnd(Match match, Optional winner) {
- formatRound.setWinner(match, winner.orElse(null));
+ public void onEnd(Match match, @Nullable TournamentTeam winner) {
+ formatRound.setWinner(match, winner);
}
public FormatRound getFormatRound() {
diff --git a/src/main/java/dev/pgm/events/format/rounds/reference/ReferenceDescription.java b/src/main/java/dev/pgm/events/format/rounds/reference/ReferenceDescription.java
index 3777960..c594cbf 100644
--- a/src/main/java/dev/pgm/events/format/rounds/reference/ReferenceDescription.java
+++ b/src/main/java/dev/pgm/events/format/rounds/reference/ReferenceDescription.java
@@ -1,5 +1,7 @@
package dev.pgm.events.format.rounds.reference;
+import static net.kyori.adventure.text.Component.text;
+
import dev.pgm.events.format.rounds.RoundDescription;
import net.kyori.adventure.text.Component;
@@ -13,8 +15,7 @@ public ReferenceDescription(ReferenceRound referenceRound) {
@Override
public Component roundInfo() {
- return Component.text(
- "Reference round -> referencing: " + referenceRound.settings().targetID());
+ return text("Reference round -> referencing: " + referenceRound.settings().targetID());
}
@Override
diff --git a/src/main/java/dev/pgm/events/format/rounds/replay/ReplayDescription.java b/src/main/java/dev/pgm/events/format/rounds/replay/ReplayDescription.java
index 3d265a4..ef5cfa2 100644
--- a/src/main/java/dev/pgm/events/format/rounds/replay/ReplayDescription.java
+++ b/src/main/java/dev/pgm/events/format/rounds/replay/ReplayDescription.java
@@ -1,5 +1,7 @@
package dev.pgm.events.format.rounds.replay;
+import static net.kyori.adventure.text.Component.text;
+
import dev.pgm.events.format.rounds.RoundDescription;
import dev.pgm.events.format.rounds.RoundPhase;
import net.kyori.adventure.text.Component;
@@ -17,15 +19,14 @@ public ReplayDescription(ReplayRound round) {
@Override
public Component roundInfo() {
// haven't yet decided if we're gonna play if here
- if (round.phase() != RoundPhase.FINISHED)
- return Component.text("Replay tied round", NamedTextColor.GRAY);
+ if (round.phase() != RoundPhase.FINISHED) return text("Replay tied round", NamedTextColor.GRAY);
// not gonna replay
if (round.shouldShowInHistory())
- return Component.text("Not replaying a round", NamedTextColor.GRAY)
+ return text("Not replaying a round", NamedTextColor.GRAY)
.decorate(TextDecoration.STRIKETHROUGH);
- return Component.text("Error replaying a round");
+ return text("Error replaying a round");
}
@Override
diff --git a/src/main/java/dev/pgm/events/format/rounds/resultfrom/ResultFromDescription.java b/src/main/java/dev/pgm/events/format/rounds/resultfrom/ResultFromDescription.java
index 6efb467..4acf571 100644
--- a/src/main/java/dev/pgm/events/format/rounds/resultfrom/ResultFromDescription.java
+++ b/src/main/java/dev/pgm/events/format/rounds/resultfrom/ResultFromDescription.java
@@ -1,5 +1,7 @@
package dev.pgm.events.format.rounds.resultfrom;
+import static net.kyori.adventure.text.Component.text;
+
import dev.pgm.events.format.rounds.RoundDescription;
import net.kyori.adventure.text.Component;
@@ -13,7 +15,7 @@ public ResultFromDescription(ResultFromRound resultFromRound) {
@Override
public Component roundInfo() {
- return Component.text(
+ return text(
"ResultFrom round -> using result from: " + resultFromRound.settings().targetID());
}
diff --git a/src/main/java/dev/pgm/events/format/rounds/single/SingleRoundDescription.java b/src/main/java/dev/pgm/events/format/rounds/single/SingleRoundDescription.java
index 43410f6..add7823 100644
--- a/src/main/java/dev/pgm/events/format/rounds/single/SingleRoundDescription.java
+++ b/src/main/java/dev/pgm/events/format/rounds/single/SingleRoundDescription.java
@@ -1,5 +1,7 @@
package dev.pgm.events.format.rounds.single;
+import static net.kyori.adventure.text.Component.text;
+
import dev.pgm.events.format.TournamentFormat;
import dev.pgm.events.format.rounds.RoundDescription;
import dev.pgm.events.team.TournamentTeam;
@@ -22,23 +24,21 @@ public SingleRoundDescription(String mapName, SingleRound singleRound, Tournamen
@Override
public Component roundInfo() {
- Component base = Component.text("Match on ", NamedTextColor.GRAY)
- .append(Component.text(mapName, NamedTextColor.GOLD));
+ Component base =
+ text("Match on ", NamedTextColor.GRAY).append(text(mapName, NamedTextColor.GOLD));
return switch (singleRound.phase()) {
case UNLOADED -> base;
- case WAITING -> base.append(Component.text(" - Waiting", NamedTextColor.GRAY));
+ case WAITING -> base.append(text(" - Waiting", NamedTextColor.GRAY));
case RUNNING ->
- base.append(Component.text(" - ", NamedTextColor.GRAY))
- .append(Component.text("Running", NamedTextColor.GREEN));
- case FINISHED ->
- base.append(Component.text(" - ", NamedTextColor.GRAY)).append(winnersComponent());
+ base.append(text(" - ", NamedTextColor.GRAY)).append(text("Running", NamedTextColor.GREEN));
+ case FINISHED -> base.append(text(" - ", NamedTextColor.GRAY)).append(winnersComponent());
};
}
private Component winnersComponent() {
Collection extends TournamentTeam> teams = singleRound.scores().keySet();
if (teams.isEmpty()) {
- return Component.text("Draw", NamedTextColor.GRAY);
+ return text("Draw", NamedTextColor.GRAY);
}
List teamNames =
@@ -46,10 +46,10 @@ private Component winnersComponent() {
Component result = Component.empty();
for (int i = 0; i < teamNames.size(); i++) {
- if (i > 0) result = result.append(Component.text(", ", NamedTextColor.GRAY));
+ if (i > 0) result = result.append(text(", ", NamedTextColor.GRAY));
result = result.append(teamNames.get(i));
}
- return result.append(Component.text(" won"));
+ return result.append(text(" won"));
}
@Override
diff --git a/src/main/java/dev/pgm/events/format/rounds/veto/VetoController.java b/src/main/java/dev/pgm/events/format/rounds/veto/VetoController.java
index 03af214..5f1ff51 100644
--- a/src/main/java/dev/pgm/events/format/rounds/veto/VetoController.java
+++ b/src/main/java/dev/pgm/events/format/rounds/veto/VetoController.java
@@ -36,25 +36,16 @@ public VetoController(
}
public boolean hasMoreVetoing() {
- // only one map left
- if (options.size() == 1) return false;
-
- for (int i = vetoIndex; i < settings.vetoList().size(); i++) {
- // teams still get to vote
- if (settings.vetoList().get(i).team > 0) return true;
- }
-
- return true;
+ return options.size() > 1;
}
public VetoSettings.VetoType currentType() {
- return settings.vetoList().get(vetoIndex).vetoType;
+ return settings.vetoList().get(vetoIndex).vetoType();
}
public Duration currentVetoDuration() {
- if (settings.vetoList().get(vetoIndex).vetoDuration != null)
- return settings.vetoList().get(vetoIndex).vetoDuration;
- return settings.vetoTime();
+ Duration duration = settings.vetoList().get(vetoIndex).vetoDuration();
+ return duration != null ? duration : settings.vetoTime();
}
public void completeVetos() {
@@ -63,22 +54,21 @@ public void completeVetos() {
for (int i = vetoIndex; i < settings.vetoList().size(); i++) {
VetoSettings.Veto veto = settings.vetoList().get(i);
VetoOption option = options.remove(random.nextInt(options.size()));
- TournamentTeam team = veto.team == 0 ? null : rankedTeams.get(veto.team - 1);
+ TournamentTeam team = veto.team() == 0 ? null : rankedTeams.get(veto.team() - 1);
- doVeto(option, veto.vetoType, team);
+ doVeto(option, veto.vetoType(), team);
}
}
public VetoHistory veto(@Nullable TournamentTeam team, int choice) {
- // maybe throw an exception?
- if (!hasMoreVetoing()) return null;
+ if (!hasMoreVetoing()) throw new IllegalStateException("No vetoing left");
VetoSettings.Veto veto = settings.vetoList().get(vetoIndex);
VetoOption vetoOption = options.remove(choice);
- doVeto(vetoOption, veto.vetoType, team);
+ doVeto(vetoOption, veto.vetoType(), team);
- VetoHistory history = new VetoHistory(team, veto.vetoType, vetoOption, veto.shouldAnnounce);
+ VetoHistory history = new VetoHistory(team, veto.vetoType(), vetoOption, veto.shouldAnnounce());
if (history.shouldAnnounce()) this.history.add(history);
vetoIndex++;
@@ -145,7 +135,7 @@ private void chooseLast(VetoOption option, TournamentTeam selectingTeam) {
* @return the current picking team or NULL if no team is picking
*/
public Optional picking() {
- int picker = settings.vetoList().get(vetoIndex).team;
+ int picker = settings.vetoList().get(vetoIndex).team();
if (picker == 0) return Optional.empty();
return Optional.of(rankedTeams.get(picker - 1));
diff --git a/src/main/java/dev/pgm/events/format/rounds/veto/VetoDescription.java b/src/main/java/dev/pgm/events/format/rounds/veto/VetoDescription.java
index 5dd19aa..c92b656 100644
--- a/src/main/java/dev/pgm/events/format/rounds/veto/VetoDescription.java
+++ b/src/main/java/dev/pgm/events/format/rounds/veto/VetoDescription.java
@@ -1,5 +1,8 @@
package dev.pgm.events.format.rounds.veto;
+import static net.kyori.adventure.text.Component.text;
+import static net.kyori.adventure.text.event.HoverEvent.showText;
+
import dev.pgm.events.format.TournamentFormat;
import dev.pgm.events.format.rounds.RoundDescription;
import dev.pgm.events.format.rounds.veto.settings.VetoOption;
@@ -8,7 +11,6 @@
import java.util.ArrayList;
import java.util.List;
import net.kyori.adventure.text.Component;
-import net.kyori.adventure.text.event.HoverEvent;
import net.kyori.adventure.text.format.NamedTextColor;
public class VetoDescription implements RoundDescription {
@@ -24,17 +26,16 @@ public VetoDescription(TournamentFormat format, VetoRound vetoRound) {
@Override
public Component roundInfo() {
return switch (vetoRound.phase()) {
- case UNLOADED -> Component.text("Waiting to begin veto process", NamedTextColor.GRAY);
+ case UNLOADED -> text("Waiting to begin veto process", NamedTextColor.GRAY);
case WAITING ->
- Component.text("Deciding veto order with veto decider", NamedTextColor.GREEN)
- .hoverEvent(
- HoverEvent.showText(tournamentFormat.currentRound().describe().roundInfo()));
+ text("Deciding veto order with veto decider", NamedTextColor.GREEN)
+ .hoverEvent(showText(tournamentFormat.currentRound().describe().roundInfo()));
case RUNNING ->
- Component.text("Veto process is running now", NamedTextColor.GREEN)
- .hoverEvent(HoverEvent.showText(formattedVetosSoFar()));
+ text("Veto process is running now", NamedTextColor.GREEN)
+ .hoverEvent(showText(formattedVetosSoFar()));
case FINISHED ->
- Component.text("Veto process has concluded", NamedTextColor.GRAY)
- .hoverEvent(HoverEvent.showText(formattedVetosSoFar()));
+ text("Veto process has concluded", NamedTextColor.GRAY)
+ .hoverEvent(showText(formattedVetosSoFar()));
};
}
@@ -49,29 +50,26 @@ private Component formattedVetosSoFar() {
}
private Component historyLine(int index, VetoHistory history) {
- return Component.text(index + 1 + ". ", NamedTextColor.GOLD)
- .append(formatHistoryComponent(history));
+ return text(index + 1 + ". ", NamedTextColor.GOLD).append(formatHistoryComponent(history));
}
public Component formatHistoryComponent(VetoHistory history) {
Component prefix;
if (history.team() == null) {
- prefix = Component.text("RANDOM", NamedTextColor.GOLD);
+ prefix = text("RANDOM", NamedTextColor.GOLD);
} else {
prefix = tournamentFormat.teamManager().formattedName(history.team());
}
- prefix = prefix.append(Component.text(" has ", NamedTextColor.GRAY));
+ prefix = prefix.append(text(" has ", NamedTextColor.GRAY));
Component action;
if (history.vetoType() == VetoSettings.VetoType.BAN) {
- action = Component.text("BANNED ", NamedTextColor.RED);
+ action = text("BANNED ", NamedTextColor.RED);
} else {
- action = Component.text("SELECTED ", NamedTextColor.GREEN);
+ action = text("SELECTED ", NamedTextColor.GREEN);
}
- return prefix
- .append(action)
- .append(Component.text(history.optionChosen().name(), NamedTextColor.GOLD));
+ return prefix.append(action).append(text(history.optionChosen().name(), NamedTextColor.GOLD));
}
public String countdown(TournamentTeam picking, VetoSettings.VetoType type) {
@@ -86,29 +84,28 @@ private String actionWord(VetoSettings.VetoType type) {
}
public Component optionsHeader(VetoSettings.VetoType type) {
- return Component.text("Choose an option to ", NamedTextColor.GRAY)
- .append(actionComponent(type));
+ return text("Choose an option to ", NamedTextColor.GRAY).append(actionComponent(type));
}
public Component commandPrompt(VetoSettings.VetoType type) {
return actionComponent(type)
- .append(Component.text(" with: ", NamedTextColor.GRAY))
- .append(Component.text("/veto ", NamedTextColor.GOLD));
+ .append(text(" with: ", NamedTextColor.GRAY))
+ .append(text("/veto ", NamedTextColor.GOLD));
}
public List formatOptions(List options, VetoSettings.VetoType type) {
List comps = new ArrayList<>(options.size());
for (int i = 0; i < options.size(); i++) {
- comps.add(Component.text((i + 1) + ". ", NamedTextColor.GOLD)
- .append(Component.text(options.get(i).name(), NamedTextColor.AQUA)));
+ comps.add(text((i + 1) + ". ", NamedTextColor.GOLD)
+ .append(text(options.get(i).name(), NamedTextColor.AQUA)));
}
return comps;
}
private Component actionComponent(VetoSettings.VetoType type) {
return switch (type) {
- case BAN -> Component.text("BAN", NamedTextColor.RED);
- case CHOOSE_FIRST, CHOOSE_LAST -> Component.text("PLAY", NamedTextColor.GREEN);
+ case BAN -> text("BAN", NamedTextColor.RED);
+ case CHOOSE_FIRST, CHOOSE_LAST -> text("PLAY", NamedTextColor.GREEN);
};
}
diff --git a/src/main/java/dev/pgm/events/format/rounds/veto/VetoHistory.java b/src/main/java/dev/pgm/events/format/rounds/veto/VetoHistory.java
index 2fbd6d4..8cab7d0 100644
--- a/src/main/java/dev/pgm/events/format/rounds/veto/VetoHistory.java
+++ b/src/main/java/dev/pgm/events/format/rounds/veto/VetoHistory.java
@@ -5,38 +5,8 @@
import dev.pgm.events.team.TournamentTeam;
import org.jspecify.annotations.Nullable;
-public class VetoHistory {
-
- private final TournamentTeam team;
- private final VetoSettings.VetoType vetoType;
- private final VetoOption chosen;
-
- private final boolean shouldAnnounce;
-
- public VetoHistory(
- @Nullable TournamentTeam team,
- VetoSettings.VetoType vetoType,
- VetoOption chosen,
- boolean shouldAnnounce) {
- this.team = team;
- this.vetoType = vetoType;
- this.chosen = chosen;
- this.shouldAnnounce = shouldAnnounce;
- }
-
- public @Nullable TournamentTeam team() {
- return team;
- }
-
- public VetoSettings.VetoType vetoType() {
- return vetoType;
- }
-
- public VetoOption optionChosen() {
- return chosen;
- }
-
- public boolean shouldAnnounce() {
- return shouldAnnounce;
- }
-}
+public record VetoHistory(
+ @Nullable TournamentTeam team,
+ VetoSettings.VetoType vetoType,
+ VetoOption optionChosen,
+ boolean shouldAnnounce) {}
diff --git a/src/main/java/dev/pgm/events/format/rounds/veto/VetoRound.java b/src/main/java/dev/pgm/events/format/rounds/veto/VetoRound.java
index fbd91aa..65d5d67 100644
--- a/src/main/java/dev/pgm/events/format/rounds/veto/VetoRound.java
+++ b/src/main/java/dev/pgm/events/format/rounds/veto/VetoRound.java
@@ -1,5 +1,7 @@
package dev.pgm.events.format.rounds.veto;
+import static net.kyori.adventure.text.Component.text;
+
import dev.pgm.events.format.TournamentFormat;
import dev.pgm.events.format.TournamentRoundOptions;
import dev.pgm.events.format.rounds.AbstractRound;
@@ -13,7 +15,6 @@
import java.util.List;
import java.util.Optional;
import java.util.Random;
-import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.NamedTextColor;
import tc.oc.pgm.api.match.Match;
@@ -75,8 +76,8 @@ public void cleanup(Match match) {
}
public void startVeto(Match match, List vetoOrder) {
- setPhase(RoundPhase.RUNNING);
this.controller = new VetoController(tournament(), settings(), vetoOrder);
+ setPhase(RoundPhase.RUNNING);
cycleVeto(match);
}
@@ -86,12 +87,12 @@ private void endVeto(Match match) {
tournament().addRoundAfterCurrent(controller.toPlay());
// move the below formatting to the description class
- match.sendMessage(Component.text("------ ", NamedTextColor.GOLD)
- .append(Component.text("Veto Finished", NamedTextColor.AQUA))
- .append(Component.text(" ------", NamedTextColor.GOLD)));
+ match.sendMessage(text("------ ", NamedTextColor.GOLD)
+ .append(text("Veto Finished", NamedTextColor.AQUA))
+ .append(text(" ------", NamedTextColor.GOLD)));
for (int i = 0; i < controller.toPlay().size(); i++) {
- match.sendMessage(Component.text((i + 1) + ". ", NamedTextColor.GOLD)
+ match.sendMessage(text((i + 1) + ". ", NamedTextColor.GOLD)
.append(controller.toPlay().get(i).describe().roundInfo()));
}
@@ -134,6 +135,8 @@ public boolean validVetoNumber(int number) {
}
public void randomVeto(Match match) {
+ if (phase() != RoundPhase.RUNNING) return;
+
Optional picking = picking();
if (picking.isEmpty()) {
tryAutoVeto(match);
@@ -171,7 +174,7 @@ public void veto(Match match, TournamentTeam team, int pick) {
// some quick checks before doing the veto
if (phase() != RoundPhase.RUNNING) return;
- if (!controller.isPicking(team) && canVeto()) return;
+ if (!controller.isPicking(team)) return;
doVeto(match, team, pick);
}
diff --git a/src/main/java/dev/pgm/events/format/rounds/veto/VetoTournamentImpl.java b/src/main/java/dev/pgm/events/format/rounds/veto/VetoTournamentImpl.java
index cbcce3a..f46c71b 100644
--- a/src/main/java/dev/pgm/events/format/rounds/veto/VetoTournamentImpl.java
+++ b/src/main/java/dev/pgm/events/format/rounds/veto/VetoTournamentImpl.java
@@ -8,8 +8,7 @@
import dev.pgm.events.team.TournamentTeamManager;
import java.util.Comparator;
import java.util.List;
-import java.util.Optional;
-import java.util.stream.Collectors;
+import org.jspecify.annotations.Nullable;
import tc.oc.pgm.api.match.Match;
public class VetoTournamentImpl extends TournamentFormatImpl {
@@ -26,15 +25,12 @@ public VetoTournamentImpl(
}
@Override
- public void onEnd(Match match, Optional winner) {
+ public void onEnd(Match match, @Nullable TournamentTeam winner) {
// list in descending order of score
List vetoOrder = this.scores().scores().stream()
.sorted(Comparator.comparingInt(Score::score).reversed())
.map(Score::team)
- .collect(Collectors.toList());
-
- // unregister everything with this fake event
- unregisterAll();
+ .toList();
// call callback to start the veto process
vetoRound.startVeto(match, vetoOrder);
diff --git a/src/main/java/dev/pgm/events/format/rounds/veto/settings/VetoOption.java b/src/main/java/dev/pgm/events/format/rounds/veto/settings/VetoOption.java
index c3984a2..442b2cb 100644
--- a/src/main/java/dev/pgm/events/format/rounds/veto/settings/VetoOption.java
+++ b/src/main/java/dev/pgm/events/format/rounds/veto/settings/VetoOption.java
@@ -3,21 +3,4 @@
import dev.pgm.events.format.rounds.RoundSettings;
import java.util.List;
-public class VetoOption {
-
- private final List rounds;
- private final String name;
-
- public VetoOption(List rounds, String name) {
- this.rounds = rounds;
- this.name = name;
- }
-
- public List rounds() {
- return rounds;
- }
-
- public String name() {
- return name;
- }
-}
+public record VetoOption(List rounds, String name) {}
diff --git a/src/main/java/dev/pgm/events/format/rounds/veto/settings/VetoSettings.java b/src/main/java/dev/pgm/events/format/rounds/veto/settings/VetoSettings.java
index b2b9993..ab0a19f 100644
--- a/src/main/java/dev/pgm/events/format/rounds/veto/settings/VetoSettings.java
+++ b/src/main/java/dev/pgm/events/format/rounds/veto/settings/VetoSettings.java
@@ -28,6 +28,7 @@ public VetoSettings(
List vetoList,
List options) {
super(id, scoring, showInHistory);
+ validate(vetoList, options);
this.score = score;
this.vetoTime = vetoTime;
this.decider = decider;
@@ -35,6 +36,40 @@ public VetoSettings(
this.options = options;
}
+ private VetoSettings(VetoSettings source, String id) {
+ super(id, source.scoring(), source.showInHistory());
+ this.score = source.score;
+ this.vetoTime = source.vetoTime;
+ this.decider = source.decider;
+ this.vetoList = source.vetoList;
+ this.options = source.options;
+ }
+
+ // the veto controller relies on these: each step consumes exactly one option, and the system
+ // enacts the last step once no choice is left
+ private static void validate(List vetoList, List options) {
+ if (options.size() < 2)
+ throw new IllegalArgumentException(
+ "Veto needs at least 2 options, but has " + options.size() + ".");
+ if (vetoList.size() != options.size())
+ throw new IllegalArgumentException("Veto order has "
+ + vetoList.size()
+ + " steps but there are "
+ + options.size()
+ + " options. The order must contain exactly one step per option.");
+ for (Veto veto : vetoList) {
+ if (veto.team() < 0)
+ throw new IllegalArgumentException(
+ "Invalid team " + veto.team() + ". It must not be negative.");
+ }
+ if (vetoList.stream().allMatch(veto -> veto.vetoType() == VetoType.BAN))
+ throw new IllegalArgumentException(
+ "Veto order has no pick steps, so no rounds would be played.");
+ if (vetoList.getLast().team() != 0)
+ throw new IllegalArgumentException(
+ "The last step of a veto order is enacted by the system and must not have a team.");
+ }
+
@Override
public TournamentRound newRound(TournamentFormat format) {
return new VetoRound(format, this);
@@ -42,9 +77,7 @@ public TournamentRound newRound(TournamentFormat format) {
@Override
public TournamentRound newRound(TournamentFormat format, String id) {
- return new VetoSettings(
- id, vetoTime, decider, score, scoring(), showInHistory(), vetoList, options)
- .newRound(format);
+ return new VetoSettings(this, id).newRound(format);
}
public int score() {
@@ -73,17 +106,5 @@ public enum VetoType {
CHOOSE_LAST
}
- public static class Veto {
- public final VetoType vetoType;
- public final int team;
- public final Duration vetoDuration;
- public final boolean shouldAnnounce;
-
- public Veto(VetoType vetoType, int team, Duration vetoDuration, boolean shouldAnnounce) {
- this.vetoType = vetoType;
- this.team = team;
- this.vetoDuration = vetoDuration;
- this.shouldAnnounce = shouldAnnounce;
- }
- }
+ public record Veto(VetoType vetoType, int team, Duration vetoDuration, boolean shouldAnnounce) {}
}
diff --git a/src/main/java/dev/pgm/events/format/rounds/vetoselector/VetoSelectorDescription.java b/src/main/java/dev/pgm/events/format/rounds/vetoselector/VetoSelectorDescription.java
index 2dba2b4..942bcbc 100644
--- a/src/main/java/dev/pgm/events/format/rounds/vetoselector/VetoSelectorDescription.java
+++ b/src/main/java/dev/pgm/events/format/rounds/vetoselector/VetoSelectorDescription.java
@@ -1,5 +1,7 @@
package dev.pgm.events.format.rounds.vetoselector;
+import static net.kyori.adventure.text.Component.text;
+
import dev.pgm.events.format.rounds.RoundDescription;
import net.kyori.adventure.text.Component;
@@ -13,7 +15,7 @@ public VetoSelectorDescription(VetoSelectorRound vetoSelectorRound) {
@Override
public Component roundInfo() {
- return Component.text(vetoSelectorRound.getSelectingTeam().getName());
+ return text(vetoSelectorRound.getSelectingTeam().getName());
}
@Override
diff --git a/src/main/java/dev/pgm/events/format/score/Scores.java b/src/main/java/dev/pgm/events/format/score/Scores.java
index 18c917d..ba8ac92 100644
--- a/src/main/java/dev/pgm/events/format/score/Scores.java
+++ b/src/main/java/dev/pgm/events/format/score/Scores.java
@@ -69,7 +69,7 @@ public Pair topTwoOrdered() {
}
}
- return Pair.create(new Score(highest, highestScore), new Score(second, secondHighestScore));
+ return new Pair<>(new Score(highest, highestScore), new Score(second, secondHighestScore));
}
public Score highestScore() {
diff --git a/src/main/java/dev/pgm/events/format/score/TwoTeamFormattedScore.java b/src/main/java/dev/pgm/events/format/score/TwoTeamFormattedScore.java
index b0bd9b0..ab0cea0 100644
--- a/src/main/java/dev/pgm/events/format/score/TwoTeamFormattedScore.java
+++ b/src/main/java/dev/pgm/events/format/score/TwoTeamFormattedScore.java
@@ -1,5 +1,7 @@
package dev.pgm.events.format.score;
+import static net.kyori.adventure.text.Component.text;
+
import dev.pgm.events.team.TournamentTeam;
import dev.pgm.events.team.TournamentTeamManager;
import dev.pgm.events.utils.Pair;
@@ -27,37 +29,37 @@ public TwoTeamFormattedScore(
@Override
public Component topLine() {
return teamManager
- .formattedName(topTwo.first.team())
- .append(Component.text(" - ", NamedTextColor.GRAY))
- .append(teamManager.formattedName(topTwo.second.team()));
+ .formattedName(topTwo.first().team())
+ .append(text(" - ", NamedTextColor.GRAY))
+ .append(teamManager.formattedName(topTwo.second().team()));
}
@Override
public Component bottomLine() {
Component first =
- Component.text(topTwo.first.score(), teamManager.teamColour(topTwo.first.team()));
- if (justWon.contains(topTwo.first.team())) {
+ text(topTwo.first().score(), teamManager.teamColour(topTwo.first().team()));
+ if (justWon.contains(topTwo.first().team())) {
first = first.decorate(TextDecoration.BOLD).decorate(TextDecoration.UNDERLINED);
}
Component second =
- Component.text(topTwo.second.score(), teamManager.teamColour(topTwo.second.team()));
- if (justWon.contains(topTwo.second.team())) {
+ text(topTwo.second().score(), teamManager.teamColour(topTwo.second().team()));
+ if (justWon.contains(topTwo.second().team())) {
second = second.decorate(TextDecoration.BOLD).decorate(TextDecoration.UNDERLINED);
}
- return first.append(Component.text(" - ", NamedTextColor.GRAY)).append(second);
+ return first.append(text(" - ", NamedTextColor.GRAY)).append(second);
}
@Override
public Component condensed() {
return teamManager
- .formattedName(topTwo.first.team())
+ .formattedName(topTwo.first().team())
.append(Component.space())
- .append(Component.text(topTwo.first.score(), NamedTextColor.WHITE))
- .append(Component.text(" - ", NamedTextColor.GRAY))
- .append(Component.text(topTwo.second.score(), NamedTextColor.WHITE))
+ .append(text(topTwo.first().score(), NamedTextColor.WHITE))
+ .append(text(" - ", NamedTextColor.GRAY))
+ .append(text(topTwo.second().score(), NamedTextColor.WHITE))
.append(Component.space())
- .append(teamManager.formattedName(topTwo.second.team()));
+ .append(teamManager.formattedName(topTwo.second().team()));
}
}
diff --git a/src/main/java/dev/pgm/events/team/DefaultTeamManager.java b/src/main/java/dev/pgm/events/team/DefaultTeamManager.java
index a70333d..a84efd8 100644
--- a/src/main/java/dev/pgm/events/team/DefaultTeamManager.java
+++ b/src/main/java/dev/pgm/events/team/DefaultTeamManager.java
@@ -1,5 +1,7 @@
package dev.pgm.events.team;
+import static net.kyori.adventure.text.Component.text;
+
import dev.pgm.events.utils.JoinUtils;
import java.util.ArrayList;
import java.util.Collection;
@@ -104,7 +106,7 @@ public NamedTextColor teamColour(TournamentTeam tournamentTeam) {
@Override
public Component formattedName(TournamentTeam tournamentTeam) {
- return Component.text(tournamentTeam.getName(), teamColour(tournamentTeam));
+ return text(tournamentTeam.getName(), teamColour(tournamentTeam));
}
@Override
diff --git a/src/main/java/dev/pgm/events/team/TournamentTeam.java b/src/main/java/dev/pgm/events/team/TournamentTeam.java
index 50c5d87..b2d0762 100644
--- a/src/main/java/dev/pgm/events/team/TournamentTeam.java
+++ b/src/main/java/dev/pgm/events/team/TournamentTeam.java
@@ -1,5 +1,7 @@
package dev.pgm.events.team;
+import static net.kyori.adventure.text.Component.text;
+
import java.util.List;
import java.util.Objects;
import java.util.UUID;
@@ -20,7 +22,7 @@ default boolean containsPlayer(UUID player) {
}
default void sendMessage(String message) {
- sendMessage(Component.text(message));
+ sendMessage(text(message));
}
default void sendMessage(Component component) {
diff --git a/src/main/java/dev/pgm/events/team/TournamentTeamManager.java b/src/main/java/dev/pgm/events/team/TournamentTeamManager.java
index 5b622d5..5700c78 100644
--- a/src/main/java/dev/pgm/events/team/TournamentTeamManager.java
+++ b/src/main/java/dev/pgm/events/team/TournamentTeamManager.java
@@ -1,5 +1,7 @@
package dev.pgm.events.team;
+import static net.kyori.adventure.text.Component.text;
+
import java.util.Collection;
import java.util.Optional;
import java.util.UUID;
@@ -37,7 +39,7 @@ public interface TournamentTeamManager {
NamedTextColor teamColour(TournamentTeam tournamentTeam);
default Component formattedName(Competitor team) {
- return tournamentTeam(team).map(this::formattedName).orElse(Component.text("NULL"));
+ return tournamentTeam(team).map(this::formattedName).orElse(text("NULL"));
}
Component formattedName(TournamentTeam tournamentTeam);
diff --git a/src/main/java/dev/pgm/events/utils/Components.java b/src/main/java/dev/pgm/events/utils/Components.java
index bf0be83..11986f3 100644
--- a/src/main/java/dev/pgm/events/utils/Components.java
+++ b/src/main/java/dev/pgm/events/utils/Components.java
@@ -1,5 +1,7 @@
package dev.pgm.events.utils;
+import static net.kyori.adventure.text.Component.text;
+
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.event.ClickEvent;
import net.kyori.adventure.text.format.NamedTextColor;
@@ -23,11 +25,9 @@ public static Component command(Style style, String command, String... cmdArgs)
for (String arg : cmdArgs) builder.append(" ").append(Components.toArgument(arg));
command = builder.toString();
- var payload = ClickEvent.Payload.string(command);
- return Component.text(command, style)
+ return text(command, style)
.clickEvent(ClickEvent.runCommand(command))
- .hoverEvent(Component.text("Click to run ", NamedTextColor.GREEN)
- .append(Component.text(command, style)));
+ .hoverEvent(text("Click to run ", NamedTextColor.GREEN).append(text(command, style)));
}
private static String toArgument(String input) {
diff --git a/src/main/java/dev/pgm/events/utils/Pair.java b/src/main/java/dev/pgm/events/utils/Pair.java
index 33a1785..f8aee49 100644
--- a/src/main/java/dev/pgm/events/utils/Pair.java
+++ b/src/main/java/dev/pgm/events/utils/Pair.java
@@ -1,16 +1,3 @@
package dev.pgm.events.utils;
-public class Pair {
-
- public final T first;
- public final U second;
-
- public Pair(T first, U second) {
- this.first = first;
- this.second = second;
- }
-
- public static Pair create(T first, U second) {
- return new Pair<>(first, second);
- }
-}
+public record Pair(T first, U second) {}
diff --git a/src/main/java/dev/pgm/events/xml/MapFormatXMLParser.java b/src/main/java/dev/pgm/events/xml/MapFormatXMLParser.java
index 4d6b34c..76149b3 100644
--- a/src/main/java/dev/pgm/events/xml/MapFormatXMLParser.java
+++ b/src/main/java/dev/pgm/events/xml/MapFormatXMLParser.java
@@ -6,34 +6,41 @@
import dev.pgm.events.format.TournamentFormatImpl;
import dev.pgm.events.format.TournamentRoundOptions;
import dev.pgm.events.format.winner.BestOfCalculation;
-import java.io.File;
import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
import java.time.Duration;
import org.jspecify.annotations.NonNull;
import tc.oc.pgm.lib.org.jdom2.Document;
import tc.oc.pgm.lib.org.jdom2.Element;
import tc.oc.pgm.lib.org.jdom2.JDOMException;
+import tc.oc.pgm.lib.org.jdom2.input.JDOMParseException;
import tc.oc.pgm.lib.org.jdom2.input.SAXBuilder;
public class MapFormatXMLParser {
public static TournamentFormat parse(String name) {
- File poolsFolder = new File(EventsPlugin.get().getDataFolder(), "formats");
- File xmlFile = new File(poolsFolder, name + ".xml");
+ // messages are shown to the sender, so they must not include server paths
+ Path formats =
+ EventsPlugin.get().getDataFolder().toPath().resolve("formats").normalize();
+ Path file = formats.resolve(name + ".xml").normalize();
+ if (!file.startsWith(formats) || !Files.isRegularFile(file))
+ throw new IllegalArgumentException("Format " + name + " was not found!");
+
Document document;
try {
- document = new SAXBuilder().build(xmlFile);
- Element root = document.getRootElement();
- return parse(root);
+ document = new SAXBuilder().build(file.toFile());
+ } catch (JDOMParseException e) {
+ throw new IllegalArgumentException(
+ "Format " + name + " has invalid XML on line " + e.getLineNumber() + "!", e);
} catch (JDOMException | IOException e) {
- e.printStackTrace();
+ throw new IllegalArgumentException("Format " + name + " could not be loaded!", e);
}
- return null;
+ return parse(document.getRootElement());
}
public static TournamentFormat parse(Element root) {
- String bestOfArgs = root.getAttributeValue("best-of");
- TournamentFormat format = getTournamentFormat(bestOfArgs);
+ TournamentFormat format = getTournamentFormat(RoundParser.parseInt(root, "best-of", null));
if (!root.getName().equalsIgnoreCase("format"))
System.out.println(
@@ -44,10 +51,7 @@ public static TournamentFormat parse(Element root) {
return format;
}
- private static @NonNull TournamentFormat getTournamentFormat(String bestOfArgs) {
- if (bestOfArgs == null) throw new IllegalArgumentException("No best-of specified on format!");
- int bestOf = Integer.parseInt(bestOfArgs);
-
+ private static @NonNull TournamentFormat getTournamentFormat(int bestOf) {
TournamentRoundOptions options = new TournamentRoundOptions(
false,
true,
diff --git a/src/main/java/dev/pgm/events/xml/RoundParser.java b/src/main/java/dev/pgm/events/xml/RoundParser.java
index d0bbc2b..dda11db 100644
--- a/src/main/java/dev/pgm/events/xml/RoundParser.java
+++ b/src/main/java/dev/pgm/events/xml/RoundParser.java
@@ -18,6 +18,7 @@
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
+import org.jspecify.annotations.Nullable;
import tc.oc.pgm.lib.org.jdom2.Element;
public class RoundParser {
@@ -34,6 +35,19 @@ public static TournamentRound parse(TournamentFormat format, Element round) {
};
}
+ static int parseInt(Element element, String attribute, @Nullable String def) {
+ String value = element.getAttributeValue(attribute, def);
+ if (value == null)
+ throw new IllegalArgumentException(
+ "No " + attribute + " specified on " + element.getName() + "!");
+ try {
+ return Integer.parseInt(value);
+ } catch (NumberFormatException e) {
+ throw new IllegalArgumentException(
+ "Invalid " + attribute + " " + value + ". It must be a whole number.");
+ }
+ }
+
public static class SingleParser {
public static SingleRound parse(TournamentFormat format, Element element) {
@@ -56,31 +70,59 @@ public static VetoRound parse(TournamentFormat format, Element element) {
String id = element.getAttributeValue("id", "veto");
Element order = element.getChild("order");
if (order == null) throw new IllegalArgumentException("Order element is missing from veto!");
- Duration vetoTime;
- try {
- vetoTime = Duration.ofSeconds(Long.parseLong(order.getAttributeValue("time", "30")));
- } catch (NumberFormatException e) {
+ int seconds = parseInt(order, "time", "30");
+ if (seconds < 1)
throw new IllegalArgumentException(
- "Invalid time! Times are provided in seconds with no units.");
- }
+ "Invalid time " + seconds + ". It must be a positive number of seconds.");
+ Duration vetoTime = Duration.ofSeconds(seconds);
+ Element deciderElement = element.getChild("decider");
+ if (deciderElement == null || deciderElement.getChildren().isEmpty())
+ throw new IllegalArgumentException("Decider element is missing from veto!");
TournamentRound decider =
- RoundParser.parse(format, element.getChild("decider").getChildren().getFirst());
-
- List options = constructVetoOptions(format, element.getChild("options"));
- List vetoList = constructVetoList(order, options.size());
+ RoundParser.parse(format, deciderElement.getChildren().getFirst());
+
+ Element optionsElement = element.getChild("options");
+ if (optionsElement == null)
+ throw new IllegalArgumentException("Options element is missing from veto!");
+ List options = constructVetoOptions(format, optionsElement);
+
+ int teams = format.teamManager().teams().size();
+ List vetoList = constructVetoList(order, options.size(), teams);
+
+ for (VetoSettings.Veto veto : vetoList) {
+ if (veto.team() > teams)
+ throw new IllegalArgumentException("Veto order refers to team "
+ + veto.team()
+ + " but only "
+ + teams
+ + " teams are registered.");
+ }
VetoSettings settings =
new VetoSettings(id, vetoTime, decider.settings(), 0, false, true, vetoList, options);
return new VetoRound(format, settings);
}
- private static List constructVetoList(Element element, int numOptions) {
+ private static List constructVetoList(
+ Element element, int numOptions, int numTeams) {
ArrayList vetos = new ArrayList<>();
if (element.getChildren().isEmpty()) {
- int until = Integer.parseInt(element.getAttributeValue("ban-until", "1"));
- int startingTeam = Integer.parseInt(element.getAttributeValue("starting-team", "2"));
- int numTeams = Integer.parseInt(element.getAttributeValue("teams", "2"));
+ int until = parseInt(element, "ban-until", "1");
+ int startingTeam = parseInt(element, "starting-team", "2");
+ if (until < 1 || until > numOptions)
+ throw new IllegalArgumentException("Invalid ban-until "
+ + until
+ + ". It must be between 1 and the number of options ("
+ + numOptions
+ + ").");
+ if (numTeams == 0) throw new IllegalArgumentException("No teams are registered!");
+ if (startingTeam < 1 || startingTeam > numTeams)
+ throw new IllegalArgumentException("Invalid starting-team "
+ + startingTeam
+ + ". It must be between 1 and the number of registered teams ("
+ + numTeams
+ + ").");
int currentTeam = startingTeam;
for (int i = numOptions; i > until; i--) {
@@ -121,7 +163,7 @@ private static VetoSettings.Veto parseVeto(Element element) {
if (type == null)
throw new IllegalArgumentException("Invalid veto order " + element.getName());
- int team = Integer.parseInt(element.getAttributeValue("team", "0"));
+ int team = parseInt(element, "team", "0");
return new VetoSettings.Veto(type, team, null, true);
}
@@ -157,9 +199,7 @@ public static FormatRound parse(TournamentFormat format, Element element) {
String name = element.getAttributeValue("name", "Format");
String id = element.getAttributeValue("id", name.toLowerCase());
- String bestOfArgs = element.getAttributeValue("best-of");
- if (bestOfArgs == null) throw new IllegalArgumentException("No best-of specified on format!");
- int bestOf = Integer.parseInt(bestOfArgs);
+ int bestOf = parseInt(element, "best-of", null);
List rounds = new ArrayList<>();
for (Element child : element.getChildren()) {
diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml
index 011cf5c..fb02931 100644
--- a/src/main/resources/plugin.yml
+++ b/src/main/resources/plugin.yml
@@ -2,5 +2,6 @@ name: Events
description: ${description}
main: ${mainClass}
version: ${version} (git-${commitHash})
+api-version: ${apiVersion}
website: ${url}
depend: [PGM]
\ No newline at end of file