diff --git a/NOTICE b/NOTICE index a30ff0914..558376a7d 100644 --- a/NOTICE +++ b/NOTICE @@ -46,6 +46,13 @@ Full License: https://github.com/filoghost/HolographicDisplays/blob/master/LICEN Source Code: https://github.com/filoghost/HolographicDisplays/ Copyright © 2014-2022 filoghost +/ DecentHolograms (Soft Dependency) / +DecentHolograms is licensed under the GNU General Public License Version 3, or any later version. +Full License: https://github.com/DecentSoftware-eu/DecentHolograms/blob/main/LICENSE +Source Code: https://github.com/DecentSoftware-eu/DecentHolograms/ +Copyright © 2021-2024 DecentSoftware and Contributors (https://github.com/DecentSoftware-eu/DecentHolograms/graphs/contributors) + + // Annotations // / JetBrains Java Annotations (compile-only) / JetBrains annotations are provided under version 2 of the Apache License. (Apache-2) diff --git a/pom.xml b/pom.xml index fd81a9398..d0c5ef3d5 100644 --- a/pom.xml +++ b/pom.xml @@ -41,7 +41,7 @@ Towny Advanced Contributor - Former FlagWar Maintainer (2021–2023) + Former FlagWar Maintainer (2021–2023) -6 https://github.com/FlagCourier @@ -85,6 +85,10 @@ daily + + jitpack + https://jitpack.io + @@ -123,6 +127,12 @@ 2.4.9 provided + + com.github.decentsoftware-eu + decentholograms + 2.8.12 + provided + @@ -276,7 +286,8 @@ .checkstyle/checkstyle.xml - UTF-8 + UTF-8 + UTF-8 true true false diff --git a/src/main/java/io/github/townyadvanced/flagwar/config/FlagWarConfig.java b/src/main/java/io/github/townyadvanced/flagwar/config/FlagWarConfig.java index f495f8436..04d199bc2 100644 --- a/src/main/java/io/github/townyadvanced/flagwar/config/FlagWarConfig.java +++ b/src/main/java/io/github/townyadvanced/flagwar/config/FlagWarConfig.java @@ -189,8 +189,10 @@ private static boolean isHologramConfigured() { if (PLUGIN.getConfig().getBoolean("holograms.enabled")) { if (PLUGIN.getServer().getPluginManager().isPluginEnabled("HolographicDisplays")) { return true; + } else if (PLUGIN.getServer().getPluginManager().isPluginEnabled("DecentHolograms")) { + return true; } else { - LOGGER.severe("HolographicDisplays was not found! Holograms will be disabled."); + LOGGER.severe("Could not find a Hologram provider. Holograms will be disabled."); return false; } } else { diff --git a/src/main/java/io/github/townyadvanced/flagwar/objects/CellUnderAttack.java b/src/main/java/io/github/townyadvanced/flagwar/objects/CellUnderAttack.java index 4691236bb..38bf6a59b 100644 --- a/src/main/java/io/github/townyadvanced/flagwar/objects/CellUnderAttack.java +++ b/src/main/java/io/github/townyadvanced/flagwar/objects/CellUnderAttack.java @@ -24,6 +24,8 @@ import com.palmergames.bukkit.towny.scheduling.ScheduledTask; import com.palmergames.bukkit.towny.scheduling.TaskScheduler; +import eu.decentsoftware.holograms.api.DHAPI; +import eu.decentsoftware.holograms.api.holograms.HologramLine; import io.github.townyadvanced.flagwar.CellAttackThread; import io.github.townyadvanced.flagwar.FlagWar; import io.github.townyadvanced.flagwar.HologramUpdateThread; @@ -35,6 +37,9 @@ import org.bukkit.World; import org.bukkit.block.Block; import org.bukkit.inventory.ItemStack; +import org.bukkit.plugin.Plugin; +import org.jetbrains.annotations.ApiStatus; + import java.time.Duration; import java.util.ArrayList; import java.util.List; @@ -69,19 +74,21 @@ public class CellUnderAttack extends Cell { /** Identifies the phase the war flag is in. **/ private int flagPhaseID; /** A thread used to update the state of the {@link CellUnderAttack} using the Scheduler's repeating task.*/ - private CellAttackThread thread; + private final CellAttackThread thread; /** A task used to the thread used to cancel the repeating task.*/ private ScheduledTask threadTask; - /** A thread used to update the {@link #hologram}'s {@link #timerLine}. */ - private HologramUpdateThread hologramThread; + /** A thread used to update the {@link #hdHologramsAPI}'s {@link #timerLine}. */ + private final HologramUpdateThread hologramThread; /** A task used to the hologramThread used to cancel the repeating task.*/ private ScheduledTask hologramTask; /** Holds the war flag hologram. */ - private Hologram hologram; + private Hologram hdHologramsAPI; /** Holds the time, in seconds, assuming 20 ticks is 1 second, of the war flag. */ private Duration flagLifeTime; - /** Holds the {@link TextLine} of the hologram timer line. */ + /** Holds the {@link TextLine} of the hologram timer line. (HolographicDisplays) */ private TextLine timerLine; + /** Holds a line for DecentHolograms, mimicking the {@link #timerLine}. */ + private HologramLine timerLineDHAPI; /** * Prepares the CellUnderAttack. @@ -275,18 +282,48 @@ public void destroyFlag() { } /** - * Function to draw the {@link #hologram}. Retrieves hologram settings via - * {@link FlagWarConfig#getHologramSettings()}. Creates a new {@link #hologram} supplying the plugin instance with - * {@link FlagWar#getInstance()}, and a temporary {@link org.bukkit.Location} using the {@link #flagLightBlock}. - * Disables visibility. Then, iterates through the hologram settings, adding lines corresponding to the line - * type and data. Finally, adjusts the location of the hologram according to the height of the {@link #hologram}, - * and enables its visibility. + * Function to draw the {@link #hdHologramsAPI}. + * Retrieves hologram settings via {@link FlagWarConfig#getHologramSettings()}. + * Will try to draw a hologram with the following priortiy: HolographicDisplays, DecentHolograms * */ public void drawHologram() { List> holoSettings = FlagWarConfig.getHologramSettings(); Location loc = flagLightBlock.getLocation(); - hologram = HologramsAPI.createHologram(FlagWar.getInstance(), loc); - hologram.getVisibilityManager().setVisibleByDefault(false); + + // HolographicDisplays + Plugin holographicDisplays = FlagWar.getInstance().getServer().getPluginManager() + .getPlugin("HolographicDisplays"); + if (holographicDisplays != null && holographicDisplays.isEnabled()) { + drawHolographicDisplay(loc, holoSettings); + return; + } + + // DecentHolograms + Plugin decentHolograms = FlagWar.getInstance().getServer().getPluginManager().getPlugin("DecentHolograms"); + if (decentHolograms != null && decentHolograms.isEnabled()) { + drawDecentHologram(loc, holoSettings); + } + } + + /** + * Draw Hologram using HolographicDisplays + *

+ * Process: + *

    + *
  1. Creates a new {@link #hdHologramsAPI}, using the plugin instance and supplied location + * (from a {@link #flagLightBlock}).
  2. + *
  3. Disables default visibility
  4. + *
  5. Iterates through hologram settings, adding lines corresponding to the line type and line data.
  6. + *
  7. Adjusts the location of the hologram according to the height of the {@link #hdHologramsAPI}
  8. + *
  9. Enables visibility.
  10. + *
+ *

+ * @param location {@link #flagLightBlock} ({@link Block#getLocation}) + * @param holoSettings Map of 'holograms.lines' from the config. + */ + private void drawHolographicDisplay(final Location location, final List> holoSettings) { + hdHologramsAPI = HologramsAPI.createHologram(FlagWar.getInstance(), location); + hdHologramsAPI.getVisibilityManager().setVisibleByDefault(false); for (Map.Entry holoSetting : holoSettings) { var type = holoSetting.getKey(); var data = holoSetting.getValue(); @@ -295,41 +332,118 @@ public void drawHologram() { case "item" -> { Material material = Material.matchMaterial(data); if (material != null) { - hologram.appendItemLine(new ItemStack(material)); + hdHologramsAPI.appendItemLine(new ItemStack(material)); } } - case "text" -> hologram.appendTextLine(data); + case "text" -> hdHologramsAPI.appendTextLine(data); case "timer" -> setTimerLine(data); - default -> hologram.appendTextLine(""); + default -> hdHologramsAPI.appendTextLine(""); + } + } + final double hOffset = 0.5d; + final double vOffset = 0.9d; + hdHologramsAPI.teleport(location.add(hOffset, vOffset + hdHologramsAPI.getHeight(), hOffset)); + hdHologramsAPI.getVisibilityManager().setVisibleByDefault(true); + } + + /** + * Draw Hologram using DecentHolograms ({@link DHAPI}) + *

+ * Process: + *

    + *
  1. Create a DecentHolograms hologram using {@link DHAPI#createHologram(String, Location)}. + * Use the CellString as the hologram's name.
  2. + *
  3. Set Invisible
  4. + *
  5. Add Lines
  6. + *
  7. Set offset
  8. + *
  9. Set Visible
  10. + *
+ *

+ * @param location Location to initially spawn the hologram. + * @param holoSettings Map of 'holograms.lines' from the config. + */ + @ApiStatus.Experimental + private void drawDecentHologram(final Location location, final List> holoSettings) { + FlagWar.getFlagWar().getLogger().warning("DecentHolograms support is experimental."); + + //Holograph Name (CellString) + String hologramName = this.getCellString(); + + // Create Invisible + eu.decentsoftware.holograms.api.holograms.Hologram hologram = + DHAPI.createHologram(hologramName, location, false); + hologram.setDefaultVisibleState(false); + + // Add Lines + for (Map.Entry holoSetting : holoSettings) { + var type = holoSetting.getKey(); + var data = holoSetting.getValue(); + + switch (type) { + case "item" -> { + Material material = Material.matchMaterial(data); + if (material != null) { + DHAPI.addHologramLine(hologram, material); + } + } + case "text" -> DHAPI.addHologramLine(hologram, data); + case "timer" -> setTimerLineDHAPI(hologram, data); + default -> DHAPI.addHologramLine(hologram, ""); } } + + //Teleport final double hOffset = 0.5d; final double vOffset = 0.9d; - hologram.teleport(loc.add(hOffset, vOffset + hologram.getHeight(), hOffset)); - hologram.getVisibilityManager().setVisibleByDefault(true); + final double textHeight = 0.23d; + Location offset = location.add(hOffset, vOffset + (hologram.getPage(0).size() * textHeight), hOffset); + hologram.setLocation(offset); + + //Set Visible + hologram.setDefaultVisibleState(true); + } /** - * Simple expression to set the timerLine for the hologram. + * Simple expression to set the {@link #timerLine} for HolographicDisplays . * @param data the value of a hologram setting (defined in {@link #drawHologram()} */ private void setTimerLine(final String data) { - timerLine = hologram.appendTextLine(formatTime(flagLifeTime, data)); + timerLine = hdHologramsAPI.appendTextLine(formatTime(flagLifeTime, data)); } /** - * Decreases {@link #flagLifeTime} by 1, and sets the {@link #hologram} {@link #timerLine} text using + * Simple expression to set the {@link #timerLineDHAPI} for DecentHolograms. + * @param holo Parent Hologram + * @param fmtT Time Format String + */ + private void setTimerLineDHAPI(final eu.decentsoftware.holograms.api.holograms.Hologram holo, final String fmtT) { + timerLineDHAPI = DHAPI.addHologramLine(holo, formatTime(flagLifeTime, fmtT)); + } + + /** + * Decreases {@link #flagLifeTime} by 1, and sets the {@link #hdHologramsAPI} {@link #timerLine} text using * {@link #formatTime(Duration, String)} with the updated {@link #flagLifeTime} and * {@link FlagWarConfig#getTimerText()} as the parameters. */ public void updateHologram() { this.flagLifeTime = flagLifeTime.minusSeconds(1); - timerLine.setText(formatTime(flagLifeTime, FlagWarConfig.getTimerText())); + if (timerLine != null) { + timerLine.setText(formatTime(flagLifeTime, FlagWarConfig.getTimerText())); + } + if (timerLineDHAPI != null) { + timerLineDHAPI.setText(formatTime(flagLifeTime, FlagWarConfig.getTimerText())); + } } - /** Deletes the {@link #hologram}. */ + /** Destroys the hologram, after some null-checking. */ public void destroyHologram() { - this.hologram.delete(); + if (hdHologramsAPI != null) { + this.hdHologramsAPI.delete(); + } + if (timerLineDHAPI != null) { + timerLineDHAPI.getParent().getParent().delete(); + } } /** @@ -366,18 +480,18 @@ public void beginAttack() { final int tps = 20; final int milliTicks = 50; final long ticksFromMs = this.flagPhaseDuration.toMillis() / milliTicks; - threadTask = scheduler.runRepeating(() -> thread.run(), ticksFromMs, ticksFromMs); + threadTask = scheduler.runRepeating(thread, ticksFromMs, ticksFromMs); if (FlagWarConfig.isHologramEnabled()) { drawHologram(); if (FlagWarConfig.hasTimerLine()) { - hologramTask = scheduler.runRepeating(() -> hologramThread.run(), tps, tps); + hologramTask = scheduler.runRepeating(hologramThread, tps, tps); } } } /** * Cancels the {@link #thread} task, started in {@link #beginAttack()}. Then runs {@link #destroyFlag()}. - * Also cancels the {@link #hologramThread} task, if running, and destroys the {@link #hologram}, if it + * Also cancels the {@link #hologramThread} task, if running, and destroys the {@link #hdHologramsAPI}, if it * exists, using {@link #destroyHologram()}. */ public void cancel() { @@ -388,7 +502,7 @@ public void cancel() { hologramTask.cancel(); } destroyFlag(); - if (hologram != null) { + if (hdHologramsAPI != null) { destroyHologram(); } } diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index 5b0973d38..a9f6b88ce 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -20,6 +20,7 @@ folia-supported: true softdepend: - HolographicDisplays + - DecentHolograms depend: - Towny