Load rune bases from all non-RACE runes, dropping static_rune_runebase reads

The 315 static_rune_runebase rows are exactly the non-RACE runes, so the loader
selects by rune_type. Removes the server type/subtype columns (no live reader),
the runereq/overwrite path, the GET_RUNEBASE cache-miss query, the runebase
attribute handler, the racerune/baseclassrune loaders and the 111111 checks.
No value changes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
MagicBotandClaude Opus 5.5 committed 2026-10-22 12:36:34 -04:00
1 parent 13e02707eb
commit 64a86152d3
8 files changed
+8 -367

No files matched your search

@@ -1,48 +0,0 @@
// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ .
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀
// Magicbane Emulator Project © 2013 - 2026
// https://www.magicbane.com
package engine.db.handlers;
import engine.gameManager.DbManager;
import engine.mbEnums;
import engine.objects.RuneBaseAttribute;
import org.pmw.tinylog.Logger;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
public class dbRuneBaseAttributeHandler extends dbHandlerBase {
public dbRuneBaseAttributeHandler() {
this.localClass = RuneBaseAttribute.class;
this.localObjectType = mbEnums.GameObjectType.valueOf(this.localClass.getSimpleName());
}
public ArrayList<RuneBaseAttribute> GET_ATTRIBUTES_FOR_RUNEBASE() {
ArrayList<RuneBaseAttribute> runeBaseAttributesList = new ArrayList<>();
try (Connection connection = DbManager.getConnection();
PreparedStatement preparedStatement = connection.prepareStatement("SELECT * FROM `static_rune_runebaseattribute`")) {
ResultSet rs = preparedStatement.executeQuery();
runeBaseAttributesList = getObjectsFromRs(rs, 10);
} catch (SQLException e) {
Logger.error(e);
}
return runeBaseAttributesList;
}
}
@@ -107,154 +107,4 @@ public class dbRuneBaseHandler extends dbHandlerBase {
Logger.info("read: " + recordsRead + " cached: " + runeSkillAdjusts.size());
return runeSkillAdjusts;
}
public void GET_RUNE_REQS(final RuneBase rb) {
try (Connection connection = DbManager.getConnection();
PreparedStatement preparedStatement = connection.prepareStatement("SELECT * FROM `static_rune_runereq` WHERE `runeID` = ?")) {
preparedStatement.setInt(1, rb.getObjectUUID());
ResultSet rs = preparedStatement.executeQuery();
while (rs.next()) {
int type = rs.getInt("type");
switch (type) {
case 1:
rb.getRace().put(rs.getInt("requiredRuneID"), rs.getBoolean("isAllowed"));
break;
case 2:
rb.getBaseClass().put(rs.getInt("requiredRuneID"), rs.getBoolean("isAllowed"));
break;
case 3:
rb.getPromotionClass().put(rs.getInt("requiredRuneID"), rs.getBoolean("isAllowed"));
break;
case 4:
rb.getDiscipline().put(rs.getInt("requiredRuneID"), rs.getBoolean("isAllowed"));
break;
case 5:
rb.getOverwrite().add(rs.getInt("requiredRuneID"));
break;
case 6:
rb.setLevelRequired(rs.getInt("requiredRuneID"));
break;
}
}
} catch (SQLException e) {
Logger.error(e);
}
}
public RuneBase GET_RUNEBASE(final int id) {
RuneBase runeBase = null;
try (Connection connection = DbManager.getConnection();
PreparedStatement preparedStatement = connection.prepareStatement("SELECT * FROM `static_rune_runebase` WHERE `ID` = ?")) {
preparedStatement.setInt(1, id);
ResultSet rs = preparedStatement.executeQuery();
runeBase = (RuneBase) getObjectFromRs(rs);
} catch (SQLException e) {
Logger.error(e);
}
return runeBase;
}
public ArrayList<RuneBase> LOAD_ALL_RUNEBASES() {
ArrayList<RuneBase> runeBasesList = new ArrayList<>();
try (Connection connection = DbManager.getConnection();
PreparedStatement preparedStatement = connection.prepareStatement("SELECT * FROM `static_rune_runebase`;")) {
ResultSet rs = preparedStatement.executeQuery();
runeBasesList = getObjectsFromRs(rs, 1000);
} catch (SQLException e) {
Logger.error(e);
}
return runeBasesList;
}
public HashMap<Integer, ArrayList<Integer>> LOAD_ALLOWED_STARTING_RUNES_FOR_BASECLASS() {
HashMap<Integer, ArrayList<Integer>> runeSets = new HashMap<>();
int recordsRead = 0;
try (Connection connection = DbManager.getConnection();
PreparedStatement preparedStatement = connection.prepareStatement("SELECT * FROM static_rune_baseclassrune")) {
ResultSet rs = preparedStatement.executeQuery();
while (rs.next()) {
recordsRead++;
int baseClassID = rs.getInt("BaseClassesID");
int runeBaseID = rs.getInt("RuneBaseID");
if (runeSets.get(baseClassID) == null) {
ArrayList<Integer> runeList = new ArrayList<>();
runeList.add(runeBaseID);
runeSets.put(baseClassID, runeList);
} else {
ArrayList<Integer> runeList = runeSets.get(baseClassID);
runeList.add(runeBaseID);
runeSets.put(baseClassID, runeList);
}
}
} catch (SQLException e) {
Logger.error(e);
}
Logger.info("read: " + recordsRead + " cached: " + runeSets.size());
return runeSets;
}
public HashMap<Integer, ArrayList<Integer>> LOAD_ALLOWED_STARTING_RUNES_FOR_RACE() {
HashMap<Integer, ArrayList<Integer>> runeSets;
runeSets = new HashMap<>();
int recordsRead = 0;
try (Connection connection = DbManager.getConnection();
PreparedStatement preparedStatement = connection.prepareStatement("SELECT * FROM static_rune_racerune")) {
ResultSet rs = preparedStatement.executeQuery();
while (rs.next()) {
recordsRead++;
int raceID = rs.getInt("RaceID");
int runeBaseID = rs.getInt("RuneBaseID");
if (runeSets.get(raceID) == null) {
ArrayList<Integer> runeList = new ArrayList<>();
runeList.add(runeBaseID);
runeSets.put(raceID, runeList);
} else {
ArrayList<Integer> runeList = runeSets.get(raceID);
runeList.add(runeBaseID);
runeSets.put(raceID, runeList);
}
}
} catch (SQLException e) {
Logger.error(e);
}
Logger.info("read: " + recordsRead + " cached: " + runeSets.size());
return runeSets;
}
}
-1
View File
@@ -58,7 +58,6 @@ public enum DbManager {
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();
-4
View File
@@ -237,10 +237,6 @@ public class BaseClass extends AbstractGameObject {
if (this.getRuneList().contains(rb.getObjectUUID()))
return true;
if (RuneBase.AllowedBaseClassRunesMap.containsKey(111111)) {
if (RuneBase.AllowedBaseClassRunesMap.get(111111).contains(rb.getObjectUUID()))
return true;
}
return false;
}
-14
View File
@@ -10,7 +10,6 @@
package engine.objects;
import engine.gameManager.DbManager;
import engine.net.ByteBufferWriter;
import org.pmw.tinylog.Logger;
import java.sql.ResultSet;
@@ -71,19 +70,6 @@ public class NPCRune extends AbstractGameObject {
}
}
public static void serializeForClientMsg(NPCRune npcRune, ByteBufferWriter writer) {
if (npcRune.runeBase != null) {
writer.putInt(npcRune.runeBase.getType());
writer.putInt(0);
writer.putInt(npcRune.runeBase.getObjectUUID());
writer.putInt(npcRune.getObjectType().ordinal());
writer.putInt(npcRune.getObjectUUID());
} else {
for (int i = 0; i < 5; i++)
writer.putInt(0);
}
}
/*
* Getters
*/
-4
View File
@@ -395,10 +395,6 @@ public class Race {
if (this.getAllowedRunes() != null)
if (this.getAllowedRunes().contains(rb.getObjectUUID()))
return true;
if (RuneBase.AllowedBaseClassRunesMap.containsKey(111111)) {
if (RuneBase.AllowedRaceRunesMap.get(111111).contains(rb.getObjectUUID()))
return true;
}
return false;
}
+8 -106
View File
@@ -11,15 +11,12 @@ package engine.objects;
import engine.gameManager.DbManager;
import engine.mbEnums;
import engine.net.ByteBufferWriter;
import engine.parsers.cache.CObjectIndex;
import engine.parsers.objects.RuneTemplate;
import engine.server.MBServerStatics;
import engine.util.Hasher;
import org.pmw.tinylog.Logger;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
@@ -37,13 +34,10 @@ public class RuneBase extends AbstractGameObject {
private static final Set<Integer> NON_CREATION_TALENTS = new HashSet<>(Arrays.asList(2910, 2911, 250081, 250116, 250117, 250123, 250124, 250125));
private final String name;
private final String description;
private final int type;
private final byte subtype;
private final ConcurrentHashMap<Integer, Boolean> race = new ConcurrentHashMap<>(MBServerStatics.CHM_INIT_CAP, MBServerStatics.CHM_LOAD, MBServerStatics.CHM_THREAD_LOW);
private final ConcurrentHashMap<Integer, Boolean> baseClass = new ConcurrentHashMap<>(MBServerStatics.CHM_INIT_CAP, MBServerStatics.CHM_LOAD, MBServerStatics.CHM_THREAD_LOW);
private final ConcurrentHashMap<Integer, Boolean> promotionClass = new ConcurrentHashMap<>(MBServerStatics.CHM_INIT_CAP, MBServerStatics.CHM_LOAD, MBServerStatics.CHM_THREAD_LOW);
private final ConcurrentHashMap<Integer, Boolean> discipline = new ConcurrentHashMap<>(MBServerStatics.CHM_INIT_CAP, MBServerStatics.CHM_LOAD, MBServerStatics.CHM_THREAD_LOW);
private final ArrayList<Integer> overwrite = new ArrayList<>();
private int levelRequired = 1;
private ArrayList<MobBaseEffects> effectsList = new ArrayList<>();
private mbEnums.RuneType runeType;
@@ -53,56 +47,11 @@ public class RuneBase extends AbstractGameObject {
private boolean classRestrict;
private boolean discRestrict;
/**
* No Table ID Constructor
*/
public RuneBase(String name, String description, int type, byte subtype, ArrayList<RuneBaseAttribute> attrs) {
super();
this.name = name;
this.description = description;
this.type = type;
this.subtype = subtype;
}
/**
* Normal Constructor
*/
public RuneBase(String name, String description, int type, byte subtype, ArrayList<RuneBaseAttribute> attrs, int newUUID) {
super(newUUID);
this.name = name;
this.description = description;
this.type = type;
this.subtype = subtype;
}
/**
* ResultSet Constructor
*/
public RuneBase(ResultSet rs) throws SQLException {
super(rs);
this.name = rs.getString("name");
this.description = rs.getString("description");
this.type = rs.getInt("type");
this.subtype = rs.getByte("subtype");
// static_rune_runereq race/class rows are whitelists, its discipline rows prohibitions
this.discRestrict = true;
DbManager.RuneBaseQueries.GET_RUNE_REQS(this);
this.effectsList = MobBaseEffects.getEffectsForRune(this.getObjectUUID());
}
/**
* Rune Template Constructor
* type and subtype are server enums that don't map cleanly from rune_type/rune_sub_type, so they
* come from the static_rune_runebase row.
* Talents with the same sub type token replace each other by rank (client 0x4695D0), so no overwrite list.
*/
public RuneBase(RuneTemplate rune, RuneBase dbRuneBase) {
public RuneBase(RuneTemplate rune) {
super(rune.template_id);
Integer classRuneID;
@@ -112,8 +61,6 @@ public class RuneBase extends AbstractGameObject {
this.name = rune.item_base_name;
this.description = rune.rune_dsc;
this.type = dbRuneBase.type;
this.subtype = dbRuneBase.subtype;
this.effectsList = MobBaseEffects.getEffectsForRune(rune.template_id);
this.runeType = rune.rune_type;
this.rank = rune.rune_rank;
@@ -171,48 +118,27 @@ public class RuneBase extends AbstractGameObject {
if (tableId == 0)
return null;
RuneBase rb = (RuneBase) DbManager.getFromCache(mbEnums.GameObjectType.RuneBase, tableId);
if (rb != null)
return rb;
return DbManager.RuneBaseQueries.GET_RUNEBASE(tableId);
return (RuneBase) DbManager.getFromCache(mbEnums.GameObjectType.RuneBase, tableId);
}
public static void serializeForClientMsg(RuneBase runeBase, ByteBufferWriter writer) {
writer.putInt(runeBase.type);
writer.putInt(0); // Pad
writer.putInt(runeBase.getObjectUUID());
writer.putInt(runeBase.getObjectType().ordinal());
writer.putInt(runeBase.getObjectUUID());
}
// Iterates the static_rune_runebase rows: no rune field separates the player runes from the mob
// talents, and each row still holds the server type/subtype.
// Rune bases are every non-RACE rune: the classes, disciplines and talents (the 315 former static_rune_runebase rows).
public static void LoadAllRuneBases() {
ArrayList<RuneBase> dbRuneBases;
ArrayList<RuneBaseAttribute> attributes;
RuneTemplate rune;
int loadedCount = 0;
dbRuneBases = DbManager.RuneBaseQueries.LOAD_ALL_RUNEBASES();
RuneBaseAttribute.runeBaseAttributeMap.clear();
for (RuneBase dbRuneBase : dbRuneBases) {
rune = RuneTemplate._runes.get(dbRuneBase.getObjectUUID());
for (RuneTemplate rune : RuneTemplate._runes.values()) {
if (rune == null) {
Logger.warn("RuneBase " + dbRuneBase.getObjectUUID() + " has no rune; loaded from static_rune_runebase without attributes");
if (rune.rune_type == mbEnums.RuneType.RACE)
continue;
}
DbManager.addToCache(new RuneBase(rune, dbRuneBase));
DbManager.addToCache(new RuneBase(rune));
attributes = RuneBaseAttribute.getAttributesForRune(rune);
// getAttrs() returns null for a rune without attributes, as the DB map did
// getAttrs() returns null for a rune without attributes
if (!attributes.isEmpty())
RuneBaseAttribute.runeBaseAttributeMap.put(rune.template_id, attributes);
@@ -224,7 +150,7 @@ public class RuneBase extends AbstractGameObject {
loadCreationTalents();
}
// Every creation race and class gets a list, so the 111111 "any" sentinel of the DB tables is no longer used.
// Every creation race and class gets an explicit list; there is no "any" entry.
private static void loadCreationTalents() {
@@ -318,15 +244,6 @@ public class RuneBase extends AbstractGameObject {
return false;
}
if (this.type != rbObj.type) {
return false;
}
if (this.subtype != rbObj.subtype) {
return false;
}
return true;
}
@@ -344,17 +261,6 @@ public class RuneBase extends AbstractGameObject {
return description;
}
public int getType() {
return type;
}
/**
* @return the subtype
*/
public byte getSubtype() {
return subtype;
}
/**
* @return the attrs
*/
@@ -378,10 +284,6 @@ public class RuneBase extends AbstractGameObject {
return this.discipline;
}
public ArrayList<Integer> getOverwrite() {
return this.overwrite;
}
public mbEnums.RuneType getRuneType() {
return this.runeType;
}
-40
View File
@@ -9,14 +9,10 @@
package engine.objects;
import engine.gameManager.DbManager;
import engine.mbEnums;
import engine.mbEnums.GameObjectType;
import engine.parsers.objects.RuneTemplate;
import engine.server.MBServerStatics;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.EnumMap;
import java.util.HashMap;
@@ -27,7 +23,6 @@ public class RuneBaseAttribute extends AbstractGameObject {
public static HashMap<Integer, ArrayList<RuneBaseAttribute>> runeBaseAttributeMap = new HashMap<>();
private short attributeID;
private short modValue;
private int runeBaseID;
/**
@@ -50,17 +45,6 @@ public class RuneBaseAttribute extends AbstractGameObject {
this.modValue = modValue;
}
/**
* ResultSet Constructor
*/
public RuneBaseAttribute(ResultSet rs) throws SQLException {
super(rs);
this.attributeID = rs.getShort("attributeID");
this.modValue = rs.getShort("modValue");
this.runeBaseID = rs.getInt("RuneBaseID");
}
// Attribute ids: 0 = rune_creation_cost, 1-5 = rune_attr_adj, 6-10 = rune_max_attr_adj,
// 11-15 = item_attr_req; the AttributeType ordinals Strength..Spirit are 1-5.
@@ -88,30 +72,6 @@ public class RuneBaseAttribute extends AbstractGameObject {
}
}
public static void LoadAllAttributes() {
DbManager.RuneBaseAttributeQueries.GET_ATTRIBUTES_FOR_RUNEBASE();
//cache attributeLists for rune.
for (AbstractGameObject ago : DbManager.getList(GameObjectType.RuneBaseAttribute)) {
RuneBaseAttribute runeBaseAttribute = (RuneBaseAttribute) ago;
int runeBaseID = ((RuneBaseAttribute) runeBaseAttribute).runeBaseID;
if (runeBaseAttributeMap.get(runeBaseID) == null) {
ArrayList<RuneBaseAttribute> attributeList = new ArrayList<>();
attributeList.add(runeBaseAttribute);
runeBaseAttributeMap.put(runeBaseID, attributeList);
} else {
ArrayList<RuneBaseAttribute> attributeList = runeBaseAttributeMap.get(runeBaseID);
attributeList.add(runeBaseAttribute);
runeBaseAttributeMap.put(runeBaseID, attributeList);
}
}
}
/*
* Getters
*/