Files
prestonbane/src/engine/objects/RuneBase.java
T
MagicBotandClaude Opus 5.5 83f57b4def Build RuneBase and its attributes from the rune and compare them
Adds RuneBase(RuneTemplate, RuneBase): name from item_base_name, description
from rune_dsc. type and subtype stay the static_rune_runebase values: they are
server enums that don't map cleanly from rune_type/rune_sub_type (CLASS runes
carry 0/2/3/5/256/289; the creation exclusive-group subtypes 1-10 leave out
Blood Gift, the MaxIncrease chains and the hashed sub types). The requirement
maps and effects are copied from the DB row until 2.5b/2.10.
RuneBaseAttribute.getAttributesForRune builds attribute 0 from
rune_creation_cost, 1-5 from rune_attr_adj, 6-10 from rune_max_attr_adj and
11-15 from item_attr_req. A static_rune_runebase comparator checks name and
attributes against the JSON.

Offline parity (scripts/p24.py, 315 runebase rows + 365 attribute rows vs the
RUNE JSON): every row has a rune; all 365 DB attribute rows match. Differences:
- name: 9 DB typos (Confesser, Theif, LagMaster, WP Dev, Exception Strength/
  Dexterity/Constitution/Intelligence/Spirit)
- attributes: 17 runes with no DB rows gain JSON values: base classes
  2500-2503, Pet 2522, admin 2905/2907/2909/2911, guards 252621-252623, and
  creation cost on 250116, 250117, 250123-250125
- description: '' (or CSR text on 2901-2911) -> rune_dsc; nothing reads it

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-21 08:25:20 -04:00

238 lines
7.3 KiB
Java

// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ .
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀
// Magicbane Emulator Project © 2013 - 2026
// https://www.magicbane.com
package engine.objects;
import engine.gameManager.DbManager;
import engine.mbEnums;
import engine.net.ByteBufferWriter;
import engine.parsers.objects.RuneTemplate;
import engine.server.MBServerStatics;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.concurrent.ConcurrentHashMap;
public class RuneBase extends AbstractGameObject {
public static HashMap<Integer, ArrayList<Integer>> AllowedBaseClassRunesMap = new HashMap<>();
public static HashMap<Integer, ArrayList<Integer>> AllowedRaceRunesMap = new HashMap<>();
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<>();
/**
* 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");
DbManager.RuneBaseQueries.GET_RUNE_REQS(this);
this.effectsList = DbManager.MobBaseQueries.GET_RUNEBASE_EFFECTS(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, as do the requirement maps and effects until 2.5b/2.10.
*/
public RuneBase(RuneTemplate rune, RuneBase dbRuneBase) {
super(rune.template_id);
this.name = rune.item_base_name;
this.description = rune.rune_dsc;
this.type = dbRuneBase.type;
this.subtype = dbRuneBase.subtype;
this.race.putAll(dbRuneBase.race);
this.baseClass.putAll(dbRuneBase.baseClass);
this.promotionClass.putAll(dbRuneBase.promotionClass);
this.discipline.putAll(dbRuneBase.discipline);
this.overwrite.addAll(dbRuneBase.overwrite);
this.levelRequired = dbRuneBase.levelRequired;
this.effectsList = dbRuneBase.effectsList;
}
public static RuneBase getRuneBase(int tableId) {
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);
}
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());
}
public static void LoadAllRuneBases() {
DbManager.RuneBaseQueries.LOAD_ALL_RUNEBASES();
RuneBase.AllowedBaseClassRunesMap = DbManager.RuneBaseQueries.LOAD_ALLOWED_STARTING_RUNES_FOR_BASECLASS();
RuneBase.AllowedRaceRunesMap = DbManager.RuneBaseQueries.LOAD_ALLOWED_STARTING_RUNES_FOR_RACE();
}
@Override
public boolean equals(Object obj) {
if (!super.equals(obj)) {
return false;
}
if (obj instanceof RuneBase) {
RuneBase rbObj = (RuneBase) obj;
if (!this.name.equals(rbObj.name)) {
return false;
}
if (!this.description.equals(rbObj.description)) {
return false;
}
if (this.type != rbObj.type) {
return false;
}
if (this.subtype != rbObj.subtype) {
return false;
}
return true;
}
return false;
}
/*
* Getters
*/
public String getName() {
return name;
}
public String getDescription() {
return description;
}
public int getType() {
return type;
}
/**
* @return the subtype
*/
public byte getSubtype() {
return subtype;
}
/**
* @return the attrs
*/
public ArrayList<RuneBaseAttribute> getAttrs() {
return RuneBaseAttribute.runeBaseAttributeMap.get(this.getObjectUUID());
}
public ConcurrentHashMap<Integer, Boolean> getRace() {
return this.race;
}
public ConcurrentHashMap<Integer, Boolean> getBaseClass() {
return this.baseClass;
}
public ConcurrentHashMap<Integer, Boolean> getPromotionClass() {
return this.promotionClass;
}
public ConcurrentHashMap<Integer, Boolean> getDiscipline() {
return this.discipline;
}
public ArrayList<Integer> getOverwrite() {
return this.overwrite;
}
/*
* Serializing
*/
public int getLevelRequired() {
return this.levelRequired;
}
public void setLevelRequired(int levelRequired) {
this.levelRequired = levelRequired;
}
@Override
public void updateDatabase() {
// TODO Auto-generated method stub
}
/**
* @return the effectsList
*/
public ArrayList<MobBaseEffects> getEffectsList() {
return effectsList;
}
}