diff --git a/src/main/java/net/server/Server.java b/src/main/java/net/server/Server.java index 17a70b985d..2feed8f403 100644 --- a/src/main/java/net/server/Server.java +++ b/src/main/java/net/server/Server.java @@ -361,7 +361,7 @@ public class Server { wldRLock.unlock(); } - Channel channel = new Channel(worldid, channelid, getCurrentTime()); + Channel channel = new Channel(worldid, channelid, getCurrentTime(), channelDependencies.dropProvider()); channel.setServerMessage(YamlConfig.config.worlds.get(worldid).why_am_i_recommended); if (world.addChannel(channel)) { @@ -434,7 +434,7 @@ public class Server { long bootTime = getCurrentTime(); for (int j = 1; j <= YamlConfig.config.worlds.get(i).channels; j++) { int channelid = j; - Channel channel = new Channel(i, channelid, bootTime); + Channel channel = new Channel(i, channelid, bootTime, channelDependencies.dropProvider()); world.addChannel(channel); channelInfo.put(channelid, channel.getIP()); diff --git a/src/main/java/net/server/channel/Channel.java b/src/main/java/net/server/channel/Channel.java index 98c3151953..2cb757f1d8 100644 --- a/src/main/java/net/server/channel/Channel.java +++ b/src/main/java/net/server/channel/Channel.java @@ -24,6 +24,7 @@ package net.server.channel; import client.Character; import config.YamlConfig; import constants.id.MapId; +import database.drop.DropProvider; import net.netty.ChannelServer; import net.packet.Packet; import net.server.PlayerStorage; @@ -73,6 +74,7 @@ public final class Channel { private MapManager mapManager; private EventScriptManager eventSM; private ServicesManager services; + private final DropProvider dropProvider; private final Map hiredMerchants = new HashMap<>(); private final Map storedVars = new HashMap<>(); private final Set playersAway = new HashSet<>(); @@ -107,12 +109,13 @@ public final class Channel { private final Lock merchRlock; private final Lock merchWlock; - public Channel(final int world, final int channel, long startTime) { + public Channel(final int world, final int channel, long startTime, DropProvider dropProvider) { this.world = world; this.channel = channel; + this.dropProvider = dropProvider; this.ongoingStartTime = startTime + 10000; // rude approach to a world's last channel boot time, placeholder for the 1st wedding reservation ever - this.mapManager = new MapManager(null, world, channel); + this.mapManager = new MapManager(null, world, channel, dropProvider); this.port = BASE_PORT + (this.channel - 1) + (world * 100); this.ip = YamlConfig.config.server.HOST + ":" + port; @@ -125,11 +128,11 @@ public final class Channel { expedType.addAll(Arrays.asList(ExpeditionType.values())); if (Server.getInstance().isOnline()) { // postpone event loading to improve boot time... thanks Riizade, daronhudson for noticing slow startup times - eventSM = new EventScriptManager(this, getEvents()); + eventSM = new EventScriptManager(this, getEvents(), dropProvider); eventSM.init(); } else { String[] ev = {"0_EXAMPLE"}; - eventSM = new EventScriptManager(this, ev); + eventSM = new EventScriptManager(this, ev, dropProvider); } dojoStage = new int[20]; @@ -162,7 +165,7 @@ public final class Channel { eventSM.cancel(); eventSM = null; - eventSM = new EventScriptManager(this, getEvents()); + eventSM = new EventScriptManager(this, getEvents(), dropProvider); } public synchronized void shutdown() { @@ -1035,4 +1038,4 @@ public final class Channel { log.debug("Guest list: {}", ongoingChapelGuests); log.debug("Starttime: {}", ongoingStartTime); } -} \ No newline at end of file +} diff --git a/src/main/java/scripting/event/EventInstanceManager.java b/src/main/java/scripting/event/EventInstanceManager.java index 9ee193cf7a..717c27f6b3 100644 --- a/src/main/java/scripting/event/EventInstanceManager.java +++ b/src/main/java/scripting/event/EventInstanceManager.java @@ -26,6 +26,7 @@ import client.Skill; import client.SkillFactory; import config.YamlConfig; import constants.inventory.ItemConstants; +import database.drop.DropProvider; import net.server.coordinator.world.EventRecallCoordinator; import net.server.world.Party; import net.server.world.PartyCharacter; @@ -110,11 +111,11 @@ public class EventInstanceManager { // forces deletion of items not supposed to be held outside of the event, dealt on a player's leaving moment. private final Set exclusiveItems = new HashSet<>(); - public EventInstanceManager(EventManager em, String name) { + public EventInstanceManager(EventManager em, String name, DropProvider dropProvider) { this.em = em; this.name = name; this.ess = new EventScriptScheduler(); - this.mapManager = new MapManager(this, em.getWorldServer().getId(), em.getChannelServer().getId()); + this.mapManager = new MapManager(this, em.getWorldServer().getId(), em.getChannelServer().getId(), dropProvider); ReadWriteLock readWriteLock = new ReentrantReadWriteLock(true); this.readLock = readWriteLock.readLock(); diff --git a/src/main/java/scripting/event/EventManager.java b/src/main/java/scripting/event/EventManager.java index 8567b93330..00c925fd3f 100644 --- a/src/main/java/scripting/event/EventManager.java +++ b/src/main/java/scripting/event/EventManager.java @@ -24,6 +24,7 @@ package scripting.event; import client.Character; import config.YamlConfig; import constants.game.GameConstants; +import database.drop.DropProvider; import net.server.Server; import net.server.channel.Channel; import net.server.guild.Guild; @@ -51,7 +52,6 @@ import java.util.concurrent.locks.ReentrantLock; import static java.util.concurrent.TimeUnit.MILLISECONDS; import static java.util.concurrent.TimeUnit.SECONDS; -//import jdk.nashorn.api.scripting.ScriptUtils; /** * @author Matze @@ -63,6 +63,7 @@ public class EventManager { private Channel cserv; private World wserv; private Server server; + private final DropProvider dropProvider; private final EventScriptScheduler ess = new EventScriptScheduler(); private final Map instances = new HashMap<>(); private final Map instanceLocks = new HashMap<>(); @@ -82,12 +83,13 @@ public class EventManager { private static final int maxLobbys = 8; // an event manager holds up to this amount of concurrent lobbys - public EventManager(Channel cserv, Invocable iv, String name) { + public EventManager(Channel cserv, Invocable iv, String name, DropProvider dropProvider) { this.server = Server.getInstance(); this.iv = iv; this.cserv = cserv; this.wserv = server.getWorld(cserv.getWorld()); this.name = name; + this.dropProvider = dropProvider; this.openedLobbys = new ArrayList<>(); for (int i = 0; i < maxLobbys; i++) { @@ -219,7 +221,7 @@ public class EventManager { EventInstanceManager ret = getReadyInstance(); if (ret == null) { - ret = new EventInstanceManager(this, name); + ret = new EventInstanceManager(this, name, dropProvider); } else { ret.setName(name); } @@ -235,7 +237,7 @@ public class EventManager { } public Marriage newMarriage(String name) throws EventInstanceInProgressException { - Marriage ret = new Marriage(this, name); + Marriage ret = new Marriage(this, name, dropProvider); synchronized (instances) { if (instances.containsKey(name)) { @@ -922,7 +924,7 @@ public class EventManager { queueLock.unlock(); } - EventInstanceManager eim = new EventInstanceManager(this, "sampleName" + nextEventId); + EventInstanceManager eim = new EventInstanceManager(this, "sampleName" + nextEventId, dropProvider); queueLock.lock(); try { if (this.isDisposed()) { // EM already disposed @@ -945,4 +947,4 @@ public class EventManager { instantiateQueuedInstance(); } } -} \ No newline at end of file +} diff --git a/src/main/java/scripting/event/EventScriptManager.java b/src/main/java/scripting/event/EventScriptManager.java index 2723aa23cb..65dd1ba65a 100644 --- a/src/main/java/scripting/event/EventScriptManager.java +++ b/src/main/java/scripting/event/EventScriptManager.java @@ -21,6 +21,7 @@ */ package scripting.event; +import database.drop.DropProvider; import net.server.channel.Channel; import org.slf4j.LoggerFactory; import scripting.AbstractScriptManager; @@ -42,6 +43,7 @@ public class EventScriptManager extends AbstractScriptManager { private static final String INJECTED_VARIABLE_NAME = "em"; private static EventEntry fallback; private final Map events = new ConcurrentHashMap<>(); + private final DropProvider dropProvider; private boolean active = false; private static class EventEntry { @@ -55,7 +57,8 @@ public class EventScriptManager extends AbstractScriptManager { public EventManager em; } - public EventScriptManager(final Channel channel, String[] scripts) { + public EventScriptManager(final Channel channel, String[] scripts, DropProvider dropProvider) { + this.dropProvider = dropProvider; for (String script : scripts) { if (!script.isEmpty()) { events.put(script, initializeEventEntry(script, channel)); @@ -106,7 +109,7 @@ public class EventScriptManager extends AbstractScriptManager { private EventEntry initializeEventEntry(String script, Channel channel) { ScriptEngine engine = getInvocableScriptEngine("event/" + script + ".js"); Invocable iv = SynchronizedInvocable.of((Invocable) engine); - EventManager eventManager = new EventManager(channel, iv, script); + EventManager eventManager = new EventManager(channel, iv, script, dropProvider); engine.put(INJECTED_VARIABLE_NAME, eventManager); return new EventEntry(iv, eventManager); } diff --git a/src/main/java/server/Marriage.java b/src/main/java/server/Marriage.java index e44a7a85f2..04bfe5e2a4 100644 --- a/src/main/java/server/Marriage.java +++ b/src/main/java/server/Marriage.java @@ -26,6 +26,7 @@ import client.inventory.InventoryType; import client.inventory.Item; import client.inventory.ItemFactory; import client.inventory.manipulator.InventoryManipulator; +import database.drop.DropProvider; import scripting.event.EventInstanceManager; import scripting.event.EventManager; import tools.DatabaseConnection; @@ -42,8 +43,8 @@ import java.util.List; * @author Ronan */ public class Marriage extends EventInstanceManager { - public Marriage(EventManager em, String name) { - super(em, name); + public Marriage(EventManager em, String name, DropProvider dropProvider) { + super(em, name, dropProvider); } public boolean giftItemToSpouse(int cid) { diff --git a/src/main/java/server/life/Monster.java b/src/main/java/server/life/Monster.java index 52f01017c8..f6ff920f5a 100644 --- a/src/main/java/server/life/Monster.java +++ b/src/main/java/server/life/Monster.java @@ -28,6 +28,7 @@ import client.status.MonsterStatusEffect; import config.YamlConfig; import constants.id.MobId; import constants.skills.*; +import database.drop.DropProvider; import net.packet.Packet; import net.server.channel.Channel; import net.server.coordinator.world.MonsterAggroCoordinator; @@ -738,9 +739,9 @@ public class Monster extends AbstractLoadedLife { } } - public List retrieveRelevantDrops() { + public List retrieveRelevantDrops(DropProvider dropProvider) { if (this.getStats().isFriendly()) { // thanks Conrad for noticing friendly mobs not spawning loots after a recent update - return MonsterInformationProvider.getInstance().retrieveEffectiveDrop(this.getId()); + return dropProvider.getMonsterDropEntries(this.getId()); } Map pchars = map.getMapAllPlayers(); @@ -753,7 +754,7 @@ public class Monster extends AbstractLoadedLife { } } - return LootManager.retrieveRelevantDrops(this.getId(), lootChars); + return LootManager.retrieveRelevantDrops(this.getId(), lootChars, dropProvider); } public Character killBy(final Character killer) { diff --git a/src/main/java/server/life/MonsterInformationProvider.java b/src/main/java/server/life/MonsterInformationProvider.java index 03ee8e02e5..a81876a01d 100644 --- a/src/main/java/server/life/MonsterInformationProvider.java +++ b/src/main/java/server/life/MonsterInformationProvider.java @@ -99,34 +99,6 @@ public class MonsterInformationProvider { } } - public List retrieveEffectiveDrop(final int monsterId) { - return retrieveDrop(monsterId); - } - - private List retrieveDrop(final int monsterId) { - if (drops.containsKey(monsterId)) { - return drops.get(monsterId); - } - final List ret = new LinkedList<>(); - - try (Connection con = DatabaseConnection.getConnection(); - PreparedStatement ps = con.prepareStatement("SELECT itemid, chance, minimum_quantity, maximum_quantity, questid FROM drop_data WHERE dropperid = ?")) { - ps.setInt(1, monsterId); - - try (ResultSet rs = ps.executeQuery()) { - while (rs.next()) { - ret.add(new MonsterDropEntry(rs.getInt("itemid"), rs.getInt("chance"), rs.getInt("minimum_quantity"), rs.getInt("maximum_quantity"), rs.getShort("questid"))); - } - } - } catch (SQLException e) { - e.printStackTrace(); - return ret; - } - - drops.put(monsterId, ret); - return ret; - } - public final void setMobAttackAnimationTime(int monsterId, int attackPos, int animationTime) { mobAttackAnimationTime.put(new Pair<>(monsterId, attackPos), animationTime); } diff --git a/src/main/java/server/loot/LootManager.java b/src/main/java/server/loot/LootManager.java index a747cc41d8..5df9aa1554 100644 --- a/src/main/java/server/loot/LootManager.java +++ b/src/main/java/server/loot/LootManager.java @@ -20,8 +20,8 @@ package server.loot; import client.Character; +import database.drop.DropProvider; import server.life.MonsterDropEntry; -import server.life.MonsterInformationProvider; import server.quest.Quest; import java.util.Collections; @@ -63,8 +63,8 @@ public class LootManager { return false; } - public static List retrieveRelevantDrops(int monsterId, List chrs) { - List drops = MonsterInformationProvider.getInstance().retrieveEffectiveDrop(monsterId); + public static List retrieveRelevantDrops(int monsterId, List chrs, DropProvider dropProvider) { + List drops = dropProvider.getMonsterDropEntries(monsterId); if (drops.isEmpty()) { return Collections.emptyList(); } diff --git a/src/main/java/server/maps/MapFactory.java b/src/main/java/server/maps/MapFactory.java index 1c7a85cd0c..9d3f808fdd 100644 --- a/src/main/java/server/maps/MapFactory.java +++ b/src/main/java/server/maps/MapFactory.java @@ -22,6 +22,7 @@ package server.maps; import constants.id.MapId; +import database.drop.DropProvider; import provider.Data; import provider.DataProvider; import provider.DataProviderFactory; @@ -127,7 +128,8 @@ public class MapFactory { } } - public static MapleMap loadMapFromWz(int mapid, int world, int channel, EventInstanceManager event) { + public static MapleMap loadMapFromWz(int mapid, int world, int channel, EventInstanceManager event, + DropProvider dropProvider) { MapleMap map; String mapName = getMapName(mapid); @@ -144,7 +146,7 @@ public class MapFactory { if (mobRate != null) { monsterRate = (Float) mobRate.getData(); } - map = new MapleMap(mapid, world, channel, DataTool.getInt("returnMap", infoData), monsterRate); + map = new MapleMap(mapid, world, channel, DataTool.getInt("returnMap", infoData), monsterRate, dropProvider); map.setEventInstance(event); String onFirstEnter = DataTool.getString(infoData.getChildByPath("onFirstUserEnter"), String.valueOf(mapid)); diff --git a/src/main/java/server/maps/MapManager.java b/src/main/java/server/maps/MapManager.java index 4b79038abf..32f43615e6 100644 --- a/src/main/java/server/maps/MapManager.java +++ b/src/main/java/server/maps/MapManager.java @@ -19,6 +19,7 @@ */ package server.maps; +import database.drop.DropProvider; import scripting.event.EventInstanceManager; import java.util.HashMap; @@ -30,17 +31,19 @@ import java.util.concurrent.locks.ReentrantReadWriteLock; public class MapManager { private final int channel; private final int world; - private EventInstanceManager event; + private final DropProvider dropProvider; + private EventInstanceManager eventInstanceManager; private final Map maps = new HashMap<>(); private final Lock mapsRLock; private final Lock mapsWLock; - public MapManager(EventInstanceManager eim, int world, int channel) { + public MapManager(EventInstanceManager eim, int world, int channel, DropProvider dropProvider) { this.world = world; this.channel = channel; - this.event = eim; + this.eventInstanceManager = eim; + this.dropProvider = dropProvider; ReadWriteLock readWriteLock = new ReentrantReadWriteLock(); this.mapsRLock = readWriteLock.readLock(); @@ -74,7 +77,7 @@ public class MapManager { } } - map = MapFactory.loadMapFromWz(mapid, world, channel, event); + map = MapFactory.loadMapFromWz(mapid, world, channel, eventInstanceManager, dropProvider); if (cache) { mapsWLock.lock(); @@ -135,7 +138,7 @@ public class MapManager { map.dispose(); } - this.event = null; + this.eventInstanceManager = null; } } diff --git a/src/main/java/server/maps/MapleMap.java b/src/main/java/server/maps/MapleMap.java index bf44ba733f..044651e58b 100644 --- a/src/main/java/server/maps/MapleMap.java +++ b/src/main/java/server/maps/MapleMap.java @@ -36,6 +36,7 @@ import constants.game.GameConstants; import constants.id.MapId; import constants.id.MobId; import constants.inventory.ItemConstants; +import database.drop.DropProvider; import net.packet.Packet; import net.server.Server; import net.server.channel.Channel; @@ -109,6 +110,7 @@ public class MapleMap { private final int world; private int seats; private byte monsterRate; + private final DropProvider dropProvider; private boolean clock; private boolean boat; private boolean docked = false; @@ -168,7 +170,7 @@ public class MapleMap { // due to the nature of loadMapFromWz (synchronized), sole function that calls 'generateMapDropRangeCache', this lock remains optional. private static final Lock bndLock = new ReentrantLock(true); - public MapleMap(int mapid, int world, int channel, int returnMapId, float monsterRate) { + public MapleMap(int mapid, int world, int channel, int returnMapId, float monsterRate, DropProvider dropProvider) { this.mapid = mapid; this.channel = channel; this.world = world; @@ -177,6 +179,7 @@ public class MapleMap { if (this.monsterRate == 0) { this.monsterRate = 1; } + this.dropProvider = dropProvider; final ReadWriteLock chrLock = new ReentrantReadWriteLock(true); chrRLock = chrLock.readLock(); @@ -733,7 +736,8 @@ public class MapleMap { final List visibleQuestEntry = new ArrayList<>(); final List otherQuestEntry = new ArrayList<>(); - List lootEntry = YamlConfig.config.server.USE_SPAWN_RELEVANT_LOOT ? mob.retrieveRelevantDrops() : mi.retrieveEffectiveDrop(mob.getId()); + List lootEntry = YamlConfig.config.server.USE_SPAWN_RELEVANT_LOOT ? + mob.retrieveRelevantDrops(dropProvider) : dropProvider.getMonsterDropEntries(mob.getId()); sortDropEntries(lootEntry, dropEntry, visibleQuestEntry, otherQuestEntry, chr); // thanks Articuno, Limit, Rohenn for noticing quest loots not showing up in only-quest item drops scenario if (lootEntry.isEmpty()) { // thanks resinate