using System;
using [Link];
using [Link];
using [Link];
using [Link];
using [Link];
using [Link];
using [Link];
using [Link];
using [Link];
using [Link];
using [Link];
using [Link];
namespace [Link];
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 = [Link]();
[Link](0, "Client info");
LoadClientInfo();
[Link](5, "Map info");
LoadMapInfo();
[Link](10, "Texts");
LoadTextData();
[Link](20, "Characters");
LoadCharacterData();
[Link](30, "Items");
LoadItemData();
[Link](40, "Skills");
LoadSkillData();
[Link](50, "Quests");
LoadQuestData();
[Link](60, "Shops");
LoadShopData();
[Link](70, "Teleporters");
LoadTeleportData();
[Link](80, "Alchemy");
LoadAlchemyData();
[Link](90, "Misc");
LoadOptLevelData();
LoadLevelData();
[Link]();
[Link](GetDebugInfo());
[Link]($"Loaded all game data in {[Link]}ms!");
[Link](100, "Done");
[Link]("OnLoadGameData");
}
private void LoadClientInfo()
{
DivisionInfo = [Link]();
GatewayInfo = [Link]();
VersionInfo = [Link]();
}
private void LoadMapInfo()
{
[Link]();
[Link](Game.DataPk2);
}
private void LoadLevelData()
{
LoadReferenceFile($"{ServerDep}\\[Link]", LevelData);
}
private void LoadShopData()
{
LoadReferenceFile($"{ServerDep}\\[Link]", Shops);
LoadReferenceFile($"{ServerDep}\\[Link]", ShopTabs);
LoadReferenceFile($"{ServerDep}\\[Link]", ShopGroups);
LoadReferenceFile($"{ServerDep}\\[Link]",
ShopGroupMapping);
LoadReferenceFile($"{ServerDep}\\[Link]",
ShopTabMapping);
if ([Link] > [Link])
LoadReferenceListFile($"{ServerDep}\\[Link]",
PackageItemScrap);
else
LoadReferenceFile($"{ServerDep}\\[Link]",
PackageItemScrap);
if ([Link] > [Link])
LoadReferenceListFile($"{ServerDep}\\[Link]", ShopGoods);
else
LoadReferenceFile($"{ServerDep}\\[Link]", ShopGoods);
private void LoadAlchemyData()
{
LoadReferenceFile($"{ServerDep}\\[Link]", MagicOptions);
LoadReferenceFile($"{ServerDep}\\[Link]",
MagicOptionAssignments);
private void LoadTeleportData()
{
LoadReferenceFile($"{ServerDep}\\[Link]", CharacterData);
LoadReferenceFile($"{ServerDep}\\[Link]", TeleportData);
LoadReferenceFile($"{ServerDep}\\[Link]", TeleportLinks);
LoadReferenceFile($"{ServerDep}\\[Link]",
OptionalTeleports);
}
private void LoadItemData()
{
if ([Link] < [Link])
LoadReferenceFile($"{ServerDep}\\[Link]", ItemData);
else
LoadReferenceListFile($"{ServerDep}\\[Link]", ItemData);
}
private void LoadOptLevelData()
{
if ([Link] > GameClientType.Japanese_Old)
{
LoadReferenceFile($"{ServerDep}\\[Link]",
AbilityItemByOptLevel);
LoadReferenceFile($"{ServerDep}\\[Link]",
SkillByItemOptLevels);
}
if ([Link] >= [Link])
LoadReferenceFile($"{ServerDep}\\
[Link]", ExtraAbilityByEquipItemOptLevel);
}
private void LoadQuestData()
{
LoadReferenceFile($"{ServerDep}\\[Link]",
QuestRewardItems);
LoadReferenceFile($"{ServerDep}\\[Link]", QuestRewards);
if ([Link] > [Link])
LoadConditionalData($"{ServerDep}\\[Link]", QuestData);
else
LoadReferenceFile($"{ServerDep}\\[Link]", QuestData);
private void LoadTextData()
{
if ([Link] >= [Link])
LoadReferenceListFile($"{ServerDep}\\[Link]", TextData);
else
LoadReferenceFile($"{ServerDep}\\[Link]", TextData);
if ([Link] >= [Link])
LoadReferenceListFile($"{ServerDep}\\[Link]", TextData);
else
LoadReferenceFile($"{ServerDep}\\[Link]", TextData);
if ([Link] >= [Link])
{
LoadReferenceListFile($"{ServerDep}\\TextQuest_OtherString.txt",
TextData);
LoadReferenceListFile($"{ServerDep}\\TextData_Object.txt", TextData);
LoadReferenceListFile($"{ServerDep}\\TextData_Equip&[Link]",
TextData);
LoadReferenceListFile($"{ServerDep}\\TextQuest_Speech&[Link]",
TextData);
LoadReferenceListFile($"{ServerDep}\\TextQuest_QuestString.txt",
TextData);
}
else
{
if ([Link] >= [Link])
{
LoadReferenceListFile($"{ServerDep}\\[Link]", TextData);
LoadReferenceListFile($"{ServerDep}\\[Link]", TextData);
return;
}
LoadReferenceFile($"{ServerDep}\\[Link]", TextData);
LoadReferenceFile($"{ServerDep}\\[Link]", TextData);
}
}
private void LoadCharacterData()
{
if ([Link] < [Link])
LoadReferenceFile($"{ServerDep}\\[Link]", CharacterData);
else
LoadReferenceListFile($"{ServerDep}\\[Link]",
CharacterData);
}
private void LoadConditionalData<TKey, TReference>(string file,
IDictionary<TKey, TReference> collection)
where TReference : IReference<TKey>, new()
{
if ([Link] < [Link])
LoadReferenceFile(file, collection);
else
LoadReferenceListFile(file, collection);
}
private void LoadSkillData()
{
if ([Link] == [Link] ||
[Link] == GameClientType.Vietnam274)
LoadReferenceListFileEnc($"{ServerDep}\\[Link]", SkillData);
else if ([Link] < [Link])
LoadReferenceFile($"{ServerDep}\\[Link]", SkillData);
else
LoadReferenceListFile($"{ServerDep}\\[Link]", SkillData);
LoadReferenceFile($"{ServerDep}\\[Link]", SkillMasteryData);
}
private void LoadReferenceListFileEnc<TKey, TReference>(string fileName,
IDictionary<TKey, TReference> destination)
where TReference : IReference<TKey>, new()
{
if ([Link](fileName, out var file))
LoadReferenceListFileEnc([Link]().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 (![Link])
{
var line = [Link]();
//Skip invalid
if ([Link](line) || [Link]("//"))
continue;
[Link](line);
}
}
var files = [Link](ServerDep, [Link]());
foreach (var file in files)
LoadReferenceFileEnc([Link]().GetStream(), destination);
}
private void LoadReferenceFileEnc<TKey, TReference>(Stream stream,
IDictionary<TKey, TReference> destination)
where TReference : IReference<TKey>, new()
{
using var decryptedStream = new MemoryStream();
[Link](stream, decryptedStream, 0x8C1F);
[Link](0, [Link]);
LoadReferenceFile(decryptedStream, destination);
}
private void LoadReferenceListFile<TReference>(string fileName,
IList<TReference> destination)
where TReference : IReference, new()
{
if ([Link](fileName, out var file))
LoadReferenceListFile([Link]().GetStream(), destination);
private void LoadReferenceListFile<TKey, TReference>(string fileName,
IDictionary<TKey, TReference> destination)
where TReference : IReference<TKey>, new()
{
if ([Link](fileName, out var file))
LoadReferenceListFile([Link]().GetStream(), destination);
}
private void LoadReferenceFile<TReference>(string fileName, IList<TReference>
destination)
where TReference : IReference, new()
{
if ([Link](fileName, out var file))
LoadReferenceFile([Link]().GetStream(), destination);
}
private void LoadReferenceFile<TKey, TReference>(string fileName,
IDictionary<TKey, TReference> destination)
where TReference : IReference<TKey>, new()
{
if ([Link](fileName, out var file))
LoadReferenceFile([Link]().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 (![Link])
{
var line = [Link](builder);
//Skip invalid
if ([Link](line) || [Link]("//"))
continue;
[Link](line);
}
var files = [Link](ServerDep, [Link]());
foreach (var file in files)
LoadReferenceFile([Link]().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 (![Link])
{
var line = [Link](builder);
//Skip invalid
if ([Link](line) || [Link]("//"))
continue;
[Link](line);
}
//Actual loading
var files = [Link](ServerDep, [Link]());
foreach (var file in files)
LoadReferenceFile([Link]().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 (![Link])
{
var line = [Link](builder);
//Skip invalid
if ([Link](line) || [Link]("//"))
continue;
try
{
var reference = new TReference();
if ([Link](new ReferenceParser(line)))
[Link](reference);
}
catch
{
[Link]($"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 (![Link])
{
var line = [Link]();
//Skip invalid
if ([Link](line) || [Link]("//"))
continue;
try
{
var reference = new TReference();
if ([Link](new ReferenceParser(line)))
destination[[Link]] = reference;
}
catch
{
[Link]($"Exception in reference line: {line}");
}
}
}
public IEnumerable<uint> GetBaseSkills()
{
return [Link](p => [Link].Basic_Code.EndsWith("_BASE_01") &&
[Link].Basic_Group != "xxx")
.Select(p => [Link]);
}
public RefShopTab GetTab(string codeName)
{
return ShopTabs[codeName];
}
public string GetTranslation(string name)
{
if ([Link](name, out var refText))
return [Link];
return name;
}
public RefObjCommon GetRefObjCommon(uint refObjID)
{
if ([Link](refObjID, out var refChar))
return refChar;
if ([Link](refObjID, out var refItem))
return refItem;
return null;
}
public RefObjChar GetRefObjChar(uint id)
{
if ([Link](id, out var data))
return data;
return null;
}
public RefObjChar GetRefObjChar(string codeName)
{
return [Link](obj => [Link] ==
codeName).Value;
}
public RefObjItem GetRefItem(uint id)
{
if ([Link](id, out var data))
return data;
return null;
}
public RefObjItem GetRefItem(string codeName)
{
return [Link](obj => [Link] ==
codeName).Value;
}
public RefObjItem GetRefItem(TypeIdFilter filter)
{
return [Link](obj =>
[Link]([Link])).Value;
}
public RefSkill GetRefSkill(uint id)
{
if ([Link](id, out var data))
return data;
return null;
}
public RefSkill GetRefSkill(string codeName)
{
var skill = [Link](s => [Link].Basic_Code == codeName);
return [Link];
}
public RefSkillMastery GetRefSkillMastery(uint id)
{
if ([Link] == [Link] &&
id >= 273 && id <= 275)
id = 277; // csro shit
if ([Link](id, out var data))
return data;
return null;
}
public RefQuest GetRefQuest(uint id)
{
if ([Link](id, out var data))
return data;
return null;
}
public RefLevel GetRefLevel(byte level)
{
if ([Link](level, out var data))
return data;
return null;
}
public RefShopGroup GetRefShopGroup(string npcCodeName)
{
return [Link](sg => [Link] ==
npcCodeName).Value;
}
public RefShopGroup GetRefShopGroupById(ushort id)
{
return [Link](sg => [Link] == 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[[Link](s => [Link] ==
slot)?.RefPackageItemCodeName];
}
public RefPackageItemScrap GetRefPackageItemById(ushort id, byte group, byte
tab, byte slot)
{
return PackageItemScrap[
GetRefShopGroupById(id).GetShops()[group].GetTabs()
[tab].GetGoods().FirstOrDefault(s => [Link] == slot)
.RefPackageItemCodeName];
}
public RefPackageItemScrap GetRefPackageItem(string codeName)
{
if ([Link](codeName, out var data))
return data;
return null;
}
public List<RefPackageItemScrap> GetRefPackageItems(RefShopGroup group)
{
var result = new List<RefPackageItemScrap>();
foreach (var shop in [Link]())
{
if (shop == null) continue;
foreach (var tab in [Link]())
{
if (tab == null) continue;
foreach (var good in [Link]())
{
if (good == null) continue;
if ()
continue;
if ([Link](g => [Link] ==
[Link]) == null)
[Link](PackageItemScrap[[Link]]);
}
}
}
return result;
}
public RefShopGood GetRefShopGood(string refPackageItemCodeName)
{
return [Link](sg => [Link] ==
refPackageItemCodeName);
}
public List<RefShopGood> GetRefShopGoods(RefShopGroup group)
{
return (from shop in @[Link]()
where shop != null
from tab in [Link]()
where tab != null
from good in [Link]()
where good != null
select good).ToList();
}
public byte GetRefShopGoodTabIndex(string npcCodeName, RefShopGood good)
{
var shopGroup = GetRefShopGroup(npcCodeName);
if (shopGroup == null) return 0xFF;
var availableShops = [Link]();
foreach (var shop in availableShops)
{
var availableTabs = [Link]();
for (byte i = 0; i < [Link]; i++)
{
var goods = availableTabs[i].GetGoods();
var availableGood =
[Link](g => [Link] ==
[Link]);
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 = [Link],
bool rare = false,
string searchPattern = null)
{
var result = new List<RefObjItem>(10000);
foreach (var refItem in [Link])
{
if ([Link])
continue;
foreach (var filter in filters)
{
// step 1 compare typeids
if ()
continue;
// step 2 compare gender
var itemGender = (ObjectGender)[Link];
if (gender != [Link] && itemGender != gender)
continue;
// step 3 compare searching item name
if ()
{
var itemRealName = [Link]();
if ([Link](searchPattern,
[Link]) == -1)
continue;
}
// step 4 compare rare
if (rare && (byte)[Link] < 2)
continue;
// step 5 compare minimum degree
// dont need to check the if it is equip items
if (degreeFrom != 0 && [Link] < degreeFrom)
continue;
// step 6 compare maximum degree
// dont need to check the if it is equip items
if (degreeTo != 0 && [Link] > degreeTo)
continue;
[Link](refItem);
}
}
return result;
}
/// <summary>
/// Gets the teleporters in the specific sector
/// </summary>
/// <param name="regionId"></param>
/// <returns></returns>
public RefTeleport[] GetTeleporters(Region region)
{
return [Link](t => [Link] == region).ToArray();
}
/// <summary>
/// Gets the ground teleporters.
/// </summary>
/// <param name="regionId">The region identifier.</param>
/// <returns></returns>
public RefTeleport[] GetGroundTeleporters(Region region)
{
return [Link](t => [Link] == region && [Link]
== 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 => [Link] == 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 => [Link] == 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 => [Link] == group && [Link] ==
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 [Link](a => a.TypeId3 == typeId3 &&
a.TypeId4 == typeId4)
?.[Link](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 [Link](p => [Link] == itemId
&& [Link] == 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 [Link](p => [Link] == itemId &&
[Link] == 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 [Link](r => [Link] == questId);
}
/// <summary>
/// Returns the reward for the specified quest
/// </summary>
/// <param name="questId"></param>
/// <returns></returns>
public RefQuestReward GetQuestReward(uint questId)
{
[Link](questId, out var result);
return result;
}
private string GetDebugInfo()
{
var builder = new StringBuilder("\n=== Reference information === \n");
[Link]("TextData: {0}\n", [Link]);
[Link]("CharacterData: {0}\n", [Link]);
[Link]("ItemData: {0}\n", [Link]);
[Link]("SkillData: {0}\n", [Link]);
[Link]("SkillMasteryData: {0}\n", [Link]);
[Link]("QuestData: {0}\n", [Link]);
[Link]("QuestRewards: {0}\n", [Link]);
[Link]("QuestRewardItems: {0}\n", [Link]);
[Link]("TeleportData: {0}\n", [Link]);
[Link]("TeleportLinks: {0}\n", [Link]);
[Link]("OptionalTeleports: {0}\n", [Link]);
[Link]("MagicOptions: {0}\n", [Link]);
[Link]("MagicOptionAssignments: {0}\n",
[Link]);
[Link]("Shops: {0}\n", [Link]);
[Link]("ShopGroups: {0}\n", [Link]);
[Link]("ShopGoods: {0}\n", [Link]);
[Link]("ShopGroupMapping: {0}\n", [Link]);
[Link]("ShopTabs: {0}\n", [Link]);
[Link]("ShopTabMapping: {0}\n", [Link]);
[Link]("PackageItemScrap: {0}\n", [Link]);
[Link]("AbilityItemByOptLevel: {0}\n",
[Link]);
[Link]("SkillByItemOptLevels: {0}\n",
[Link]);
[Link]("ExtraAbilityByEquipItemOptLevel: {0}\n",
[Link]);
return [Link]();
}
}