diff --git a/pom.xml b/pom.xml
index 73c46273c6..411d3b015c 100644
--- a/pom.xml
+++ b/pom.xml
@@ -406,8 +406,21 @@
org.jetbrains
annotations
+
+ io.papermc.paper
+ paper-api
+
+
+
+
+
+ io.papermc.paper
+ paper-api
+ 1.20.4-R0.1-20240205.114523-90
+ test
+
diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/storage/backend/legacy/LegacyStorage.java b/src/main/java/io/github/thebusybiscuit/slimefun4/storage/backend/legacy/LegacyStorage.java
index d7981a5466..59b0c82b96 100644
--- a/src/main/java/io/github/thebusybiscuit/slimefun4/storage/backend/legacy/LegacyStorage.java
+++ b/src/main/java/io/github/thebusybiscuit/slimefun4/storage/backend/legacy/LegacyStorage.java
@@ -91,7 +91,17 @@ public void savePlayerData(@Nonnull UUID uuid, @Nonnull PlayerData data) {
playerFile.setValue("researches." + research.getID(), true);
// Remove the research if it's no longer researched
- } else if (playerFile.contains("researches." + research.getID())) {
+ // ----
+ // We have a duplicate ID (173) used for both Coal Gen and Bio Reactor
+ // If you researched the Goal Gen we would remove it on save if you didn't also have the Bio Reactor
+ // Due to the fact we would set it as researched (true in the branch above) on Coal Gen
+ // but then go into this branch and remove it if you didn't have Bio Reactor
+ // Sooooo we're gonna hack this for now while we move away from the Legacy Storage
+ // Let's make sure the user doesn't have _any_ research with this ID and _then_ remove it
+ } else if (
+ playerFile.contains("researches." + research.getID())
+ && !data.getResearches().stream().anyMatch((r) -> r.getID() == research.getID())
+ ) {
playerFile.setValue("researches." + research.getID(), null);
}
}
diff --git a/src/test/java/io/github/thebusybiscuit/slimefun4/storage/backend/TestLegacyBackend.java b/src/test/java/io/github/thebusybiscuit/slimefun4/storage/backend/TestLegacyBackend.java
index c8e1916f54..98653ee5b7 100644
--- a/src/test/java/io/github/thebusybiscuit/slimefun4/storage/backend/TestLegacyBackend.java
+++ b/src/test/java/io/github/thebusybiscuit/slimefun4/storage/backend/TestLegacyBackend.java
@@ -17,6 +17,7 @@
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
@@ -52,8 +53,6 @@ public static void load() {
// within the class isn't being fired (where ItemStack and other classes are registered)
ConfigurationSerialization.registerClass(ItemStack.class);
ConfigurationSerialization.registerClass(ItemMeta.class);
-
- setupResearches();
}
@AfterAll
@@ -62,9 +61,16 @@ public static void unload() throws IOException {
FileUtils.deleteDirectory(new File("data-storage"));
}
+ @AfterEach
+ public void cleanup() {
+ Slimefun.getRegistry().getResearches().clear();
+ }
+
// Test simple loading and saving of player data
@Test
void testLoadingResearches() throws IOException {
+ setupResearches();
+
// Create a player file which we can load
UUID uuid = UUID.randomUUID();
File playerFile = new File("data-storage/Slimefun/Players/" + uuid + ".yml");
@@ -184,6 +190,8 @@ void testLoadingWaypoints() throws IOException {
@Test
void testSavingResearches() throws InterruptedException {
+ setupResearches();
+
// Create a player file which we can load
UUID uuid = UUID.randomUUID();
File playerFile = new File("data-storage/Slimefun/Players/" + uuid + ".yml");
@@ -279,6 +287,8 @@ void testSavingWaypoints() throws InterruptedException {
// Test realistic situations
@Test
void testResearchChanges() throws InterruptedException {
+ setupResearches();
+
UUID uuid = UUID.randomUUID();
File playerFile = new File("data-storage/Slimefun/Players/" + uuid + ".yml");
@@ -372,6 +382,41 @@ void testWaypointChanges() throws InterruptedException {
Assertions.assertEquals(1, assertion.getWaypoints().size());
}
+ @Test
+ void testDuplicateResearchesDontGetUnResearched() throws InterruptedException {
+ // Create a player file which we can load
+ UUID uuid = UUID.randomUUID();
+ File playerFile = new File("data-storage/Slimefun/Players/" + uuid + ".yml");
+
+ OfflinePlayer player = Bukkit.getOfflinePlayer(uuid);
+ PlayerProfile profile = TestUtilities.awaitProfile(player);
+
+ // Setup initial research
+ NamespacedKey initialKey = new NamespacedKey(plugin, "test_1");
+ Research initialResearch = new Research(initialKey, 1, "Test 1", 100);
+ initialResearch.register();
+
+ // Setup duplicate research
+ // Keep the ID as 1 but change name and key
+ NamespacedKey duplicateKey = new NamespacedKey(plugin, "test_2");
+ Research duplicateResearch = new Research(duplicateKey, 1, "Test 2", 100);
+ duplicateResearch.register();
+
+ profile.setResearched(initialResearch, true);
+
+ // Save the player data
+ LegacyStorage storage = new LegacyStorage();
+ storage.savePlayerData(uuid, profile.getPlayerData());
+
+ // Assert the file exists and data is correct
+ Assertions.assertTrue(playerFile.exists());
+ PlayerData assertion = storage.loadPlayerData(uuid);
+ // Will have both the initial and duplicate research
+ Assertions.assertEquals(2, assertion.getResearches().size());
+ Assertions.assertTrue(assertion.getResearches().contains(initialResearch));
+ Assertions.assertTrue(assertion.getResearches().contains(duplicateResearch));
+ }
+
// Utils
private static void setupResearches() {
for (int i = 0; i < 10; i++) {