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