From abfa6d66ada82999b52a652e853c9497a6557b39 Mon Sep 17 00:00:00 2001 From: War Pigeon <54217755+minus1over12@users.noreply.github.com> Date: Wed, 12 Jun 2024 17:57:58 -0500 Subject: [PATCH] Initial work --- .github/workflows/gradle.yml | 69 ++++++++++ .gitignore | 118 ++++++++++++++++++ .idea/.gitignore | 8 ++ .idea/.name | 1 + .idea/compiler.xml | 6 + .idea/externalDependencies.xml | 6 + .idea/gradle.xml | 16 +++ .idea/jarRepositories.xml | 35 ++++++ .idea/modules.xml | 8 ++ .idea/modules/QuadWars.main.iml | 14 +++ .idea/vcs.xml | 6 + build.gradle | 104 +++++++++++++++ gradle.properties | 0 gradle/wrapper/gradle-wrapper.properties | 1 + settings.gradle | 5 + .../minus1over12/quadwars/GameState.java | 20 +++ .../minus1over12/quadwars/GameStateEvent.java | 32 +++++ .../minus1over12/quadwars/PlayerControl.java | 29 +++++ .../minus1over12/quadwars/QuadWars.java | 19 +++ .../minus1over12/quadwars/TeamControl.java | 69 ++++++++++ .../quadwars/WorldBorderControl.java | 60 +++++++++ .../minus1over12/quadwars/WorldControl.java | 32 +++++ src/main/resources/config.yml | 0 src/main/resources/plugin.yml | 9 ++ 24 files changed, 667 insertions(+) create mode 100644 .github/workflows/gradle.yml create mode 100644 .gitignore create mode 100644 .idea/.gitignore create mode 100644 .idea/.name create mode 100644 .idea/compiler.xml create mode 100644 .idea/externalDependencies.xml create mode 100644 .idea/gradle.xml create mode 100644 .idea/jarRepositories.xml create mode 100644 .idea/modules.xml create mode 100644 .idea/modules/QuadWars.main.iml create mode 100644 .idea/vcs.xml create mode 100644 build.gradle create mode 100644 gradle.properties create mode 100644 gradle/wrapper/gradle-wrapper.properties create mode 100644 settings.gradle create mode 100644 src/main/java/io/github/minus1over12/quadwars/GameState.java create mode 100644 src/main/java/io/github/minus1over12/quadwars/GameStateEvent.java create mode 100644 src/main/java/io/github/minus1over12/quadwars/PlayerControl.java create mode 100644 src/main/java/io/github/minus1over12/quadwars/QuadWars.java create mode 100644 src/main/java/io/github/minus1over12/quadwars/TeamControl.java create mode 100644 src/main/java/io/github/minus1over12/quadwars/WorldBorderControl.java create mode 100644 src/main/java/io/github/minus1over12/quadwars/WorldControl.java create mode 100644 src/main/resources/config.yml create mode 100644 src/main/resources/plugin.yml diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml new file mode 100644 index 0000000..e8dcbc8 --- /dev/null +++ b/.github/workflows/gradle.yml @@ -0,0 +1,69 @@ +# This workflow uses actions that are not certified by GitHub. +# They are provided by a third-party and are governed by +# separate terms of service, privacy policy, and support +# documentation. +# This workflow will build a Java project with Gradle and cache/restore any dependencies to improve the workflow execution time +# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-java-with-gradle + +name: Java CI with Gradle + +on: + push: + branches: [ "master" ] + pull_request: + branches: [ "master" ] + +jobs: + build: + + runs-on: ubuntu-latest + permissions: + contents: read + + steps: + - uses: actions/checkout@v4 + - name: Set up JDK 21 + uses: actions/setup-java@v4 + with: + java-version: '21' + distribution: 'zulu' + + # Configure Gradle for optimal use in GitHub Actions, including caching of downloaded dependencies. + # See: https://github.com/gradle/actions/blob/main/setup-gradle/README.md + # - name: Setup Gradle + # uses: gradle/actions/setup-gradle@417ae3ccd767c252f5661f1ace9f835f9654f2b5 # v3.1.0 + + # - name: Build with Gradle Wrapper + # run: ./gradlew build + + # NOTE: The Gradle Wrapper is the default and recommended way to run Gradle (https://docs.gradle.org/current/userguide/gradle_wrapper.html). + # If your project does not have the Gradle Wrapper configured, you can use the following configuration to run Gradle with a specified version. + + - name: Setup Gradle + uses: gradle/actions/setup-gradle@417ae3ccd767c252f5661f1ace9f835f9654f2b5 # v3.1.0 + with: + gradle-version: '8.7' + + - name: Build with Gradle 8.7 + run: gradle build + + dependency-submission: + + runs-on: ubuntu-latest + permissions: + contents: write + + steps: + - uses: actions/checkout@v4 + - name: Set up JDK 21 + uses: actions/setup-java@v4 + with: + java-version: '21' + distribution: 'zulu' + + # Generates and submits a dependency graph, enabling Dependabot Alerts for all project dependencies. + # See: https://github.com/gradle/actions/blob/main/dependency-submission/README.md + - name: Generate and submit dependency graph + uses: gradle/actions/dependency-submission@417ae3ccd767c252f5661f1ace9f835f9654f2b5 # v3.1.0 + with: + gradle-version: '8.7' diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..3c37caf --- /dev/null +++ b/.gitignore @@ -0,0 +1,118 @@ +# User-specific stuff +.idea/ + +*.iml +*.ipr +*.iws + +# IntelliJ +out/ +# mpeltonen/sbt-idea plugin +.idea_modules/ + +# JIRA plugin +atlassian-ide-plugin.xml + +# Compiled class file +*.class + +# Log file +*.log + +# BlueJ files +*.ctxt + +# Package Files # +*.jar +*.war +*.nar +*.ear +*.zip +*.tar.gz +*.rar + +# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml +hs_err_pid* + +*~ + +# temporary files which can be created if a process still has a handle open of a deleted file +.fuse_hidden* + +# KDE directory preferences +.directory + +# Linux trash folder which might appear on any partition or disk +.Trash-* + +# .nfs files are created when an open file is removed but is still being accessed +.nfs* + +# General +.DS_Store +.AppleDouble +.LSOverride + +# Icon must end with two \r +Icon + +# Thumbnails +._* + +# Files that might appear in the root of a volume +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +.VolumeIcon.icns +.com.apple.timemachine.donotpresent + +# Directories potentially created on remote AFP share +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk + +# Windows thumbnail cache files +Thumbs.db +Thumbs.db:encryptable +ehthumbs.db +ehthumbs_vista.db + +# Dump file +*.stackdump + +# Folder config file +[Dd]esktop.ini + +# Recycle Bin used on file shares +$RECYCLE.BIN/ + +# Windows Installer files +*.cab +*.msi +*.msix +*.msm +*.msp + +# Windows shortcuts +*.lnk + +.gradle +build/ + +# Ignore Gradle GUI config +gradle-app.setting + +# Cache of project +.gradletasknamecache + +**/build/ + +# Common working directory +run/ + +# Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored) +!gradle-wrapper.jar diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..13566b8 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,8 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Editor-based HTTP Client requests +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/.idea/.name b/.idea/.name new file mode 100644 index 0000000..8c9eef9 --- /dev/null +++ b/.idea/.name @@ -0,0 +1 @@ +QuadWars \ No newline at end of file diff --git a/.idea/compiler.xml b/.idea/compiler.xml new file mode 100644 index 0000000..b86273d --- /dev/null +++ b/.idea/compiler.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.idea/externalDependencies.xml b/.idea/externalDependencies.xml new file mode 100644 index 0000000..acf33bf --- /dev/null +++ b/.idea/externalDependencies.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.idea/gradle.xml b/.idea/gradle.xml new file mode 100644 index 0000000..ce1c62c --- /dev/null +++ b/.idea/gradle.xml @@ -0,0 +1,16 @@ + + + + + + + \ No newline at end of file diff --git a/.idea/jarRepositories.xml b/.idea/jarRepositories.xml new file mode 100644 index 0000000..1a4a525 --- /dev/null +++ b/.idea/jarRepositories.xml @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..9467975 --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/modules/QuadWars.main.iml b/.idea/modules/QuadWars.main.iml new file mode 100644 index 0000000..bbeeb3e --- /dev/null +++ b/.idea/modules/QuadWars.main.iml @@ -0,0 +1,14 @@ + + + + + + + PAPER + ADVENTURE + + 1 + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..94a25f7 --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/build.gradle b/build.gradle new file mode 100644 index 0000000..809f4ad --- /dev/null +++ b/build.gradle @@ -0,0 +1,104 @@ +import xyz.jpenilla.runtask.task.AbstractRun + +plugins { + id 'java' + id("xyz.jpenilla.run-paper") version "2.3.0" + id("io.github.goooler.shadow") version "8.1.7" +} + +group = 'io.github.minus1over12' +version = '1.0-SNAPSHOT' + +repositories { + mavenCentral() + maven { + name = "papermc-repo" + url = "https://repo.papermc.io/repository/maven-public/" + } + maven { + name = "sonatype" + url = "https://oss.sonatype.org/content/groups/public/" + } + maven { + name = "Minecraft Libraries" + url = "https://libraries.minecraft.net" + } +} + +dependencies { + compileOnly "io.papermc.paper:paper-api:1.20.6-R0.1-SNAPSHOT" + compileOnly 'org.jetbrains:annotations:24.1.0' + implementation "org.bstats:bstats-bukkit:3.0.2" +} + +def targetJavaVersion = 21 +java { + def javaVersion = JavaVersion.toVersion(targetJavaVersion) + sourceCompatibility = javaVersion + targetCompatibility = javaVersion + if (JavaVersion.current() < javaVersion) { + toolchain.languageVersion = JavaLanguageVersion.of(targetJavaVersion) + } +} + +tasks.withType(JavaCompile).configureEach { + options.encoding = 'UTF-8' + + if (targetJavaVersion >= 10 || JavaVersion.current().isJava10Compatible()) { + options.release.set(targetJavaVersion) + } +} + +processResources { + def props = [version: version] + inputs.properties props + filteringCharset 'UTF-8' + filesMatching('plugin.yml') { + expand props + } +} + +tasks { + runServer { + // Configure the Minecraft version for our task. + // This is the only required configuration besides applying the plugin. + // Your plugin's jar (or shadowJar if present) will be used automatically. + minecraftVersion("1.20.6") + downloadPlugins { + hangar("Geyser", "Geyser") + hangar("Floodgate", "Floodgate") + modrinth("FastAsyncWorldEdit", "2.10.0") + hangar("ViaBackwards", "4.10.2") + hangar("ViaVersion", "4.10.2") + github("PaperMC", "Debuggery", "v1.5.1", "debuggery-bukkit-1.5.1.jar") + } + } + shadowJar { + relocate 'org.bstats', 'io.github.minus1over12.quadwars.bstats' + } +} + +tasks.jar { + manifest { + attributes["Implementation-Title"] = "QuadWars" + attributes["Implementation-Version"] = version + attributes["Implementation-Vendor"] = "War Pigeon" + attributes["paperweight-mappings-namespace"] = "mojang" + } + reproducibleFileOrder = true +} + +tasks.withType(AbstractRun).configureEach { + javaLauncher = javaToolchains.launcherFor { + languageVersion = JavaLanguageVersion.of(targetJavaVersion) + } + jvmArgs("-Xms512M", "-Xmx6G", "-XX:+UseG1GC", "-XX:+ParallelRefProcEnabled", + "-XX:MaxGCPauseMillis=200", + "-XX:+UnlockExperimentalVMOptions", "-XX:+DisableExplicitGC", "-XX:+AlwaysPreTouch", + "-XX:G1NewSizePercent=30", "-XX:G1MaxNewSizePercent=40", "-XX:G1HeapRegionSize=8M", + "-XX:G1ReservePercent=20", "-XX:G1HeapWastePercent=5", "-XX:G1MixedGCCountTarget=4", + "-XX:InitiatingHeapOccupancyPercent=15", "-XX:G1MixedGCLiveThresholdPercent=90", + "-XX:G1RSetUpdatingPauseTimePercent=5", "-XX:SurvivorRatio=32", + "-XX:+PerfDisableSharedMem", "-XX:MaxTenuringThreshold=1", + "-Dusing.aikars.flags=https://mcflags.emc.gs", "-Daikars.new.flags=true") +} \ No newline at end of file diff --git a/gradle.properties b/gradle.properties new file mode 100644 index 0000000..e69de29 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..3bacd7f --- /dev/null +++ b/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1 @@ +distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip \ No newline at end of file diff --git a/settings.gradle b/settings.gradle new file mode 100644 index 0000000..9457274 --- /dev/null +++ b/settings.gradle @@ -0,0 +1,5 @@ +plugins { + id("org.gradle.toolchains.foojay-resolver-convention") version "0.8.0" +} + +rootProject.name = 'QuadWars' diff --git a/src/main/java/io/github/minus1over12/quadwars/GameState.java b/src/main/java/io/github/minus1over12/quadwars/GameState.java new file mode 100644 index 0000000..fc65700 --- /dev/null +++ b/src/main/java/io/github/minus1over12/quadwars/GameState.java @@ -0,0 +1,20 @@ +package io.github.minus1over12.quadwars; + +public enum GameState { + /** + * State before the game starts. + */ + PREGAME, + /** + * State during the team preparation phase. Teams are restricted to their own quadrants. + */ + PREP, + /** + * Teams can move around. Hardcore is switched on. + */ + BATTLE, + /** + * The game has ended. + */ + POSTGAME +} diff --git a/src/main/java/io/github/minus1over12/quadwars/GameStateEvent.java b/src/main/java/io/github/minus1over12/quadwars/GameStateEvent.java new file mode 100644 index 0000000..4fd692b --- /dev/null +++ b/src/main/java/io/github/minus1over12/quadwars/GameStateEvent.java @@ -0,0 +1,32 @@ +package io.github.minus1over12.quadwars; + +import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; +import org.jetbrains.annotations.NotNull; + +public class GameStateEvent extends Event { + private static HandlerList handlerList = new HandlerList(); + + private final GameState state; + + protected GameStateEvent(GameState state) { + this.state = state; + } + + @Override + public @NotNull HandlerList getHandlers() { + return handlerList; + } + + /** + * Static method required by the API. + * @return The handler list for this event. + */ + public static HandlerList getHandlerList() { + return handlerList; + } + + public GameState getState() { + return state; + } +} diff --git a/src/main/java/io/github/minus1over12/quadwars/PlayerControl.java b/src/main/java/io/github/minus1over12/quadwars/PlayerControl.java new file mode 100644 index 0000000..a8f5c77 --- /dev/null +++ b/src/main/java/io/github/minus1over12/quadwars/PlayerControl.java @@ -0,0 +1,29 @@ +package io.github.minus1over12.quadwars; + +import net.kyori.adventure.key.Key; +import net.kyori.adventure.sound.Sound; +import org.bukkit.Bukkit; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; + +public class PlayerControl implements Listener { + @EventHandler + public void onGameStateChange(GameStateEvent event) { + GameState state = event.getState(); + switch (state) { + case PREGAME: + // Do nothing + break; + case PREP: + // Do nothing + break; + case BATTLE: + // Do nothing + Bukkit.getOnlinePlayers().forEach(player -> player.playSound(Sound.sound(Key.key("event.raid.horn"), Sound.Source.MASTER, 1, 1))); + case POSTGAME: + // Do nothing + break; + } + } + +} diff --git a/src/main/java/io/github/minus1over12/quadwars/QuadWars.java b/src/main/java/io/github/minus1over12/quadwars/QuadWars.java new file mode 100644 index 0000000..47c4087 --- /dev/null +++ b/src/main/java/io/github/minus1over12/quadwars/QuadWars.java @@ -0,0 +1,19 @@ +package io.github.minus1over12.quadwars; + +import org.bukkit.plugin.java.JavaPlugin; + +public final class QuadWars extends JavaPlugin { + TeamControl teamControl; + + + @Override + public void onEnable() { + // Plugin startup logic + teamControl = new TeamControl(this); + } + + @Override + public void onDisable() { + // Plugin shutdown logic + } +} diff --git a/src/main/java/io/github/minus1over12/quadwars/TeamControl.java b/src/main/java/io/github/minus1over12/quadwars/TeamControl.java new file mode 100644 index 0000000..a8a4e38 --- /dev/null +++ b/src/main/java/io/github/minus1over12/quadwars/TeamControl.java @@ -0,0 +1,69 @@ +package io.github.minus1over12.quadwars; + +import net.kyori.adventure.text.Component; +import org.bukkit.Bukkit; +import org.bukkit.entity.Entity; +import org.bukkit.plugin.Plugin; +import org.bukkit.scoreboard.Scoreboard; +import org.bukkit.scoreboard.Team; + +import java.util.Objects; +import java.util.logging.Logger; + +public class TeamControl { + private final Logger logger; + + + protected TeamControl(Plugin plugin) { + Scoreboard scoreboard = Bukkit.getScoreboardManager().getMainScoreboard(); + logger = plugin.getLogger(); + for (Quadrant quadrant : Quadrant.values()) { + String teamName = "quadwars:" + quadrant; + if (scoreboard.getTeam(teamName) == null) { + logger.info("Creating Scoreboard team " + teamName); + Team team = scoreboard.registerNewTeam(teamName); + team.setCanSeeFriendlyInvisibles(true); + team.setAllowFriendlyFire(false); + //TODO: Allow setting name, prefix, and suffix from config + team.prefix(Component.text(quadrant.toString())); + team.displayName(Component.text(quadrant.toString())); + team.suffix(Component.text(quadrant.toString())); + } + } + } + + protected void addEntryToTeam(Entity entity, Quadrant quadrant) { + Objects.requireNonNull(Bukkit.getScoreboardManager().getMainScoreboard() + .getTeam("quadwars:" + quadrant)).addEntity(entity); + logger.info("Adding " + entity.getName() + " to team " + quadrant); + entity.teleportAsync( + entity.getWorld().getHighestBlockAt(quadrant.xSign * 1024, quadrant.zSign * 1024) + .getLocation().add(0, 1, 0)); + } + + protected enum Quadrant { + /** + * The team in the north-west quadrant of the map. + */ + NW(-1, -1), + /** + * The team in the north-east quadrant of the map. + */ + NE(1, -1), + /** + * The team in the south-east quadrant of the map. + */ + SE(1, 1), + /** + * The team in the south-west quadrant of the map. + */ + SW(-1, 1); + final int xSign; + final int zSign; + + Quadrant(int xSign, int zSign) { + this.xSign = xSign; + this.zSign = zSign; + } + } +} diff --git a/src/main/java/io/github/minus1over12/quadwars/WorldBorderControl.java b/src/main/java/io/github/minus1over12/quadwars/WorldBorderControl.java new file mode 100644 index 0000000..314781f --- /dev/null +++ b/src/main/java/io/github/minus1over12/quadwars/WorldBorderControl.java @@ -0,0 +1,60 @@ +package io.github.minus1over12.quadwars; + +import net.kyori.adventure.text.Component; +import org.bukkit.Bukkit; +import org.bukkit.WorldBorder; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.player.PlayerJoinEvent; +import org.bukkit.scoreboard.Team; + +import java.util.HashMap; +import java.util.Map; + +public class WorldBorderControl implements Listener { + private final Map worldBorders = HashMap.newHashMap(4); + + GameState gameState; + + protected WorldBorderControl() { + for (TeamControl.Quadrant quadrant : TeamControl.Quadrant.values()) { + WorldBorder worldBorder = Bukkit.createWorldBorder(); + worldBorder.setCenter(10_000 * quadrant.xSign, 10_000 * quadrant.zSign); + worldBorder.setSize(10_000); + worldBorders.put(quadrant, worldBorder); + } + } + + @EventHandler + public void onPlayerJoin(PlayerJoinEvent event) { + Player player = event.getPlayer(); + if (!player.isOp() || player.hasPermission("quadwars.gamemaster")) { + Team team = + Bukkit.getScoreboardManager().getMainScoreboard().getEntityTeam(player); + switch (gameState) { + case GameState.PREGAME -> { + //todo team selection + } + case GameState.PREP -> { + + if (team == null) { + //TODO player team selection + } else { + player.setWorldBorder(worldBorders.get( + TeamControl.Quadrant.valueOf(team.getName().split(":")[1]))); + } + } + case GameState.BATTLE, GameState.POSTGAME -> { + if (team == null) { + //todo prevent new player from joining + } + } + } + } else { + player.sendMessage(Component.text( + "This is a friendly reminder that QuadWars does not control the world border " + + "for ops.")); + } + } +} diff --git a/src/main/java/io/github/minus1over12/quadwars/WorldControl.java b/src/main/java/io/github/minus1over12/quadwars/WorldControl.java new file mode 100644 index 0000000..b78d9aa --- /dev/null +++ b/src/main/java/io/github/minus1over12/quadwars/WorldControl.java @@ -0,0 +1,32 @@ +package io.github.minus1over12.quadwars; + +import org.bukkit.Bukkit; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; + +public class WorldControl implements Listener { + @EventHandler + public void onGameStateChange(GameStateEvent event) { + GameState state = event.getState(); + Bukkit.getWorlds().forEach(world -> { + switch (state) { + case PREGAME: + world.setPVP(false); + world.setHardcore(false); + break; + case PREP: + world.setPVP(false); + world.setHardcore(false); + break; + case BATTLE: + world.setPVP(true); + world.setHardcore(true); + break; + case POSTGAME: + world.setPVP(false); + world.setHardcore(false); + break; + } + }); + } +} diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml new file mode 100644 index 0000000..e69de29 diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml new file mode 100644 index 0000000..4dc0b66 --- /dev/null +++ b/src/main/resources/plugin.yml @@ -0,0 +1,9 @@ +name: QuadWars +version: '${version}' +main: io.github.minus1over12.quadwars.QuadWars +api-version: '1.20.6' +author: War Pigeon +permissions: + quadwars.gamemaster: + description: Exempts the player from team world border controls. + default: op \ No newline at end of file