Skip to content

Commit

Permalink
Implement feature system and Hologram API
Browse files Browse the repository at this point in the history
On its own, this does not do anything, but allows for third party plugins (mainly arena extensions) to have access to APIs that act more as a service provider.

As an example, the Hologram API offered in this commit lets third party plugins interface with a common API that currently creates holograms if *either* FancyHolograms or DecentHolograms is installed. This can realistically be expanded to work with any hologram plugin, but still use the same API.

This prevents developers from needing to implement support for multiple hologram plugins in their arena extensions, and rather just offers a common system they can use instead. This may further be expanded in the future to other features, like NPCs.
  • Loading branch information
Redned235 committed Dec 9, 2024
1 parent cca76a9 commit 2389b1e
Show file tree
Hide file tree
Showing 17 changed files with 709 additions and 0 deletions.
9 changes: 9 additions & 0 deletions module/hologram-integration/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
repositories {
maven("https://jitpack.io")
maven("https://repo.fancyplugins.de/releases")
}

dependencies {
compileOnly("com.github.decentsoftware-eu:decentholograms:2.8.12")
compileOnly("de.oliver:FancyHolograms:2.4.0")
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package org.battleplugins.arena.module.hologram;

import org.battleplugins.arena.event.BattleArenaPostInitializeEvent;
import org.battleplugins.arena.feature.hologram.Holograms;
import org.battleplugins.arena.module.ArenaModule;
import org.battleplugins.arena.module.ArenaModuleInitializer;
import org.battleplugins.arena.module.hologram.decentholograms.DecentHologramsFeature;
import org.battleplugins.arena.module.hologram.fancyholograms.FancyHologramsFeature;
import org.bukkit.Bukkit;
import org.bukkit.event.EventHandler;

/**
* A module that allows for hooking into various hologram plugin.
*/
@ArenaModule(id = HologramIntegration.ID, name = "Hologram", description = "Adds support for hooking into various Hologram plugins.", authors = "BattlePlugins")
public class HologramIntegration implements ArenaModuleInitializer {
public static final String ID = "hologram";

@EventHandler
public void onPostInitialize(BattleArenaPostInitializeEvent event) {
if (Bukkit.getPluginManager().isPluginEnabled("FancyHolograms")) {
Holograms.register(new FancyHologramsFeature());

event.getBattleArena().info("FancyHolograms found. Using FancyHolograms for hologram integration.");
}

if (Bukkit.getPluginManager().isPluginEnabled("DecentHolograms")) {
Holograms.register(new DecentHologramsFeature());

event.getBattleArena().info("DecentHolograms found. Using DecentHolograms for hologram integration.");
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
package org.battleplugins.arena.module.hologram.decentholograms;

import eu.decentsoftware.holograms.api.holograms.HologramLine;
import eu.decentsoftware.holograms.api.holograms.HologramPage;
import eu.decentsoftware.holograms.api.holograms.enums.HologramLineType;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
import org.battleplugins.arena.competition.LiveCompetition;
import org.battleplugins.arena.feature.hologram.Hologram;
import org.bukkit.Location;

import java.util.ArrayList;
import java.util.List;

public class DecentHologram implements Hologram {
private static final LegacyComponentSerializer SERIALIZER = LegacyComponentSerializer.builder()
.hexColors()
.useUnusualXRepeatedCharacterHexFormat()
.build();

private final LiveCompetition<?> competition;
private final eu.decentsoftware.holograms.api.holograms.Hologram impl;

public DecentHologram(LiveCompetition<?> competition, eu.decentsoftware.holograms.api.holograms.Hologram impl) {
this.competition = competition;
this.impl = impl;
}

@Override
public LiveCompetition<?> getCompetition() {
return this.competition;
}

@Override
public Location getLocation() {
return this.impl.getLocation();
}

@Override
public List<Component> getLines() {
if (this.impl.getPages().isEmpty()) {
return List.of();
}

// TODO: Support multiple pages
HologramPage page = this.impl.getPage(0);
List<Component> lines = new ArrayList<>();
for (HologramLine line : page.getLines()) {
if (line.getType() == HologramLineType.TEXT) {
lines.add(SERIALIZER.deserialize(line.getText()));
}
}

return lines;
}

@Override
public void setLines(Component... lines) {
if (this.impl.getPages().isEmpty()) {
return;
}

HologramPage page = this.impl.getPage(0);
for (int i = 0; i < page.getLines().size(); i++) {
page.removeLine(i);
}

for (Component line : lines) {
page.addLine(new HologramLine(page, this.getLocation(), SERIALIZER.serialize(line)));
}
}

@Override
public void addLine(Component line) {
if (this.impl.getPages().isEmpty()) {
return;
}

HologramPage page = this.impl.getPage(0);
page.addLine(new HologramLine(page, this.getLocation(), SERIALIZER.serialize(line)));
}

@Override
public void removeLine(int index) {
if (this.impl.getPages().isEmpty()) {
return;
}

HologramPage page = this.impl.getPage(0);
page.removeLine(index);
}

public eu.decentsoftware.holograms.api.holograms.Hologram getImpl() {
return this.impl;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package org.battleplugins.arena.module.hologram.decentholograms;

import eu.decentsoftware.holograms.api.DecentHologramsAPI;
import net.kyori.adventure.text.Component;
import org.battleplugins.arena.competition.LiveCompetition;
import org.battleplugins.arena.feature.PluginFeature;
import org.battleplugins.arena.feature.hologram.Hologram;
import org.battleplugins.arena.feature.hologram.HologramFeature;
import org.bukkit.Location;

import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

public class DecentHologramsFeature extends PluginFeature<HologramFeature> implements HologramFeature {
private final List<Hologram> holograms = new ArrayList<>();

public DecentHologramsFeature() {
super(DecentHologramsAPI.get().getPlugin());
}

@Override
public Hologram createHologram(LiveCompetition<?> competition, Location location, Component... lines) {
eu.decentsoftware.holograms.api.holograms.Hologram impl = new eu.decentsoftware.holograms.api.holograms.Hologram(UUID.randomUUID().toString(), location);
impl.setSaveToFile(false);

DecentHologramsAPI.get().getHologramManager().registerHologram(impl);

DecentHologram hologram = new DecentHologram(competition, impl);
hologram.setLines(lines);

this.holograms.add(hologram);
return hologram;
}

@Override
public void removeHologram(Hologram hologram) {
this.holograms.remove(hologram);

DecentHologram decentHologram = (DecentHologram) hologram;
DecentHologramsAPI.get().getHologramManager().removeHologram(decentHologram.getImpl().getName());
}

@Override
public List<Hologram> getHolograms() {
return this.holograms;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
package org.battleplugins.arena.module.hologram.fancyholograms;

import de.oliver.fancyholograms.api.data.TextHologramData;
import de.oliver.fancyholograms.libs.chatcolorhandler.ModernChatColorHandler;
import de.oliver.fancyholograms.libs.chatcolorhandler.messengers.MiniMessageMessenger;
import net.kyori.adventure.text.Component;
import org.battleplugins.arena.competition.LiveCompetition;
import org.battleplugins.arena.feature.hologram.Hologram;
import org.bukkit.Location;

import java.util.Arrays;
import java.util.List;

public class FancyHologram implements Hologram {
private final LiveCompetition<?> competition;
private final de.oliver.fancyholograms.api.hologram.Hologram impl;

public FancyHologram(LiveCompetition<?> competition, de.oliver.fancyholograms.api.hologram.Hologram impl) {
this.competition = competition;
this.impl = impl;
}

@Override
public LiveCompetition<?> getCompetition() {
return this.competition;
}

@Override
public Location getLocation() {
return this.impl.getData().getLocation();
}

@Override
public List<Component> getLines() {
if (this.impl.getData() instanceof TextHologramData data) {
List<String> stringLines = data.getText();
return ModernChatColorHandler.translate(stringLines);
}

return List.of();
}

@Override
public void setLines(Component... lines) {
if (this.impl.getData() instanceof TextHologramData data) {
List<String> stringLines = Arrays.stream(lines).map(MiniMessageMessenger.MINI_MESSAGE::serialize).toList();
data.setText(stringLines);
}
}

@Override
public void addLine(Component line) {
if (this.impl.getData() instanceof TextHologramData data) {
data.addLine(MiniMessageMessenger.MINI_MESSAGE.serialize(line));
}
}

@Override
public void removeLine(int index) {
if (this.impl.getData() instanceof TextHologramData data) {
data.removeLine(index);
}
}

de.oliver.fancyholograms.api.hologram.Hologram getImpl() {
return this.impl;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package org.battleplugins.arena.module.hologram.fancyholograms;

import de.oliver.fancyholograms.api.FancyHologramsPlugin;
import de.oliver.fancyholograms.api.data.TextHologramData;
import net.kyori.adventure.text.Component;
import org.battleplugins.arena.competition.LiveCompetition;
import org.battleplugins.arena.feature.PluginFeature;
import org.battleplugins.arena.feature.hologram.Hologram;
import org.battleplugins.arena.feature.hologram.HologramFeature;
import org.bukkit.Location;

import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

public class FancyHologramsFeature extends PluginFeature<HologramFeature> implements HologramFeature {
private final List<Hologram> holograms = new ArrayList<>();

public FancyHologramsFeature() {
super(FancyHologramsPlugin.get().getPlugin());
}

@Override
public Hologram createHologram(LiveCompetition<?> competition, Location location, Component... lines) {
de.oliver.fancyholograms.api.hologram.Hologram impl = FancyHologramsPlugin.get().getHologramManager().create(new TextHologramData(UUID.randomUUID().toString(), location));
impl.getData().setPersistent(false);

FancyHologram hologram = new FancyHologram(competition, impl);
hologram.setLines(lines);
FancyHologramsPlugin.get().getHologramManager().addHologram(impl);

this.holograms.add(hologram);
return hologram;
}

@Override
public void removeHologram(Hologram hologram) {
this.holograms.remove(hologram);

FancyHologram fancyHologram = (FancyHologram) hologram;
FancyHologramsPlugin.get().getHologramManager().removeHologram(fancyHologram.getImpl());
}

@Override
public List<Hologram> getHolograms() {
return List.copyOf(this.holograms);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import org.battleplugins.arena.competition.phase.CompetitionPhaseType;
import org.battleplugins.arena.competition.phase.phases.VictoryPhase;
import org.battleplugins.arena.event.arena.ArenaCreateCompetitionEvent;
import org.battleplugins.arena.event.arena.ArenaRemoveCompetitionEvent;
import org.battleplugins.arena.event.player.ArenaLeaveEvent;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
Expand Down Expand Up @@ -199,6 +200,10 @@ public void removeCompetition(Arena arena, Competition<?> competition) {
}

competitions.remove(competition);

ArenaRemoveCompetitionEvent event = new ArenaRemoveCompetitionEvent(arena, competition);
this.plugin.getServer().getPluginManager().callEvent(event);

if (competition.getMap().getType() == MapType.DYNAMIC && competition.getMap() instanceof LiveCompetitionMap map) {
this.clearDynamicMap(map);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package org.battleplugins.arena.event.arena;

import org.battleplugins.arena.Arena;
import org.battleplugins.arena.competition.Competition;
import org.battleplugins.arena.event.ArenaEvent;
import org.bukkit.event.Event;
import org.bukkit.event.HandlerList;
import org.jetbrains.annotations.NotNull;

/**
* Called when a competition is removed from an {@link Arena}.
*/
public class ArenaRemoveCompetitionEvent extends Event implements ArenaEvent {
private final static HandlerList HANDLERS = new HandlerList();

private final Arena arena;
private final Competition<?> competition;

public ArenaRemoveCompetitionEvent(Arena arena, Competition<?> competition) {
this.arena = arena;
this.competition = competition;
}

@Override
public Arena getArena() {
return this.arena;
}

@Override
public Competition<?> getCompetition() {
return this.competition;
}

@NotNull
@Override
public HandlerList getHandlers() {
return HANDLERS;
}

public static HandlerList getHandlerList() {
return HANDLERS;
}
}
Loading

0 comments on commit 2389b1e

Please sign in to comment.