/* * Copyright (C) 2012-2017 CypherCore * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ using Framework.Constants; using Framework.Database; using Framework.GameMath; using Framework.IO; using System; using System.Collections.Generic; using System.Reflection; namespace Game.DataStorage { public interface IDB2Storage { bool HasRecord(uint id); void WriteRecord(uint id, LocaleConstant locale, ByteBuffer buffer); void EraseRecord(uint id); } [Serializable] public class DB6Storage : Dictionary, IDB2Storage where T : new() { public void LoadData(uint indexField, DBClientHelper[] helpers, HotfixStatements preparedStatement, HotfixStatements preparedStatementLocale) { SQLResult result = DB.Hotfix.Query(DB.Hotfix.GetPreparedStatement(preparedStatement)); if (!result.IsEmpty()) { do { var idValue = result.Read((int)indexField); var obj = new T(); int index = 0; for (var fieldIndex = 0; fieldIndex < helpers.Length; fieldIndex++) { var helper = helpers[fieldIndex]; if (helper.IsArray) { Array array = (Array)helper.Getter(obj); for (var i = 0; i < array.Length; ++i) { switch (Type.GetTypeCode(helper.RealType)) { case TypeCode.SByte: helper.SetValue(array, result.Read(index++), i); break; case TypeCode.Byte: helper.SetValue(array, result.Read(index++), i); break; case TypeCode.Int16: helper.SetValue(array, result.Read(index++), i); break; case TypeCode.UInt16: helper.SetValue(array, result.Read(index++), i); break; case TypeCode.Int32: helper.SetValue(array, result.Read(index++), i); break; case TypeCode.UInt32: helper.SetValue(array, result.Read(index++), i); break; case TypeCode.Single: helper.SetValue(array, result.Read(index++), i); break; case TypeCode.String: helper.SetValue(array, result.Read(index++), i); break; case TypeCode.Object: switch (helper.FieldType.Name) { case "Vector2": var vector2 = new Vector2(); vector2.X = result.Read(index++); vector2.Y = result.Read(index++); helper.SetValue(array, vector2, i); break; case "Vector3": var vector3 = new Vector3(); vector3.X = result.Read(index++); vector3.Y = result.Read(index++); vector3.Z = result.Read(index++); helper.SetValue(array, vector3, i); break; case "LocalizedString": LocalizedString locString = new LocalizedString(); locString[Global.WorldMgr.GetDefaultDbcLocale()] = result.Read(index++); helper.SetValue(array, locString, i); break; default: Log.outError(LogFilter.ServerLoading, "Wrong Array Type: {0}", helper.FieldType.Name); break; } break; default: Log.outError(LogFilter.ServerLoading, "Wrong Array Type: {0}", helper.FieldType.Name); break; } } } else { switch (Type.GetTypeCode(helper.RealType)) { case TypeCode.SByte: helper.SetValue(obj, result.Read(index++)); break; case TypeCode.Byte: helper.SetValue(obj, result.Read(index++)); break; case TypeCode.Int16: helper.SetValue(obj, result.Read(index++)); break; case TypeCode.UInt16: helper.SetValue(obj, result.Read(index++)); break; case TypeCode.Int32: helper.SetValue(obj, result.Read(index++)); break; case TypeCode.UInt32: helper.SetValue(obj, result.Read(index++)); break; case TypeCode.Single: helper.SetValue(obj, result.Read(index++)); break; case TypeCode.String: string str = result.Read(index++); helper.SetValue(obj, str); break; case TypeCode.Object: switch (helper.FieldType.Name) { case "Vector2": var vector2 = new Vector2(); vector2.X = result.Read(index++); vector2.Y = result.Read(index++); helper.SetValue(obj, vector2); break; case "Vector3": var vector3 = new Vector3(); vector3.X = result.Read(index++); vector3.Y = result.Read(index++); vector3.Z = result.Read(index++); helper.SetValue(obj, vector3); break; case "LocalizedString": LocalizedString locString = new LocalizedString(); locString[Global.WorldMgr.GetDefaultDbcLocale()] = result.Read(index++); helper.SetValue(obj, locString); break; default: Log.outError(LogFilter.ServerLoading, "Wrong Array Type: {0}", helper.FieldType.Name); break; } break; default: Log.outError(LogFilter.ServerLoading, "Wrong Array Type: {0}", helper.FieldType.Name); break; } } } base[idValue] = obj; } while (result.NextRow()); } if (preparedStatementLocale == 0) return; for (LocaleConstant locale = 0; locale < LocaleConstant.OldTotal; ++locale) { if (Global.WorldMgr.GetDefaultDbcLocale() == locale || locale == LocaleConstant.None) continue; PreparedStatement stmt = DB.Hotfix.GetPreparedStatement(preparedStatementLocale); stmt.AddValue(0, locale.ToString()); SQLResult localeResult = DB.Hotfix.Query(stmt); if (localeResult.IsEmpty()) continue; do { int index = 0; var obj = this.LookupByKey(localeResult.Read(index++)); if (obj == null) continue; for (var i = 0; i < helpers.Length; i++) { var fieldInfo = helpers[i]; if (fieldInfo.FieldType != typeof(LocalizedString)) continue; LocalizedString locString = (LocalizedString)fieldInfo.Getter(obj); locString[locale] = localeResult.Read(index++); } } while (localeResult.NextRow()); } } public bool HasRecord(uint id) { return ContainsKey(id); } public void WriteRecord(uint id, LocaleConstant locale, ByteBuffer buffer) { T entry = this.LookupByKey(id); foreach (var fieldInfo in entry.GetType().GetFields()) { if (fieldInfo.Name == "Id") continue; var type = fieldInfo.FieldType; if (type.IsArray) { WriteArrayValues(entry, fieldInfo, buffer); continue; } switch (Type.GetTypeCode(type)) { case TypeCode.Boolean: buffer.WriteUInt8(fieldInfo.GetValue(entry)); break; case TypeCode.SByte: buffer.WriteInt8(fieldInfo.GetValue(entry)); break; case TypeCode.Byte: buffer.WriteUInt8(fieldInfo.GetValue(entry)); break; case TypeCode.Int16: buffer.WriteInt16(fieldInfo.GetValue(entry)); break; case TypeCode.UInt16: buffer.WriteUInt16(fieldInfo.GetValue(entry)); break; case TypeCode.Int32: buffer.WriteInt32(fieldInfo.GetValue(entry)); break; case TypeCode.UInt32: buffer.WriteUInt32(fieldInfo.GetValue(entry)); break; case TypeCode.Int64: buffer.WriteInt64(fieldInfo.GetValue(entry)); break; case TypeCode.UInt64: buffer.WriteUInt64(fieldInfo.GetValue(entry)); break; case TypeCode.Single: buffer.WriteFloat(fieldInfo.GetValue(entry)); break; case TypeCode.Object: switch (type.Name) { case "LocalizedString": LocalizedString locStr = (LocalizedString)fieldInfo.GetValue(entry); if (!locStr.HasString(locale)) { locale = 0; if (!locStr.HasString(locale)) { buffer.WriteUInt16(0); break; } } string str = locStr[locale]; buffer.WriteCString(str); break; } break; } } } void WriteArrayValues(object entry, FieldInfo fieldInfo, ByteBuffer buffer) { var type = fieldInfo.FieldType.GetElementType(); var array = (Array)fieldInfo.GetValue(entry); for (var i = 0; i < array.Length; ++i) { switch (Type.GetTypeCode(type)) { case TypeCode.Boolean: buffer.WriteUInt8(array.GetValue(i)); break; case TypeCode.SByte: buffer.WriteInt8(array.GetValue(i)); break; case TypeCode.Byte: buffer.WriteUInt8(array.GetValue(i)); break; case TypeCode.Int16: buffer.WriteInt16(array.GetValue(i)); break; case TypeCode.UInt16: buffer.WriteUInt16(array.GetValue(i)); break; case TypeCode.Int32: buffer.WriteInt32(array.GetValue(i)); break; case TypeCode.UInt32: buffer.WriteUInt32(array.GetValue(i)); break; case TypeCode.Int64: buffer.WriteInt64(array.GetValue(i)); break; case TypeCode.UInt64: buffer.WriteUInt64(array.GetValue(i)); break; case TypeCode.Single: buffer.WriteFloat(array.GetValue(i)); break; case TypeCode.String: var str = (string)array.GetValue(i); buffer.WriteCString(str); break; } } } public void EraseRecord(uint id) { Remove(id); } } }