diff --git a/src/engine/parsers/map/GuildSeedParser.java b/src/engine/parsers/map/GuildSeedParser.java new file mode 100644 index 00000000..9e17a49f --- /dev/null +++ b/src/engine/parsers/map/GuildSeedParser.java @@ -0,0 +1,103 @@ +// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ . +// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌· +// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀ +// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌ +// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀ +// Magicbane Emulator Project © 2013 - 2026 +// https://www.magicbane.com + +package engine.parsers.map; + +import engine.gameManager.ConfigManager; +import engine.mbEnums; +import engine.parsers.cache.CacheParserUtil; +import engine.parsers.objects.GuildSeed; +import engine.parsers.objects.GuildSeedEntry; +import org.json.JSONArray; +import org.json.JSONObject; +import org.pmw.tinylog.Logger; + +import java.io.File; + +// Loads the NPC guild seed for a map (maps/.guild), in file order. Guild keys are unsigned in the file. + +public class GuildSeedParser { + + private static final String mapPath = ConfigManager.DEFAULT_DATA_DIR + "maps/"; + + public static GuildSeed parseGuildSeed(int mapID) { + + GuildSeed guildSeed = new GuildSeed(); + File seedFile = new File(mapPath + mapID + ".guild"); + JSONObject seedJson; + JSONArray guildsJson; + JSONArray noGuildJson; + + if (!seedFile.exists()) { + Logger.error("Guild seed not found: " + seedFile.getAbsolutePath()); + return null; + } + + try { + seedJson = CacheParserUtil.readJsonFile(seedFile); + + if (seedJson.getInt("map") != mapID) { + Logger.error(seedFile.getName() + ": map " + seedJson.getInt("map") + " does not match MB_WORLD_MAPID " + mapID); + return null; + } + + guildsJson = seedJson.getJSONArray("guilds"); + + for (int i = 0; i < guildsJson.length(); i++) + guildSeed.guilds.add(parseGuildEntry(guildsJson.getJSONObject(i))); + + noGuildJson = seedJson.getJSONArray("noGuildKeys"); + + for (int i = 0; i < noGuildJson.length(); i++) + guildSeed.noGuildKeys.add((int) noGuildJson.getLong(i)); + + } catch (Exception e) { + Logger.error(seedFile.getName() + ": " + e); + return null; + } + + Logger.info("Loaded " + guildSeed.guilds.size() + " guilds from " + seedFile.getName()); + + return guildSeed; + } + + private static GuildSeedEntry parseGuildEntry(JSONObject guildJson) { + + GuildSeedEntry guild = new GuildSeedEntry(); + JSONArray keysJson = guildJson.getJSONArray("guildKeys"); + JSONArray crestJson = guildJson.getJSONArray("crest"); + + for (int i = 0; i < keysJson.length(); i++) + guild.guildKeys.add((int) keysJson.getLong(i)); + + guild.nationKey = (int) guildJson.getLong("nationKey"); + guild.name = guildJson.getString("name"); + guild.charter = mbEnums.GuildCharterType.valueOf(guildJson.getString("charter")); + guild.leadershipType = guildJson.getString("leadershipType"); + guild.motto = guildJson.getString("motto"); + guild.repledgeMin = guildJson.getInt("repledgeMin"); + guild.repledgeMax = guildJson.getInt("repledgeMax"); + guild.repledgeKick = guildJson.getInt("repledgeKick"); + guild.teleportMin = guildJson.getInt("teleportMin"); + guild.teleportMax = guildJson.getInt("teleportMax"); + + if (guild.guildKeys.isEmpty()) + throw new IllegalStateException("guild " + guild.name + " has no guild keys"); + + if (crestJson.length() != 5) + throw new IllegalStateException("guild " + guild.name + " crest has " + crestJson.length() + " values"); + + guild.crest = new int[5]; + + for (int i = 0; i < 5; i++) + guild.crest[i] = crestJson.getInt(i); + + return guild; + } + +} diff --git a/src/engine/parsers/objects/GuildSeed.java b/src/engine/parsers/objects/GuildSeed.java new file mode 100644 index 00000000..38c5a30a --- /dev/null +++ b/src/engine/parsers/objects/GuildSeed.java @@ -0,0 +1,22 @@ +// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ . +// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌· +// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀ +// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌ +// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀ +// Magicbane Emulator Project © 2013 - 2026 +// https://www.magicbane.com + +package engine.parsers.objects; + +import java.util.ArrayList; +import java.util.HashSet; + +// A map's server-owned NPC guild seed (maps/.guild). Guilds are in static ID order. +// noGuildKeys are CITY-prop guild keys known to have no guild: placeholders and Ruins. + +public class GuildSeed { + + public final ArrayList guilds = new ArrayList<>(); + public final HashSet noGuildKeys = new HashSet<>(); + +} diff --git a/src/engine/parsers/objects/GuildSeedEntry.java b/src/engine/parsers/objects/GuildSeedEntry.java new file mode 100644 index 00000000..cdf1a6b9 --- /dev/null +++ b/src/engine/parsers/objects/GuildSeedEntry.java @@ -0,0 +1,33 @@ +// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ . +// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌· +// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀ +// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌ +// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀ +// Magicbane Emulator Project © 2013 - 2026 +// https://www.magicbane.com + +package engine.parsers.objects; + +import engine.mbEnums; + +import java.util.ArrayList; + +// One NPC guild of a .guild seed file. guildKeys and nationKey are CZONE city_prop_gm_guild / _nation values. +// Crest is in obj_guild column order: backgroundColor01, backgroundColor02, symbolColor, backgroundDesign, symbol. + +public class GuildSeedEntry { + + public final ArrayList guildKeys = new ArrayList<>(); + public int nationKey; + public String name; + public int[] crest; + public mbEnums.GuildCharterType charter; + public String leadershipType; + public String motto; + public int repledgeMin; + public int repledgeMax; + public int repledgeKick; + public int teleportMin; + public int teleportMax; + +}