Core/DataStores: Implement optional data in hotfix packets
Port From (https://github.com/TrinityCore/TrinityCore/commit/fbbf40981cc14523fa181cf6125336b254e8ae4d)
This commit is contained in:
@@ -285,7 +285,7 @@ namespace Game.DataStorage
|
||||
SpellVisualKitStorage = ReadDB2<SpellVisualKitRecord>("SpellVisualKit.db2", HotfixStatements.SEL_SPELL_VISUAL_KIT);
|
||||
SpellXSpellVisualStorage = ReadDB2<SpellXSpellVisualRecord>("SpellXSpellVisual.db2", HotfixStatements.SEL_SPELL_X_SPELL_VISUAL);
|
||||
SummonPropertiesStorage = ReadDB2<SummonPropertiesRecord>("SummonProperties.db2", HotfixStatements.SEL_SUMMON_PROPERTIES);
|
||||
//TactKeyStorage = ReadDB2<TactKeyRecord>("TactKey.db2", HotfixStatements.SEL_TACT_KEY);
|
||||
TactKeyStorage = ReadDB2<TactKeyRecord>("TactKey.db2", HotfixStatements.SEL_TACT_KEY);
|
||||
TalentStorage = ReadDB2<TalentRecord>("Talent.db2", HotfixStatements.SEL_TALENT, HotfixStatements.SEL_TALENT_LOCALE);
|
||||
TaxiNodesStorage = ReadDB2<TaxiNodesRecord>("TaxiNodes.db2", HotfixStatements.SEL_TAXI_NODES, HotfixStatements.SEL_TAXI_NODES_LOCALE);
|
||||
TaxiPathStorage = ReadDB2<TaxiPathRecord>("TaxiPath.db2", HotfixStatements.SEL_TAXI_PATH);
|
||||
@@ -641,7 +641,7 @@ namespace Game.DataStorage
|
||||
public static DB6Storage<SpellVisualKitRecord> SpellVisualKitStorage;
|
||||
public static DB6Storage<SpellXSpellVisualRecord> SpellXSpellVisualStorage;
|
||||
public static DB6Storage<SummonPropertiesRecord> SummonPropertiesStorage;
|
||||
//public static DB6Storage<TactKeyRecord> TactKeyStorage;
|
||||
public static DB6Storage<TactKeyRecord> TactKeyStorage;
|
||||
public static DB6Storage<TalentRecord> TalentStorage;
|
||||
public static DB6Storage<TaxiNodesRecord> TaxiNodesStorage;
|
||||
public static DB6Storage<TaxiPathRecord> TaxiPathStorage;
|
||||
|
||||
@@ -39,8 +39,12 @@ namespace Game.DataStorage
|
||||
[Serializable]
|
||||
public class DB6Storage<T> : Dictionary<uint, T>, IDB2Storage where T : new()
|
||||
{
|
||||
public void LoadData(int indexField, BitSet availableDb2Locales, HotfixStatements preparedStatement, HotfixStatements preparedStatementLocale)
|
||||
uint _tableHash;
|
||||
|
||||
public void LoadData(WDCHeader header, BitSet availableDb2Locales, HotfixStatements preparedStatement, HotfixStatements preparedStatementLocale)
|
||||
{
|
||||
_tableHash = header.TableHash;
|
||||
|
||||
SQLResult result = DB.Hotfix.Query(DB.Hotfix.GetPreparedStatement(preparedStatement));
|
||||
if (!result.IsEmpty())
|
||||
{
|
||||
@@ -183,7 +187,7 @@ namespace Game.DataStorage
|
||||
}
|
||||
}
|
||||
|
||||
var id = (uint)fields[indexField == -1 ? 0 : indexField].GetValue(obj);
|
||||
var id = (uint)fields[header.IdIndex == -1 ? 0 : header.IdIndex].GetValue(obj);
|
||||
base[id] = obj;
|
||||
}
|
||||
while (result.NextRow());
|
||||
@@ -358,5 +362,7 @@ namespace Game.DataStorage
|
||||
{
|
||||
Remove(id);
|
||||
}
|
||||
|
||||
public uint GetTableHash() { return _tableHash; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,7 +58,7 @@ namespace Game.DataStorage
|
||||
foreach (var b in reader._records)
|
||||
storage.Add((uint)b.Key, b.Value.As<T>());
|
||||
|
||||
storage.LoadData(reader.Header.IdIndex, availableDb2Locales, preparedStatement, preparedStatementLocale);
|
||||
storage.LoadData(reader.Header, availableDb2Locales, preparedStatement, preparedStatementLocale);
|
||||
|
||||
Global.DB2Mgr.AddDB2(reader.Header.TableHash, storage);
|
||||
loadedFileCount++;
|
||||
|
||||
@@ -43,7 +43,10 @@ namespace Game.DataStorage
|
||||
_nameValidators[i] = new List<string>();
|
||||
|
||||
for (var i = 0; i < (int)Locale.Total; ++i)
|
||||
_hotfixBlob[i] = new Dictionary<Tuple<uint, int>, byte[]>();
|
||||
{
|
||||
_hotfixBlob[i] = new Dictionary<(uint tableHas, int recordId), byte[]>();
|
||||
_hotfixOptionalData[i] = new MultiMap<(uint tableHas, int recordId), HotfixOptionalData>();
|
||||
}
|
||||
}
|
||||
|
||||
public void LoadStores()
|
||||
@@ -748,7 +751,7 @@ namespace Game.DataStorage
|
||||
var storeItr = _storage.LookupByKey(tableHash);
|
||||
if (storeItr != null)
|
||||
{
|
||||
Log.outError(LogFilter.ServerLoading, $"Table hash 0x{tableHash:X} points to a loaded DB2 store {nameof(storeItr)}, fill related table instead of hotfix_blob");
|
||||
Log.outError(LogFilter.Sql, $"Table hash 0x{tableHash:X} points to a loaded DB2 store {nameof(storeItr)}, fill related table instead of hotfix_blob");
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -758,20 +761,96 @@ namespace Game.DataStorage
|
||||
Locale locale = localeName.ToEnum<Locale>();
|
||||
if (!SharedConst.IsValidLocale(locale))
|
||||
{
|
||||
Log.outError(LogFilter.ServerLoading, $"`hotfix_blob` contains invalid locale: {localeName} at TableHash: 0x{tableHash:X} and RecordID: {recordId}");
|
||||
Log.outError(LogFilter.Sql, $"`hotfix_blob` contains invalid locale: {localeName} at TableHash: 0x{tableHash:X} and RecordID: {recordId}");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!availableDb2Locales[(int)locale])
|
||||
continue;
|
||||
|
||||
_hotfixBlob[(int)locale][Tuple.Create(tableHash, recordId)] = result.Read<byte[]>(3);
|
||||
_hotfixBlob[(int)locale][(tableHash, recordId)] = result.Read<byte[]>(3);
|
||||
hotfixBlobCount++;
|
||||
} while (result.NextRow());
|
||||
|
||||
Log.outInfo(LogFilter.ServerLoading, $"Loaded {hotfixBlobCount} hotfix blob records in {Time.GetMSTimeDiffToNow(oldMSTime)} ms");
|
||||
}
|
||||
|
||||
public void LoadHotfixOptionalData(BitSet availableDb2Locales)
|
||||
{
|
||||
// Register allowed optional data keys
|
||||
_allowedHotfixOptionalData.Add(CliDB.BroadcastTextStorage.GetTableHash(), Tuple.Create(CliDB.TactKeyStorage.GetTableHash(), (AllowedHotfixOptionalData)ValidateBroadcastTextTactKeyOptionalData));
|
||||
|
||||
uint oldMSTime = Time.GetMSTime();
|
||||
|
||||
SQLResult result = DB.Hotfix.Query("SELECT TableHash, RecordId, locale, `Key`, `Data` FROM hotfix_optional_data ORDER BY TableHash");
|
||||
if (result.IsEmpty())
|
||||
{
|
||||
Log.outInfo(LogFilter.ServerLoading, "Loaded 0 hotfix optional data records.");
|
||||
return;
|
||||
}
|
||||
|
||||
uint hotfixOptionalDataCount = 0;
|
||||
do
|
||||
{
|
||||
uint tableHash = result.Read<uint>(0);
|
||||
var allowedHotfixes = _allowedHotfixOptionalData.LookupByKey(tableHash);
|
||||
if (allowedHotfixes.Empty())
|
||||
{
|
||||
Log.outError(LogFilter.Sql, $"Table `hotfix_optional_data` references DB2 store by hash 0x{tableHash:X} that is not allowed to have optional data");
|
||||
continue;
|
||||
}
|
||||
|
||||
uint recordId = result.Read<uint>(1);
|
||||
var db2storage = _storage.LookupByKey(tableHash);
|
||||
if (db2storage == null)
|
||||
{
|
||||
Log.outError(LogFilter.Sql, $"Table `hotfix_optional_data` references unknown DB2 store by hash 0x{tableHash:X} with RecordID: {recordId}");
|
||||
continue;
|
||||
}
|
||||
|
||||
string localeName = result.Read<string>(2);
|
||||
Locale locale = localeName.ToEnum<Locale>();
|
||||
|
||||
if (!SharedConst.IsValidLocale(locale))
|
||||
{
|
||||
Log.outError(LogFilter.Sql, $"`hotfix_optional_data` contains invalid locale: {localeName} at TableHash: 0x{tableHash:X} and RecordID: {recordId}");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!availableDb2Locales[(int)locale])
|
||||
continue;
|
||||
|
||||
HotfixOptionalData optionalData = new HotfixOptionalData();
|
||||
optionalData.Key = result.Read<uint>(3);
|
||||
var allowedHotfixItr = allowedHotfixes.Find(v =>
|
||||
{
|
||||
return v.Item1 == optionalData.Key;
|
||||
});
|
||||
if (allowedHotfixItr == null)
|
||||
{
|
||||
Log.outError(LogFilter.Sql, $"Table `hotfix_optional_data` references non-allowed optional data key 0x{optionalData.Key:X} for DB2 store by hash 0x{tableHash:X} and RecordID: {recordId}");
|
||||
continue;
|
||||
}
|
||||
|
||||
optionalData.Data = result.Read<byte[]>(4);
|
||||
if (!allowedHotfixItr.Item2(optionalData.Data))
|
||||
{
|
||||
Log.outError(LogFilter.Sql, $"Table `hotfix_optional_data` contains invalid data for DB2 store 0x{tableHash:X}, RecordID: {recordId} and Key: 0x{optionalData.Key:X}");
|
||||
continue;
|
||||
}
|
||||
|
||||
_hotfixOptionalData[(int)locale].Add((tableHash, (int)recordId), optionalData);
|
||||
hotfixOptionalDataCount++;
|
||||
} while (result.NextRow());
|
||||
|
||||
Log.outInfo(LogFilter.ServerLoading, $"Loaded {hotfixOptionalDataCount} hotfix optional data records in {Time.GetMSTimeDiffToNow(oldMSTime)} ms");
|
||||
}
|
||||
|
||||
public bool ValidateBroadcastTextTactKeyOptionalData(byte[] data)
|
||||
{
|
||||
return data.Length == 8 + 16;
|
||||
}
|
||||
|
||||
public uint GetHotfixCount() { return (uint)_hotfixData.Count; }
|
||||
|
||||
public List<HotfixRecord> GetHotfixData() { return _hotfixData; }
|
||||
@@ -783,6 +862,13 @@ namespace Game.DataStorage
|
||||
return _hotfixBlob[(int)locale].LookupByKey(Tuple.Create(tableHash, recordId));
|
||||
}
|
||||
|
||||
public List<HotfixOptionalData> GetHotfixOptionalData(uint tableHash, uint recordId, Locale locale)
|
||||
{
|
||||
Cypher.Assert(SharedConst.IsValidLocale(locale), $"Locale {locale} is invalid locale");
|
||||
|
||||
return _hotfixOptionalData[(int)locale].LookupByKey((tableHash, (int)recordId));
|
||||
}
|
||||
|
||||
public uint GetEmptyAnimStateID()
|
||||
{
|
||||
return (uint)CliDB.AnimationDataStorage.Count;
|
||||
@@ -2154,9 +2240,13 @@ namespace Game.DataStorage
|
||||
_storage[tableHash] = store;
|
||||
}
|
||||
|
||||
delegate bool AllowedHotfixOptionalData(byte[] data);
|
||||
|
||||
Dictionary<uint, IDB2Storage> _storage = new Dictionary<uint, IDB2Storage>();
|
||||
List<HotfixRecord> _hotfixData = new List<HotfixRecord>();
|
||||
Dictionary<Tuple<uint, int>, byte[]>[] _hotfixBlob = new Dictionary<Tuple<uint, int>, byte[]>[(int)Locale.Total];
|
||||
Dictionary<(uint tableHas, int recordId), byte[]>[] _hotfixBlob = new Dictionary<(uint tableHas, int recordId), byte[]>[(int)Locale.Total];
|
||||
MultiMap<uint, Tuple<uint, AllowedHotfixOptionalData>> _allowedHotfixOptionalData = new MultiMap<uint, Tuple<uint, AllowedHotfixOptionalData>>();
|
||||
MultiMap<(uint tableHas, int recordId), HotfixOptionalData>[]_hotfixOptionalData = new MultiMap<(uint tableHas, int recordId), HotfixOptionalData>[(int)Locale.Total];
|
||||
|
||||
MultiMap<uint, uint> _areaGroupMembers = new MultiMap<uint, uint>();
|
||||
MultiMap<uint, ArtifactPowerRecord> _artifactPowers = new MultiMap<uint, ArtifactPowerRecord>();
|
||||
@@ -2408,7 +2498,13 @@ namespace Game.DataStorage
|
||||
HotfixID = data.ReadInt32();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public class HotfixOptionalData
|
||||
{
|
||||
public uint Key;
|
||||
public byte[] Data;
|
||||
}
|
||||
|
||||
class ChrClassesXPowerTypesRecordComparer : IComparer<ChrClassesXPowerTypesRecord>
|
||||
{
|
||||
public int Compare(ChrClassesXPowerTypesRecord left, ChrClassesXPowerTypesRecord right)
|
||||
|
||||
Reference in New Issue
Block a user