Public Repository for the Magicbane Shadowbane Emulator
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

328 lines
11 KiB

// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ .
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀
// Magicbane Emulator Project © 2013 - 2022
// www.magicbane.com
package engine.gameManager;
import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import engine.Enum;
import engine.Enum.GameObjectType;
import engine.db.handlers.*;
import engine.objects.*;
import engine.server.MBServerStatics;
import engine.util.Hasher;
import org.pmw.tinylog.Logger;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.EnumMap;
import java.util.concurrent.ConcurrentHashMap;
public enum DbManager {
DBMANAGER;
private static HikariDataSource connectionPool = null;
public static Hasher hasher;
//Local Object Caching
private static final EnumMap<GameObjectType, ConcurrentHashMap<Integer, AbstractGameObject>> objectCache = new EnumMap<>(GameObjectType.class);
public static AbstractGameObject getObject(GameObjectType objectType, int objectUUID) {
AbstractGameObject outObject = null;
switch (objectType) {
case PlayerCharacter:
outObject = PlayerCharacter.getPlayerCharacter(objectUUID);
break;
case NPC:
outObject = NPC.getNPC(objectUUID);
break;
case Mob:
outObject = Mob.getFromCache(objectUUID);
break;
case Building:
outObject = BuildingManager.getBuilding(objectUUID);
break;
case Guild:
outObject = Guild.getGuild(objectUUID);
break;
case Item:
outObject = Item.getFromCache(objectUUID);
break;
case MobLoot:
outObject = MobLoot.getFromCache(objectUUID);
break;
case City:
outObject = City.getCity(objectUUID);
break;
default:
Logger.error("Attempt to retrieve nonexistant " + objectType +
" from object cache." );
break;
}
return outObject;
}
public static boolean inCache(GameObjectType gameObjectType, int uuid) {
if (objectCache.get(gameObjectType) == null)
return false;
return (objectCache.get(gameObjectType).containsKey(uuid));
}
public static AbstractGameObject getFromCache(GameObjectType gameObjectType, int uuid) {
if (objectCache.get(gameObjectType) == null)
return null;
return objectCache.get(gameObjectType).get(uuid);
}
public static void removeFromCache(GameObjectType gameObjectType, int uuid) {
AbstractGameObject abstractGameObject;
if (objectCache.get(gameObjectType) == null)
return;
abstractGameObject = objectCache.get(gameObjectType).get(uuid);
if (abstractGameObject == null)
return;
removeFromCache(abstractGameObject);
}
public static void removeFromCache(AbstractGameObject abstractGameObject) {
if (abstractGameObject == null)
return;
if (objectCache.get(abstractGameObject.getObjectType()) == null)
return;
// Remove object from game cache
objectCache.get(abstractGameObject.getObjectType()).remove(abstractGameObject.getObjectUUID());
// Release bounds as we're dispensing with this object.
if (abstractGameObject instanceof AbstractWorldObject) {
AbstractWorldObject abstractWorldObject = (AbstractWorldObject)abstractGameObject;
if (abstractWorldObject.getBounds() != null) {
abstractWorldObject.getBounds().release();
abstractWorldObject.setBounds(null);
}
}
}
public static boolean addToCache(AbstractGameObject gameObject) {
boolean isWorldServer = ConfigManager.serverType.equals(Enum.ServerType.WORLDSERVER);
if (!isWorldServer) {
if (MBServerStatics.SKIP_CACHE_LOGIN)
return true;
if (MBServerStatics.SKIP_CACHE_LOGIN_PLAYER
&& (gameObject.getObjectType() == GameObjectType.PlayerCharacter))
return true;
if (MBServerStatics.SKIP_CACHE_LOGIN_ITEM &&
(gameObject.getObjectType() == GameObjectType.Item))
return true;
}
// First time this object type has been cached. Create the hashmap.
if (objectCache.get(gameObject.getObjectType()) == null) {
int initialCapacity;
// Provide initial sizing hints
switch (gameObject.getObjectType()) {
case Building:
initialCapacity = 46900;
break;
case Mob:
initialCapacity = 11700;
break;
case NPC:
initialCapacity = 900;
break;
case Zone:
initialCapacity = 1070;
break;
case Account:
initialCapacity = 10000;
break;
case Guild:
initialCapacity = 100;
break;
case ItemContainer:
initialCapacity = 100;
break;
case Item:
initialCapacity = 1000;
break;
case MobLoot:
initialCapacity = 10000;
break;
case PlayerCharacter:
initialCapacity = 100;
break;
default:
initialCapacity = 100; // Lookup api default should be ok for small maps
break;
}
objectCache.put(gameObject.getObjectType(), new ConcurrentHashMap<>(initialCapacity));
}
// Add the object to the cache. This will overwrite the current map entry.
objectCache.get(gameObject.getObjectType()).put(gameObject.getObjectUUID(), gameObject);
return true;
}
public static java.util.Collection<AbstractGameObject> getList(GameObjectType gameObjectType) {
if (objectCache.get(gameObjectType) == null)
return null;
return objectCache.get(gameObjectType).values();
}
public static PreparedStatement prepareStatement(String sql) throws SQLException {
return getConnection().prepareStatement(sql, 1);
}
// Omg refactor this out, somebody!
public static ConcurrentHashMap<Integer, AbstractGameObject> getMap(
GameObjectType gameObjectType) {
if (objectCache.get(gameObjectType) == null)
return null;
return objectCache.get(gameObjectType);
}
public static void printCacheCount(PlayerCharacter pc) {
ChatManager.chatSystemInfo(pc, "Cache Lists");
for (GameObjectType gameObjectType : GameObjectType.values()) {
if (objectCache.get(gameObjectType) == null)
continue;
String ret = gameObjectType.name() + ": " + objectCache.get(gameObjectType).size();
ChatManager.chatSystemInfo(pc, ret + '\n');
}
}
/**
* @return the conn
*/
//XXX I think we have a severe resource leak here! No one is putting the connections back!
public static Connection getConnection() {
try {
return DbManager.connectionPool.getConnection();
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
public static final dbAccountHandler AccountQueries = new dbAccountHandler();
public static final dbBaneHandler BaneQueries = new dbBaneHandler();
public static final dbBaseClassHandler BaseClassQueries = new dbBaseClassHandler();
public static final dbBuildingHandler BuildingQueries = new dbBuildingHandler();
public static final dbBuildingLocationHandler BuildingLocationQueries = new dbBuildingLocationHandler();
public static final dbCharacterPowerHandler CharacterPowerQueries = new dbCharacterPowerHandler();
public static final dbCharacterRuneHandler CharacterRuneQueries = new dbCharacterRuneHandler();
public static final dbCharacterSkillHandler CharacterSkillQueries = new dbCharacterSkillHandler();
public static final dbCityHandler CityQueries = new dbCityHandler();
public static final dbContractHandler ContractQueries = new dbContractHandler();
public static final dbWarehouseHandler WarehouseQueries = new dbWarehouseHandler();
public static final dbCSSessionHandler CSSessionQueries = new dbCSSessionHandler();
public static final dbEnchantmentHandler EnchantmentQueries = new dbEnchantmentHandler();
public static final dbEffectsResourceCostHandler EffectsResourceCostsQueries = new dbEffectsResourceCostHandler();
public static final dbGuildHandler GuildQueries = new dbGuildHandler();
public static final dbItemHandler ItemQueries = new dbItemHandler();
public static final dbItemBaseHandler ItemBaseQueries = new dbItemBaseHandler();
public static final dbKitHandler KitQueries = new dbKitHandler();
public static final dbLootTableHandler LootQueries = new dbLootTableHandler();
public static final dbMenuHandler MenuQueries = new dbMenuHandler();
public static final dbMineHandler MineQueries = new dbMineHandler();
public static final dbMobHandler MobQueries = new dbMobHandler();
public static final dbMobBaseHandler MobBaseQueries = new dbMobBaseHandler();
public static final dbNPCHandler NPCQueries = new dbNPCHandler();
public static final dbPlayerCharacterHandler PlayerCharacterQueries = new dbPlayerCharacterHandler();
public static final dbPromotionClassHandler PromotionQueries = new dbPromotionClassHandler();
public static final dbRaceHandler RaceQueries = new dbRaceHandler();
public static final dbResistHandler ResistQueries = new dbResistHandler();
public static final dbRuneBaseAttributeHandler RuneBaseAttributeQueries = new dbRuneBaseAttributeHandler();
public static final dbRuneBaseEffectHandler RuneBaseEffectQueries = new dbRuneBaseEffectHandler();
public static final dbRuneBaseHandler RuneBaseQueries = new dbRuneBaseHandler();
public static final dbSkillBaseHandler SkillsBaseQueries = new dbSkillBaseHandler();
public static final dbSkillReqHandler SkillReqQueries = new dbSkillReqHandler();
public static final dbVendorDialogHandler VendorDialogQueries = new dbVendorDialogHandler();
public static final dbZoneHandler ZoneQueries = new dbZoneHandler();
public static final dbRealmHandler RealmQueries = new dbRealmHandler();
public static final dbBlueprintHandler BlueprintQueries = new dbBlueprintHandler();
public static final dbBoonHandler BoonQueries = new dbBoonHandler();
public static final dbShrineHandler ShrineQueries = new dbShrineHandler();
public static final dbHeightMapHandler HeightMapQueries = new dbHeightMapHandler();
public static final dbRunegateHandler RunegateQueries = new dbRunegateHandler();
public static void configureConnectionPool() {
HikariConfig config = new HikariConfig();
int connectionCount = (Runtime.getRuntime().availableProcessors() * 2) + 1;
config.setMaximumPoolSize(connectionCount);
config.setJdbcUrl("jdbc:mysql://" + ConfigManager.MB_DATABASE_ADDRESS.getValue() +
":" + ConfigManager.MB_DATABASE_PORT.getValue() + "/" +
ConfigManager.MB_DATABASE_NAME.getValue());
config.setUsername(ConfigManager.MB_DATABASE_USER.getValue());
config.setPassword(ConfigManager.MB_DATABASE_PASS.getValue());
config.addDataSourceProperty("minimumIdle", "5");
config.addDataSourceProperty("maxLifetime", "3600000");
config.addDataSourceProperty("characterEncoding", "utf8");
config.addDataSourceProperty("useServerPrepStmts", "true");
config.addDataSourceProperty("cachePrepStmts", "true");
config.addDataSourceProperty("prepStmtCacheSize", "500");
config.addDataSourceProperty("prepStmtCacheSqlLimit", "2048");
config.addDataSourceProperty("leakDetectionThreshold", "5000");
config.addDataSourceProperty("cacheServerConfiguration", "true");
connectionPool = new HikariDataSource(config); // setup the connection pool
Logger.info("Database pool has " + connectionCount + " max connections");
}
}