forked from MagicBane/Server
Dev commands, BuildingManager, ChatManager, ForgeManager, NPCManager, NPC, Warehouse, WorkOrder and ManageNPCMsg now call CObjectTemplate.lookup instead of ItemTemplate.templates.get. Forge production cost reads getItemResourceCosts(). Only the DB loader and linkCacheTemplates still use the legacy class (removed in Task 1.8). Removes the static_item_templates ParityCheck comparator. Final parity (offline p17.py, 7586 rows): every id has a cache template, 0 item_type differences, 0 item_resource_costs differences (84 ITEMs have costs). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
119 lines
4.1 KiB
Java
119 lines
4.1 KiB
Java
// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ .
|
|
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
|
|
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
|
|
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
|
|
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀
|
|
// Magicbane Emulator Project © 2013 - 2026
|
|
// https://www.magicbane.com
|
|
|
|
package engine.parsers.cache;
|
|
|
|
import engine.gameManager.ConfigManager;
|
|
import engine.gameManager.DbManager;
|
|
import engine.mbEnums;
|
|
import engine.objects.AbstractGameObject;
|
|
import engine.objects.BaseClass;
|
|
import engine.parsers.objects.RuneTemplate;
|
|
import org.pmw.tinylog.Logger;
|
|
|
|
import java.util.LinkedHashMap;
|
|
import java.util.Objects;
|
|
import java.util.concurrent.ConcurrentHashMap;
|
|
import java.util.function.Consumer;
|
|
|
|
// Dev-only check that compares DB-built objects with the cache JSON before a loader is switched.
|
|
// Enabled by the optional env var MB_PARITY_CHECK; not in the ConfigManager enum, which requires every entry.
|
|
|
|
public class ParityCheck {
|
|
|
|
private static final String FLAG_NAME = "MB_PARITY_CHECK";
|
|
private static final LinkedHashMap<String, Consumer<ParityCheck>> comparators = new LinkedHashMap<>();
|
|
|
|
private final String table;
|
|
private int comparedCount = 0;
|
|
private int differenceCount = 0;
|
|
private int missingCount = 0;
|
|
|
|
static {
|
|
register("static_rune_baseclass", ParityCheck::compareBaseClasses);
|
|
}
|
|
|
|
private ParityCheck(String table) {
|
|
this.table = table;
|
|
}
|
|
|
|
public static boolean isEnabled() {
|
|
return ConfigManager.configMap.getOrDefault(FLAG_NAME, "false").equalsIgnoreCase("true");
|
|
}
|
|
|
|
public static void register(String table, Consumer<ParityCheck> comparator) {
|
|
comparators.put(table, comparator);
|
|
}
|
|
|
|
public static void run() {
|
|
|
|
ParityCheck check;
|
|
|
|
for (String table : comparators.keySet()) {
|
|
check = new ParityCheck(table);
|
|
|
|
try {
|
|
comparators.get(table).accept(check);
|
|
} catch (Exception e) {
|
|
Logger.error("Parity: " + table + ": comparator failed: " + e);
|
|
}
|
|
|
|
Logger.info("Parity: " + table + ": " + check.comparedCount + " compared, "
|
|
+ check.differenceCount + " differences, " + check.missingCount + " missing in json");
|
|
}
|
|
}
|
|
|
|
// Returns false when the row has no JSON counterpart, so the comparator can skip its fields.
|
|
|
|
public boolean compareRow(int id, Object jsonObject) {
|
|
|
|
comparedCount++;
|
|
|
|
if (jsonObject == null) {
|
|
missingCount++;
|
|
Logger.warn("Parity: " + table + "/" + id + ": missing in json");
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
public void compareField(int id, String field, Object dbValue, Object jsonValue) {
|
|
|
|
if (Objects.equals(dbValue, jsonValue))
|
|
return;
|
|
|
|
differenceCount++;
|
|
Logger.warn("Parity: " + table + "/" + id + "/" + field + ": db=" + dbValue + " json=" + jsonValue);
|
|
}
|
|
|
|
private static void compareBaseClasses(ParityCheck check) {
|
|
|
|
ConcurrentHashMap<Integer, AbstractGameObject> cache;
|
|
BaseClass baseClass;
|
|
RuneTemplate rune;
|
|
|
|
cache = DbManager.getMap(mbEnums.GameObjectType.BaseClass);
|
|
|
|
if (cache == null) {
|
|
Logger.warn("Parity: static_rune_baseclass: no BaseClass objects loaded");
|
|
return;
|
|
}
|
|
|
|
for (AbstractGameObject cached : cache.values()) {
|
|
baseClass = (BaseClass) cached;
|
|
rune = RuneTemplate._runes.get(baseClass.getObjectUUID());
|
|
|
|
if (!check.compareRow(baseClass.getObjectUUID(), rune))
|
|
continue;
|
|
|
|
check.compareField(baseClass.getObjectUUID(), "name", baseClass.getName(), rune.obj_name);
|
|
}
|
|
}
|
|
}
|