diff --git a/api/pom.xml b/api/pom.xml
index 0010a501..c9d258ff 100644
--- a/api/pom.xml
+++ b/api/pom.xml
@@ -6,7 +6,7 @@
net.donnypz.displayentityutils
deu
- 3.8.0
+ 3.8.1
api
diff --git a/api/src/main/java/net/donnypz/displayentityutils/database/DisplayStorage.java b/api/src/main/java/net/donnypz/displayentityutils/database/DisplayStorage.java
index 20870750..b544a3a5 100644
--- a/api/src/main/java/net/donnypz/displayentityutils/database/DisplayStorage.java
+++ b/api/src/main/java/net/donnypz/displayentityutils/database/DisplayStorage.java
@@ -2,33 +2,40 @@
import net.donnypz.displayentityutils.utils.DisplayEntities.DisplayAnimation;
import net.donnypz.displayentityutils.utils.DisplayEntities.DisplayEntityGroup;
+import net.kyori.adventure.text.logger.slf4j.ComponentLogger;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.List;
-public interface DisplayStorage {
+public abstract class DisplayStorage {
- boolean isEnabled();
+ protected final ComponentLogger logger;
- boolean saveDisplayEntityGroup(@NotNull DisplayEntityGroup group, @Nullable Player saver);
+ public DisplayStorage(ComponentLogger logger) {
+ this.logger = logger;
+ }
- void deleteDisplayEntityGroup(@NotNull String group, @Nullable Player deleter);
+ public abstract boolean isEnabled();
- @Nullable DisplayEntityGroup getDisplayEntityGroup(@NotNull String tag);
+ public abstract boolean saveDisplayEntityGroup(@NotNull DisplayEntityGroup group, @Nullable Player saver);
- boolean saveDisplayAnimation(@NotNull DisplayAnimation animation, @Nullable Player saver);
+ public abstract void deleteDisplayEntityGroup(@NotNull String group, @Nullable Player deleter);
- void deleteDisplayAnimation(@NotNull String tag, @Nullable Player deleter);
+ public @Nullable abstract DisplayEntityGroup getDisplayEntityGroup(@NotNull String tag);
- @Nullable DisplayAnimation getDisplayAnimation(@NotNull String tag);
+ public abstract boolean saveDisplayAnimation(@NotNull DisplayAnimation animation, @Nullable Player saver);
- @NotNull List getGroupTags();
+ public abstract void deleteDisplayAnimation(@NotNull String tag, @Nullable Player deleter);
- @NotNull List getGroupTags(int page, int size);
+ public @Nullable abstract DisplayAnimation getDisplayAnimation(@NotNull String tag);
- @NotNull List getAnimationTags();
+ public @NotNull abstract List getGroupTags();
- @NotNull List getAnimationTags(int page, int size);
+ public @NotNull abstract List getGroupTags(int page, int size);
+
+ public @NotNull abstract List getAnimationTags();
+
+ public @NotNull abstract List getAnimationTags(int page, int size);
}
diff --git a/api/src/main/java/net/donnypz/displayentityutils/utils/version/VersionUtils.java b/api/src/main/java/net/donnypz/displayentityutils/utils/version/VersionUtils.java
index 97ae846a..f98bbb9f 100644
--- a/api/src/main/java/net/donnypz/displayentityutils/utils/version/VersionUtils.java
+++ b/api/src/main/java/net/donnypz/displayentityutils/utils/version/VersionUtils.java
@@ -26,13 +26,10 @@ public final class VersionUtils {
public static final boolean IS_26_1 = Bukkit.getUnsafe().getProtocolVersion() >= 775;
public static final boolean IS_26_2 = Bukkit.getUnsafe().getProtocolVersion() >= 776;
- public static final boolean IS_DEV_VERSION;
private static Particle ENTITY_EFFECT_PARTICLE;
private static Particle ITEM_PARTICLE;
static{
- String pluginVer = DisplayAPI.getPlugin().getPluginMeta().getVersion();
- IS_DEV_VERSION = isDevVersion(pluginVer);
setParticles();
}
@@ -47,23 +44,32 @@ private VersionUtils(){}
}
public static boolean isDevVersion(){
- return IS_DEV_VERSION;
+ return isDevVersion(DisplayAPI.getPlugin().getPluginMeta().getVersion());
}
@ApiStatus.Internal
- public static boolean isDevVersion(@NotNull String version){
+ static boolean isDevVersion(@NotNull String version){
String clean = cleanVersionString(version);
return !version.equals(clean);
}
@ApiStatus.Internal
public static @NotNull String cleanVersionString(@NotNull String version){
- return version.replaceAll("[^0-9.]", "");
+ String[] versionNumbers = version.split("\\.");
+
+ return versionNumbers[0] +
+ "." +
+ versionNumbers[1] +
+ "." +
+ versionNumbers[2].split("-")[0];
}
public static boolean isCurrentOlderThan(@NotNull String comparedVersion){
- String current = getPluginVersion();
- String cleanCurrent = VersionUtils.cleanVersionString(current);
+ return isOlderThan(getPluginVersion(), comparedVersion);
+ }
+
+ static boolean isOlderThan(@NotNull String version,@NotNull String comparedVersion){
+ String cleanCurrent = VersionUtils.cleanVersionString(version);
String cleanComparedVersion = VersionUtils.cleanVersionString(comparedVersion);
String[] currentArr = cleanCurrent.split("\\.");
diff --git a/api/src/test/java/net/donnypz/displayentityutils/utils/controller/DisplayControllerTests.java b/api/src/test/java/net/donnypz/displayentityutils/utils/controller/DisplayControllerTests.java
index 0b68f785..1cc5b3d2 100644
--- a/api/src/test/java/net/donnypz/displayentityutils/utils/controller/DisplayControllerTests.java
+++ b/api/src/test/java/net/donnypz/displayentityutils/utils/controller/DisplayControllerTests.java
@@ -51,9 +51,10 @@ void testInvalidConfigs(String configName) {
private DisplayController testConfig(String configName, String packageName){
DisplayController controller;
- try (InputStream stream = getClass().getResourceAsStream("/test/controllers/"+packageName+"/" + configName + ".yml")) {
- InputStreamReader reader = new InputStreamReader(stream);
-
+ try (
+ InputStream stream = getClass().getResourceAsStream("/test/controllers/"+packageName+"/" + configName + ".yml");
+ InputStreamReader reader = new InputStreamReader(stream))
+ {
YamlConfiguration config = YamlConfiguration.loadConfiguration(reader);
controller = DisplayControllerReader.read(
config,
@@ -62,7 +63,7 @@ private DisplayController testConfig(String configName, String packageName){
logger,
false
);
- } catch (IOException e) {
+ } catch (IOException | NullPointerException e) {
throw new RuntimeException(e);
}
diff --git a/api/src/test/java/net/donnypz/displayentityutils/utils/version/VersionTests.java b/api/src/test/java/net/donnypz/displayentityutils/utils/version/VersionTests.java
new file mode 100644
index 00000000..ac6e5ca3
--- /dev/null
+++ b/api/src/test/java/net/donnypz/displayentityutils/utils/version/VersionTests.java
@@ -0,0 +1,95 @@
+package net.donnypz.displayentityutils.utils.version;
+
+import org.bukkit.Bukkit;
+import org.bukkit.UnsafeValues;
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.ValueSource;
+import org.mockito.MockedStatic;
+import org.mockito.Mockito;
+import org.mockito.junit.jupiter.MockitoExtension;
+import org.yaml.snakeyaml.Yaml;
+
+import java.io.InputStream;
+import java.util.Map;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+@ExtendWith(MockitoExtension.class)
+public class VersionTests {
+
+ private static MockedStatic bukkitMock;
+
+ @BeforeAll
+ static void mockBukkit(){
+ bukkitMock = Mockito.mockStatic(Bukkit.class);
+ UnsafeValues unsafeValues = Mockito.mock(UnsafeValues.class);
+
+ bukkitMock.when(Bukkit::getUnsafe).thenReturn(unsafeValues);
+ Mockito.when(unsafeValues.getProtocolVersion()).thenReturn(Integer.MAX_VALUE);
+ }
+
+ @AfterAll
+ static void closeBukkitMock(){
+ bukkitMock.close();
+ }
+
+
+ @ParameterizedTest
+ @ValueSource(strings = {
+ "2.3.2-ex-39a286e|2.3.2",
+ "3.1.0-main|3.1.0",
+ "3.5.0-PRE|3.5.0",
+ "3.6.1-develop|3.6.1",
+ "3.7.0-dev|3.7.0",
+ "3.8.0-dev-1da350c|3.8.0",
+ })
+ void shouldCleanVersionString(String version) {
+ String[] split = version.split("\\|");
+ String dirtyVersion = split[0];
+ String cleanVersion = split[1];
+
+ String cleaned = VersionUtils.cleanVersionString(dirtyVersion);
+
+ assertEquals(cleaned, cleanVersion);
+ }
+
+
+ @ParameterizedTest
+ @ValueSource(strings = {
+ "2.3.2-ex-39a286e",
+ "3.1.0-main",
+ "3.5.3-develop",
+ "3.5.0-PRE",
+ "3.7.0-dev",
+ })
+ void shouldBeDevVersion(String version) {
+ boolean isDevVersion = VersionUtils.isDevVersion(version);
+ assertTrue(isDevVersion, "Version is not a develop version: " + version);
+ }
+
+ @ParameterizedTest
+ @ValueSource(strings = {
+ "3.7.0",
+ "3.6.0",
+ "3.5.5",
+ "3.5.1",
+ "3.6.0",
+ })
+ void currentVersionShouldBeNewer(String comparedVersion) {
+ Yaml yaml = new Yaml();
+
+ try (InputStream inputStream = getClass().getResourceAsStream("/plugin.yml")) {
+ Map config = yaml.load(inputStream);
+ String currentVersion = (String) config.get("version");
+
+ boolean isNewer = VersionUtils.isOlderThan(comparedVersion, currentVersion);
+
+ assertTrue(isNewer, "Current version (" + currentVersion + ") should be newer than compared version: " + comparedVersion);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+}
diff --git a/docs/release-notes/3.8.1.md b/docs/release-notes/3.8.1.md
new file mode 100644
index 00000000..2a1f2a04
--- /dev/null
+++ b/docs/release-notes/3.8.1.md
@@ -0,0 +1,19 @@
+**Release Highlights**
+- Breaking API Changes 🔨
+- Bug Fixes 🐛
+
+## API Changes
+> [!NOTE]
+>**New Version:** `3.8.1`
+
+### Breaking Changes
+- Removed `IS_DEV_VERSION` field from `VersionUtils`
+- Changed `DisplayStorage` and `DBDisplayStorage` to abstract classes to accept Logger in constructor
+ - May require recompilation of plugins depending on `DisplayEntityUtils`
+
+
+## Bug Fixes / QOL
+- Corrected logic for `VersionUtils#cleanVersionString`
+- Fixed an `NPE` that occurred when trying to message a player after deleting groups/animations
+- Fixed deleting groups/animations not working as intended when using `MySQL` storage
+- Fixed saving/deleting animations not working as intended when using `MongoDB` storage
diff --git a/plugin/pom.xml b/plugin/pom.xml
index 83853a76..14c01c35 100644
--- a/plugin/pom.xml
+++ b/plugin/pom.xml
@@ -6,7 +6,7 @@
net.donnypz.displayentityutils
deu
- 3.8.0
+ 3.8.1
plugin
@@ -26,6 +26,7 @@
deg
+ deanim
@@ -150,6 +151,29 @@
2.12.2
provided
+
+
+
+ org.testcontainers
+ mysql
+ 1.21.4
+ test
+
+
+
+ com.mysql
+ mysql-connector-j
+ 8.3.0
+ test
+
+
+
+
+ org.testcontainers
+ mongodb
+ 1.21.4
+ test
+
diff --git a/plugin/src/main/java/net/donnypz/displayentityutils/DisplayAPIInitializer.java b/plugin/src/main/java/net/donnypz/displayentityutils/DisplayAPIInitializer.java
new file mode 100644
index 00000000..3620f377
--- /dev/null
+++ b/plugin/src/main/java/net/donnypz/displayentityutils/DisplayAPIInitializer.java
@@ -0,0 +1,125 @@
+package net.donnypz.displayentityutils;
+
+import ch.njol.skript.Skript;
+import ch.njol.skript.util.Version;
+import net.donnypz.displayentityutils.database.DisplayStorage;
+import net.donnypz.displayentityutils.database.LocalDisplayStorage;
+import net.donnypz.displayentityutils.database.MYSQLDisplayStorage;
+import net.donnypz.displayentityutils.database.MongoDisplayStorage;
+import net.donnypz.displayentityutils.listeners.entity.mythic.DEUMythicListener;
+import net.donnypz.displayentityutils.listeners.player.essentials.DEUEssentialsListener;
+import net.donnypz.displayentityutils.managers.LoadMethod;
+import net.donnypz.displayentityutils.skript.SkriptTypes;
+import net.donnypz.displayentityutils.skript.active.ActiveModule;
+import net.donnypz.displayentityutils.skript.animation.AnimatorModule;
+import net.donnypz.displayentityutils.skript.events.SimpleEvents;
+import net.donnypz.displayentityutils.skript.framepoints.FramePointsModule;
+import net.donnypz.displayentityutils.skript.group.activegroup.ActiveGroupModule;
+import net.donnypz.displayentityutils.skript.group.packetgroup.PacketGroupModule;
+import net.donnypz.displayentityutils.skript.group.spawnedgroup.SpawnedGroupModule;
+import net.donnypz.displayentityutils.skript.io.IOModule;
+import net.donnypz.displayentityutils.skript.misc.MiscModule;
+import net.donnypz.displayentityutils.skript.partfilter.PartFilterModule;
+import net.donnypz.displayentityutils.skript.parts.PartsModule;
+import net.donnypz.displayentityutils.skript.player.PlayerModule;
+import net.donnypz.displayentityutils.utils.DisplayEntities.AnimationPlayerProviderImpl;
+import net.donnypz.displayentityutils.utils.bdengine.convert.common.BDEConversionHandlerImpl;
+import net.donnypz.displayentityutils.utils.version.VersionUtils;
+import net.donnypz.displayentityutils.utils.version.folia.SchedulerImpl;
+import net.kyori.adventure.text.Component;
+import net.kyori.adventure.text.format.NamedTextColor;
+import net.kyori.adventure.text.logger.slf4j.ComponentLogger;
+import org.bstats.bukkit.Metrics;
+import org.bukkit.Bukkit;
+
+import java.util.Map;
+
+public final class DisplayAPIInitializer {
+
+ private DisplayAPIInitializer() {
+ }
+
+ public static void initializeImpls(ComponentLogger logger) {
+ DisplayAPI.ANIMATION_PLAYER_SERVICE = new AnimationPlayerProviderImpl();
+ DisplayAPI.BDE_CONVERSION_HANDLER = new BDEConversionHandlerImpl();
+ DisplayAPI.SCHEDULER = new SchedulerImpl();
+
+ // Storage providers
+ Map storages = DisplayAPI.storages;
+
+ storages.put(LoadMethod.LOCAL, new LocalDisplayStorage(logger));
+ storages.put(LoadMethod.MONGODB, new MongoDisplayStorage(logger));
+ storages.put(LoadMethod.MYSQL, new MYSQLDisplayStorage(logger));
+ }
+
+ static void initializeDependencies(DisplayEntityPlugin plugin) {
+ DisplayAPI.isMythicMobsInstalled = Bukkit.getPluginManager().isPluginEnabled("MythicMobs");
+ if (DisplayAPI.isMythicMobsInstalled) {
+ Bukkit.getPluginManager().registerEvents(new DEUMythicListener(), plugin);
+ }
+
+ DisplayAPI.isLibsDisguisesInstalled = Bukkit.getPluginManager().isPluginEnabled("LibsDisguises");
+ DisplayAPI.isViaVerInstalled = Bukkit.getPluginManager().isPluginEnabled("ViaVersion");
+ DisplayAPI.isWorldEditInstalled = Bukkit.getPluginManager().isPluginEnabled("WorldEdit");
+ DisplayAPI.isPAPIInstalled = Bukkit.getPluginManager().isPluginEnabled("PlaceholderAPI");
+ DisplayAPI.isEssentialsInstalled = Bukkit.getPluginManager().isPluginEnabled("Essentials");
+ if (DisplayAPI.isEssentialsInstalled) {
+ Bukkit.getPluginManager().registerEvents(new DEUEssentialsListener(), plugin);
+ }
+
+ //Skript
+ DisplayAPI.isSkriptInstalled = Bukkit.getPluginManager().isPluginEnabled("Skript");
+ if (DisplayAPI.isSkriptInstalled) registerSkript(plugin);
+
+ //bStats
+ boolean isDevVersion = VersionUtils.isDevVersion();
+ if (!isDevVersion){
+ initializeBStats(plugin);
+ }
+ else{
+ plugin.getLogger().warning("bStats disabled on server using dev version.");
+ }
+ }
+
+ private static void initializeBStats(DisplayEntityPlugin plugin) {
+ int pluginID = 24875;
+ new Metrics(plugin, pluginID);
+ }
+
+ private static void registerSkript(DisplayEntityPlugin plugin) {
+ if (Skript.getVersion().isSmallerThan(new Version(2, 14, 0))) {
+ plugin
+ .getComponentLogger()
+ .info(
+ DisplayAPI.pluginPrefix
+ .append(Component.text("Skript Version below 2.10.0 Detected! Skript Syntax Disabled!", NamedTextColor.RED))
+ );
+ DisplayAPI.isSkriptInstalled = false;
+ } else {
+ plugin.addon = Skript.instance().registerAddon(DisplayEntityPlugin.class, "DisplayEntityUtils");
+ plugin.addon.loadModules(
+ new ActiveModule(),
+ new AnimatorModule(),
+ new FramePointsModule(),
+ new ActiveGroupModule(),
+ new PacketGroupModule(),
+ new SpawnedGroupModule(),
+ new IOModule(),
+ new MiscModule(),
+ new PartFilterModule(),
+ new PartsModule(),
+ new PlayerModule()
+ );
+ plugin.addon.localizer().setSourceDirectories("lang", null);
+ SimpleEvents.register();
+ new SkriptTypes();
+ plugin
+ .getComponentLogger()
+ .info(
+ DisplayAPI.pluginPrefix
+ .append(Component.text("Skript Syntax Enabled!", NamedTextColor.GREEN))
+ );
+ }
+ }
+
+}
diff --git a/plugin/src/main/java/net/donnypz/displayentityutils/DisplayEntityPlugin.java b/plugin/src/main/java/net/donnypz/displayentityutils/DisplayEntityPlugin.java
index 7086cc09..c7f79f73 100644
--- a/plugin/src/main/java/net/donnypz/displayentityutils/DisplayEntityPlugin.java
+++ b/plugin/src/main/java/net/donnypz/displayentityutils/DisplayEntityPlugin.java
@@ -1,7 +1,5 @@
package net.donnypz.displayentityutils;
-import ch.njol.skript.Skript;
-import ch.njol.skript.util.Version;
import com.github.retrooper.packetevents.PacketEvents;
import com.github.retrooper.packetevents.event.PacketListenerPriority;
import net.donnypz.displayentityutils.command.DisplayEntityPluginCommand;
@@ -12,35 +10,14 @@
import net.donnypz.displayentityutils.listeners.entity.DEUEntityListener;
import net.donnypz.displayentityutils.listeners.entity.DEUInteractionListener;
import net.donnypz.displayentityutils.listeners.entity.DEUMannequinEditorListener;
-import net.donnypz.displayentityutils.listeners.entity.mythic.DEUMythicListener;
import net.donnypz.displayentityutils.listeners.gizmo.DEUGizmoListener;
import net.donnypz.displayentityutils.listeners.player.*;
-import net.donnypz.displayentityutils.listeners.player.essentials.DEUEssentialsListener;
-import net.donnypz.displayentityutils.managers.LoadMethod;
import net.donnypz.displayentityutils.managers.PluginFolders;
-import net.donnypz.displayentityutils.skript.SkriptTypes;
-import net.donnypz.displayentityutils.skript.active.ActiveModule;
-import net.donnypz.displayentityutils.skript.animation.AnimatorModule;
-import net.donnypz.displayentityutils.skript.framepoints.FramePointsModule;
-import net.donnypz.displayentityutils.skript.events.SimpleEvents;
-import net.donnypz.displayentityutils.skript.group.packetgroup.PacketGroupModule;
-import net.donnypz.displayentityutils.skript.misc.MiscModule;
-import net.donnypz.displayentityutils.skript.group.activegroup.ActiveGroupModule;
-import net.donnypz.displayentityutils.skript.group.spawnedgroup.SpawnedGroupModule;
-import net.donnypz.displayentityutils.skript.io.IOModule;
-import net.donnypz.displayentityutils.skript.parts.PartsModule;
-import net.donnypz.displayentityutils.skript.partfilter.PartFilterModule;
-import net.donnypz.displayentityutils.skript.player.PlayerModule;
-import net.donnypz.displayentityutils.utils.DisplayEntities.AnimationPlayerProviderImpl;
import net.donnypz.displayentityutils.utils.DisplayEntities.SpawnedDisplayEntityGroup;
import net.donnypz.displayentityutils.utils.DisplayEntities.machine.MachineState;
-import net.donnypz.displayentityutils.utils.bdengine.convert.common.BDEConversionHandlerImpl;
import net.donnypz.displayentityutils.utils.controller.DisplayControllerUtils;
-import net.donnypz.displayentityutils.utils.version.VersionUtils;
-import net.donnypz.displayentityutils.utils.version.folia.SchedulerImpl;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.NamedTextColor;
-import org.bstats.bukkit.Metrics;
import org.bukkit.Bukkit;
import org.bukkit.command.PluginCommand;
import org.bukkit.event.EventHandler;
@@ -51,8 +28,6 @@
import org.jetbrains.annotations.ApiStatus;
import org.skriptlang.skript.addon.SkriptAddon;
-import java.util.Map;
-
public final class DisplayEntityPlugin extends JavaPlugin implements Listener {
SkriptAddon addon;
@@ -69,30 +44,15 @@ public void onLoad() {
@Override
public void onEnable() {
DisplayAPI.plugin = this;
- Map storages = DisplayAPI.storages;
- storages.put(LoadMethod.LOCAL, new LocalDisplayStorage());
- storages.put(LoadMethod.MONGODB, new MongoDisplayStorage());
- storages.put(LoadMethod.MYSQL, new MYSQLDisplayStorage());
-
- DisplayAPI.ANIMATION_PLAYER_SERVICE = new AnimationPlayerProviderImpl();
- DisplayAPI.BDE_CONVERSION_HANDLER = new BDEConversionHandlerImpl();
- DisplayAPI.SCHEDULER = new SchedulerImpl();
+ DisplayAPIInitializer.initializeImpls(this.getComponentLogger());
getConfig().options().copyDefaults(true);
reloadPlugin(true);
ConfigUtils.registerDisplayControllers();
- initializeDependencies();
+ DisplayAPIInitializer.initializeDependencies(this);
registerListeners();
checkFolia();
- boolean isDevVersion = VersionUtils.isDevVersion();
- if (!isDevVersion){
- initializeBStats();
- }
- else{
- getComponentLogger().warn(Component.text("bStats disabled on server using dev version."));
- }
-
Permission.registerPermissions();
getServer().getConsoleSender().sendMessage(DisplayAPI.pluginPrefix.append(Component.text("Plugin Enabled!", NamedTextColor.GREEN)));
}
@@ -115,54 +75,6 @@ void checkFolia(){
}
}
- private void initializeDependencies(){
- //MythicMobs
- DisplayAPI.isMythicMobsInstalled = Bukkit.getPluginManager().isPluginEnabled("MythicMobs");
- if (DisplayAPI.isMythicMobsInstalled){
- Bukkit.getPluginManager().registerEvents(new DEUMythicListener(), this);
- }
-
- DisplayAPI.isLibsDisguisesInstalled = Bukkit.getPluginManager().isPluginEnabled("LibsDisguises");
- DisplayAPI.isViaVerInstalled = Bukkit.getPluginManager().isPluginEnabled("ViaVersion");
- DisplayAPI.isWorldEditInstalled = Bukkit.getPluginManager().isPluginEnabled("WorldEdit");
- DisplayAPI.isPAPIInstalled = Bukkit.getPluginManager().isPluginEnabled("PlaceholderAPI");
- DisplayAPI.isEssentialsInstalled = Bukkit.getPluginManager().isPluginEnabled("Essentials");
- if (DisplayAPI.isEssentialsInstalled){
- Bukkit.getPluginManager().registerEvents(new DEUEssentialsListener(), this);
- }
-
- //Skript
- DisplayAPI.isSkriptInstalled = Bukkit.getPluginManager().isPluginEnabled("Skript");
- if (DisplayAPI.isSkriptInstalled) registerSkript();
- }
-
- private void registerSkript(){
- if (Skript.getVersion().isSmallerThan(new Version(2,14,0))){
- getServer().getConsoleSender().sendMessage(DisplayAPI.pluginPrefix.append(Component.text("Skript Version below 2.10.0 Detected! Skript Syntax Disabled!", NamedTextColor.RED)));
- DisplayAPI.isSkriptInstalled = false;
- }
- else{
- addon = Skript.instance().registerAddon(DisplayEntityPlugin.class, "DisplayEntityUtils");
- addon.loadModules(
- new ActiveModule(),
- new AnimatorModule(),
- new FramePointsModule(),
- new ActiveGroupModule(),
- new PacketGroupModule(),
- new SpawnedGroupModule(),
- new IOModule(),
- new MiscModule(),
- new PartFilterModule(),
- new PartsModule(),
- new PlayerModule()
- );
- addon.localizer().setSourceDirectories("lang", null);
- SimpleEvents.register();
- new SkriptTypes();
- getServer().getConsoleSender().sendMessage(DisplayAPI.pluginPrefix.append(Component.text("Skript Syntax Enabled!", NamedTextColor.GREEN)));
- }
- }
-
private void registerListeners(){
Bukkit.getPluginManager().registerEvents(this, this);
Bukkit.getPluginManager().registerEvents(new DEULoadingListeners(), this);
@@ -179,11 +91,6 @@ private void registerListeners(){
Bukkit.getPluginManager().registerEvents(new DEUMannequinEditorListener(), this);
}
- private void initializeBStats(){
- int pluginID = 24875;
- new Metrics(this, pluginID);
- }
-
/**
* Determines whether {@link SpawnedDisplayEntityGroup}s should be unregistered in a world based
diff --git a/plugin/src/main/java/net/donnypz/displayentityutils/database/DBDisplayStorage.java b/plugin/src/main/java/net/donnypz/displayentityutils/database/DBDisplayStorage.java
index 635eba9b..be85ee60 100644
--- a/plugin/src/main/java/net/donnypz/displayentityutils/database/DBDisplayStorage.java
+++ b/plugin/src/main/java/net/donnypz/displayentityutils/database/DBDisplayStorage.java
@@ -1,15 +1,21 @@
package net.donnypz.displayentityutils.database;
-public interface DBDisplayStorage extends DisplayStorage {
+import net.kyori.adventure.text.logger.slf4j.ComponentLogger;
+
+public abstract class DBDisplayStorage extends DisplayStorage {
+
+ public DBDisplayStorage(ComponentLogger logger) {
+ super(logger);
+ }
/**
* Check if this Database store is connected
* @return a boolean
*/
- boolean isConnected();
+ public abstract boolean isConnected();
/**
* Close this active database connection
*/
- void closeConnection();
+ public abstract void closeConnection();
}
diff --git a/plugin/src/main/java/net/donnypz/displayentityutils/database/LocalDisplayStorage.java b/plugin/src/main/java/net/donnypz/displayentityutils/database/LocalDisplayStorage.java
index caa21dea..51993e3a 100644
--- a/plugin/src/main/java/net/donnypz/displayentityutils/database/LocalDisplayStorage.java
+++ b/plugin/src/main/java/net/donnypz/displayentityutils/database/LocalDisplayStorage.java
@@ -10,6 +10,7 @@
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.NamedTextColor;
import net.kyori.adventure.text.format.TextDecoration;
+import net.kyori.adventure.text.logger.slf4j.ComponentLogger;
import net.kyori.adventure.text.minimessage.MiniMessage;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
@@ -21,9 +22,12 @@
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
-import java.util.zip.GZIPOutputStream;
-public final class LocalDisplayStorage implements DisplayStorage {
+public final class LocalDisplayStorage extends DisplayStorage {
+
+ public LocalDisplayStorage(ComponentLogger logger) {
+ super(logger);
+ }
@Override
public boolean isEnabled() {
@@ -33,15 +37,7 @@ public boolean isEnabled() {
@Override
public boolean saveDisplayEntityGroup(@NotNull DisplayEntityGroup displayEntityGroup, @Nullable Player saver){
try{
- ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
- GZIPOutputStream gzipOut = new GZIPOutputStream(byteOut);
- ObjectOutputStream objOut = new ObjectOutputStream(gzipOut);
- objOut.writeObject(displayEntityGroup);
-
- gzipOut.close();
- objOut.close();
-
- byte[] data = byteOut.toByteArray();
+ byte[] data = CommonDisplayStorageUtils.toByteArray(displayEntityGroup);
File saveFile = new File(PluginFolders.groupSaveFolder, "/"+displayEntityGroup.getTag()+DisplayEntityGroup.FILE_EXTENSION);
if (saveFile.exists()){
@@ -54,6 +50,7 @@ public boolean saveDisplayEntityGroup(@NotNull DisplayEntityGroup displayEntityG
}
saveFile.delete();
}
+
saveFile.createNewFile();
FileOutputStream fileOut = new FileOutputStream(saveFile);
fileOut.write(data);
@@ -99,15 +96,7 @@ public void deleteDisplayEntityGroup(@NotNull String tag, @Nullable Player delet
@Override
public boolean saveDisplayAnimation(@NotNull DisplayAnimation displayAnimation, @Nullable Player saver){
try{
- ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
- GZIPOutputStream gzipOut = new GZIPOutputStream(byteOut);
- ObjectOutputStream objOut = new ObjectOutputStream(gzipOut);
- objOut.writeObject(displayAnimation);
- gzipOut.close();
- objOut.close();
-
- byte[] data = byteOut.toByteArray();
- byteOut.close();
+ byte[] data = CommonDisplayStorageUtils.toByteArray(displayAnimation);
File saveFile = new File(PluginFolders.animSaveFolder, "/"+displayAnimation.getAnimationTag()+DisplayAnimation.FILE_EXTENSION);
if (saveFile.exists()){
diff --git a/plugin/src/main/java/net/donnypz/displayentityutils/database/MYSQLDisplayStorage.java b/plugin/src/main/java/net/donnypz/displayentityutils/database/MYSQLDisplayStorage.java
index 4d8247fc..38dde95b 100644
--- a/plugin/src/main/java/net/donnypz/displayentityutils/database/MYSQLDisplayStorage.java
+++ b/plugin/src/main/java/net/donnypz/displayentityutils/database/MYSQLDisplayStorage.java
@@ -11,9 +11,9 @@
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.NamedTextColor;
import net.kyori.adventure.text.format.TextDecoration;
+import net.kyori.adventure.text.logger.slf4j.ComponentLogger;
import net.kyori.adventure.text.minimessage.MiniMessage;
import org.apache.commons.dbutils.DbUtils;
-import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -26,13 +26,13 @@
import java.util.List;
-public final class MYSQLDisplayStorage implements DBDisplayStorage {
+public final class MYSQLDisplayStorage extends DBDisplayStorage {
- private static final String GROUP_TABLE = "saved_displays";
+ static final String GROUP_TABLE = "saved_displays";
private static final String GROUP_COLUMN = "display_group";
private static final String GROUP_DISPLAY_NAME = "display entity group";
- private static final String ANIMATION_TABLE = "saved_animations";
+ static final String ANIMATION_TABLE = "saved_animations";
private static final String ANIMATION_COLUMN = "display_anim";
private static final String ANIMATION_DISPLAY_NAME = "animation";
@@ -42,6 +42,10 @@ public final class MYSQLDisplayStorage implements DBDisplayStorage {
private boolean connected = false;
private HikariDataSource dataSource;
+ public MYSQLDisplayStorage(ComponentLogger logger) {
+ super(logger);
+ }
+
public void createConnection(
String host,
int port,
@@ -66,40 +70,48 @@ public void createConnection(
return;
}
DisplayAPI.getScheduler().runAsync(() -> {
- try {
- //Set Data Source
- dataSource = new HikariDataSource();
- dataSource.setJdbcUrl(url);
- dataSource.setUsername(username);
- dataSource.setPassword(password);
+ connect(url, username, password);
+ });
+ }
- dataSource.setMinimumIdle(3);
- dataSource.setMaximumPoolSize(6);
+ void connect(
+ String url,
+ String username,
+ String password
+ ) {
+ try {
+ //Set Data Source
+ dataSource = new HikariDataSource();
+ dataSource.setJdbcUrl(url);
+ dataSource.setUsername(username);
+ dataSource.setPassword(password);
- //Test Connection
- Connection connection = dataSource.getConnection();
+ dataSource.setMinimumIdle(3);
+ dataSource.setMaximumPoolSize(6);
+ //Test Connection
+ Connection connection = dataSource.getConnection();
- //Create Default Table
- Statement statement = connection.createStatement();
- String groupTableSQL = "CREATE TABLE IF NOT EXISTS saved_displays(tag VARCHAR(128) UNIQUE, display_group BLOB)";
- statement.execute(groupTableSQL);
- String animTableSQL = "CREATE TABLE IF NOT EXISTS saved_animations(tag VARCHAR(128) UNIQUE, display_anim BLOB)";
- statement.execute(animTableSQL);
+ //Create Default Table
+ Statement statement = connection.createStatement();
+ String groupTableSQL = "CREATE TABLE IF NOT EXISTS saved_displays(tag VARCHAR(128) UNIQUE, display_group BLOB)";
+ statement.execute(groupTableSQL);
+ String animTableSQL = "CREATE TABLE IF NOT EXISTS saved_animations(tag VARCHAR(128) UNIQUE, display_anim BLOB)";
+ statement.execute(animTableSQL);
- DbUtils.closeQuietly(statement);
- DbUtils.closeQuietly(connection);
- Bukkit.getConsoleSender().sendMessage(DisplayAPI.pluginPrefix.append(MiniMessage.miniMessage().deserialize("Successfully connected to MYSQL!")));
- connected = true;
- } catch (SQLException e) {
- e.printStackTrace();
- Bukkit.getConsoleSender().sendMessage(DisplayAPI.pluginPrefix.append(Component.text("There was an error connecting to the MYSQL database", NamedTextColor.RED)));
- closeConnection();
- }
- });
+ DbUtils.closeQuietly(statement);
+ DbUtils.closeQuietly(connection);
+
+ logger.info(DisplayAPI.pluginPrefix.append(MiniMessage.miniMessage().deserialize("Successfully connected to MYSQL!")));
+ connected = true;
+ } catch (SQLException e) {
+ logger.error(DisplayAPI.pluginPrefix.append(Component.text("There was an error connecting to the MYSQL database", NamedTextColor.RED)));
+ e.printStackTrace();
+ closeConnection();
+ }
}
@Override
@@ -124,7 +136,7 @@ public boolean isConnected() {
return connected;
}
- private Connection getConnection(){
+ Connection getConnection(){
try{
return dataSource.getConnection();
}
@@ -284,7 +296,6 @@ private boolean saveEntity(String tag, Object entity, String tableName, String d
}
}
statement.executeUpdate();
- blobStream.close();
if (saver != null) {
saver.sendMessage(MiniMessage.miniMessage().deserialize("- Successfully saved "+displayName+" to MYSQL!"));
}
@@ -325,14 +336,16 @@ private void deleteEntity(String tag, Player deleter, String tableName, String d
}
statement.setString(1, tag);
- statement.executeUpdate(delete);
+ statement.executeUpdate();
if (deleter != null){
deleter.sendMessage(MiniMessage.miniMessage().deserialize("- Successfully deleted "+displayName+" from MYSQL database!"));
}
}
catch(SQLException e){
e.printStackTrace();
- deleter.sendMessage(MiniMessage.miniMessage().deserialize("- Saved "+displayName+" does not exist in MYSQL database!"));
+ if (deleter != null){
+ deleter.sendMessage(MiniMessage.miniMessage().deserialize("- Saved "+displayName+" does not exist in MYSQL database!"));
+ }
}
}
diff --git a/plugin/src/main/java/net/donnypz/displayentityutils/database/MongoDisplayStorage.java b/plugin/src/main/java/net/donnypz/displayentityutils/database/MongoDisplayStorage.java
index 251fd70f..0182991a 100644
--- a/plugin/src/main/java/net/donnypz/displayentityutils/database/MongoDisplayStorage.java
+++ b/plugin/src/main/java/net/donnypz/displayentityutils/database/MongoDisplayStorage.java
@@ -17,11 +17,11 @@
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.NamedTextColor;
import net.kyori.adventure.text.format.TextDecoration;
+import net.kyori.adventure.text.logger.slf4j.ComponentLogger;
import net.kyori.adventure.text.minimessage.MiniMessage;
import org.bson.Document;
import org.bson.conversions.Bson;
import org.bson.types.Binary;
-import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -30,13 +30,13 @@
import java.io.IOException;
import java.util.*;
-public final class MongoDisplayStorage implements DBDisplayStorage {
+public final class MongoDisplayStorage extends DBDisplayStorage {
- private static MongoCollection GROUP_COLLECTION;
+ static MongoCollection GROUP_COLLECTION;
private static final String GROUP_FIELD = "displayGroup";
private static final String GROUP_DISPLAY_NAME = "display entity group";
- private static MongoCollection ANIMATION_COLLECTION;
+ static MongoCollection ANIMATION_COLLECTION;
private static final String ANIMATION_FIELD = "displayAnimation";
private static final String ANIMATION_DISPLAY_NAME = "animation";
@@ -46,6 +46,10 @@ public final class MongoDisplayStorage implements DBDisplayStorage {
private MongoDatabase database;
private boolean isConnected = false;
+ public MongoDisplayStorage(ComponentLogger logger) {
+ super(logger);
+ }
+
public void createConnection(
String host,
int port,
@@ -80,35 +84,48 @@ public void createConnection(
if (!this.canConnect(databaseName, groupCollection, animationCollection)) return;
DisplayAPI.getScheduler().runAsync(() -> {
- try{
- ConnectionString cString = new ConnectionString(connectionString);
- MongoClientSettings settings = MongoClientSettings.builder()
- .applyConnectionString(cString)
- .serverApi(ServerApi.builder()
- .version(ServerApiVersion.V1)
- .build())
- .build();
-
- client = MongoClients.create(settings);
- database = client.getDatabase(databaseName);
-
- this.createIfNotExisting(groupCollection);
- this.createIfNotExisting(animationCollection);
-
- GROUP_COLLECTION = database.getCollection(groupCollection);
- ANIMATION_COLLECTION = database.getCollection(animationCollection);
-
- Bukkit.getConsoleSender().sendMessage(DisplayAPI.pluginPrefix.append(MiniMessage.miniMessage().deserialize("Successfully connected to MongoDB!")));
- isConnected = true;
- }
- catch (IllegalArgumentException | MongoException e){
- isConnected = false;
- Bukkit.getConsoleSender().sendMessage(Component.text("There was an error connecting to the MongoDB Database!", NamedTextColor.RED));
- e.printStackTrace();
- }
+ connect(
+ connectionString,
+ databaseName,
+ groupCollection,
+ animationCollection
+ );
});
}
+ void connect(
+ String connectionString,
+ String databaseName,
+ String groupCollection,
+ String animationCollection
+ ) {
+ try {
+ ConnectionString cString = new ConnectionString(connectionString);
+ MongoClientSettings settings = MongoClientSettings.builder()
+ .applyConnectionString(cString)
+ .serverApi(ServerApi.builder()
+ .version(ServerApiVersion.V1)
+ .build())
+ .build();
+
+ client = MongoClients.create(settings);
+ database = client.getDatabase(databaseName);
+
+ this.createIfNotExisting(groupCollection);
+ this.createIfNotExisting(animationCollection);
+
+ GROUP_COLLECTION = database.getCollection(groupCollection);
+ ANIMATION_COLLECTION = database.getCollection(animationCollection);
+
+ logger.info(DisplayAPI.pluginPrefix.append(MiniMessage.miniMessage().deserialize("Successfully connected to MongoDB!")));
+ isConnected = true;
+ } catch (IllegalArgumentException | MongoException e) {
+ isConnected = false;
+ logger.error(Component.text("There was an error connecting to the MongoDB Database!", NamedTextColor.RED));
+ e.printStackTrace();
+ }
+ }
+
private boolean canConnect(
String databaseName,
String groupCollection,
@@ -117,7 +134,7 @@ private boolean canConnect(
if (isConnected()) return false;
if (databaseName.isBlank() || groupCollection.isBlank() || animationCollection.isBlank()){
- Bukkit.getConsoleSender().sendMessage(Component.text("There was an error connecting to the MongoDB Database! Database and/or Collection names are empty!", NamedTextColor.RED));
+ logger.error(Component.text("There was an error connecting to the MongoDB Database! Database and/or Collection names are empty!", NamedTextColor.RED));
isConnected = false;
return false;
}
@@ -155,8 +172,8 @@ public void closeConnection(){
}
catch(MongoException e){
isConnected = false;
+ logger.error(Component.text("There was an error closing the connection to the MongoDB Database", NamedTextColor.RED));
e.printStackTrace();
- Bukkit.getConsoleSender().sendMessage(Component.text("There was an error closing the connection to the MongoDB Database", NamedTextColor.RED));
}
}
@@ -190,7 +207,7 @@ public void deleteDisplayEntityGroup(@NotNull String tag, @Nullable Player delet
@Override
public @Nullable DisplayEntityGroup getDisplayEntityGroup(@NotNull String tag){
if (!isConnected) return null;
- Document doc = getGroupDocument(tag);
+ Document doc = getDocument(GROUP_COLLECTION, tag);
if (doc == null){
return null;
}
@@ -228,7 +245,7 @@ public void deleteDisplayAnimation(@NotNull String tag, @Nullable Player deleter
if (!isConnected){
return null;
}
- Document doc = getAnimationDocument(tag);
+ Document doc = getDocument(ANIMATION_COLLECTION, tag);
if (doc == null){
return null;
}
@@ -307,7 +324,7 @@ private boolean saveEntity(
.append(TAG_FIELD, tag)
.append(fieldName, data);
- Document existing = getGroupDocument(tag);
+ Document existing = getDocument(collection, tag);
if (existing != null){
if (DisplayConfig.overwritexistingSaves()){
Bson updateOperation = new Document ("$set", doc);
@@ -347,7 +364,7 @@ private void deleteEntity(
Player deleter
){
if (!isConnected()) return;
- Document doc = getGroupDocument(tag);
+ Document doc = getDocument(collection, tag);
if (doc != null){
collection.deleteOne(doc);
if (deleter != null){
@@ -360,14 +377,15 @@ private void deleteEntity(
}
}
- private Document getGroupDocument(String tag){
- return GROUP_COLLECTION.find(new Document(TAG_FIELD, tag))
- .first();
- }
-
- private Document getAnimationDocument(String tag){
- return ANIMATION_COLLECTION.find(new Document(TAG_FIELD, tag))
- .first();
+ private Document getDocument(MongoCollection collection, String tag){
+ if (collection == GROUP_COLLECTION){
+ return GROUP_COLLECTION.find(new Document(TAG_FIELD, tag))
+ .first();
+ }
+ else if (collection == ANIMATION_COLLECTION){
+ return ANIMATION_COLLECTION.find(new Document(TAG_FIELD, tag))
+ .first();
+ }
+ else return null;
}
-
}
diff --git a/plugin/src/main/resources/test/animations/sp_sp_summon.deanim b/plugin/src/main/resources/test/animations/sp_sp_summon.deanim
new file mode 100644
index 00000000..f73467a2
Binary files /dev/null and b/plugin/src/main/resources/test/animations/sp_sp_summon.deanim differ
diff --git a/plugin/src/main/resources/test/animations/wave_anim_wave.deanim b/plugin/src/main/resources/test/animations/wave_anim_wave.deanim
new file mode 100644
index 00000000..15e312e0
Binary files /dev/null and b/plugin/src/main/resources/test/animations/wave_anim_wave.deanim differ
diff --git a/plugin/src/main/resources/test/groups/star_platinum.deg b/plugin/src/main/resources/test/groups/star_platinum.deg
new file mode 100644
index 00000000..796bdf5e
Binary files /dev/null and b/plugin/src/main/resources/test/groups/star_platinum.deg differ
diff --git a/plugin/src/main/resources/test/groups/wumpus.deg b/plugin/src/main/resources/test/groups/wumpus.deg
new file mode 100644
index 00000000..d11b6cb0
Binary files /dev/null and b/plugin/src/main/resources/test/groups/wumpus.deg differ
diff --git a/plugin/src/test/java/net/donnypz/displayentityutils/command/CommandFrameIdsTests.java b/plugin/src/test/java/net/donnypz/displayentityutils/command/CommandFrameIdsTests.java
index 84865d7a..ff64e644 100644
--- a/plugin/src/test/java/net/donnypz/displayentityutils/command/CommandFrameIdsTests.java
+++ b/plugin/src/test/java/net/donnypz/displayentityutils/command/CommandFrameIdsTests.java
@@ -13,7 +13,7 @@ public class CommandFrameIdsTests {
"1,2",
"9,3,5",
})
- void tests(String idString){
+ void shouldBeValidFrameIds(String idString){
assertNotNull(CMDUtils.commaSeparatedIDs(idString));
}
diff --git a/plugin/src/test/java/net/donnypz/displayentityutils/command/CommandUsageTests.java b/plugin/src/test/java/net/donnypz/displayentityutils/command/CommandUsageTests.java
index cb74b11d..f02e3609 100644
--- a/plugin/src/test/java/net/donnypz/displayentityutils/command/CommandUsageTests.java
+++ b/plugin/src/test/java/net/donnypz/displayentityutils/command/CommandUsageTests.java
@@ -3,11 +3,17 @@
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.TestInstance;
import org.junit.jupiter.params.ParameterizedTest;
-import org.junit.jupiter.params.provider.ValueSource;
+import org.junit.jupiter.params.provider.MethodSource;
+
+import java.util.stream.Stream;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
public class CommandUsageTests {
+ record CommandCase(String arg1, String arg2, String commandSubArgs){ }
+
DisplayEntityPluginCommand deuCmd;
@BeforeAll
@@ -15,31 +21,62 @@ void before(){
this.deuCmd = new DisplayEntityPluginCommand();
}
+ Stream shortCommandUsageCases(){
+ return Stream.of(
+ new CommandCase("group", "spawn", null),
+ new CommandCase("group", "save", null),
+ new CommandCase("group", "despawnat", null),
+ new CommandCase("group", "ride", null),
+ new CommandCase("anim", "addframe", null),
+ new CommandCase("anim", "editframe", null),
+ new CommandCase("anim", "frameinfo", null),
+ new CommandCase("anim", "showpoints", null),
+ new CommandCase("anim", "drawpoints", null),
+ new CommandCase("anim", "drawpos", null),
+ new CommandCase("text", "edit", null),
+ new CommandCase("parts", "create", null),
+ new CommandCase("mannequin", "mainhand", null),
+ new CommandCase("mannequin", "togglegravity", null)
+ );
+ }
+
+ @ParameterizedTest
+ @MethodSource("shortCommandUsageCases")
+ void shouldBeValidShortCommandUsage(CommandCase commandCase){
+ String arg1 = commandCase.arg1;
+ String arg2 = commandCase.arg2;
+
+ DEUSubCommand subCmd = deuCmd
+ .getCommand(arg1)
+ .getCommand(arg2);
+
+ assertEquals("/deu "+arg1+" "+arg2, subCmd.getShortCommandUsage());
+ }
+
+ Stream fullCommandUsageCases() {
+ return Stream.of(
+ new CommandCase("group", "spawn", " [-packet]"),
+ new CommandCase("group", "save", ""),
+ new CommandCase("group", "despawnat", " [-force] [-packet ] [-world ]"),
+ new CommandCase("group", "ride", "<-target | player-name | entity-uuid> [group-tag] [storage] [controller-id]"),
+ new CommandCase("anim", "addframe", " "),
+ new CommandCase("anim", "drawpoints", " [points-per-frame]"),
+ new CommandCase("parts", "create", " [-addtogroup]"),
+ new CommandCase("mannequin", "togglegravity", "[-all ]")
+ );
+ }
+
@ParameterizedTest
- @ValueSource(strings = {
- "group,spawn",
- "group,save",
- "group,despawnat",
- "group,ride",
- "anim,addframe",
- "anim,editframe",
- "anim,frameinfo",
- "anim,showpoints",
- "anim,drawpoints",
- "anim,drawpos",
- "text,edit",
- "parts,create",
- "mannequin,mainhand",
- "mannequin,togglegravity"
- })
- void testCmd(String cmds){
- String[] split = cmds.split(",");
+ @MethodSource("fullCommandUsageCases")
+ void shouldBeValidFullCommandUsage(CommandCase commandCase){
+ String arg1 = commandCase.arg1;
+ String arg2 = commandCase.arg2;
+ String cmdArgs = commandCase.commandSubArgs;
+
DEUSubCommand subCmd = deuCmd
- .getCommand(split[0])
- .getCommand(split[1]);
+ .getCommand(arg1)
+ .getCommand(arg2);
- System.out.println();
- System.out.println(subCmd.getShortCommandUsage());
- System.out.println(subCmd.getCommandUsage());
+ assertEquals("/deu "+arg1+" "+arg2+" "+cmdArgs, subCmd.getCommandUsage());
}
}
diff --git a/plugin/src/test/java/net/donnypz/displayentityutils/database/DBStorageTest.java b/plugin/src/test/java/net/donnypz/displayentityutils/database/DBStorageTest.java
new file mode 100644
index 00000000..5ff0c20a
--- /dev/null
+++ b/plugin/src/test/java/net/donnypz/displayentityutils/database/DBStorageTest.java
@@ -0,0 +1,129 @@
+package net.donnypz.displayentityutils.database;
+
+import net.donnypz.displayentityutils.managers.DisplayAnimationManager;
+import net.donnypz.displayentityutils.managers.DisplayGroupManager;
+import net.donnypz.displayentityutils.utils.DisplayEntities.DisplayAnimation;
+import net.donnypz.displayentityutils.utils.DisplayEntities.DisplayEntityGroup;
+import net.kyori.adventure.text.logger.slf4j.ComponentLogger;
+import org.junit.jupiter.api.*;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.ValueSource;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+@TestInstance(TestInstance.Lifecycle.PER_CLASS)
+public abstract class DBStorageTest {
+
+ protected static final ComponentLogger log = ComponentLogger.logger();
+ protected DisplayStorage storage;
+
+ protected abstract void connect();
+
+ protected abstract void wipeTables();
+
+ @BeforeEach
+ void beforeEach() {
+ connect();
+ wipeTables();
+ }
+
+ @AfterEach
+ void afterEach() {
+ if (storage instanceof DBDisplayStorage db){
+ db.closeConnection();
+ }
+ }
+
+ @ParameterizedTest
+ @ValueSource(strings = {
+ "star_platinum",
+ "wumpus"
+ })
+ public void displayEntityGroupPersistsInDatabase(String resource) {
+ String resourcePath = "/test/groups/"+resource+".deg";
+ try (InputStream stream = getClass().getResourceAsStream(resourcePath)) {
+ DisplayEntityGroup group = DisplayGroupManager.getGroup(stream);
+ String tag = group.getTag();
+
+ storage.saveDisplayEntityGroup(group, null);
+ DisplayEntityGroup savedGroupFromDB = storage.getDisplayEntityGroup(tag);
+
+ assertNotNull(savedGroupFromDB, "Failed to save group tagged \"" + tag + "\" to database");
+ assertEquals(tag, savedGroupFromDB.getTag(), "Group tags are not the same");
+
+ } catch (IOException e) {
+ throw new RuntimeException("Failed to get group from resources", e);
+ }
+ }
+
+ @ParameterizedTest
+ @ValueSource(strings = {
+ "star_platinum",
+ "wumpus"
+ })
+ public void displayEntityGroupDeletesFromDatabase(String resource){
+ String resourcePath = "/test/groups/"+resource+".deg";
+ try (InputStream stream = getClass().getResourceAsStream(resourcePath)) {
+ DisplayEntityGroup group = DisplayGroupManager.getGroup(stream);
+ String tag = group.getTag();
+
+ storage.saveDisplayEntityGroup(group, null);
+ storage.deleteDisplayEntityGroup(tag, null);
+
+ DisplayEntityGroup savedGroupFromDB = storage.getDisplayEntityGroup(tag);
+
+ assertNull(savedGroupFromDB, "Failed to delete group tagged \"" + tag + "\" from database");
+
+ } catch (IOException e) {
+ throw new RuntimeException("Failed to get group from resources", e);
+ }
+ }
+
+ @ParameterizedTest
+ @ValueSource(strings = {
+ "sp_sp_summon",
+ "wave_anim_wave"
+ })
+ public void displayAnimationPersistsInDatabase(String resource) {
+ String resourcePath = "/test/animations/"+resource+".deanim";
+ try (InputStream stream = getClass().getResourceAsStream(resourcePath)) {
+ DisplayAnimation anim = DisplayAnimationManager.getAnimation(stream);
+ String tag = anim.getAnimationTag();
+
+ storage.saveDisplayAnimation(anim, null);
+ DisplayAnimation savedAnimationFromDB = storage.getDisplayAnimation(tag);
+
+ assertNotNull(savedAnimationFromDB, "Failed to save animation tagged \"" + tag + "\" to database");
+ assertEquals(tag, savedAnimationFromDB.getAnimationTag(), "Animation tags are not the same");
+
+ } catch (IOException e) {
+ throw new RuntimeException("Failed to get animation from resources", e);
+ }
+ }
+
+ @ParameterizedTest
+ @ValueSource(strings = {
+ "sp_sp_summon",
+ "wave_anim_wave"
+ })
+ public void displayAnimationDeletesFromDatabase(String resource){
+ String resourcePath = "/test/animations/"+resource+".deanim";
+ try (InputStream stream = getClass().getResourceAsStream(resourcePath)) {
+ DisplayAnimation anim = DisplayAnimationManager.getAnimation(stream);
+ String tag = anim.getAnimationTag();
+
+ storage.saveDisplayAnimation(anim, null);
+ storage.deleteDisplayAnimation(tag, null);
+
+ DisplayAnimation savedAnimationFromDB = storage.getDisplayAnimation(tag);
+
+ assertNull(savedAnimationFromDB, "Failed to delete animation tagged \"" + tag + "\" from database");
+
+ } catch (IOException e) {
+ throw new RuntimeException("Failed to get animation from resources", e);
+ }
+ }
+}
diff --git a/plugin/src/test/java/net/donnypz/displayentityutils/database/MongoStorageTestIT.java b/plugin/src/test/java/net/donnypz/displayentityutils/database/MongoStorageTestIT.java
new file mode 100644
index 00000000..65b88599
--- /dev/null
+++ b/plugin/src/test/java/net/donnypz/displayentityutils/database/MongoStorageTestIT.java
@@ -0,0 +1,46 @@
+package net.donnypz.displayentityutils.database;
+
+import net.donnypz.displayentityutils.DisplayAPI;
+import net.donnypz.displayentityutils.DisplayAPIInitializer;
+import net.donnypz.displayentityutils.managers.LoadMethod;
+import org.bson.Document;
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.BeforeAll;
+import org.testcontainers.containers.MongoDBContainer;
+import org.testcontainers.utility.DockerImageName;
+
+
+public class MongoStorageTestIT extends DBStorageTest{
+
+ static DockerImageName imageName = DockerImageName.parse("mongo:9.0.4");
+ static MongoDBContainer mongoDB = new MongoDBContainer(imageName);
+
+ @BeforeAll
+ void beforeAll() {
+ DisplayAPIInitializer.initializeImpls(log);
+ storage = DisplayAPI.getStorage(LoadMethod.MONGODB);
+ mongoDB.start();
+ }
+
+ @AfterAll
+ void afterAll() {
+ mongoDB.stop();
+ }
+
+ @Override
+ protected void connect() {
+ ((MongoDisplayStorage) storage).connect(
+ mongoDB.getConnectionString(),
+ "db",
+ "groups",
+ "animations"
+ );
+ }
+
+
+ @Override
+ public void wipeTables() {
+ MongoDisplayStorage.GROUP_COLLECTION.deleteMany(new Document());
+ MongoDisplayStorage.ANIMATION_COLLECTION.deleteMany(new Document());
+ }
+}
diff --git a/plugin/src/test/java/net/donnypz/displayentityutils/database/MySQLStorageTestIT.java b/plugin/src/test/java/net/donnypz/displayentityutils/database/MySQLStorageTestIT.java
new file mode 100644
index 00000000..b3ab14e9
--- /dev/null
+++ b/plugin/src/test/java/net/donnypz/displayentityutils/database/MySQLStorageTestIT.java
@@ -0,0 +1,58 @@
+package net.donnypz.displayentityutils.database;
+
+import net.donnypz.displayentityutils.DisplayAPI;
+import net.donnypz.displayentityutils.DisplayAPIInitializer;
+import net.donnypz.displayentityutils.managers.LoadMethod;
+import org.junit.jupiter.api.*;
+import org.testcontainers.containers.MySQLContainer;
+import org.testcontainers.utility.DockerImageName;
+
+import java.sql.Connection;
+import java.sql.SQLException;
+import java.sql.Statement;
+
+
+public class MySQLStorageTestIT extends DBStorageTest{
+
+ //Testcontainers has a check to make sure official image is used
+ //Below bypasses that
+ static DockerImageName imageName = DockerImageName.parse("mysql/mysql-server:8.0")
+ .asCompatibleSubstituteFor("mysql");
+
+ static MySQLContainer> mysql = new MySQLContainer<>(imageName)
+ .withDatabaseName("db");
+
+ @BeforeAll
+ void beforeAll() {
+ DisplayAPIInitializer.initializeImpls(log);
+ storage = DisplayAPI.getStorage(LoadMethod.MYSQL);
+ mysql.start();
+ }
+
+ @AfterAll
+ void afterAll() {
+ mysql.stop();
+ }
+
+ @Override
+ protected void connect() {
+ ((MYSQLDisplayStorage) storage).connect(
+ mysql.getJdbcUrl(),
+ mysql.getUsername(),
+ mysql.getPassword()
+ );
+ }
+
+
+ @Override
+ public void wipeTables() {
+ try (Connection c = ((MYSQLDisplayStorage) storage).getConnection()) {
+ Statement st = c.createStatement();
+
+ st.execute("TRUNCATE TABLE " + MYSQLDisplayStorage.GROUP_TABLE);
+ st.execute("TRUNCATE TABLE " + MYSQLDisplayStorage.ANIMATION_TABLE);
+ } catch (SQLException e) {
+ throw new RuntimeException("Failed to clean up test data", e);
+ }
+ }
+}
diff --git a/pom.xml b/pom.xml
index b00eeb87..2c87008b 100644
--- a/pom.xml
+++ b/pom.xml
@@ -6,7 +6,7 @@
net.donnypz.displayentityutils
deu
- 3.8.0
+ 3.8.1
pom
DisplayEntityUtils
@@ -143,7 +143,13 @@
org.junit.jupiter
junit-jupiter
- 6.1.0
+ 6.1.3
+ test
+
+
+ org.mockito
+ mockito-junit-jupiter
+ 5.24.0
test