mirror of
https://github.com/FancyInnovations/FancyPlugins.git
synced 2025-12-06 07:43:36 +00:00
Add FancyHolograms sources
This commit is contained in:
71
plugins/fancyholograms-v2/api/build.gradle.kts
Normal file
71
plugins/fancyholograms-v2/api/build.gradle.kts
Normal file
@@ -0,0 +1,71 @@
|
||||
plugins {
|
||||
id("java-library")
|
||||
id("maven-publish")
|
||||
id("com.gradleup.shadow")
|
||||
}
|
||||
|
||||
val minecraftVersion = "1.19.4"
|
||||
|
||||
dependencies {
|
||||
compileOnly("io.papermc.paper:paper-api:$minecraftVersion-R0.1-SNAPSHOT")
|
||||
|
||||
compileOnly("de.oliver:FancyLib:36")
|
||||
compileOnly("de.oliver.FancyAnalytics:logger:0.0.6")
|
||||
|
||||
implementation("org.lushplugins:ChatColorHandler:5.1.2")
|
||||
}
|
||||
|
||||
tasks {
|
||||
shadowJar {
|
||||
relocate("org.lushplugins.chatcolorhandler", "de.oliver.fancyholograms.libs.chatcolorhandler")
|
||||
|
||||
archiveClassifier.set("")
|
||||
}
|
||||
|
||||
publishing {
|
||||
repositories {
|
||||
maven {
|
||||
name = "fancypluginsReleases"
|
||||
url = uri("https://repo.fancyplugins.de/releases")
|
||||
credentials(PasswordCredentials::class)
|
||||
authentication {
|
||||
isAllowInsecureProtocol = true
|
||||
create<BasicAuthentication>("basic")
|
||||
}
|
||||
}
|
||||
|
||||
maven {
|
||||
name = "fancypluginsSnapshots"
|
||||
url = uri("https://repo.fancyplugins.de/snapshots")
|
||||
credentials(PasswordCredentials::class)
|
||||
authentication {
|
||||
isAllowInsecureProtocol = true
|
||||
create<BasicAuthentication>("basic")
|
||||
}
|
||||
}
|
||||
}
|
||||
publications {
|
||||
create<MavenPublication>("maven") {
|
||||
groupId = "de.oliver"
|
||||
artifactId = "FancyHolograms"
|
||||
version = project.version.toString()
|
||||
from(project.components["java"])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
java {
|
||||
withSourcesJar()
|
||||
withJavadocJar()
|
||||
}
|
||||
|
||||
javadoc {
|
||||
options.encoding = Charsets.UTF_8.name()
|
||||
}
|
||||
|
||||
compileJava {
|
||||
options.encoding = Charsets.UTF_8.name()
|
||||
|
||||
options.release.set(17)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
package de.oliver.fancyholograms.api;
|
||||
|
||||
import de.oliver.fancyanalytics.logger.ExtendedFancyLogger;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
|
||||
public interface FancyHologramsPlugin {
|
||||
|
||||
static FancyHologramsPlugin get() {
|
||||
if (isEnabled()) {
|
||||
return EnabledChecker.getPlugin();
|
||||
}
|
||||
|
||||
throw new NullPointerException("Plugin is not enabled");
|
||||
}
|
||||
|
||||
static boolean isEnabled() {
|
||||
return EnabledChecker.isFancyHologramsEnabled();
|
||||
}
|
||||
|
||||
JavaPlugin getPlugin();
|
||||
|
||||
ExtendedFancyLogger getFancyLogger();
|
||||
|
||||
HologramManager getHologramManager();
|
||||
|
||||
/**
|
||||
* Returns the configuration of the plugin.
|
||||
*
|
||||
* @return The configuration.
|
||||
*/
|
||||
HologramConfiguration getHologramConfiguration();
|
||||
|
||||
/**
|
||||
* Sets the configuration of the plugin.
|
||||
*
|
||||
* @param configuration The new configuration.
|
||||
* @param reload Whether the configuration should be reloaded.
|
||||
*/
|
||||
void setHologramConfiguration(HologramConfiguration configuration, boolean reload);
|
||||
|
||||
/**
|
||||
* @return The hologram storage.
|
||||
*/
|
||||
HologramStorage getHologramStorage();
|
||||
|
||||
/**
|
||||
* @return The hologram thread
|
||||
*/
|
||||
ScheduledExecutorService getHologramThread();
|
||||
|
||||
/**
|
||||
* Sets the hologram storage.
|
||||
*
|
||||
* @param storage The new hologram storage.
|
||||
* @param reload Whether the current hologram cache should be reloaded.
|
||||
*/
|
||||
void setHologramStorage(HologramStorage storage, boolean reload);
|
||||
|
||||
class EnabledChecker {
|
||||
|
||||
private static Boolean enabled;
|
||||
private static FancyHologramsPlugin plugin;
|
||||
|
||||
public static Boolean isFancyHologramsEnabled() {
|
||||
if (enabled != null) return enabled;
|
||||
|
||||
Plugin pl = Bukkit.getPluginManager().getPlugin("FancyHolograms");
|
||||
|
||||
if (pl != null && pl.isEnabled()) {
|
||||
try {
|
||||
plugin = (FancyHologramsPlugin) pl;
|
||||
} catch (ClassCastException e) {
|
||||
throw new IllegalStateException("API failed to access plugin, if using the FancyHolograms API make sure to set the dependency to compile only.");
|
||||
}
|
||||
|
||||
enabled = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static FancyHologramsPlugin getPlugin() {
|
||||
return plugin;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
package de.oliver.fancyholograms.api;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public interface HologramConfiguration {
|
||||
|
||||
/**
|
||||
* Reloads the configuration.
|
||||
*
|
||||
* @param plugin The plugin instance.
|
||||
*/
|
||||
void reload(@NotNull FancyHologramsPlugin plugin);
|
||||
|
||||
/**
|
||||
* Returns whether version notifications are muted.
|
||||
*
|
||||
* @return {@code true} if version notifications are muted, {@code false} otherwise.
|
||||
*/
|
||||
boolean areVersionNotificationsMuted();
|
||||
|
||||
/**
|
||||
* Returns whether autosave is enabled.
|
||||
*
|
||||
* @return {@code true} if autosave is enabled, {@code false} otherwise.
|
||||
*/
|
||||
boolean isAutosaveEnabled();
|
||||
|
||||
/**
|
||||
* Returns the interval at which autosave is performed.
|
||||
*
|
||||
* @return The autosave interval in minutes.
|
||||
*/
|
||||
int getAutosaveInterval();
|
||||
|
||||
/**
|
||||
* Returns whether the plugin should save holograms when they are changed.
|
||||
*
|
||||
* @return {@code true} if the plugin should save holograms when they are changed, {@code false} otherwise.
|
||||
*/
|
||||
boolean isSaveOnChangedEnabled();
|
||||
|
||||
/**
|
||||
* Returns the default visibility distance for holograms.
|
||||
*
|
||||
* @return The default hologram visibility distance.
|
||||
*/
|
||||
int getDefaultVisibilityDistance();
|
||||
|
||||
/**
|
||||
* Returns whether the plugin should register its commands.
|
||||
*
|
||||
* @return {@code true} if the plugin should register its commands, {@code false} otherwise.
|
||||
*/
|
||||
boolean isRegisterCommands();
|
||||
|
||||
/**
|
||||
* Returns the log level for the plugin.
|
||||
*
|
||||
* @return The log level for the plugin.
|
||||
*/
|
||||
String getLogLevel();
|
||||
|
||||
/**
|
||||
* Returns the interval at which hologram visibility is updated.
|
||||
*
|
||||
* @return The hologram visibility update interval in milliseconds.
|
||||
*/
|
||||
int getUpdateVisibilityInterval();
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package de.oliver.fancyholograms.api;
|
||||
|
||||
import de.oliver.fancyholograms.api.data.HologramData;
|
||||
import de.oliver.fancyholograms.api.hologram.Hologram;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Optional;
|
||||
|
||||
public interface HologramManager {
|
||||
|
||||
Optional<Hologram> getHologram(String name);
|
||||
|
||||
Collection<Hologram> getPersistentHolograms();
|
||||
|
||||
Collection<Hologram> getHolograms();
|
||||
|
||||
void addHologram(Hologram hologram);
|
||||
|
||||
void removeHologram(Hologram hologram);
|
||||
|
||||
Hologram create(HologramData hologramData);
|
||||
|
||||
void loadHolograms();
|
||||
|
||||
void saveHolograms();
|
||||
|
||||
void reloadHolograms();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
package de.oliver.fancyholograms.api;
|
||||
|
||||
import de.oliver.fancyholograms.api.hologram.Hologram;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
public interface HologramStorage {
|
||||
|
||||
/**
|
||||
* Saves a collection of holograms.
|
||||
*
|
||||
* @param holograms The holograms to save.
|
||||
* @param override Whether to override existing holograms.
|
||||
*/
|
||||
void saveBatch(Collection<Hologram> holograms, boolean override);
|
||||
|
||||
/**
|
||||
* Saves a hologram.
|
||||
*
|
||||
* @param hologram The hologram to save.
|
||||
*/
|
||||
void save(Hologram hologram);
|
||||
|
||||
/**
|
||||
* Deletes a hologram.
|
||||
*
|
||||
* @param hologram The hologram to delete.
|
||||
*/
|
||||
void delete(Hologram hologram);
|
||||
|
||||
/**
|
||||
* Loads all holograms from all worlds
|
||||
*
|
||||
* @return A collection of all loaded holograms.
|
||||
*/
|
||||
Collection<Hologram> loadAll();
|
||||
|
||||
/**
|
||||
* Loads all holograms from a specific world
|
||||
*
|
||||
* @param world The world to load the holograms from.
|
||||
* @return A collection of all loaded holograms.
|
||||
*/
|
||||
Collection<Hologram> loadAll(String world);
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
package de.oliver.fancyholograms.api.data;
|
||||
|
||||
import de.oliver.fancyholograms.api.hologram.HologramType;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
public class BlockHologramData extends DisplayHologramData {
|
||||
|
||||
public static Material DEFAULT_BLOCK = Material.GRASS_BLOCK;
|
||||
|
||||
private Material block = DEFAULT_BLOCK;
|
||||
|
||||
/**
|
||||
* @param name Name of hologram
|
||||
* @param location Location of hologram
|
||||
* Default values are already set
|
||||
*/
|
||||
public BlockHologramData(String name, Location location) {
|
||||
super(name, HologramType.BLOCK, location);
|
||||
}
|
||||
|
||||
public Material getBlock() {
|
||||
return block;
|
||||
}
|
||||
|
||||
public BlockHologramData setBlock(Material block) {
|
||||
if (!Objects.equals(this.block, block)) {
|
||||
this.block = block;
|
||||
setHasChanges(true);
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean read(ConfigurationSection section, String name) {
|
||||
super.read(section, name);
|
||||
block = Material.getMaterial(section.getString("block", "GRASS_BLOCK").toUpperCase());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean write(ConfigurationSection section, String name) {
|
||||
super.write(section, name);
|
||||
section.set("block", block.name());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockHologramData copy(String name) {
|
||||
BlockHologramData blockHologramData = new BlockHologramData(name, getLocation());
|
||||
blockHologramData
|
||||
.setBlock(this.getBlock())
|
||||
.setScale(this.getScale())
|
||||
.setShadowRadius(this.getShadowRadius())
|
||||
.setShadowStrength(this.getShadowStrength())
|
||||
.setBillboard(this.getBillboard())
|
||||
.setTranslation(this.getTranslation())
|
||||
.setBrightness(this.getBrightness())
|
||||
.setVisibilityDistance(getVisibilityDistance())
|
||||
.setVisibility(this.getVisibility())
|
||||
.setPersistent(this.isPersistent())
|
||||
.setLinkedNpcName(getLinkedNpcName());
|
||||
|
||||
return blockHologramData;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,211 @@
|
||||
package de.oliver.fancyholograms.api.data;
|
||||
|
||||
import de.oliver.fancyholograms.api.hologram.HologramType;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.bukkit.entity.Display;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.joml.Vector3f;
|
||||
|
||||
import java.util.Locale;
|
||||
import java.util.Objects;
|
||||
|
||||
public class DisplayHologramData extends HologramData {
|
||||
|
||||
public static final Display.Billboard DEFAULT_BILLBOARD = Display.Billboard.CENTER;
|
||||
public static final Vector3f DEFAULT_SCALE = new Vector3f(1, 1, 1);
|
||||
public static final Vector3f DEFAULT_TRANSLATION = new Vector3f(0, 0, 0);
|
||||
public static final float DEFAULT_SHADOW_RADIUS = 0.0f;
|
||||
public static final float DEFAULT_SHADOW_STRENGTH = 1.0f;
|
||||
public static final int DEFAULT_INTERPOLATION_DURATION = 0;
|
||||
|
||||
private Display.Billboard billboard = DEFAULT_BILLBOARD;
|
||||
private Vector3f scale = new Vector3f(DEFAULT_SCALE);
|
||||
private Vector3f translation = new Vector3f(DEFAULT_TRANSLATION);
|
||||
private Display.Brightness brightness;
|
||||
private float shadowRadius = DEFAULT_SHADOW_RADIUS;
|
||||
private float shadowStrength = DEFAULT_SHADOW_STRENGTH;
|
||||
private int interpolationDuration = DEFAULT_INTERPOLATION_DURATION;
|
||||
|
||||
/**
|
||||
* @param name Name of hologram
|
||||
* @param type Type of hologram
|
||||
* @param location Location of hologram
|
||||
* Default values are already set
|
||||
*/
|
||||
public DisplayHologramData(String name, HologramType type, Location location) {
|
||||
super(name, type, location);
|
||||
}
|
||||
|
||||
public Display.Billboard getBillboard() {
|
||||
return billboard;
|
||||
}
|
||||
|
||||
public DisplayHologramData setBillboard(Display.Billboard billboard) {
|
||||
if (!Objects.equals(this.billboard, billboard)) {
|
||||
this.billboard = billboard;
|
||||
setHasChanges(true);
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public Vector3f getScale() {
|
||||
return scale;
|
||||
}
|
||||
|
||||
public DisplayHologramData setScale(Vector3f scale) {
|
||||
if (!Objects.equals(this.scale, scale)) {
|
||||
this.scale = scale;
|
||||
setHasChanges(true);
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public Vector3f getTranslation() {
|
||||
return translation;
|
||||
}
|
||||
|
||||
public DisplayHologramData setTranslation(Vector3f translation) {
|
||||
if (!Objects.equals(this.translation, translation)) {
|
||||
this.translation = translation;
|
||||
setHasChanges(true);
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public Display.Brightness getBrightness() {
|
||||
return brightness;
|
||||
}
|
||||
|
||||
public DisplayHologramData setBrightness(Display.Brightness brightness) {
|
||||
if (!Objects.equals(this.brightness, brightness)) {
|
||||
this.brightness = brightness;
|
||||
setHasChanges(true);
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public float getShadowRadius() {
|
||||
return shadowRadius;
|
||||
}
|
||||
|
||||
public DisplayHologramData setShadowRadius(float shadowRadius) {
|
||||
if (this.shadowRadius != shadowRadius) {
|
||||
this.shadowRadius = shadowRadius;
|
||||
setHasChanges(true);
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public float getShadowStrength() {
|
||||
return shadowStrength;
|
||||
}
|
||||
|
||||
public DisplayHologramData setShadowStrength(float shadowStrength) {
|
||||
if (this.shadowStrength != shadowStrength) {
|
||||
this.shadowStrength = shadowStrength;
|
||||
setHasChanges(true);
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
@ApiStatus.Experimental
|
||||
public int getInterpolationDuration() {
|
||||
return interpolationDuration;
|
||||
}
|
||||
|
||||
@ApiStatus.Experimental
|
||||
public DisplayHologramData setInterpolationDuration(int interpolationDuration) {
|
||||
if (this.interpolationDuration != interpolationDuration) {
|
||||
this.interpolationDuration = interpolationDuration;
|
||||
setHasChanges(true);
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean read(ConfigurationSection section, String name) {
|
||||
super.read(section, name);
|
||||
scale = new Vector3f(
|
||||
(float) section.getDouble("scale_x", DEFAULT_SCALE.x),
|
||||
(float) section.getDouble("scale_y", DEFAULT_SCALE.y),
|
||||
(float) section.getDouble("scale_z", DEFAULT_SCALE.z)
|
||||
);
|
||||
|
||||
translation = new Vector3f(
|
||||
(float) section.getDouble("translation_x", DEFAULT_TRANSLATION.x),
|
||||
(float) section.getDouble("translation_y", DEFAULT_TRANSLATION.y),
|
||||
(float) section.getDouble("translation_z", DEFAULT_TRANSLATION.z)
|
||||
);
|
||||
|
||||
shadowRadius = (float) section.getDouble("shadow_radius", DEFAULT_SHADOW_RADIUS);
|
||||
shadowStrength = (float) section.getDouble("shadow_strength", DEFAULT_SHADOW_STRENGTH);
|
||||
|
||||
String billboardStr = section.getString("billboard", DEFAULT_BILLBOARD.name());
|
||||
billboard = switch (billboardStr.toLowerCase()) {
|
||||
case "fixed" -> Display.Billboard.FIXED;
|
||||
case "vertical" -> Display.Billboard.VERTICAL;
|
||||
case "horizontal" -> Display.Billboard.HORIZONTAL;
|
||||
default -> Display.Billboard.CENTER;
|
||||
};
|
||||
|
||||
int blockBrightness = Math.min(15, section.getInt("block_brightness", -1));
|
||||
int skyBrightness = Math.min(15, section.getInt("sky_brightness", -1));
|
||||
|
||||
if(blockBrightness > -1 || skyBrightness > -1) {
|
||||
brightness = new Display.Brightness(
|
||||
Math.max(0, blockBrightness),
|
||||
Math.max(0, skyBrightness)
|
||||
);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean write(ConfigurationSection section, String name) {
|
||||
super.write(section, name);
|
||||
section.set("scale_x", scale.x);
|
||||
section.set("scale_y", scale.y);
|
||||
section.set("scale_z", scale.z);
|
||||
section.set("translation_x", translation.x);
|
||||
section.set("translation_y", translation.y);
|
||||
section.set("translation_z", translation.z);
|
||||
section.set("shadow_radius", shadowRadius);
|
||||
section.set("shadow_strength", shadowStrength);
|
||||
|
||||
if(brightness != null) {
|
||||
section.set("block_brightness", brightness.getBlockLight());
|
||||
section.set("sky_brightness", brightness.getSkyLight());
|
||||
}
|
||||
|
||||
section.set("billboard", billboard != Display.Billboard.CENTER ? billboard.name().toLowerCase(Locale.ROOT) : null);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DisplayHologramData copy(String name) {
|
||||
DisplayHologramData displayHologramData = new DisplayHologramData(name, getType(), getLocation());
|
||||
displayHologramData
|
||||
.setScale(this.getScale())
|
||||
.setShadowRadius(this.getShadowRadius())
|
||||
.setShadowStrength(this.getShadowStrength())
|
||||
.setBillboard(this.getBillboard())
|
||||
.setTranslation(this.getTranslation())
|
||||
.setBrightness(this.getBrightness())
|
||||
.setVisibilityDistance(this.getVisibilityDistance())
|
||||
.setVisibility(this.getVisibility())
|
||||
.setPersistent(this.isPersistent())
|
||||
.setLinkedNpcName(this.getLinkedNpcName());
|
||||
|
||||
return displayHologramData;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,190 @@
|
||||
package de.oliver.fancyholograms.api.data;
|
||||
|
||||
import de.oliver.fancyholograms.api.FancyHologramsPlugin;
|
||||
import de.oliver.fancyholograms.api.data.property.Visibility;
|
||||
import de.oliver.fancyholograms.api.hologram.HologramType;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
|
||||
public class HologramData implements YamlData {
|
||||
|
||||
public static final int DEFAULT_VISIBILITY_DISTANCE = -1;
|
||||
public static final Visibility DEFAULT_VISIBILITY = Visibility.ALL;
|
||||
public static final boolean DEFAULT_IS_VISIBLE = true;
|
||||
public static final boolean DEFAULT_PERSISTENCE = true;
|
||||
|
||||
private final String name;
|
||||
private final HologramType type;
|
||||
private Location location;
|
||||
private boolean hasChanges;
|
||||
private int visibilityDistance = DEFAULT_VISIBILITY_DISTANCE;
|
||||
private Visibility visibility = DEFAULT_VISIBILITY;
|
||||
private boolean persistent = DEFAULT_PERSISTENCE;
|
||||
private String linkedNpcName;
|
||||
|
||||
/**
|
||||
* @param name Name of hologram
|
||||
* @param type Type of hologram
|
||||
* @param location Location of hologram
|
||||
* Default values are already set
|
||||
*/
|
||||
public HologramData(String name, HologramType type, Location location) {
|
||||
this.name = name;
|
||||
this.type = type;
|
||||
this.location = location;
|
||||
}
|
||||
|
||||
public @NotNull String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public @NotNull HologramType getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public @NotNull Location getLocation() {
|
||||
return location.clone();
|
||||
}
|
||||
|
||||
public HologramData setLocation(@Nullable Location location) {
|
||||
this.location = location != null ? location.clone() : null;
|
||||
setHasChanges(true);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Whether the hologram needs to send an update to players
|
||||
*/
|
||||
public final boolean hasChanges() {
|
||||
return hasChanges;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param hasChanges Whether the hologram needs to send an update to players
|
||||
*/
|
||||
public final void setHasChanges(boolean hasChanges) {
|
||||
this.hasChanges = hasChanges;
|
||||
}
|
||||
|
||||
public int getVisibilityDistance() {
|
||||
if (visibilityDistance > 0) {
|
||||
return visibilityDistance;
|
||||
}
|
||||
|
||||
return FancyHologramsPlugin.get().getHologramConfiguration().getDefaultVisibilityDistance();
|
||||
}
|
||||
|
||||
public HologramData setVisibilityDistance(int visibilityDistance) {
|
||||
this.visibilityDistance = visibilityDistance;
|
||||
setHasChanges(true);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the type of visibility for the hologram.
|
||||
*
|
||||
* @return type of visibility.
|
||||
*/
|
||||
public Visibility getVisibility() {
|
||||
return this.visibility;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the type of visibility for the hologram.
|
||||
*/
|
||||
public HologramData setVisibility(@NotNull Visibility visibility) {
|
||||
if (!Objects.equals(this.visibility, visibility)) {
|
||||
this.visibility = visibility;
|
||||
setHasChanges(true);
|
||||
|
||||
if (this.visibility.equals(Visibility.MANUAL)) {
|
||||
Visibility.ManualVisibility.clear();
|
||||
}
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public boolean isPersistent() {
|
||||
return persistent;
|
||||
}
|
||||
|
||||
public HologramData setPersistent(boolean persistent) {
|
||||
this.persistent = persistent;
|
||||
return this;
|
||||
}
|
||||
|
||||
public String getLinkedNpcName() {
|
||||
return linkedNpcName;
|
||||
}
|
||||
|
||||
public HologramData setLinkedNpcName(String linkedNpcName) {
|
||||
if (!Objects.equals(this.linkedNpcName, linkedNpcName)) {
|
||||
this.linkedNpcName = linkedNpcName;
|
||||
setHasChanges(true);
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean read(ConfigurationSection section, String name) {
|
||||
String worldName = section.getString("location.world", "world");
|
||||
float x = (float) section.getDouble("location.x", 0);
|
||||
float y = (float) section.getDouble("location.y", 0);
|
||||
float z = (float) section.getDouble("location.z", 0);
|
||||
float yaw = (float) section.getDouble("location.yaw", 0);
|
||||
float pitch = (float) section.getDouble("location.pitch", 0);
|
||||
|
||||
World world = Bukkit.getWorld(worldName);
|
||||
if (world == null) {
|
||||
FancyHologramsPlugin.get().getFancyLogger().warn("Could not load hologram '" + name + "', because the world '" + worldName + "' is not loaded");
|
||||
return false;
|
||||
}
|
||||
|
||||
location = new Location(world, x, y, z, yaw, pitch);
|
||||
visibilityDistance = section.getInt("visibility_distance", DEFAULT_VISIBILITY_DISTANCE);
|
||||
visibility = Optional.ofNullable(section.getString("visibility"))
|
||||
.flatMap(Visibility::byString)
|
||||
.orElseGet(() -> {
|
||||
final var visibleByDefault = section.getBoolean("visible_by_default", DisplayHologramData.DEFAULT_IS_VISIBLE);
|
||||
return visibleByDefault ? Visibility.ALL : Visibility.PERMISSION_REQUIRED;
|
||||
});
|
||||
linkedNpcName = section.getString("linkedNpc");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean write(ConfigurationSection section, String name) {
|
||||
section.set("type", type.name());
|
||||
section.set("location.world", location.getWorld().getName());
|
||||
section.set("location.x", location.x());
|
||||
section.set("location.y", location.y());
|
||||
section.set("location.z", location.z());
|
||||
section.set("location.yaw", location.getYaw());
|
||||
section.set("location.pitch", location.getPitch());
|
||||
|
||||
section.set("visibility_distance", visibilityDistance);
|
||||
section.set("visibility", visibility.name());
|
||||
section.set("persistent", persistent);
|
||||
section.set("linkedNpc", linkedNpcName);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public HologramData copy(String name) {
|
||||
return new HologramData(name, type, this.getLocation())
|
||||
.setVisibilityDistance(this.getVisibilityDistance())
|
||||
.setVisibility(this.getVisibility())
|
||||
.setPersistent(this.isPersistent())
|
||||
.setLinkedNpcName(this.getLinkedNpcName());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
package de.oliver.fancyholograms.api.data;
|
||||
|
||||
import de.oliver.fancyholograms.api.hologram.HologramType;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
public class ItemHologramData extends DisplayHologramData {
|
||||
|
||||
public static final ItemStack DEFAULT_ITEM = new ItemStack(Material.APPLE);
|
||||
|
||||
private ItemStack item = DEFAULT_ITEM;
|
||||
|
||||
/**
|
||||
* @param name Name of hologram
|
||||
* @param location Location of hologram
|
||||
* Default values are already set
|
||||
*/
|
||||
public ItemHologramData(String name, Location location) {
|
||||
super(name, HologramType.ITEM, location);
|
||||
}
|
||||
|
||||
public ItemStack getItemStack() {
|
||||
return item;
|
||||
}
|
||||
|
||||
public ItemHologramData setItemStack(ItemStack item) {
|
||||
if (!Objects.equals(this.item, item)) {
|
||||
this.item = item;
|
||||
setHasChanges(true);
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean read(ConfigurationSection section, String name) {
|
||||
super.read(section, name);
|
||||
item = section.getItemStack("item", DEFAULT_ITEM);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean write(ConfigurationSection section, String name) {
|
||||
super.write(section, name);
|
||||
section.set("item", item);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemHologramData copy(String name) {
|
||||
ItemHologramData itemHologramData = new ItemHologramData(name, getLocation());
|
||||
itemHologramData
|
||||
.setItemStack(this.getItemStack())
|
||||
.setScale(this.getScale())
|
||||
.setShadowRadius(this.getShadowRadius())
|
||||
.setShadowStrength(this.getShadowStrength())
|
||||
.setBillboard(this.getBillboard())
|
||||
.setTranslation(this.getTranslation())
|
||||
.setBrightness(this.getBrightness())
|
||||
.setVisibilityDistance(this.getVisibilityDistance())
|
||||
.setVisibility(this.getVisibility())
|
||||
.setPersistent(this.isPersistent())
|
||||
.setLinkedNpcName(this.getLinkedNpcName());
|
||||
|
||||
return itemHologramData;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,212 @@
|
||||
package de.oliver.fancyholograms.api.data;
|
||||
|
||||
import de.oliver.fancyholograms.api.hologram.Hologram;
|
||||
import de.oliver.fancyholograms.api.hologram.HologramType;
|
||||
import net.kyori.adventure.text.format.NamedTextColor;
|
||||
import org.bukkit.Color;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.bukkit.entity.TextDisplay;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Objects;
|
||||
|
||||
public class TextHologramData extends DisplayHologramData {
|
||||
|
||||
public static final TextDisplay.TextAlignment DEFAULT_TEXT_ALIGNMENT = TextDisplay.TextAlignment.CENTER;
|
||||
public static final boolean DEFAULT_TEXT_SHADOW_STATE = false;
|
||||
public static final boolean DEFAULT_SEE_THROUGH = false;
|
||||
public static final int DEFAULT_TEXT_UPDATE_INTERVAL = -1;
|
||||
|
||||
private List<String> text;
|
||||
private Color background;
|
||||
private TextDisplay.TextAlignment textAlignment = DEFAULT_TEXT_ALIGNMENT;
|
||||
private boolean textShadow = DEFAULT_TEXT_SHADOW_STATE;
|
||||
private boolean seeThrough = DEFAULT_SEE_THROUGH;
|
||||
private int textUpdateInterval = DEFAULT_TEXT_UPDATE_INTERVAL;
|
||||
|
||||
/**
|
||||
* @param name Name of hologram
|
||||
* @param location Location of hologram
|
||||
* Default values are already set
|
||||
*/
|
||||
public TextHologramData(String name, Location location) {
|
||||
super(name, HologramType.TEXT, location);
|
||||
text = new ArrayList<>(List.of("Edit this line with /hologram edit " + name));
|
||||
}
|
||||
|
||||
public List<String> getText() {
|
||||
return text;
|
||||
}
|
||||
|
||||
public TextHologramData setText(List<String> text) {
|
||||
if (!Objects.equals(this.text, text)) {
|
||||
this.text = text;
|
||||
setHasChanges(true);
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public void addLine(String line) {
|
||||
text.add(line);
|
||||
setHasChanges(true);
|
||||
}
|
||||
|
||||
public void removeLine(int index) {
|
||||
text.remove(index);
|
||||
setHasChanges(true);
|
||||
}
|
||||
|
||||
public Color getBackground() {
|
||||
return background;
|
||||
}
|
||||
|
||||
public TextHologramData setBackground(Color background) {
|
||||
if (!Objects.equals(this.background, background)) {
|
||||
this.background = background;
|
||||
setHasChanges(true);
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public TextDisplay.TextAlignment getTextAlignment() {
|
||||
return textAlignment;
|
||||
}
|
||||
|
||||
public TextHologramData setTextAlignment(TextDisplay.TextAlignment textAlignment) {
|
||||
if (!Objects.equals(this.textAlignment, textAlignment)) {
|
||||
this.textAlignment = textAlignment;
|
||||
setHasChanges(true);
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public boolean hasTextShadow() {
|
||||
return textShadow;
|
||||
}
|
||||
|
||||
public TextHologramData setTextShadow(boolean textShadow) {
|
||||
if (this.textShadow != textShadow) {
|
||||
this.textShadow = textShadow;
|
||||
setHasChanges(true);
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public boolean isSeeThrough() {
|
||||
return seeThrough;
|
||||
}
|
||||
|
||||
public TextHologramData setSeeThrough(boolean seeThrough) {
|
||||
if (this.seeThrough != seeThrough) {
|
||||
this.seeThrough = seeThrough;
|
||||
setHasChanges(true);
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public int getTextUpdateInterval() {
|
||||
return textUpdateInterval;
|
||||
}
|
||||
|
||||
public TextHologramData setTextUpdateInterval(int textUpdateInterval) {
|
||||
if (this.textUpdateInterval != textUpdateInterval) {
|
||||
this.textUpdateInterval = textUpdateInterval;
|
||||
setHasChanges(true);
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean read(ConfigurationSection section, String name) {
|
||||
super.read(section, name);
|
||||
text = section.getStringList("text");
|
||||
if (text.isEmpty()) {
|
||||
text = List.of("Could not load hologram text");
|
||||
//TODO: maybe return false here?
|
||||
}
|
||||
|
||||
textShadow = section.getBoolean("text_shadow", DEFAULT_TEXT_SHADOW_STATE);
|
||||
seeThrough = section.getBoolean("see_through", DEFAULT_SEE_THROUGH);
|
||||
textUpdateInterval = section.getInt("update_text_interval", DEFAULT_TEXT_UPDATE_INTERVAL);
|
||||
|
||||
String textAlignmentStr = section.getString("text_alignment", DEFAULT_TEXT_ALIGNMENT.name().toLowerCase());
|
||||
textAlignment = switch (textAlignmentStr.toLowerCase(Locale.ROOT)) {
|
||||
case "right" -> TextDisplay.TextAlignment.RIGHT;
|
||||
case "left" -> TextDisplay.TextAlignment.LEFT;
|
||||
default -> TextDisplay.TextAlignment.CENTER;
|
||||
};
|
||||
|
||||
background = null;
|
||||
String backgroundStr = section.getString("background", null);
|
||||
if (backgroundStr != null) {
|
||||
if (backgroundStr.equalsIgnoreCase("transparent")) {
|
||||
background = Hologram.TRANSPARENT;
|
||||
} else if (backgroundStr.startsWith("#")) {
|
||||
background = Color.fromARGB((int) Long.parseLong(backgroundStr.substring(1), 16));
|
||||
//backwards compatibility, make rgb hex colors solid color -their alpha is 0 by default-
|
||||
if (backgroundStr.length() == 7) background = background.setAlpha(255);
|
||||
} else {
|
||||
background = Color.fromARGB(NamedTextColor.NAMES.value(backgroundStr.toLowerCase(Locale.ROOT).trim().replace(' ', '_')).value() | 0xC8000000);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean write(ConfigurationSection section, String name) {
|
||||
super.write(section, name);
|
||||
section.set("text", text);
|
||||
section.set("text_shadow", textShadow);
|
||||
section.set("see_through", seeThrough);
|
||||
section.set("text_alignment", textAlignment.name().toLowerCase(Locale.ROOT));
|
||||
section.set("update_text_interval", textUpdateInterval);
|
||||
|
||||
final String color;
|
||||
if (background == null) {
|
||||
color = null;
|
||||
} else if (background == Hologram.TRANSPARENT) {
|
||||
color = "transparent";
|
||||
} else {
|
||||
NamedTextColor named = background.getAlpha() == 255 ? NamedTextColor.namedColor(background.asRGB()) : null;
|
||||
color = named != null ? named.toString() : '#' + Integer.toHexString(background.asARGB());
|
||||
}
|
||||
|
||||
section.set("background", color);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TextHologramData copy(String name) {
|
||||
TextHologramData textHologramData = new TextHologramData(name, getLocation());
|
||||
textHologramData
|
||||
.setText(this.getText())
|
||||
.setBackground(this.getBackground())
|
||||
.setTextAlignment(this.getTextAlignment())
|
||||
.setTextShadow(this.hasTextShadow())
|
||||
.setSeeThrough(this.isSeeThrough())
|
||||
.setTextUpdateInterval(this.getTextUpdateInterval())
|
||||
.setScale(this.getScale())
|
||||
.setShadowRadius(this.getShadowRadius())
|
||||
.setShadowStrength(this.getShadowStrength())
|
||||
.setBillboard(this.getBillboard())
|
||||
.setTranslation(this.getTranslation())
|
||||
.setBrightness(this.getBrightness())
|
||||
.setVisibilityDistance(this.getVisibilityDistance())
|
||||
.setVisibility(this.getVisibility())
|
||||
.setPersistent(this.isPersistent())
|
||||
.setLinkedNpcName(this.getLinkedNpcName());
|
||||
|
||||
return textHologramData;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package de.oliver.fancyholograms.api.data;
|
||||
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
|
||||
public interface YamlData {
|
||||
|
||||
/**
|
||||
* Reads the data from the given configuration section.
|
||||
*
|
||||
* @return Whether the data was read successfully.
|
||||
*/
|
||||
boolean read(ConfigurationSection section, String name);
|
||||
|
||||
/**
|
||||
* Writes the data to the given configuration section.
|
||||
*
|
||||
* @return Whether the data was written successfully.
|
||||
*/
|
||||
boolean write(ConfigurationSection section, String name);
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
package de.oliver.fancyholograms.api.data.property;
|
||||
|
||||
import com.google.common.collect.HashMultimap;
|
||||
import de.oliver.fancyholograms.api.hologram.Hologram;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
public enum Visibility {
|
||||
/**
|
||||
* Everybody can see a hologram.
|
||||
*/
|
||||
ALL((player, hologram) -> true),
|
||||
/**
|
||||
* The player needs permission to see a specific hologram.
|
||||
*/
|
||||
PERMISSION_REQUIRED(
|
||||
(player, hologram) -> player.hasPermission("fancyholograms.viewhologram." + hologram.getData().getName())
|
||||
),
|
||||
/**
|
||||
* The player needs to be added manually through the API
|
||||
*/
|
||||
MANUAL(ManualVisibility::canSee);
|
||||
|
||||
private final VisibilityPredicate predicate;
|
||||
|
||||
Visibility(VisibilityPredicate predicate) {
|
||||
this.predicate = predicate;
|
||||
}
|
||||
|
||||
public static Optional<Visibility> byString(String value) {
|
||||
return Arrays.stream(Visibility.values())
|
||||
.filter(visibility -> visibility.toString().equalsIgnoreCase(value))
|
||||
.findFirst();
|
||||
}
|
||||
|
||||
public boolean canSee(Player player, Hologram hologram) {
|
||||
return this.predicate.canSee(player, hologram);
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
public interface VisibilityPredicate {
|
||||
boolean canSee(Player player, Hologram hologram);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handling of Visibility.MANUAL
|
||||
* <br>
|
||||
* TODO: Discussion needed - Potentially condense this into one singular multimap within the enum?
|
||||
*/
|
||||
public static class ManualVisibility {
|
||||
private static final HashMultimap<String, UUID> distantViewers = HashMultimap.create();
|
||||
|
||||
public static boolean canSee(Player player, Hologram hologram) {
|
||||
return hologram.isViewer(player) || distantViewers.containsEntry(hologram.getName(), player.getUniqueId());
|
||||
}
|
||||
|
||||
public static void addDistantViewer(Hologram hologram, UUID uuid) {
|
||||
addDistantViewer(hologram.getName(), uuid);
|
||||
}
|
||||
|
||||
public static void addDistantViewer(String hologramName, UUID uuid) {
|
||||
distantViewers.put(hologramName, uuid);
|
||||
}
|
||||
|
||||
public static void removeDistantViewer(Hologram hologram, UUID uuid) {
|
||||
removeDistantViewer(hologram.getName(), uuid);
|
||||
}
|
||||
|
||||
public static void removeDistantViewer(String hologramName, UUID uuid) {
|
||||
distantViewers.remove(hologramName, uuid);
|
||||
}
|
||||
|
||||
public static void remove(Hologram hologram) {
|
||||
remove(hologram.getName());
|
||||
}
|
||||
|
||||
public static void remove(String hologramName) {
|
||||
distantViewers.removeAll(hologramName);
|
||||
}
|
||||
|
||||
public static void clear() {
|
||||
distantViewers.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package de.oliver.fancyholograms.api.events;
|
||||
|
||||
import de.oliver.fancyholograms.api.hologram.Hologram;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.HandlerList;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* Called when a hologram is being created, any hologram data changed will be reflected in the new hologram
|
||||
*/
|
||||
public final class HologramCreateEvent extends HologramEvent {
|
||||
|
||||
private static final HandlerList handlerList = new HandlerList();
|
||||
|
||||
|
||||
@NotNull
|
||||
private final Player player;
|
||||
|
||||
public HologramCreateEvent(@NotNull final Hologram hologram, @NotNull final Player player) {
|
||||
super(hologram, false);
|
||||
|
||||
this.player = player;
|
||||
}
|
||||
|
||||
public static HandlerList getHandlerList() {
|
||||
return handlerList;
|
||||
}
|
||||
|
||||
public @NotNull Player getPlayer() {
|
||||
return this.player;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull HandlerList getHandlers() {
|
||||
return handlerList;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
package de.oliver.fancyholograms.api.events;
|
||||
|
||||
import de.oliver.fancyholograms.api.hologram.Hologram;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.event.HandlerList;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* Called when a hologram is being deleted, any hologram data changed will be reflected in the hologram if
|
||||
* the event is called
|
||||
*/
|
||||
public final class HologramDeleteEvent extends HologramEvent {
|
||||
|
||||
private static final HandlerList handlerList = new HandlerList();
|
||||
|
||||
|
||||
@NotNull
|
||||
private final CommandSender player;
|
||||
|
||||
public HologramDeleteEvent(@NotNull final Hologram hologram, @NotNull final CommandSender player) {
|
||||
super(hologram, false);
|
||||
|
||||
this.player = player;
|
||||
}
|
||||
|
||||
public static HandlerList getHandlerList() {
|
||||
return handlerList;
|
||||
}
|
||||
|
||||
public @NotNull CommandSender getPlayer() {
|
||||
return this.player;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull HandlerList getHandlers() {
|
||||
return handlerList;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
package de.oliver.fancyholograms.api.events;
|
||||
|
||||
import de.oliver.fancyholograms.api.hologram.Hologram;
|
||||
import org.bukkit.event.Cancellable;
|
||||
import org.bukkit.event.Event;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* Represents a base event related to Holograms. This is an abstract class that other event classes related to Holograms should extend.
|
||||
* This event is cancellable, which means it can be prevented from being processed by the server.
|
||||
*/
|
||||
public abstract class HologramEvent extends Event implements Cancellable {
|
||||
|
||||
@NotNull
|
||||
private final Hologram hologram;
|
||||
|
||||
|
||||
private boolean cancelled;
|
||||
|
||||
|
||||
protected HologramEvent(@NotNull final Hologram hologram, final boolean isAsync) {
|
||||
super(isAsync);
|
||||
this.hologram = hologram;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the hologram involved in this event.
|
||||
*
|
||||
* @return the hologram involved in this event
|
||||
*/
|
||||
public final @NotNull Hologram getHologram() {
|
||||
return this.hologram;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public final boolean isCancelled() {
|
||||
return this.cancelled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void setCancelled(final boolean cancel) {
|
||||
this.cancelled = cancel;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
package de.oliver.fancyholograms.api.events;
|
||||
|
||||
import de.oliver.fancyholograms.api.hologram.Hologram;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.HandlerList;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* Called when a hologram is being hidden from a player
|
||||
*/
|
||||
public final class HologramHideEvent extends HologramEvent {
|
||||
|
||||
private static final HandlerList handlerList = new HandlerList();
|
||||
|
||||
|
||||
@NotNull
|
||||
private final Player player;
|
||||
|
||||
public HologramHideEvent(@NotNull final Hologram hologram, @NotNull final Player player) {
|
||||
super(hologram, !Bukkit.isPrimaryThread());
|
||||
|
||||
this.player = player;
|
||||
}
|
||||
|
||||
public static HandlerList getHandlerList() {
|
||||
return handlerList;
|
||||
}
|
||||
|
||||
public @NotNull Player getPlayer() {
|
||||
return this.player;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull HandlerList getHandlers() {
|
||||
return handlerList;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
package de.oliver.fancyholograms.api.events;
|
||||
|
||||
import de.oliver.fancyholograms.api.hologram.Hologram;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.HandlerList;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* Called when a hologram is being shown to a player
|
||||
*/
|
||||
public final class HologramShowEvent extends HologramEvent {
|
||||
|
||||
private static final HandlerList handlerList = new HandlerList();
|
||||
|
||||
|
||||
@NotNull
|
||||
private final Player player;
|
||||
|
||||
public HologramShowEvent(@NotNull final Hologram hologram, @NotNull final Player player) {
|
||||
super(hologram, !Bukkit.isPrimaryThread());
|
||||
|
||||
this.player = player;
|
||||
}
|
||||
|
||||
public static HandlerList getHandlerList() {
|
||||
return handlerList;
|
||||
}
|
||||
|
||||
public @NotNull Player getPlayer() {
|
||||
return this.player;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull HandlerList getHandlers() {
|
||||
return handlerList;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
package de.oliver.fancyholograms.api.events;
|
||||
|
||||
import de.oliver.fancyholograms.api.hologram.Hologram;
|
||||
import de.oliver.fancyholograms.api.data.*;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.event.HandlerList;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* Called when a hologram is being updated, the data in the hologram is current and the event holds the new data
|
||||
*/
|
||||
public final class HologramUpdateEvent extends HologramEvent {
|
||||
|
||||
private static final HandlerList handlerList = new HandlerList();
|
||||
|
||||
private final @NotNull CommandSender player;
|
||||
private final @NotNull HologramData updatedData;
|
||||
private final @NotNull HologramModification modification;
|
||||
|
||||
public HologramUpdateEvent(@NotNull final Hologram hologram, @NotNull final CommandSender player, @NotNull final HologramData updatedData, @NotNull final HologramModification modification) {
|
||||
super(hologram, false);
|
||||
|
||||
this.player = player;
|
||||
this.updatedData = updatedData;
|
||||
this.modification = modification;
|
||||
}
|
||||
|
||||
public static HandlerList getHandlerList() {
|
||||
return handlerList;
|
||||
}
|
||||
|
||||
public @NotNull CommandSender getPlayer() {
|
||||
return this.player;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current data of the hologram.
|
||||
*
|
||||
* @return the current data of the hologram
|
||||
*/
|
||||
public @NotNull HologramData getCurrentData() {
|
||||
return getHologram().getData();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the updated data of the hologram.
|
||||
*
|
||||
* @return the updated data of the hologram
|
||||
*/
|
||||
public @NotNull HologramData getUpdatedData() {
|
||||
return this.updatedData;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the type of modification performed on the hologram.
|
||||
*
|
||||
* @return the type of modification performed on the hologram
|
||||
*/
|
||||
public @NotNull HologramModification getModification() {
|
||||
return this.modification;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull HandlerList getHandlers() {
|
||||
return handlerList;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Represents the various types of modifications that can be made to a Hologram.
|
||||
*/
|
||||
public enum HologramModification {
|
||||
TEXT,
|
||||
POSITION,
|
||||
SCALE,
|
||||
TRANSLATION,
|
||||
BILLBOARD,
|
||||
BACKGROUND,
|
||||
TEXT_SHADOW,
|
||||
TEXT_ALIGNMENT,
|
||||
SEE_THROUGH,
|
||||
SHADOW_RADIUS,
|
||||
SHADOW_STRENGTH,
|
||||
UPDATE_TEXT_INTERVAL,
|
||||
UPDATE_VISIBILITY_DISTANCE;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package de.oliver.fancyholograms.api.events;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import de.oliver.fancyholograms.api.hologram.Hologram;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.event.Event;
|
||||
import org.bukkit.event.HandlerList;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public final class HologramsLoadedEvent extends Event {
|
||||
|
||||
private static final HandlerList handlerList = new HandlerList();
|
||||
|
||||
private final ImmutableList<Hologram> holograms;
|
||||
|
||||
public HologramsLoadedEvent(@NotNull final ImmutableList<Hologram> holograms) {
|
||||
super(!Bukkit.isPrimaryThread());
|
||||
|
||||
this.holograms = holograms;
|
||||
}
|
||||
|
||||
public static HandlerList getHandlerList() {
|
||||
return handlerList;
|
||||
}
|
||||
|
||||
public @NotNull ImmutableList<Hologram> getManager() {
|
||||
return this.holograms;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull HandlerList getHandlers() {
|
||||
return handlerList;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package de.oliver.fancyholograms.api.events;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import de.oliver.fancyholograms.api.hologram.Hologram;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.event.Event;
|
||||
import org.bukkit.event.HandlerList;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public final class HologramsUnloadedEvent extends Event {
|
||||
|
||||
private static final HandlerList handlerList = new HandlerList();
|
||||
|
||||
private final ImmutableList<Hologram> holograms;
|
||||
|
||||
public HologramsUnloadedEvent(@NotNull final ImmutableList<Hologram> holograms) {
|
||||
super(!Bukkit.isPrimaryThread());
|
||||
|
||||
this.holograms = holograms;
|
||||
}
|
||||
|
||||
public static HandlerList getHandlerList() {
|
||||
return handlerList;
|
||||
}
|
||||
|
||||
public @NotNull ImmutableList<Hologram> getManager() {
|
||||
return this.holograms;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull HandlerList getHandlers() {
|
||||
return handlerList;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,372 @@
|
||||
package de.oliver.fancyholograms.api.hologram;
|
||||
|
||||
import de.oliver.fancyholograms.api.data.HologramData;
|
||||
import de.oliver.fancyholograms.api.data.TextHologramData;
|
||||
import de.oliver.fancyholograms.api.data.property.Visibility;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Color;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.entity.Display;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.lushplugins.chatcolorhandler.ModernChatColorHandler;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Abstract base class for creating, updating, and managing holograms.
|
||||
* <p>
|
||||
* This class provides the basic functionality needed to work with holograms
|
||||
* across multiple versions of Minecraft. To create a hologram specific to a version of Minecraft,
|
||||
* extend this class and implement the abstract methods.
|
||||
* <p>
|
||||
* Note that the specific way holograms are created, updated, and deleted
|
||||
* will vary depending on the Minecraft version.
|
||||
* <p>
|
||||
* A Hologram object includes data about the hologram and maintains a set of players to whom the hologram is shown.
|
||||
*/
|
||||
public abstract class Hologram {
|
||||
|
||||
public static final int LINE_WIDTH = 1000;
|
||||
public static final Color TRANSPARENT = Color.fromARGB(0);
|
||||
protected static final int MINIMUM_PROTOCOL_VERSION = 762;
|
||||
|
||||
protected final @NotNull HologramData data;
|
||||
/**
|
||||
* Set of UUIDs of players to whom the hologram is currently shown.
|
||||
*/
|
||||
protected final @NotNull Set<UUID> viewers = new HashSet<>();
|
||||
|
||||
protected Hologram(@NotNull final HologramData data) {
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public String getName() {
|
||||
return data.getName();
|
||||
}
|
||||
|
||||
public final @NotNull HologramData getData() {
|
||||
return this.data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the entity id of this hologram
|
||||
* This id is for packet use only as the entity is not registered to the server
|
||||
* @return entity id
|
||||
*/
|
||||
public abstract int getEntityId();
|
||||
|
||||
/**
|
||||
* Returns the Display entity of this Hologram object.
|
||||
* The entity is not registered in the world or server.
|
||||
* Only use this method if you know what you're doing.
|
||||
* <p>
|
||||
* This method will return <code>null</code> in 1.20.5 and newer versions
|
||||
*
|
||||
* @return the Display entity of this Hologram object
|
||||
*/
|
||||
@ApiStatus.Internal
|
||||
@Deprecated(forRemoval = true, since = "2.4.1")
|
||||
public abstract @Nullable Display getDisplayEntity();
|
||||
|
||||
protected abstract void create();
|
||||
|
||||
protected abstract void delete();
|
||||
|
||||
protected abstract void update();
|
||||
|
||||
protected abstract boolean show(@NotNull final Player player);
|
||||
|
||||
protected abstract boolean hide(@NotNull final Player player);
|
||||
|
||||
protected abstract void refresh(@NotNull final Player player);
|
||||
|
||||
/**
|
||||
* Create the hologram entity.
|
||||
* Only run this if creating custom Hologram implementations as this is run in
|
||||
* {@link de.oliver.fancyholograms.api.HologramManager#create(HologramData)}.
|
||||
*/
|
||||
public final void createHologram() {
|
||||
create();
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes the hologram entity.
|
||||
*/
|
||||
public final void deleteHologram() {
|
||||
delete();
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows the hologram to a collection of players.
|
||||
* Use {@link #forceShowHologram(Player)} if this hologram is not registered to the HologramManager.
|
||||
*
|
||||
* @param players The players to show the hologram to
|
||||
*/
|
||||
public final void showHologram(Collection<? extends Player> players) {
|
||||
players.forEach(this::showHologram);
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows the hologram to a player.
|
||||
* Use {@link #forceShowHologram(Player)} if this hologram is not registered to the HologramManager.
|
||||
*
|
||||
* @param player The player to show the hologram to
|
||||
*/
|
||||
public final void showHologram(Player player) {
|
||||
viewers.add(player.getUniqueId());
|
||||
}
|
||||
|
||||
/**
|
||||
* Forcefully shows the hologram to a player.
|
||||
*
|
||||
* @param player The player to show the hologram to
|
||||
*/
|
||||
public final void forceShowHologram(Player player) {
|
||||
show(player);
|
||||
|
||||
if (this.getData().getVisibility().equals(Visibility.MANUAL)) {
|
||||
Visibility.ManualVisibility.addDistantViewer(this, player.getUniqueId());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Hides the hologram from a collection of players.
|
||||
* Use {@link #forceHideHologram(Player)} if this hologram is not registered to the HologramManager.
|
||||
*
|
||||
* @param players The players to hide the hologram from
|
||||
*/
|
||||
public final void hideHologram(Collection<? extends Player> players) {
|
||||
players.forEach(this::hideHologram);
|
||||
}
|
||||
|
||||
/**
|
||||
* Hides the hologram from a player.
|
||||
* Use {@link #forceHideHologram(Player)} if this hologram is not registered to the HologramManager.
|
||||
*
|
||||
* @param player The player to hide the hologram from
|
||||
*/
|
||||
public final void hideHologram(Player player) {
|
||||
viewers.remove(player.getUniqueId());
|
||||
}
|
||||
|
||||
/**
|
||||
* Forcefully hides the hologram from a player.
|
||||
*
|
||||
* @param player The player to show the hologram to
|
||||
*/
|
||||
public final void forceHideHologram(Player player) {
|
||||
hide(player);
|
||||
|
||||
if (this.getData().getVisibility().equals(Visibility.MANUAL)) {
|
||||
Visibility.ManualVisibility.removeDistantViewer(this, player.getUniqueId());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Queues hologram to update and refresh for players.
|
||||
*
|
||||
* @deprecated in favour of {@link #queueUpdate()}
|
||||
*/
|
||||
@Deprecated(forRemoval = true)
|
||||
public final void updateHologram() {
|
||||
queueUpdate();
|
||||
}
|
||||
|
||||
/**
|
||||
* Queues hologram to update and refresh for players
|
||||
* Use {@link #forceUpdate()} if this hologram is not registered to the HologramManager.
|
||||
*/
|
||||
public final void queueUpdate() {
|
||||
data.setHasChanges(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Forcefully updates and refreshes hologram for players.
|
||||
*/
|
||||
public final void forceUpdate() {
|
||||
update();
|
||||
}
|
||||
|
||||
/**
|
||||
* Refreshes the hologram for the players currently viewing it.
|
||||
*/
|
||||
public void refreshForViewers() {
|
||||
final var players = getViewers()
|
||||
.stream()
|
||||
.map(Bukkit::getPlayer)
|
||||
.toList();
|
||||
|
||||
refreshHologram(players);
|
||||
}
|
||||
|
||||
/**
|
||||
* Refreshes the hologram for players currently viewing it in the same world as the hologram.
|
||||
*/
|
||||
public void refreshForViewersInWorld() {
|
||||
World world = data.getLocation().getWorld();
|
||||
final var players = getViewers()
|
||||
.stream()
|
||||
.map(Bukkit::getPlayer)
|
||||
.filter(player -> player != null && player.getWorld().equals(world))
|
||||
.toList();
|
||||
|
||||
refreshHologram(players);
|
||||
}
|
||||
|
||||
/**
|
||||
* Refreshes the hologram's data for a player.
|
||||
*
|
||||
* @param player the player to refresh for
|
||||
*/
|
||||
public final void refreshHologram(@NotNull final Player player) {
|
||||
refresh(player);
|
||||
}
|
||||
|
||||
/**
|
||||
* Refreshes the hologram's data for a collection of players.
|
||||
*
|
||||
* @param players the collection of players to refresh for
|
||||
*/
|
||||
public final void refreshHologram(@NotNull final Collection<? extends Player> players) {
|
||||
players.forEach(this::refreshHologram);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return a copy of the set of UUIDs of players currently viewing the hologram
|
||||
*/
|
||||
public final @NotNull Set<UUID> getViewers() {
|
||||
return new HashSet<>(this.viewers);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param player the player to check for
|
||||
* @return whether the player is currently viewing the hologram
|
||||
*/
|
||||
public final boolean isViewer(@NotNull final Player player) {
|
||||
return isViewer(player.getUniqueId());
|
||||
}
|
||||
|
||||
/**
|
||||
* @param player the uuid of the player to check for
|
||||
* @return whether the player is currently viewing the hologram
|
||||
*/
|
||||
public final boolean isViewer(@NotNull final UUID player) {
|
||||
return this.viewers.contains(player);
|
||||
}
|
||||
|
||||
protected boolean shouldShowTo(@NotNull final Player player) {
|
||||
if (!meetsVisibilityConditions(player)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return isWithinVisibilityDistance(player);
|
||||
}
|
||||
|
||||
public boolean meetsVisibilityConditions(@NotNull final Player player) {
|
||||
return this.getData().getVisibility().canSee(player, this);
|
||||
}
|
||||
|
||||
public boolean isWithinVisibilityDistance(@NotNull final Player player) {
|
||||
final var location = getData().getLocation();
|
||||
if (!location.getWorld().equals(player.getWorld())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int visibilityDistance = data.getVisibilityDistance();
|
||||
double distanceSquared = location.distanceSquared(player.getLocation());
|
||||
|
||||
return distanceSquared <= visibilityDistance * visibilityDistance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks and updates the shown state for a player.
|
||||
* If the hologram is shown and should not be, it hides it.
|
||||
* If the hologram is not shown and should be, it shows it.
|
||||
* Use {@link #forceUpdateShownStateFor(Player)} if this hologram is not registered to the HologramManager.
|
||||
*
|
||||
* @param player the player to check and update the shown state for
|
||||
*/
|
||||
public void updateShownStateFor(Player player) {
|
||||
boolean isShown = isViewer(player);
|
||||
boolean shouldBeShown = shouldShowTo(player);
|
||||
|
||||
if (isShown && !shouldBeShown) {
|
||||
showHologram(player);
|
||||
} else if (!isShown && shouldBeShown) {
|
||||
hideHologram(player);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks and forcefully updates the shown state for a player.
|
||||
* If the hologram is shown and should not be, it hides it.
|
||||
* If the hologram is not shown and should be, it shows it.
|
||||
*
|
||||
* @param player the player to check and update the shown state for
|
||||
*/
|
||||
public void forceUpdateShownStateFor(Player player) {
|
||||
boolean isShown = isViewer(player);
|
||||
|
||||
if (meetsVisibilityConditions(player)) {
|
||||
if (isWithinVisibilityDistance(player)) {
|
||||
// Ran if the player meets the visibility conditions and is within visibility distance
|
||||
if (!isShown) {
|
||||
show(player);
|
||||
|
||||
if (getData().getVisibility().equals(Visibility.MANUAL)) {
|
||||
Visibility.ManualVisibility.removeDistantViewer(this, player.getUniqueId());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Ran if the player meets the visibility conditions but is not within visibility distance
|
||||
if (isShown) {
|
||||
hide(player);
|
||||
|
||||
if (getData().getVisibility().equals(Visibility.MANUAL)) {
|
||||
Visibility.ManualVisibility.addDistantViewer(this, player.getUniqueId());
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Ran if the player does not meet visibility conditions
|
||||
if (isShown) {
|
||||
hide(player);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the text shown in the hologram. If a player is specified, placeholders in the text are replaced
|
||||
* with their corresponding values for the player.
|
||||
*
|
||||
* @param player the player to get the placeholders for, or null if no placeholders should be replaced
|
||||
* @return the text shown in the hologram
|
||||
*/
|
||||
public final Component getShownText(@Nullable final Player player) {
|
||||
if (!(getData() instanceof TextHologramData textData)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
var text = String.join("\n", textData.getText());
|
||||
|
||||
return ModernChatColorHandler.translate(text, player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean equals(@Nullable final Object o) {
|
||||
if (this == o) return true;
|
||||
if (!(o instanceof Hologram that)) return false;
|
||||
|
||||
return Objects.equals(this.getData(), that.getData());
|
||||
}
|
||||
|
||||
@Override
|
||||
public final int hashCode() {
|
||||
return Objects.hash(this.getData());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package de.oliver.fancyholograms.api.hologram;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
public enum HologramType {
|
||||
TEXT(Arrays.asList("background", "textshadow", "textalignment", "seethrough", "setline", "removeline", "addline", "insertbefore", "insertafter", "updatetextinterval")),
|
||||
ITEM(List.of("item")),
|
||||
BLOCK(List.of("block"));
|
||||
|
||||
private final List<String> commands;
|
||||
|
||||
HologramType(List<String> commands) {
|
||||
this.commands = commands;
|
||||
}
|
||||
|
||||
public static HologramType getByName(String name) {
|
||||
for (HologramType type : values()) {
|
||||
if (type.name().equalsIgnoreCase(name)) {
|
||||
return type;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public List<String> getCommands() {
|
||||
return commands;
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user