From 53768555a26e4d32484c56026ee82c7e2d2e6bc1 Mon Sep 17 00:00:00 2001 From: P0nk Date: Thu, 9 Mar 2023 20:08:20 +0100 Subject: [PATCH] Add table, data, and provider method for global drops --- src/main/java/database/JdbiConfig.java | 4 ++- src/main/java/database/drop/DropDao.java | 12 ++++++++ src/main/java/database/drop/DropProvider.java | 23 +++++++++++++++ .../java/database/drop/GlobalMonsterDrop.java | 4 +++ .../drop/GlobalMonsterDropRowMapper.java | 21 ++++++++++++++ .../postgresql/V0.5__global_monster_drop.sql | 20 +++++++++++++ .../java/database/drop/DropProviderTest.java | 28 +++++++++++++++++++ 7 files changed, 111 insertions(+), 1 deletion(-) create mode 100644 src/main/java/database/drop/GlobalMonsterDrop.java create mode 100644 src/main/java/database/drop/GlobalMonsterDropRowMapper.java create mode 100644 src/main/resources/db/migration/postgresql/V0.5__global_monster_drop.sql diff --git a/src/main/java/database/JdbiConfig.java b/src/main/java/database/JdbiConfig.java index 7caa49e434..16d2a7b43c 100644 --- a/src/main/java/database/JdbiConfig.java +++ b/src/main/java/database/JdbiConfig.java @@ -1,5 +1,6 @@ package database; +import database.drop.GlobalMonsterDropRowMapper; import database.drop.MonsterDropRowMapper; import database.maker.MakerIngredientRowMapper; import database.maker.MakerReagentRowMapper; @@ -18,6 +19,7 @@ public final class JdbiConfig { .registerRowMapper(new MakerReagentRowMapper()) .registerRowMapper(new MakerRecipeRowMapper()) .registerRowMapper(new MakerIngredientRowMapper()) - .registerRowMapper(new MonsterDropRowMapper()); + .registerRowMapper(new MonsterDropRowMapper()) + .registerRowMapper(new GlobalMonsterDropRowMapper()); } } diff --git a/src/main/java/database/drop/DropDao.java b/src/main/java/database/drop/DropDao.java index 8e3cc0a02e..dc042e4f4b 100644 --- a/src/main/java/database/drop/DropDao.java +++ b/src/main/java/database/drop/DropDao.java @@ -26,4 +26,16 @@ public class DropDao { throw new DaoException("Failed to get monster drops for id %d".formatted(monsterId), e); } } + + public List getGlobalMonsterDrops() { + try (Handle handle = connection.getHandle()) { + return handle.createQuery(""" + SELECT * + FROM global_monster_drop;""") + .mapTo(GlobalMonsterDrop.class) + .list(); + } catch (JdbiException e) { + throw new DaoException("Failed to get global monster drops", e); + } + } } diff --git a/src/main/java/database/drop/DropProvider.java b/src/main/java/database/drop/DropProvider.java index c272b13ad6..1cc76c019a 100644 --- a/src/main/java/database/drop/DropProvider.java +++ b/src/main/java/database/drop/DropProvider.java @@ -3,12 +3,14 @@ package database.drop; import com.github.benmanes.caffeine.cache.Cache; import com.github.benmanes.caffeine.cache.Caffeine; import server.life.MonsterDropEntry; +import server.life.MonsterGlobalDropEntry; import java.util.List; public class DropProvider { private final DropDao dropDao; private final Cache> monsterDropCache = Caffeine.newBuilder().build(); + private volatile List globalMonsterDrops = null; public DropProvider(DropDao dropDao) { if (dropDao == null) { @@ -29,4 +31,25 @@ public class DropProvider { return new MonsterDropEntry(monsterDrop.itemId(), monsterDrop.chance(), monsterDrop.minQuantity(), monsterDrop.maxQuantity(), questId); } + + public List getGlobalDropEntries() { + if (this.globalMonsterDrops == null) { + loadGlobalDrops(); + } + + return globalMonsterDrops.stream() + .map(this::mapToDropEntry) + .toList(); + } + + private void loadGlobalDrops() { + this.globalMonsterDrops = dropDao.getGlobalMonsterDrops(); + } + + // TODO: Temporary. MonsterDropEntry should be removed. + private MonsterGlobalDropEntry mapToDropEntry(GlobalMonsterDrop globalDrop) { + short questId = globalDrop.questId() == null ? 0 : globalDrop.questId().shortValue(); + return new MonsterGlobalDropEntry(globalDrop.itemId(), globalDrop.chance(), globalDrop.continent(), + globalDrop.minQuantity(), globalDrop.maxQuantity(), questId); + } } diff --git a/src/main/java/database/drop/GlobalMonsterDrop.java b/src/main/java/database/drop/GlobalMonsterDrop.java new file mode 100644 index 0000000000..14acaf1573 --- /dev/null +++ b/src/main/java/database/drop/GlobalMonsterDrop.java @@ -0,0 +1,4 @@ +package database.drop; + +public record GlobalMonsterDrop(int itemId, int continent, int minQuantity, int maxQuantity, Integer questId, int chance) { +} diff --git a/src/main/java/database/drop/GlobalMonsterDropRowMapper.java b/src/main/java/database/drop/GlobalMonsterDropRowMapper.java new file mode 100644 index 0000000000..49989dc888 --- /dev/null +++ b/src/main/java/database/drop/GlobalMonsterDropRowMapper.java @@ -0,0 +1,21 @@ +package database.drop; + +import org.jdbi.v3.core.mapper.RowMapper; +import org.jdbi.v3.core.statement.StatementContext; + +import java.sql.ResultSet; +import java.sql.SQLException; + +public class GlobalMonsterDropRowMapper implements RowMapper { + + @Override + public GlobalMonsterDrop map(ResultSet rs, StatementContext ctx) throws SQLException { + final int itemId = rs.getInt("item_id"); + final int continent = rs.getInt("continent"); + final int minQuantity = rs.getInt("min_quantity"); + final int maxQuantity = rs.getInt("max_quantity"); + final Integer questId = rs.getObject("quest_id", Integer.class); + final int chance = rs.getInt("chance"); + return new GlobalMonsterDrop(itemId, continent, minQuantity, maxQuantity, questId, chance); + } +} diff --git a/src/main/resources/db/migration/postgresql/V0.5__global_monster_drop.sql b/src/main/resources/db/migration/postgresql/V0.5__global_monster_drop.sql new file mode 100644 index 0000000000..c43b529d37 --- /dev/null +++ b/src/main/resources/db/migration/postgresql/V0.5__global_monster_drop.sql @@ -0,0 +1,20 @@ +CREATE TABLE global_monster_drop +( + id serial NOT NULL, + item_id integer NOT NULL, + continent integer NOT NULL, + min_quantity integer NOT NULL, + max_quantity integer NOT NULL, + quest_id integer, + chance integer NOT NULL, + PRIMARY KEY (id) +); +GRANT SELECT ON global_monster_drop TO ${server-username}; + +INSERT INTO global_monster_drop (continent, item_id, min_quantity, max_quantity, quest_id, chance) +VALUES (-1, 4031865, 1, 1, NULL, 35000), + (-1, 4031866, 1, 1, NULL, 20000), + (-1, 4001126, 1, 2, NULL, 8000), + (-1, 2049100, 1, 1, NULL, 1200), + (-1, 2340000, 1, 1, NULL, 1200), + (-1, 4001006, 1, 1, NULL, 10000); diff --git a/src/test/java/database/drop/DropProviderTest.java b/src/test/java/database/drop/DropProviderTest.java index 0b6a9c2e2c..3456ba04a6 100644 --- a/src/test/java/database/drop/DropProviderTest.java +++ b/src/test/java/database/drop/DropProviderTest.java @@ -5,6 +5,7 @@ import org.junit.jupiter.api.Test; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import server.life.MonsterDropEntry; +import server.life.MonsterGlobalDropEntry; import java.util.Collections; import java.util.List; @@ -76,4 +77,31 @@ class DropProviderTest { return new MonsterDrop(100100, 4000019, 1, 2, null, 600_000); } + @Test + void getCachedGlobalDropEntries() { + GlobalMonsterDrop globalDrop = new GlobalMonsterDrop(2049100, -1, 2, 3, null, 450); + when(dropDao.getGlobalMonsterDrops()).thenReturn(List.of(globalDrop)); + + List dropEntries1 = dropProvider.getGlobalDropEntries(); + List dropEntries2 = dropProvider.getGlobalDropEntries(); + + assertEquals(1, dropEntries1.size()); + assertEquals(1, dropEntries2.size()); + MonsterGlobalDropEntry dropEntry1 = dropEntries1.get(0); + MonsterGlobalDropEntry dropEntry2 = dropEntries2.get(0); + assertEquals(2049100, dropEntry1.itemId); + assertEquals(dropEntry1.itemId, dropEntry2.itemId); + assertEquals(-1, dropEntry1.continentid); + assertEquals(dropEntry1.continentid, dropEntry2.continentid); + assertEquals(2, dropEntry1.Minimum); + assertEquals(dropEntry1.Minimum, dropEntry2.Minimum); + assertEquals(3, dropEntry1.Maximum); + assertEquals(dropEntry1.Maximum, dropEntry2.Maximum); + assertEquals(0, dropEntry1.questid); + assertEquals(dropEntry1.questid, dropEntry2.questid); + assertEquals(450, dropEntry1.chance); + assertEquals(dropEntry1.chance, dropEntry2.chance); + verify(dropDao, times(1)).getGlobalMonsterDrops(); + } + }