From db67e56302e01b085935687babdb0451a090272c Mon Sep 17 00:00:00 2001 From: MagicBot Date: Fri, 23 Oct 2026 11:35:58 -0400 Subject: [PATCH] Write static_rune_lookup from the loaded race and class caches at world boot The DB views char_perAccount and dyn_trash_detail lost their race and class names when 2.11 dropped the Phase 2 tables. The world server now rewrites the generated static_rune_lookup table (ID, type, name) after the second Race.loadAllRaces(): 26 player races, 4 base classes, the promotion runes and the CSR promotion rows 2901-2911. One transaction (delete, batch insert, commit); on any failure it rolls back and logs a warning, the boot continues. Names come from the runes: races use obj_name (as in 2.3), classes the rune names, so DB typos such as "Theif" become "Thief" in the views. No gameplay change. Needs JSON-Refactor-Plan/sql/2.12-rune-lookup.sql (table, level functions, views) run before boot. Co-Authored-By: Claude Opus 5.5 --- src/engine/db/handlers/dbRuneBaseHandler.java | 58 +++++++++++++++++++ src/engine/objects/Race.java | 5 ++ src/engine/server/world/WorldServer.java | 3 + 3 files changed, 66 insertions(+) diff --git a/src/engine/db/handlers/dbRuneBaseHandler.java b/src/engine/db/handlers/dbRuneBaseHandler.java index d46c1fe4..365b59d8 100644 --- a/src/engine/db/handlers/dbRuneBaseHandler.java +++ b/src/engine/db/handlers/dbRuneBaseHandler.java @@ -11,6 +11,10 @@ package engine.db.handlers; import engine.gameManager.DbManager; import engine.mbEnums; +import engine.objects.AbstractGameObject; +import engine.objects.BaseClass; +import engine.objects.PromotionClass; +import engine.objects.Race; import engine.objects.RuneBase; import engine.powers.RunePowerEntry; import org.pmw.tinylog.Logger; @@ -67,4 +71,58 @@ public class dbRuneBaseHandler extends dbHandlerBase { Logger.info("read: " + recordsRead + " cached: " + mobPowers.size()); return mobPowers; } + + // static_rune_lookup is generated for the DB views; a failed write must never stop the boot + public static void WRITE_RUNE_LOOKUP() { + + int rowsWritten = 0; + + try (Connection connection = DbManager.getConnection(); + PreparedStatement deleteStatement = connection.prepareStatement("DELETE FROM `static_rune_lookup`"); + PreparedStatement insertStatement = connection.prepareStatement("INSERT INTO `static_rune_lookup` (`ID`, `type`, `name`) VALUES (?, ?, ?)")) { + + connection.setAutoCommit(false); + + try { + deleteStatement.executeUpdate(); + + for (Race race : Race.getAllRaces()) { + addRuneLookupRow(insertStatement, race.getRaceRuneID(), "RACE", race.getName()); + rowsWritten++; + } + + for (AbstractGameObject baseClass : DbManager.getMap(mbEnums.GameObjectType.BaseClass).values()) { + addRuneLookupRow(insertStatement, baseClass.getObjectUUID(), "BASECLASS", ((BaseClass) baseClass).getName()); + rowsWritten++; + } + + for (AbstractGameObject promotionClass : DbManager.getMap(mbEnums.GameObjectType.PromotionClass).values()) { + addRuneLookupRow(insertStatement, promotionClass.getObjectUUID(), "PROMOTION", ((PromotionClass) promotionClass).getName()); + rowsWritten++; + } + + insertStatement.executeBatch(); + connection.commit(); + } catch (SQLException | RuntimeException e) { + // Roll back before setAutoCommit(true), which would otherwise commit the delete + connection.rollback(); + throw e; + } finally { + connection.setAutoCommit(true); + } + + } catch (Exception e) { + Logger.warn("static_rune_lookup not written; DB views keep their old names: " + e.getMessage()); + return; + } + + Logger.info("static_rune_lookup: wrote " + rowsWritten + " rows"); + } + + private static void addRuneLookupRow(PreparedStatement insertStatement, int runeID, String type, String name) throws SQLException { + insertStatement.setInt(1, runeID); + insertStatement.setString(2, type); + insertStatement.setString(3, name); + insertStatement.addBatch(); + } } diff --git a/src/engine/objects/Race.java b/src/engine/objects/Race.java index 64bd7687..52e87c03 100644 --- a/src/engine/objects/Race.java +++ b/src/engine/objects/Race.java @@ -19,6 +19,7 @@ import engine.util.Hasher; import org.pmw.tinylog.Logger; import java.util.ArrayList; +import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.Map; @@ -174,6 +175,10 @@ public class Race { return _raceByID.get(id); } + public static Collection getAllRaces() { + return _raceByID.values(); + } + @Override public boolean equals(Object object) { diff --git a/src/engine/server/world/WorldServer.java b/src/engine/server/world/WorldServer.java index d0c9fa50..9ca41018 100644 --- a/src/engine/server/world/WorldServer.java +++ b/src/engine/server/world/WorldServer.java @@ -484,6 +484,9 @@ public class WorldServer { mbEnums.RaceType.initRaceTypeTables(); Race.loadAllRaces(); + Logger.info("Writing rune name lookup for the DB views"); + dbRuneBaseHandler.WRITE_RUNE_LOOKUP(); + if (ParityCheck.isEnabled()) { Logger.info("Running DB/JSON parity check"); ParityCheck.run();