diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 0000000..9dc42fa --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,38 @@ +name: Build Plugin + +on: + push: + branches: + - master + - fix/finished-phases-hologram + pull_request: + workflow_dispatch: + +jobs: + build: + runs-on: ubuntu-latest + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup Java + uses: actions/setup-java@v4 + with: + distribution: temurin + java-version: '17' + + - name: Setup Gradle + uses: gradle/actions/setup-gradle@v4 + + - name: Build plugin + run: chmod +x gradlew && ./gradlew build --no-daemon + env: + STABLE_BUILD: true + + - name: Upload JAR artifact + uses: actions/upload-artifact@v4 + with: + name: SSBOneBlock + path: target/*.jar + if-no-files-found: error diff --git a/build.gradle b/build.gradle index 7633bd3..9b64d73 100644 --- a/build.gradle +++ b/build.gradle @@ -52,7 +52,7 @@ allprojects { dependencies { compileOnly "com.bgsoftware.common.config:CommentedConfiguration:b1" compileOnly 'com.bgsoftware.common.reflection:ReflectionUtils:b6' - compileOnly 'com.bgsoftware.common.nmsloader:NMSLoader:b18' + compileOnly 'com.bgsoftware.common.nmsloader:NMSLoader:b21' compileOnly 'com.bgsoftware:SuperiorSkyblockAPI:2024.3' @@ -90,8 +90,9 @@ shadowJar { try { def reobfTask = sub.tasks.named('reobfJar') dependsOn(reobfTask) - from(reobfTask.flatMap { it.outputJar }.map { zipTree(it) }) { - exclude 'META-INF/MANIFEST.MF', 'META-INF/*.SF', 'META-INF/*.DSA', 'META-INF/*.RSA' + from(reobfTask.flatMap { it.outputJar }) { + rename { sub.name } + into('com/bgsoftware/ssboneblock/nms') } } catch (Exception ignored) { from sub.sourceSets.main.output diff --git a/src/main/java/com/bgsoftware/ssboneblock/OneBlockModule.java b/src/main/java/com/bgsoftware/ssboneblock/OneBlockModule.java index 64b40b3..1dab193 100644 --- a/src/main/java/com/bgsoftware/ssboneblock/OneBlockModule.java +++ b/src/main/java/com/bgsoftware/ssboneblock/OneBlockModule.java @@ -16,6 +16,7 @@ import com.bgsoftware.ssboneblock.nms.NMSAdapter; import com.bgsoftware.ssboneblock.phases.IslandPhaseData; import com.bgsoftware.ssboneblock.phases.PhaseData; +import com.bgsoftware.ssboneblock.task.FinishedPhasesHologram; import com.bgsoftware.ssboneblock.task.NextPhaseTimer; import com.bgsoftware.ssboneblock.task.SaveTimer; import com.bgsoftware.superiorskyblock.api.SuperiorSkyblock; @@ -98,6 +99,7 @@ public void onReload(SuperiorSkyblock plugin) { @Override public void onDisable(SuperiorSkyblock plugin) { NextPhaseTimer.cancelTimers(); + FinishedPhasesHologram.removeAll(); SaveTimer.stopTimer(); if (this.phasesHandler != null) this.phasesHandler.getDataStore().save(); diff --git a/src/main/java/com/bgsoftware/ssboneblock/handler/PhasesHandler.java b/src/main/java/com/bgsoftware/ssboneblock/handler/PhasesHandler.java index a00f24a..33e361a 100644 --- a/src/main/java/com/bgsoftware/ssboneblock/handler/PhasesHandler.java +++ b/src/main/java/com/bgsoftware/ssboneblock/handler/PhasesHandler.java @@ -6,6 +6,7 @@ import com.bgsoftware.ssboneblock.lang.Message; import com.bgsoftware.ssboneblock.phases.IslandPhaseData; import com.bgsoftware.ssboneblock.phases.PhaseData; +import com.bgsoftware.ssboneblock.task.FinishedPhasesHologram; import com.bgsoftware.ssboneblock.task.NextPhaseTimer; import com.bgsoftware.ssboneblock.utils.JsonUtils; import com.bgsoftware.ssboneblock.utils.Resources; @@ -82,6 +83,8 @@ public void runNextAction(Island island, @Nullable SuperiorPlayer superiorPlayer nextPhaseTimer.cancel(); }); + FinishedPhasesHologram.remove(island); + action.run(oneBlockLocation, island, superiorPlayer); IslandPhaseData newPhaseData = this.dataStore.getPhaseData(island, false); @@ -116,9 +119,24 @@ private void runNextActionTimer(Island island, @Nullable SuperiorPlayer superior new NextPhaseTimer(island, phaseData.getNextPhaseCooldown(), () -> setPhaseLevel(island, nextPhaseLevel, superiorPlayer) ); + } else { + FinishedPhasesHologram.show(island); } } + public boolean hasFinishedAllPhases(Island island) { + IslandPhaseData islandPhaseData = this.dataStore.getPhaseData(island, true); + + if (islandPhaseData.getPhaseLevel() >= phaseData.length) + return true; + + if (islandPhaseData.getPhaseLevel() < phaseData.length - 1) + return false; + + PhaseData lastPhase = phaseData[islandPhaseData.getPhaseLevel()]; + return islandPhaseData.getPhaseBlock() >= lastPhase.getActionsSize(); + } + public boolean setPhaseLevel(Island island, int phaseLevel, @Nullable SuperiorPlayer superiorPlayer) { if (phaseLevel >= phaseData.length) return false; diff --git a/src/main/java/com/bgsoftware/ssboneblock/handler/SettingsHandler.java b/src/main/java/com/bgsoftware/ssboneblock/handler/SettingsHandler.java index fcbb586..4c3af0e 100644 --- a/src/main/java/com/bgsoftware/ssboneblock/handler/SettingsHandler.java +++ b/src/main/java/com/bgsoftware/ssboneblock/handler/SettingsHandler.java @@ -31,6 +31,7 @@ public final class SettingsHandler { public final boolean pistonsInteraction; public final boolean dropNaturally; public final boolean gravity; + public final List finishedPhasesHologram; public SettingsHandler(OneBlockModule module) { File file = new File(module.getModuleFolder(), "config.yml"); @@ -88,6 +89,20 @@ public SettingsHandler(OneBlockModule module) { this.dropNaturally = cfg.getBoolean("drop-naturally", true); this.gravity = cfg.getBoolean("gravity", true); + Object finishedPhasesHologram = cfg.get("finished-phases-hologram"); + if (finishedPhasesHologram instanceof String) { + this.finishedPhasesHologram = Collections.singletonList( + ChatColor.translateAlternateColorCodes('&', (String) finishedPhasesHologram)); + } else if (finishedPhasesHologram instanceof List) { + // noinspection unchecked + this.finishedPhasesHologram = ((List) finishedPhasesHologram).stream() + .map(line -> ChatColor.translateAlternateColorCodes('&', line)) + .collect(Collectors.toList()); + } else { + this.finishedPhasesHologram = Collections.emptyList(); + } + Collections.reverse(this.finishedPhasesHologram); + } } diff --git a/src/main/java/com/bgsoftware/ssboneblock/listeners/BlocksListener.java b/src/main/java/com/bgsoftware/ssboneblock/listeners/BlocksListener.java index efbb71c..15a14f0 100644 --- a/src/main/java/com/bgsoftware/ssboneblock/listeners/BlocksListener.java +++ b/src/main/java/com/bgsoftware/ssboneblock/listeners/BlocksListener.java @@ -1,6 +1,7 @@ package com.bgsoftware.ssboneblock.listeners; import com.bgsoftware.ssboneblock.OneBlockModule; +import com.bgsoftware.ssboneblock.task.FinishedPhasesHologram; import com.bgsoftware.ssboneblock.task.NextPhaseTimer; import com.bgsoftware.ssboneblock.utils.EntityTypes; import com.bgsoftware.ssboneblock.utils.WorldUtils; @@ -185,8 +186,15 @@ public void onChunkLoad(ChunkLoadEvent event) { if (NextPhaseTimer.getTimer(island) != null) return; - if (oneBlockLocation.getBlock().getType() == Material.BEDROCK) - module.getPhasesHandler().runNextAction(island, null); + if (oneBlockLocation.getBlock().getType() != Material.BEDROCK) + return; + + if (module.getPhasesHandler().hasFinishedAllPhases(island)) { + FinishedPhasesHologram.show(island); + return; + } + + module.getPhasesHandler().runNextAction(island, null); }); } diff --git a/src/main/java/com/bgsoftware/ssboneblock/listeners/IslandsListener.java b/src/main/java/com/bgsoftware/ssboneblock/listeners/IslandsListener.java index 85f2675..089af16 100644 --- a/src/main/java/com/bgsoftware/ssboneblock/listeners/IslandsListener.java +++ b/src/main/java/com/bgsoftware/ssboneblock/listeners/IslandsListener.java @@ -1,6 +1,7 @@ package com.bgsoftware.ssboneblock.listeners; import com.bgsoftware.ssboneblock.OneBlockModule; +import com.bgsoftware.ssboneblock.task.FinishedPhasesHologram; import com.bgsoftware.superiorskyblock.api.events.IslandDisbandEvent; import com.bgsoftware.superiorskyblock.api.events.PostIslandCreateEvent; import org.bukkit.event.EventHandler; @@ -17,6 +18,7 @@ public IslandsListener(OneBlockModule module) { @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) public void onIslandDelete(IslandDisbandEvent e) { + FinishedPhasesHologram.remove(e.getIsland()); module.getPhasesHandler().getDataStore().removeIsland(e.getIsland()); } diff --git a/src/main/java/com/bgsoftware/ssboneblock/nms/ModuleNMSConfiguration.java b/src/main/java/com/bgsoftware/ssboneblock/nms/ModuleNMSConfiguration.java index d6f0431..eec33d0 100644 --- a/src/main/java/com/bgsoftware/ssboneblock/nms/ModuleNMSConfiguration.java +++ b/src/main/java/com/bgsoftware/ssboneblock/nms/ModuleNMSConfiguration.java @@ -4,12 +4,15 @@ import com.bgsoftware.ssboneblock.OneBlockModule; import java.io.File; +import java.io.InputStream; public class ModuleNMSConfiguration extends NMSConfiguration { + private final OneBlockModule module; private final File cacheFolder; public ModuleNMSConfiguration(OneBlockModule module) { + this.module = module; this.cacheFolder = new File(module.getModuleFolder(), ".cache"); } @@ -28,4 +31,9 @@ public File getCacheFolder() { return this.cacheFolder; } + @Override + public InputStream getResource(String path) { + return this.module.getResource(path); + } + } diff --git a/src/main/java/com/bgsoftware/ssboneblock/task/FinishedPhasesHologram.java b/src/main/java/com/bgsoftware/ssboneblock/task/FinishedPhasesHologram.java new file mode 100644 index 0000000..a92e6a5 --- /dev/null +++ b/src/main/java/com/bgsoftware/ssboneblock/task/FinishedPhasesHologram.java @@ -0,0 +1,68 @@ +package com.bgsoftware.ssboneblock.task; + +import com.bgsoftware.ssboneblock.OneBlockModule; +import com.bgsoftware.ssboneblock.factory.HologramFactory; +import com.bgsoftware.ssboneblock.utils.WorldUtils; +import com.bgsoftware.superiorskyblock.api.island.Island; +import com.bgsoftware.superiorskyblock.api.service.hologram.Hologram; +import org.bukkit.Location; + +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; + +public final class FinishedPhasesHologram { + + private static final Map> holograms = new ConcurrentHashMap<>(); + private static final OneBlockModule module = OneBlockModule.getModule(); + + private FinishedPhasesHologram() { + + } + + public static void show(Island island) { + List hologramLines = module.getSettings().finishedPhasesHologram; + if (hologramLines.isEmpty()) + return; + + remove(island); + + Location oneBlockLocation = WorldUtils.getOneBlock(island); + List islandHolograms = new LinkedList<>(); + + for (int i = 0; i < hologramLines.size(); i++) { + Hologram hologram = createHologram(oneBlockLocation, i); + if (hologram == null) + continue; + + hologram.setHologramName(hologramLines.get(i)); + islandHolograms.add(hologram); + } + + if (!islandHolograms.isEmpty()) + holograms.put(island.getUniqueId(), islandHolograms); + } + + public static void remove(Island island) { + List islandHolograms = holograms.remove(island.getUniqueId()); + if (islandHolograms == null) + return; + + islandHolograms.forEach(Hologram::removeHologram); + } + + public static void removeAll() { + new HashMap<>(holograms).values().forEach(islandHolograms -> + islandHolograms.forEach(Hologram::removeHologram)); + holograms.clear(); + } + + private static Hologram createHologram(Location firstLocation, int index) { + Location hologramLocation = firstLocation.clone().add(0.5, 2 + (index * 0.3), 0.5); + return HologramFactory.createHologram(hologramLocation); + } + +} diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index 802ee83..6cb5c5d 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -43,6 +43,12 @@ data-type: FLAT # When enabled, people that finish the last phase will be back to phase 1, starting over again. phases-loop: false +# Hologram lines shown above the OneBlock when all phases are finished. +# Supports multiple lines. Use & for color codes. +finished-phases-hologram: + - '&e&lUkończono wszystkie fazy!' + - '&7Użyj &b/fazy &7aby zmienić fazę wyspy' + # Whether OneBlock can be interacted with pistons. # When true, players will be able to move the OneBlock using pistons. piston-interaction: true