0% found this document useful (0 votes)
11 views

ReferenceManager.cs

The ReferenceManager class is responsible for loading and managing various game data references including text, characters, items, skills, quests, and shops. It utilizes a background worker to report progress while loading data from specified files, handling different client types for compatibility. The class also provides methods to retrieve specific game references and translations based on loaded data.

Uploaded by

ilkerbarax
Copyright
© © All Rights Reserved
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
11 views

ReferenceManager.cs

The ReferenceManager class is responsible for loading and managing various game data references including text, characters, items, skills, quests, and shops. It utilizes a background worker to report progress while loading data from specified files, handling different client types for compatibility. The class also provides methods to retrieve specific game references and translations based on loaded data.

Uploaded by

ilkerbarax
Copyright
© © All Rights Reserved
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
You are on page 1/ 15

using System;

using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using RSBot.Core.Client.ReferenceObjects;
using RSBot.Core.Cryptography;
using RSBot.Core.Event;
using RSBot.Core.Extensions;
using RSBot.Core.Objects;
using RSBot.NavMeshApi;

namespace RSBot.Core.Client;

public class ReferenceManager


{
private const string ServerDep = "server_dep\\silkroad\\textdata";

public int LanguageTab { get; set; }

public Dictionary<string, RefText> TextData { get; } = new(50000);


public Dictionary<uint, RefObjChar> CharacterData { get; } = new(20000);
public Dictionary<uint, RefObjItem> ItemData { get; } = new(20000);
public Dictionary<byte, RefLevel> LevelData { get; } = new(128);
public Dictionary<uint, RefQuest> QuestData { get; } = new(1024);
public Dictionary<uint, RefSkill> SkillData { get; } = new(35000);
public Dictionary<uint, RefSkillMastery> SkillMasteryData { get; } = new(32);
public Dictionary<int, RefAbilityByItemOptLevel> AbilityItemByOptLevel { get; }
= new(256);
public List<RefSkillByItemOptLevel> SkillByItemOptLevels { get; } = new(256);
public List<RefExtraAbilityByEquipItemOptLevel> ExtraAbilityByEquipItemOptLevel
{ get; } = new(4096);
public Dictionary<string, RefShop> Shops { get; } = new(128);
public Dictionary<string, RefShopTab> ShopTabs { get; } = new(256);
public Dictionary<string, RefShopGroup> ShopGroups { get; } = new(128);
public List<RefMappingShopGroup> ShopGroupMapping { get; } = new(128);
public List<RefMappingShopWithTab> ShopTabMapping { get; } = new(128);
public List<RefShopGood> ShopGoods { get; } = new(4096);
public Dictionary<string, RefPackageItemScrap> PackageItemScrap { get; } =
new(2048);
public List<RefTeleport> TeleportData { get; } = new(256);
public List<RefTeleportLink> TeleportLinks { get; } = new(256);
public Dictionary<int, RefOptionalTeleport> OptionalTeleports { get; } =
new(32);
public Dictionary<uint, RefQuestReward> QuestRewards { get; } = new(1024);
public List<RefQuestRewardItem> QuestRewardItems { get; } = new(1024);
public GatewayInfo GatewayInfo { get; private set; }
public DivisionInfo DivisionInfo { get; private set; }
public VersionInfo VersionInfo { get; private set; }
public List<RefMagicOpt> MagicOptions { get; } = new(1024);
public List<RefMagicOptAssign> MagicOptionAssignments { get; } = new(128);

public void Load(int languageTab, BackgroundWorker worker)


{
LanguageTab = languageTab; //until language wizard is reworked?
var sw = Stopwatch.StartNew();

worker.ReportProgress(0, "Client info");


LoadClientInfo();

worker.ReportProgress(5, "Map info");


LoadMapInfo();

worker.ReportProgress(10, "Texts");
LoadTextData();

worker.ReportProgress(20, "Characters");
LoadCharacterData();

worker.ReportProgress(30, "Items");
LoadItemData();

worker.ReportProgress(40, "Skills");
LoadSkillData();

worker.ReportProgress(50, "Quests");
LoadQuestData();

worker.ReportProgress(60, "Shops");
LoadShopData();

worker.ReportProgress(70, "Teleporters");
LoadTeleportData();

worker.ReportProgress(80, "Alchemy");
LoadAlchemyData();

worker.ReportProgress(90, "Misc");
LoadOptLevelData();
LoadLevelData();

sw.Stop();

Log.Debug(GetDebugInfo());
Log.Notify($"Loaded all game data in {sw.ElapsedMilliseconds}ms!");

worker.ReportProgress(100, "Done");
EventManager.FireEvent("OnLoadGameData");
}

private void LoadClientInfo()


{
DivisionInfo = DivisionInfo.Load();
GatewayInfo = GatewayInfo.Load();
VersionInfo = VersionInfo.Load();
}

private void LoadMapInfo()


{
RegionInfoManager.Load();
NavMeshManager.Initialize(Game.DataPk2);
}
private void LoadLevelData()
{
LoadReferenceFile($"{ServerDep}\\LevelData.txt", LevelData);
}

private void LoadShopData()


{
LoadReferenceFile($"{ServerDep}\\RefShop.txt", Shops);
LoadReferenceFile($"{ServerDep}\\RefShopTab.txt", ShopTabs);
LoadReferenceFile($"{ServerDep}\\RefShopGroup.txt", ShopGroups);
LoadReferenceFile($"{ServerDep}\\RefMappingShopGroup.txt",
ShopGroupMapping);
LoadReferenceFile($"{ServerDep}\\RefMappingShopWithTab.txt",
ShopTabMapping);

if (Game.ClientType > GameClientType.Chinese)


LoadReferenceListFile($"{ServerDep}\\RefScrapOfPackageItem.txt",
PackageItemScrap);
else
LoadReferenceFile($"{ServerDep}\\RefScrapOfPackageItem.txt",
PackageItemScrap);

if (Game.ClientType > GameClientType.Chinese)


LoadReferenceListFile($"{ServerDep}\\RefShopGoods.txt", ShopGoods);
else
LoadReferenceFile($"{ServerDep}\\RefShopGoods.txt", ShopGoods);

private void LoadAlchemyData()


{
LoadReferenceFile($"{ServerDep}\\magicoption.txt", MagicOptions);
LoadReferenceFile($"{ServerDep}\\magicoptionassign.txt",
MagicOptionAssignments);

private void LoadTeleportData()


{
LoadReferenceFile($"{ServerDep}\\TeleportBuilding.txt", CharacterData);
LoadReferenceFile($"{ServerDep}\\TeleportData.txt", TeleportData);
LoadReferenceFile($"{ServerDep}\\TeleportLink.txt", TeleportLinks);
LoadReferenceFile($"{ServerDep}\\refoptionalteleport.txt",
OptionalTeleports);
}

private void LoadItemData()


{
if (Game.ClientType < GameClientType.Thailand)
LoadReferenceFile($"{ServerDep}\\ItemData.txt", ItemData);
else
LoadReferenceListFile($"{ServerDep}\\ItemData.txt", ItemData);
}

private void LoadOptLevelData()


{
if (Game.ClientType > GameClientType.Japanese_Old)
{
LoadReferenceFile($"{ServerDep}\\refabilitybyitemoptleveldata.txt",
AbilityItemByOptLevel);
LoadReferenceFile($"{ServerDep}\\refskillbyitemoptleveldata.txt",
SkillByItemOptLevels);
}

if (Game.ClientType >= GameClientType.Chinese)


LoadReferenceFile($"{ServerDep}\\
refextraabilitybyequipitemoptlevel.txt", ExtraAbilityByEquipItemOptLevel);
}

private void LoadQuestData()


{
LoadReferenceFile($"{ServerDep}\\refquestrewarditems.txt",
QuestRewardItems);
LoadReferenceFile($"{ServerDep}\\refqusetreward.txt", QuestRewards);

if (Game.ClientType > GameClientType.Chinese)


LoadConditionalData($"{ServerDep}\\QuestData.txt", QuestData);
else
LoadReferenceFile($"{ServerDep}\\questdata.txt", QuestData);

private void LoadTextData()


{
if (Game.ClientType >= GameClientType.Global)
LoadReferenceListFile($"{ServerDep}\\TextUISystem.txt", TextData);
else
LoadReferenceFile($"{ServerDep}\\TextUISystem.txt", TextData);

if (Game.ClientType >= GameClientType.Global)


LoadReferenceListFile($"{ServerDep}\\TextZoneName.txt", TextData);
else
LoadReferenceFile($"{ServerDep}\\TextZoneName.txt", TextData);
if (Game.ClientType >= GameClientType.Global)
{
LoadReferenceListFile($"{ServerDep}\\TextQuest_OtherString.txt",
TextData);
LoadReferenceListFile($"{ServerDep}\\TextData_Object.txt", TextData);
LoadReferenceListFile($"{ServerDep}\\TextData_Equip&Skill.txt",
TextData);
LoadReferenceListFile($"{ServerDep}\\TextQuest_Speech&Name.txt",
TextData);
LoadReferenceListFile($"{ServerDep}\\TextQuest_QuestString.txt",
TextData);
}
else
{
if (Game.ClientType >= GameClientType.Thailand)
{
LoadReferenceListFile($"{ServerDep}\\TextDataName.txt", TextData);
LoadReferenceListFile($"{ServerDep}\\TextQuest.txt", TextData);
return;
}

LoadReferenceFile($"{ServerDep}\\TextDataName.txt", TextData);
LoadReferenceFile($"{ServerDep}\\TextQuest.txt", TextData);
}
}
private void LoadCharacterData()
{
if (Game.ClientType < GameClientType.Thailand)
LoadReferenceFile($"{ServerDep}\\CharacterData.txt", CharacterData);
else
LoadReferenceListFile($"{ServerDep}\\CharacterData.txt",
CharacterData);
}

private void LoadConditionalData<TKey, TReference>(string file,


IDictionary<TKey, TReference> collection)
where TReference : IReference<TKey>, new()
{
if (Game.ClientType < GameClientType.Thailand)
LoadReferenceFile(file, collection);
else
LoadReferenceListFile(file, collection);
}

private void LoadSkillData()


{
if (Game.ClientType == GameClientType.Vietnam ||
Game.ClientType == GameClientType.Vietnam274)
LoadReferenceListFileEnc($"{ServerDep}\\SkillDataEnc.txt", SkillData);
else if (Game.ClientType < GameClientType.Thailand)
LoadReferenceFile($"{ServerDep}\\SkillData.txt", SkillData);
else
LoadReferenceListFile($"{ServerDep}\\SkillData.txt", SkillData);

LoadReferenceFile($"{ServerDep}\\SkillMasteryData.txt", SkillMasteryData);
}

private void LoadReferenceListFileEnc<TKey, TReference>(string fileName,


IDictionary<TKey, TReference> destination)
where TReference : IReference<TKey>, new()
{
if (Game.MediaPk2.TryGetFile(fileName, out var file))
LoadReferenceListFileEnc(file.OpenRead().GetStream(), destination);
}

private void LoadReferenceListFileEnc<TKey, TReference>(Stream stream,


IDictionary<TKey, TReference> destination)
where TReference : IReference<TKey>, new()
{
var filesToLoad = new List<string>();
using (var reader = new StreamReader(stream))
{
while (!reader.EndOfStream)
{
var line = reader.ReadLineByCRLF();

//Skip invalid
if (string.IsNullOrEmpty(line) || line.StartsWith("//"))
continue;

filesToLoad.Add(line);
}
}
var files = Game.MediaPk2.GetFileList(ServerDep, filesToLoad.ToArray());
foreach (var file in files)
LoadReferenceFileEnc(file.OpenRead().GetStream(), destination);
}

private void LoadReferenceFileEnc<TKey, TReference>(Stream stream,


IDictionary<TKey, TReference> destination)
where TReference : IReference<TKey>, new()
{
using var decryptedStream = new MemoryStream();

SkillCryptoHelper.DecryptStream(stream, decryptedStream, 0x8C1F);


decryptedStream.Seek(0, SeekOrigin.Begin);

LoadReferenceFile(decryptedStream, destination);
}

private void LoadReferenceListFile<TReference>(string fileName,


IList<TReference> destination)
where TReference : IReference, new()
{
if (Game.MediaPk2.TryGetFile(fileName, out var file))
LoadReferenceListFile(file.OpenRead().GetStream(), destination);

private void LoadReferenceListFile<TKey, TReference>(string fileName,


IDictionary<TKey, TReference> destination)
where TReference : IReference<TKey>, new()
{
if (Game.MediaPk2.TryGetFile(fileName, out var file))
LoadReferenceListFile(file.OpenRead().GetStream(), destination);
}

private void LoadReferenceFile<TReference>(string fileName, IList<TReference>


destination)
where TReference : IReference, new()
{
if (Game.MediaPk2.TryGetFile(fileName, out var file))
LoadReferenceFile(file.OpenRead().GetStream(), destination);
}

private void LoadReferenceFile<TKey, TReference>(string fileName,


IDictionary<TKey, TReference> destination)
where TReference : IReference<TKey>, new()
{
if (Game.MediaPk2.TryGetFile(fileName, out var file))
LoadReferenceFile(file.OpenRead().GetStream(), destination);
}

private void LoadReferenceListFile<TReference>(Stream stream, IList<TReference>


destination)
where TReference : IReference, new()
{
var filesToLoad = new List<string>(16);

using var reader = new StreamReader(stream);


var builder = new StringBuilder(1024);
while (!reader.EndOfStream)
{
var line = reader.ReadLineByCRLF(builder);

//Skip invalid
if (string.IsNullOrEmpty(line) || line.StartsWith("//"))
continue;

filesToLoad.Add(line);
}

var files = Game.MediaPk2.GetFileList(ServerDep, filesToLoad.ToArray());


foreach (var file in files)
LoadReferenceFile(file.OpenRead().GetStream(), destination);
}

private void LoadReferenceListFile<TKey, TReference>(Stream stream,


IDictionary<TKey, TReference> destination)
where TReference : IReference<TKey>, new()
{
var filesToLoad = new List<string>(16);

using var reader = new StreamReader(stream);


var builder = new StringBuilder(1024);

//Read list of files to load


while (!reader.EndOfStream)
{
var line = reader.ReadLineByCRLF(builder);

//Skip invalid
if (string.IsNullOrEmpty(line) || line.StartsWith("//"))
continue;

filesToLoad.Add(line);
}

//Actual loading
var files = Game.MediaPk2.GetFileList(ServerDep, filesToLoad.ToArray());
foreach (var file in files)
LoadReferenceFile(file.OpenRead().GetStream(), destination);
}

private void LoadReferenceFile<TReference>(Stream stream, IList<TReference>


destination)
where TReference : IReference, new()
{
using var reader = new StreamReader(stream);
var builder = new StringBuilder(1024);

while (!reader.EndOfStream)
{
var line = reader.ReadLineByCRLF(builder);

//Skip invalid
if (string.IsNullOrEmpty(line) || line.StartsWith("//"))
continue;
try
{
var reference = new TReference();
if (reference.Load(new ReferenceParser(line)))
destination.Add(reference);
}
catch
{
Debug.WriteLine($"Exception in reference line: {line}");
}
}
}

private void LoadReferenceFile<TKey, TReference>(Stream stream,


IDictionary<TKey, TReference> destination)
where TReference : IReference<TKey>, new()
{
using var reader = new StreamReader(stream);
while (!reader.EndOfStream)
{
var line = reader.ReadLineByCRLF();

//Skip invalid
if (string.IsNullOrEmpty(line) || line.StartsWith("//"))
continue;

try
{
var reference = new TReference();
if (reference.Load(new ReferenceParser(line)))
destination[reference.PrimaryKey] = reference;
}
catch
{
Debug.WriteLine($"Exception in reference line: {line}");
}
}
}

public IEnumerable<uint> GetBaseSkills()


{
return SkillData.Where(p => p.Value.Basic_Code.EndsWith("_BASE_01") &&
p.Value.Basic_Group != "xxx")
.Select(p => p.Key);
}

public RefShopTab GetTab(string codeName)


{
return ShopTabs[codeName];
}

public string GetTranslation(string name)


{
if (TextData.TryGetValue(name, out var refText))
return refText.Data;

return name;
}
public RefObjCommon GetRefObjCommon(uint refObjID)
{
if (CharacterData.TryGetValue(refObjID, out var refChar))
return refChar;

if (ItemData.TryGetValue(refObjID, out var refItem))


return refItem;

return null;
}

public RefObjChar GetRefObjChar(uint id)


{
if (CharacterData.TryGetValue(id, out var data))
return data;

return null;
}

public RefObjChar GetRefObjChar(string codeName)


{
return CharacterData.FirstOrDefault(obj => obj.Value.CodeName ==
codeName).Value;
}

public RefObjItem GetRefItem(uint id)


{
if (ItemData.TryGetValue(id, out var data))
return data;

return null;
}

public RefObjItem GetRefItem(string codeName)


{
return ItemData.FirstOrDefault(obj => obj.Value.CodeName ==
codeName).Value;
}

public RefObjItem GetRefItem(TypeIdFilter filter)


{
return ItemData.FirstOrDefault(obj =>
filter.EqualsRefItem(obj.Value)).Value;
}

public RefSkill GetRefSkill(uint id)


{
if (SkillData.TryGetValue(id, out var data))
return data;

return null;
}

public RefSkill GetRefSkill(string codeName)


{
var skill = SkillData.FirstOrDefault(s => s.Value.Basic_Code == codeName);

return skill.Value;
}
public RefSkillMastery GetRefSkillMastery(uint id)
{
if (Game.ClientType == GameClientType.Chinese &&
id >= 273 && id <= 275)
id = 277; // csro shit

if (SkillMasteryData.TryGetValue(id, out var data))


return data;

return null;
}

public RefQuest GetRefQuest(uint id)


{
if (QuestData.TryGetValue(id, out var data))
return data;

return null;
}

public RefLevel GetRefLevel(byte level)


{
if (LevelData.TryGetValue(level, out var data))
return data;

return null;
}

public RefShopGroup GetRefShopGroup(string npcCodeName)


{
return ShopGroups.FirstOrDefault(sg => sg.Value.RefNpcCodeName ==
npcCodeName).Value;
}

public RefShopGroup GetRefShopGroupById(ushort id)


{
return ShopGroups.FirstOrDefault(sg => sg.Value.Id == id).Value;
}

public RefPackageItemScrap GetRefPackageItem(string npcCodeName, byte tab, byte


slot)
{
var shops = GetRefShopGroup(npcCodeName).GetShops();
var tabs = shops[0].GetTabs();
var goods = tabs[tab].GetGoods();
return PackageItemScrap[goods.FirstOrDefault(s => s.SlotIndex ==
slot)?.RefPackageItemCodeName];
}

public RefPackageItemScrap GetRefPackageItemById(ushort id, byte group, byte


tab, byte slot)
{
return PackageItemScrap[
GetRefShopGroupById(id).GetShops()[group].GetTabs()
[tab].GetGoods().FirstOrDefault(s => s.SlotIndex == slot)
.RefPackageItemCodeName];
}
public RefPackageItemScrap GetRefPackageItem(string codeName)
{
if (PackageItemScrap.TryGetValue(codeName, out var data))
return data;

return null;
}

public List<RefPackageItemScrap> GetRefPackageItems(RefShopGroup group)


{
var result = new List<RefPackageItemScrap>();
foreach (var shop in group.GetShops())
{
if (shop == null) continue;
foreach (var tab in shop.GetTabs())
{
if (tab == null) continue;
foreach (var good in tab.GetGoods())
{
if (good == null) continue;

if (!PackageItemScrap.ContainsKey(good.RefPackageItemCodeName))
continue;

if (result.FirstOrDefault(g => g.RefPackageItemCodeName ==


good.RefPackageItemCodeName) == null)
result.Add(PackageItemScrap[good.RefPackageItemCodeName]);
}
}
}

return result;
}

public RefShopGood GetRefShopGood(string refPackageItemCodeName)


{
return ShopGoods.FirstOrDefault(sg => sg.RefPackageItemCodeName ==
refPackageItemCodeName);
}

public List<RefShopGood> GetRefShopGoods(RefShopGroup group)


{
return (from shop in @group.GetShops()
where shop != null
from tab in shop.GetTabs()
where tab != null
from good in tab.GetGoods()
where good != null
select good).ToList();
}

public byte GetRefShopGoodTabIndex(string npcCodeName, RefShopGood good)


{
var shopGroup = GetRefShopGroup(npcCodeName);
if (shopGroup == null) return 0xFF;

var availableShops = shopGroup.GetShops();

foreach (var shop in availableShops)


{
var availableTabs = shop.GetTabs();

for (byte i = 0; i < availableTabs.Count; i++)


{
var goods = availableTabs[i].GetGoods();
var availableGood =
goods.FirstOrDefault(g => g.RefPackageItemCodeName ==
good.RefPackageItemCodeName);

if (availableGood != null)
return i;
}
}

return 0xFF;
}

/// <summary>
/// Gets the filtered items.
/// </summary>
/// <param name="filters">The filters.</param>
/// <param name="degreeFrom">The degree from.</param>
/// <param name="degreeTo">The degree to.</param>
/// <param name="gender">The gender.</param>
/// <param name="searchPattern">The search pattern.</param>
/// <returns></returns>
public List<RefObjItem> GetFilteredItems(
List<TypeIdFilter> filters,
byte degreeFrom = 0,
byte degreeTo = 0,
ObjectGender gender = ObjectGender.Neutral,
bool rare = false,
string searchPattern = null)
{
var result = new List<RefObjItem>(10000);
foreach (var refItem in ItemData.Values)
{
if (refItem.IsGold)
continue;

foreach (var filter in filters)


{
// step 1 compare typeids
if (!filter.EqualsRefItem(refItem))
continue;

// step 2 compare gender


var itemGender = (ObjectGender)refItem.ReqGender;
if (gender != ObjectGender.Neutral && itemGender != gender)
continue;

// step 3 compare searching item name


if (!string.IsNullOrEmpty(searchPattern))
{
var itemRealName = refItem.GetRealName();

if (itemRealName.IndexOf(searchPattern,
StringComparison.InvariantCultureIgnoreCase) == -1)
continue;
}

// step 4 compare rare


if (rare && (byte)refItem.Rarity < 2)
continue;

// step 5 compare minimum degree


// dont need to check the if it is equip items
if (degreeFrom != 0 && refItem.Degree < degreeFrom)
continue;

// step 6 compare maximum degree


// dont need to check the if it is equip items
if (degreeTo != 0 && refItem.Degree > degreeTo)
continue;

result.Add(refItem);
}
}

return result;
}

/// <summary>
/// Gets the teleporters in the specific sector
/// </summary>
/// <param name="regionId"></param>
/// <returns></returns>
public RefTeleport[] GetTeleporters(Region region)
{
return TeleportData.Where(t => t.GenRegionID == region).ToArray();
}

/// <summary>
/// Gets the ground teleporters.
/// </summary>
/// <param name="regionId">The region identifier.</param>
/// <returns></returns>
public RefTeleport[] GetGroundTeleporters(Region region)
{
return TeleportData.Where(t => t.GenRegionID == region && t.AssocRefObjId
== 0).ToArray();
}

/// <summary>
/// Gets a magic option by its id
/// </summary>
/// <param name="id">The id of the magic option</param>
/// <returns></returns>
public RefMagicOpt GetMagicOption(uint id)
{
return MagicOptions?.FirstOrDefault(m => m.Id == id);
}

/// <summary>
/// Gets the first magic option of the specified group
/// </summary>
/// <param name="group">The group</param>
/// <returns></returns>
public RefMagicOpt GetMagicOption(string group)
{
return MagicOptions?.FirstOrDefault(m => m.Group == group);
}

/// <summary>
/// Gets a magic option by its group and degree
/// </summary>
/// <param name="group">The group</param>
/// <param name="degree">The degree</param>
/// <returns></returns>
public RefMagicOpt GetMagicOption(string group, byte degree)
{
return MagicOptions?.FirstOrDefault(m => m.Group == group && m.Level ==
degree);
}

/// <summary>
/// Gets a list of magic options for the specified type ids
/// </summary>
/// <param name="typeId3">The TID3</param>
/// <param name="typeId4">The TID4</param>
/// <returns></returns>
public List<RefMagicOpt> GetAssignments(byte typeId3, byte typeId4)
{
return MagicOptionAssignments.FirstOrDefault(a => a.TypeId3 == typeId3 &&
a.TypeId4 == typeId4)
?.AvailableMagicOptions.Select(GetMagicOption).ToList();
}

/// <summary>
/// Gets a ability item for the specified <paramref name="itemId" /> and
<paramref name="optLevel" />
/// </summary>
/// <param name="itemId">Item Id</param>
/// <param name="optLevel">Opt Level</param>
/// <returns></returns>
public RefAbilityByItemOptLevel GetAbilityItem(uint itemId, byte optLevel)
{
return AbilityItemByOptLevel.Values.FirstOrDefault(p => p.ItemId == itemId
&& p.OptLevel == optLevel);
}

/// <summary>
/// Gets a ability item for the specified <paramref name="itemId" /> and
<paramref name="optLevel" />
/// </summary>
/// <param name="itemId">Item Id</param>
/// <param name="optLevel">Opt Level</param>
/// <returns></returns>
public IEnumerable<RefExtraAbilityByEquipItemOptLevel>
GetExtraAbilityItems(uint itemId, byte optLevel)
{
return ExtraAbilityByEquipItemOptLevel.Where(p => p.ItemId == itemId &&
p.OptLevel == optLevel);
}
/// <summary>
/// Gets a list of reward items for the specified quest.
/// </summary>
/// <param name="questId"></param>
/// <returns></returns>
public IEnumerable<RefQuestRewardItem> GetQuestRewardItems(uint questId)
{
return QuestRewardItems.Where(r => r.QuestId == questId);
}

/// <summary>
/// Returns the reward for the specified quest
/// </summary>
/// <param name="questId"></param>
/// <returns></returns>
public RefQuestReward GetQuestReward(uint questId)
{
QuestRewards.TryGetValue(questId, out var result);

return result;
}

private string GetDebugInfo()


{
var builder = new StringBuilder("\n=== Reference information === \n");

builder.AppendFormat("TextData: {0}\n", TextData.Count);


builder.AppendFormat("CharacterData: {0}\n", CharacterData.Count);
builder.AppendFormat("ItemData: {0}\n", ItemData.Count);
builder.AppendFormat("SkillData: {0}\n", SkillData.Count);
builder.AppendFormat("SkillMasteryData: {0}\n", SkillMasteryData.Count);
builder.AppendFormat("QuestData: {0}\n", QuestData.Count);
builder.AppendFormat("QuestRewards: {0}\n", QuestRewards.Count);
builder.AppendFormat("QuestRewardItems: {0}\n", QuestRewardItems.Count);
builder.AppendFormat("TeleportData: {0}\n", TeleportData.Count);
builder.AppendFormat("TeleportLinks: {0}\n", TeleportLinks.Count);
builder.AppendFormat("OptionalTeleports: {0}\n", OptionalTeleports.Count);
builder.AppendFormat("MagicOptions: {0}\n", MagicOptions.Count);
builder.AppendFormat("MagicOptionAssignments: {0}\n",
MagicOptionAssignments.Count);
builder.AppendFormat("Shops: {0}\n", Shops.Count);
builder.AppendFormat("ShopGroups: {0}\n", ShopGroups.Count);
builder.AppendFormat("ShopGoods: {0}\n", ShopGoods.Count);
builder.AppendFormat("ShopGroupMapping: {0}\n", ShopGroupMapping.Count);
builder.AppendFormat("ShopTabs: {0}\n", ShopTabs.Count);
builder.AppendFormat("ShopTabMapping: {0}\n", ShopTabMapping.Count);
builder.AppendFormat("PackageItemScrap: {0}\n", PackageItemScrap.Count);
builder.AppendFormat("AbilityItemByOptLevel: {0}\n",
AbilityItemByOptLevel.Count);
builder.AppendFormat("SkillByItemOptLevels: {0}\n",
SkillByItemOptLevels.Count);
builder.AppendFormat("ExtraAbilityByEquipItemOptLevel: {0}\n",
ExtraAbilityByEquipItemOptLevel.Count);

return builder.ToString();
}
}

You might also like