Core/DBLayer: Implement async transaction completion callbacks
Port From (https://github.com/TrinityCore/TrinityCore/commit/0f0ca3a9194d76afa0227943e86469ad8368c5e2)
This commit is contained in:
@@ -55,7 +55,7 @@ namespace BNetServer.Networking
|
||||
stmt.AddValue(0, ip_address);
|
||||
stmt.AddValue(1, BitConverter.ToUInt32(GetRemoteIpAddress().GetAddressBytes(), 0));
|
||||
|
||||
_queryProcessor.AddQuery(DB.Login.AsyncQuery(stmt).WithCallback(CheckIpCallback));
|
||||
_queryProcessor.AddCallback(DB.Login.AsyncQuery(stmt).WithCallback(CheckIpCallback));
|
||||
}
|
||||
|
||||
void CheckIpCallback(SQLResult result)
|
||||
@@ -89,7 +89,7 @@ namespace BNetServer.Networking
|
||||
if (!base.Update())
|
||||
return false;
|
||||
|
||||
_queryProcessor.ProcessReadyQueries();
|
||||
_queryProcessor.ProcessReadyCallbacks();
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -631,7 +631,7 @@ namespace BNetServer.Networking
|
||||
|
||||
bool _authed;
|
||||
|
||||
QueryCallbackProcessor _queryProcessor = new QueryCallbackProcessor();
|
||||
AsyncCallbackProcessor<QueryCallback> _queryProcessor = new AsyncCallbackProcessor<QueryCallback>();
|
||||
|
||||
Dictionary<uint, Action<CodedInputStream>> _responseCallbacks = new Dictionary<uint, Action<CodedInputStream>>();
|
||||
uint _requestToken;
|
||||
|
||||
+12
-6
@@ -19,21 +19,27 @@ using System.Collections.Generic;
|
||||
|
||||
namespace Framework.Database
|
||||
{
|
||||
public class QueryCallbackProcessor
|
||||
public interface ISqlCallback
|
||||
{
|
||||
public void AddQuery(QueryCallback query)
|
||||
bool InvokeIfReady();
|
||||
}
|
||||
|
||||
public class AsyncCallbackProcessor<T> where T : ISqlCallback
|
||||
{
|
||||
List<T> _callbacks = new List<T>();
|
||||
|
||||
public T AddCallback(T query)
|
||||
{
|
||||
_callbacks.Add(query);
|
||||
return query;
|
||||
}
|
||||
|
||||
public void ProcessReadyQueries()
|
||||
public void ProcessReadyCallbacks()
|
||||
{
|
||||
if (_callbacks.Empty())
|
||||
return;
|
||||
|
||||
_callbacks.RemoveAll(callback => callback.InvokeIfReady() == QueryCallbackStatus.Completed);
|
||||
_callbacks.RemoveAll(callback => callback.InvokeIfReady());
|
||||
}
|
||||
|
||||
List<QueryCallback> _callbacks = new List<QueryCallback>();
|
||||
}
|
||||
}
|
||||
@@ -253,7 +253,15 @@ namespace Framework.Database
|
||||
_queue.Push(new TransactionTask(transaction));
|
||||
}
|
||||
|
||||
public bool DirectCommitTransaction(SQLTransaction transaction)
|
||||
public TransactionCallback AsyncCommitTransaction(SQLTransaction transaction)
|
||||
{
|
||||
TransactionWithResultTask task = new TransactionWithResultTask(transaction);
|
||||
Task<bool> result = task.GetFuture();
|
||||
_queue.Push(task);
|
||||
return new TransactionCallback(result);
|
||||
}
|
||||
|
||||
public MySqlErrorCode DirectCommitTransaction(SQLTransaction transaction)
|
||||
{
|
||||
using (var Connection = _connectionInfo.GetConnection())
|
||||
{
|
||||
@@ -277,13 +285,12 @@ namespace Framework.Database
|
||||
trans.Commit();
|
||||
scope.Complete();
|
||||
}
|
||||
return true;
|
||||
return MySqlErrorCode.None;
|
||||
}
|
||||
catch (MySqlException ex) //error occurred
|
||||
{
|
||||
HandleMySQLException(ex, query);
|
||||
trans.Rollback();
|
||||
return false;
|
||||
return HandleMySQLException(ex, query);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ using System.Threading.Tasks;
|
||||
|
||||
namespace Framework.Database
|
||||
{
|
||||
public class QueryCallback
|
||||
public class QueryCallback : ISqlCallback
|
||||
{
|
||||
public QueryCallback(Task<SQLResult> result)
|
||||
{
|
||||
@@ -49,7 +49,7 @@ namespace Framework.Database
|
||||
_result = next._result;
|
||||
}
|
||||
|
||||
public QueryCallbackStatus InvokeIfReady()
|
||||
public bool InvokeIfReady()
|
||||
{
|
||||
QueryCallbackData callback = _callbacks.Peek();
|
||||
|
||||
@@ -68,17 +68,17 @@ namespace Framework.Database
|
||||
if (_callbacks.Count == 0)
|
||||
{
|
||||
Cypher.Assert(!hasNext);
|
||||
return QueryCallbackStatus.Completed;
|
||||
return true;
|
||||
}
|
||||
|
||||
// abort chain
|
||||
if (!hasNext)
|
||||
return QueryCallbackStatus.Completed;
|
||||
return true;
|
||||
|
||||
callback = _callbacks.Peek();
|
||||
}
|
||||
else
|
||||
return QueryCallbackStatus.NotReady;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -100,11 +100,4 @@ namespace Framework.Database
|
||||
|
||||
public Action<QueryCallback, SQLResult> _result;
|
||||
}
|
||||
|
||||
public enum QueryCallbackStatus
|
||||
{
|
||||
NotReady,
|
||||
NextStep,
|
||||
Completed
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,6 +17,8 @@
|
||||
|
||||
using MySql.Data.MySqlClient;
|
||||
using System.Collections.Generic;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Framework.Database
|
||||
{
|
||||
@@ -52,10 +54,98 @@ namespace Framework.Database
|
||||
}
|
||||
|
||||
public bool Execute<T>(MySqlBase<T> mySqlBase)
|
||||
{
|
||||
MySqlErrorCode errorCode = TryExecute(mySqlBase);
|
||||
if (errorCode == MySqlErrorCode.None)
|
||||
return true;
|
||||
|
||||
if (errorCode == MySqlErrorCode.LockDeadlock)
|
||||
{
|
||||
// Make sure only 1 async thread retries a transaction so they don't keep dead-locking each other
|
||||
lock (_deadlockLock)
|
||||
{
|
||||
byte loopBreaker = 5; // Handle MySQL Errno 1213 without extending deadlock to the core itself
|
||||
for (byte i = 0; i < loopBreaker; ++i)
|
||||
if (TryExecute(mySqlBase) == MySqlErrorCode.None)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public MySqlErrorCode TryExecute<T>(MySqlBase<T> mySqlBase)
|
||||
{
|
||||
return mySqlBase.DirectCommitTransaction(m_trans);
|
||||
}
|
||||
|
||||
SQLTransaction m_trans;
|
||||
public static object _deadlockLock = new object();
|
||||
}
|
||||
|
||||
class TransactionWithResultTask : TransactionTask
|
||||
{
|
||||
public TransactionWithResultTask(SQLTransaction trans) : base(trans) { }
|
||||
|
||||
public new bool Execute<T>(MySqlBase<T> mySqlBase)
|
||||
{
|
||||
MySqlErrorCode errorCode = TryExecute(mySqlBase);
|
||||
if (errorCode == MySqlErrorCode.None)
|
||||
{
|
||||
m_result.SetResult(true);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (errorCode == MySqlErrorCode.LockDeadlock)
|
||||
{
|
||||
// Make sure only 1 async thread retries a transaction so they don't keep dead-locking each other
|
||||
lock (_deadlockLock)
|
||||
{
|
||||
byte loopBreaker = 5; // Handle MySQL Errno 1213 without extending deadlock to the core itself
|
||||
for (byte i = 0; i < loopBreaker; ++i)
|
||||
{
|
||||
if (TryExecute(mySqlBase) == MySqlErrorCode.None)
|
||||
{
|
||||
m_result.SetResult(true);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_result.SetResult(false);
|
||||
return false;
|
||||
}
|
||||
|
||||
public Task<bool> GetFuture() { return m_result.Task; }
|
||||
|
||||
TaskCompletionSource<bool> m_result = new TaskCompletionSource<bool>();
|
||||
}
|
||||
|
||||
public class TransactionCallback : ISqlCallback
|
||||
{
|
||||
public TransactionCallback(Task<bool> future)
|
||||
{
|
||||
m_future = future;
|
||||
}
|
||||
|
||||
public void AfterComplete(Action<bool> callback)
|
||||
{
|
||||
m_callback = callback;
|
||||
}
|
||||
|
||||
public bool InvokeIfReady()
|
||||
{
|
||||
if (m_future != null && m_future.Wait(0))
|
||||
{
|
||||
m_callback(m_future.Result);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
Task<bool> m_future;
|
||||
Action<bool> m_callback;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -73,6 +73,7 @@ namespace Game.Entities
|
||||
{
|
||||
return MapSpecificCreate(type, (byte)subType, (ushort)mapId, 0, entry, counter);
|
||||
}
|
||||
|
||||
static ObjectGuid GlobalCreate(HighGuid type, ulong counter)
|
||||
{
|
||||
return new ObjectGuid((ulong)type << 58, counter);
|
||||
|
||||
@@ -3107,6 +3107,17 @@ namespace Game.Entities
|
||||
}
|
||||
|
||||
public void SaveToDB(bool create = false)
|
||||
{
|
||||
SQLTransaction loginTransaction = new SQLTransaction();
|
||||
SQLTransaction characterTransaction = new SQLTransaction();
|
||||
|
||||
SaveToDB(loginTransaction, characterTransaction, create);
|
||||
|
||||
DB.Characters.CommitTransaction(characterTransaction);
|
||||
DB.Login.CommitTransaction(loginTransaction);
|
||||
}
|
||||
|
||||
public void SaveToDB(SQLTransaction loginTransaction, SQLTransaction characterTransaction, bool create = false)
|
||||
{
|
||||
// delay auto save at any saves (manual, in code, or autosave)
|
||||
m_nextSave = WorldConfig.GetUIntValue(WorldCfg.IntervalSave);
|
||||
@@ -3126,13 +3137,12 @@ namespace Game.Entities
|
||||
if (!create)
|
||||
Global.ScriptMgr.OnPlayerSave(this);
|
||||
|
||||
SQLTransaction trans = new SQLTransaction();
|
||||
PreparedStatement stmt;
|
||||
byte index = 0;
|
||||
|
||||
stmt = DB.Characters.GetPreparedStatement(CharStatements.DEL_CHAR_FISHINGSTEPS);
|
||||
stmt.AddValue(0, GetGUID().GetCounter());
|
||||
trans.Append(stmt);
|
||||
characterTransaction.Append(stmt);
|
||||
|
||||
float finiteAlways(float f) { return !float.IsInfinity(f) ? f : 0.0f; };
|
||||
|
||||
@@ -3428,7 +3438,7 @@ namespace Game.Entities
|
||||
stmt.AddValue(index, GetGUID().GetCounter());
|
||||
}
|
||||
|
||||
trans.Append(stmt);
|
||||
characterTransaction.Append(stmt);
|
||||
|
||||
if (m_fishingSteps != 0)
|
||||
{
|
||||
@@ -3436,58 +3446,55 @@ namespace Game.Entities
|
||||
index = 0;
|
||||
stmt.AddValue(index++, GetGUID().GetCounter());
|
||||
stmt.AddValue(index++, m_fishingSteps);
|
||||
trans.Append(stmt);
|
||||
characterTransaction.Append(stmt);
|
||||
}
|
||||
|
||||
if (m_mailsUpdated) //save mails only when needed
|
||||
_SaveMail(trans);
|
||||
_SaveMail(characterTransaction);
|
||||
|
||||
_SaveBGData(trans);
|
||||
_SaveInventory(trans);
|
||||
_SaveVoidStorage(trans);
|
||||
_SaveQuestStatus(trans);
|
||||
_SaveDailyQuestStatus(trans);
|
||||
_SaveWeeklyQuestStatus(trans);
|
||||
_SaveSeasonalQuestStatus(trans);
|
||||
_SaveMonthlyQuestStatus(trans);
|
||||
_SaveGlyphs(trans);
|
||||
_SaveTalents(trans);
|
||||
_SaveSpells(trans);
|
||||
GetSpellHistory().SaveToDB<Player>(trans);
|
||||
_SaveActions(trans);
|
||||
_SaveAuras(trans);
|
||||
_SaveSkills(trans);
|
||||
m_achievementSys.SaveToDB(trans);
|
||||
reputationMgr.SaveToDB(trans);
|
||||
m_questObjectiveCriteriaMgr.SaveToDB(trans);
|
||||
_SaveEquipmentSets(trans);
|
||||
GetSession().SaveTutorialsData(trans); // changed only while character in game
|
||||
_SaveInstanceTimeRestrictions(trans);
|
||||
_SaveCurrency(trans);
|
||||
_SaveCUFProfiles(trans);
|
||||
_SaveBGData(characterTransaction);
|
||||
_SaveInventory(characterTransaction);
|
||||
_SaveVoidStorage(characterTransaction);
|
||||
_SaveQuestStatus(characterTransaction);
|
||||
_SaveDailyQuestStatus(characterTransaction);
|
||||
_SaveWeeklyQuestStatus(characterTransaction);
|
||||
_SaveSeasonalQuestStatus(characterTransaction);
|
||||
_SaveMonthlyQuestStatus(characterTransaction);
|
||||
_SaveGlyphs(characterTransaction);
|
||||
_SaveTalents(characterTransaction);
|
||||
_SaveSpells(characterTransaction);
|
||||
GetSpellHistory().SaveToDB<Player>(characterTransaction);
|
||||
_SaveActions(characterTransaction);
|
||||
_SaveAuras(characterTransaction);
|
||||
_SaveSkills(characterTransaction);
|
||||
m_achievementSys.SaveToDB(characterTransaction);
|
||||
reputationMgr.SaveToDB(characterTransaction);
|
||||
m_questObjectiveCriteriaMgr.SaveToDB(characterTransaction);
|
||||
_SaveEquipmentSets(characterTransaction);
|
||||
GetSession().SaveTutorialsData(characterTransaction); // changed only while character in game
|
||||
_SaveInstanceTimeRestrictions(characterTransaction);
|
||||
_SaveCurrency(characterTransaction);
|
||||
_SaveCUFProfiles(characterTransaction);
|
||||
if (_garrison != null)
|
||||
_garrison.SaveToDB(trans);
|
||||
_garrison.SaveToDB(characterTransaction);
|
||||
|
||||
// check if stats should only be saved on logout
|
||||
// save stats can be out of transaction
|
||||
if (GetSession().IsLogingOut() || !WorldConfig.GetBoolValue(WorldCfg.StatsSaveOnlyOnLogout))
|
||||
_SaveStats(trans);
|
||||
|
||||
DB.Characters.CommitTransaction(trans);
|
||||
_SaveStats(characterTransaction);
|
||||
|
||||
// TODO: Move this out
|
||||
trans = new SQLTransaction();
|
||||
GetSession().GetCollectionMgr().SaveAccountToys(trans);
|
||||
GetSession().GetBattlePetMgr().SaveToDB(trans);
|
||||
GetSession().GetCollectionMgr().SaveAccountHeirlooms(trans);
|
||||
GetSession().GetCollectionMgr().SaveAccountMounts(trans);
|
||||
GetSession().GetCollectionMgr().SaveAccountItemAppearances(trans);
|
||||
GetSession().GetCollectionMgr().SaveAccountToys(loginTransaction);
|
||||
GetSession().GetBattlePetMgr().SaveToDB(loginTransaction);
|
||||
GetSession().GetCollectionMgr().SaveAccountHeirlooms(loginTransaction);
|
||||
GetSession().GetCollectionMgr().SaveAccountMounts(loginTransaction);
|
||||
GetSession().GetCollectionMgr().SaveAccountItemAppearances(loginTransaction);
|
||||
|
||||
stmt = DB.Login.GetPreparedStatement(LoginStatements.DEL_BNET_LAST_PLAYER_CHARACTERS);
|
||||
stmt.AddValue(0, GetSession().GetAccountId());
|
||||
stmt.AddValue(1, Global.WorldMgr.GetRealmId().Region);
|
||||
stmt.AddValue(2, Global.WorldMgr.GetRealmId().Site);
|
||||
trans.Append(stmt);
|
||||
loginTransaction.Append(stmt);
|
||||
|
||||
stmt = DB.Login.GetPreparedStatement(LoginStatements.INS_BNET_LAST_PLAYER_CHARACTERS);
|
||||
stmt.AddValue(0, GetSession().GetAccountId());
|
||||
@@ -3497,9 +3504,7 @@ namespace Game.Entities
|
||||
stmt.AddValue(4, GetName());
|
||||
stmt.AddValue(5, GetGUID().GetCounter());
|
||||
stmt.AddValue(6, Time.UnixTime);
|
||||
trans.Append(stmt);
|
||||
|
||||
DB.Login.CommitTransaction(trans);
|
||||
loginTransaction.Append(stmt);
|
||||
|
||||
// save pet (hunter pet level and experience and all type pets health/mana).
|
||||
Pet pet = GetPet();
|
||||
|
||||
@@ -383,7 +383,7 @@ namespace Game.Entities
|
||||
stmt.AddValue(1, GetActiveTalentGroup());
|
||||
|
||||
WorldSession mySess = GetSession();
|
||||
mySess.GetQueryProcessor().AddQuery(DB.Characters.AsyncQuery(stmt).WithCallback(result =>
|
||||
mySess.GetQueryProcessor().AddCallback(DB.Characters.AsyncQuery(stmt).WithCallback(result =>
|
||||
{
|
||||
// in case player logs out before db response (player would be deleted in that case)
|
||||
Player thisPlayer = mySess.GetPlayer();
|
||||
|
||||
@@ -49,7 +49,7 @@ namespace Game
|
||||
stmt.AddValue(0, PetSaveMode.AsCurrent);
|
||||
stmt.AddValue(1, GetAccountId());
|
||||
|
||||
_queryProcessor.AddQuery(DB.Characters.AsyncQuery(stmt).WithCallback(HandleCharEnumCallback));
|
||||
_queryProcessor.AddCallback(DB.Characters.AsyncQuery(stmt).WithCallback(HandleCharEnumCallback));
|
||||
}
|
||||
|
||||
void HandleCharEnumCallback(SQLResult result)
|
||||
@@ -144,7 +144,7 @@ namespace Game
|
||||
stmt.AddValue(0, (uint)PetSaveMode.AsCurrent);
|
||||
stmt.AddValue(1, GetAccountId());
|
||||
|
||||
_queryProcessor.AddQuery(DB.Characters.AsyncQuery(stmt).WithCallback(HandleCharUndeleteEnumCallback));
|
||||
_queryProcessor.AddCallback(DB.Characters.AsyncQuery(stmt).WithCallback(HandleCharUndeleteEnumCallback));
|
||||
}
|
||||
|
||||
void HandleCharUndeleteEnumCallback(SQLResult result)
|
||||
@@ -307,7 +307,7 @@ namespace Game
|
||||
PreparedStatement stmt = DB.Characters.GetPreparedStatement(CharStatements.SEL_CHECK_NAME);
|
||||
stmt.AddValue(0, charCreate.CreateInfo.Name);
|
||||
|
||||
_queryProcessor.AddQuery(DB.Characters.AsyncQuery(stmt).WithChainingCallback((queryCallback, result) =>
|
||||
_queryProcessor.AddCallback(DB.Characters.AsyncQuery(stmt).WithChainingCallback((queryCallback, result) =>
|
||||
{
|
||||
if (!result.IsEmpty())
|
||||
{
|
||||
@@ -334,6 +334,7 @@ namespace Game
|
||||
stmt = DB.Characters.GetPreparedStatement(CharStatements.SEL_SUM_CHARS);
|
||||
stmt.AddValue(0, GetAccountId());
|
||||
queryCallback.SetNextQuery(DB.Characters.AsyncQuery(stmt));
|
||||
|
||||
}).WithChainingCallback((queryCallback, result) =>
|
||||
{
|
||||
if (!result.IsEmpty())
|
||||
@@ -347,16 +348,15 @@ namespace Game
|
||||
}
|
||||
}
|
||||
|
||||
int demonHunterReqLevel = WorldConfig.GetIntValue(WorldCfg.CharacterCreatingMinLevelForDemonHunter);
|
||||
bool hasDemonHunterReqLevel = demonHunterReqLevel == 0;
|
||||
bool allowTwoSideAccounts = !Global.WorldMgr.IsPvPRealm() || HasPermission(RBACPermissions.TwoSideCharacterCreation);
|
||||
int skipCinematics = WorldConfig.GetIntValue(WorldCfg.SkipCinematics);
|
||||
bool checkDemonHunterReqs = createInfo.ClassId == Class.DemonHunter && !HasPermission(RBACPermissions.SkipCheckCharacterCreationDemonHunter);
|
||||
|
||||
void finalizeCharacterCreation(SQLResult result1)
|
||||
{
|
||||
bool haveSameRace = false;
|
||||
int demonHunterReqLevel = WorldConfig.GetIntValue(WorldCfg.CharacterCreatingMinLevelForDemonHunter);
|
||||
bool hasDemonHunterReqLevel = (demonHunterReqLevel == 0);
|
||||
bool checkDemonHunterReqs = createInfo.ClassId == Class.DemonHunter && !HasPermission(RBACPermissions.SkipCheckCharacterCreationDemonHunter);
|
||||
|
||||
if (result1 != null && !result1.IsEmpty())
|
||||
{
|
||||
Team team = Player.TeamForRace(createInfo.RaceId);
|
||||
@@ -461,33 +461,39 @@ namespace Game
|
||||
|
||||
newChar.atLoginFlags = AtLoginFlags.FirstLogin; // First login
|
||||
|
||||
// Player created, save it now
|
||||
newChar.SaveToDB(true);
|
||||
createInfo.CharCount += 1;
|
||||
SQLTransaction characterTransaction = new SQLTransaction();
|
||||
SQLTransaction loginTransaction = new SQLTransaction();
|
||||
|
||||
SQLTransaction trans = new SQLTransaction();
|
||||
// Player created, save it now
|
||||
newChar.SaveToDB(loginTransaction, characterTransaction, true);
|
||||
createInfo.CharCount += 1;
|
||||
|
||||
stmt = DB.Login.GetPreparedStatement(LoginStatements.DEL_REALM_CHARACTERS_BY_REALM);
|
||||
stmt.AddValue(0, GetAccountId());
|
||||
stmt.AddValue(1, Global.WorldMgr.GetRealm().Id.Realm);
|
||||
trans.Append(stmt);
|
||||
loginTransaction.Append(stmt);
|
||||
|
||||
stmt = DB.Login.GetPreparedStatement(LoginStatements.INS_REALM_CHARACTERS);
|
||||
stmt.AddValue(0, createInfo.CharCount);
|
||||
stmt.AddValue(1, GetAccountId());
|
||||
stmt.AddValue(2, Global.WorldMgr.GetRealm().Id.Realm);
|
||||
trans.Append(stmt);
|
||||
loginTransaction.Append(stmt);
|
||||
|
||||
DB.Login.CommitTransaction(trans);
|
||||
DB.Login.CommitTransaction(loginTransaction);
|
||||
|
||||
// Success
|
||||
SendCharCreate(ResponseCodes.CharCreateSuccess, newChar.GetGUID());
|
||||
AddTransactionCallback(DB.Characters.AsyncCommitTransaction(characterTransaction)).AfterComplete(success =>
|
||||
{
|
||||
if (success)
|
||||
{
|
||||
Log.outInfo(LogFilter.Player, "Account: {0} (IP: {1}) Create Character: {2} {3}", GetAccountId(), GetRemoteAddress(), createInfo.Name, newChar.GetGUID().ToString());
|
||||
Global.ScriptMgr.OnPlayerCreate(newChar);
|
||||
Global.CharacterCacheStorage.AddCharacterCacheEntry(newChar.GetGUID(), GetAccountId(), newChar.GetName(), newChar.m_playerData.NativeSex, (byte)newChar.GetRace(), (byte)newChar.GetClass(), (byte)newChar.GetLevel(), false);
|
||||
|
||||
Log.outInfo(LogFilter.Player, "Account: {0} (IP: {1}) Create Character: {2} {3}", GetAccountId(), GetRemoteAddress(), createInfo.Name, newChar.GetGUID().ToString());
|
||||
Global.ScriptMgr.OnPlayerCreate(newChar);
|
||||
Global.CharacterCacheStorage.AddCharacterCacheEntry(newChar.GetGUID(), GetAccountId(), newChar.GetName(), newChar.m_playerData.NativeSex, (byte)newChar.GetRace(), (byte)newChar.GetClass(), (byte)newChar.GetLevel(), false);
|
||||
|
||||
newChar.CleanupsBeforeDelete();
|
||||
SendCharCreate(ResponseCodes.CharCreateSuccess, newChar.GetGUID());
|
||||
}
|
||||
else
|
||||
SendCharCreate(ResponseCodes.CharCreateError);
|
||||
});
|
||||
}
|
||||
|
||||
if (!allowTwoSideAccounts || skipCinematics == 1 || createInfo.ClassId == Class.DemonHunter)
|
||||
@@ -1021,7 +1027,7 @@ namespace Game
|
||||
stmt.AddValue(0, request.RenameInfo.Guid.GetCounter());
|
||||
stmt.AddValue(1, request.RenameInfo.NewName);
|
||||
|
||||
_queryProcessor.AddQuery(DB.Characters.AsyncQuery(stmt).WithCallback(HandleCharRenameCallBack, request.RenameInfo));
|
||||
_queryProcessor.AddCallback(DB.Characters.AsyncQuery(stmt).WithCallback(HandleCharRenameCallBack, request.RenameInfo));
|
||||
}
|
||||
|
||||
void HandleCharRenameCallBack(CharacterRenameInfo renameInfo, SQLResult result)
|
||||
@@ -1211,7 +1217,7 @@ namespace Game
|
||||
PreparedStatement stmt = DB.Characters.GetPreparedStatement(CharStatements.SEL_CHAR_CUSTOMIZE_INFO);
|
||||
stmt.AddValue(0, packet.CustomizeInfo.CharGUID.GetCounter());
|
||||
|
||||
_queryProcessor.AddQuery(DB.Characters.AsyncQuery(stmt).WithCallback(HandleCharCustomizeCallback, packet.CustomizeInfo));
|
||||
_queryProcessor.AddCallback(DB.Characters.AsyncQuery(stmt).WithCallback(HandleCharCustomizeCallback, packet.CustomizeInfo));
|
||||
}
|
||||
|
||||
void HandleCharCustomizeCallback(CharCustomizeInfo customizeInfo, SQLResult result)
|
||||
@@ -1492,7 +1498,7 @@ namespace Game
|
||||
PreparedStatement stmt = DB.Characters.GetPreparedStatement(CharStatements.SEL_CHAR_RACE_OR_FACTION_CHANGE_INFOS);
|
||||
stmt.AddValue(0, packet.RaceOrFactionChangeInfo.Guid.GetCounter());
|
||||
|
||||
_queryProcessor.AddQuery(DB.Characters.AsyncQuery(stmt).WithCallback(HandleCharRaceOrFactionChangeCallback, packet.RaceOrFactionChangeInfo));
|
||||
_queryProcessor.AddCallback(DB.Characters.AsyncQuery(stmt).WithCallback(HandleCharRaceOrFactionChangeCallback, packet.RaceOrFactionChangeInfo));
|
||||
}
|
||||
|
||||
void HandleCharRaceOrFactionChangeCallback(CharRaceOrFactionChangeInfo factionChangeInfo, SQLResult result)
|
||||
@@ -2045,7 +2051,7 @@ namespace Game
|
||||
PreparedStatement stmt = DB.Login.GetPreparedStatement(LoginStatements.SEL_LAST_CHAR_UNDELETE);
|
||||
stmt.AddValue(0, GetBattlenetAccountId());
|
||||
|
||||
_queryProcessor.AddQuery(DB.Login.AsyncQuery(stmt).WithCallback(HandleUndeleteCooldownStatusCallback));
|
||||
_queryProcessor.AddCallback(DB.Login.AsyncQuery(stmt).WithCallback(HandleUndeleteCooldownStatusCallback));
|
||||
}
|
||||
|
||||
void HandleUndeleteCooldownStatusCallback(SQLResult result)
|
||||
@@ -2076,7 +2082,7 @@ namespace Game
|
||||
stmt.AddValue(0, GetBattlenetAccountId());
|
||||
|
||||
CharacterUndeleteInfo undeleteInfo = undeleteCharacter.UndeleteInfo;
|
||||
_queryProcessor.AddQuery(DB.Login.AsyncQuery(stmt).WithChainingCallback((queryCallback, result) =>
|
||||
_queryProcessor.AddCallback(DB.Login.AsyncQuery(stmt).WithChainingCallback((queryCallback, result) =>
|
||||
{
|
||||
if (!result.IsEmpty())
|
||||
{
|
||||
|
||||
@@ -351,7 +351,7 @@ namespace Game
|
||||
stmt.AddValue(1, PetSaveMode.FirstStableSlot);
|
||||
stmt.AddValue(2, PetSaveMode.LastStableSlot);
|
||||
|
||||
_queryProcessor.AddQuery(DB.Characters.AsyncQuery(stmt).WithCallback(SendStablePetCallback, guid));
|
||||
_queryProcessor.AddCallback(DB.Characters.AsyncQuery(stmt).WithCallback(SendStablePetCallback, guid));
|
||||
}
|
||||
|
||||
void SendStablePetCallback(ObjectGuid guid, SQLResult result)
|
||||
|
||||
@@ -188,7 +188,7 @@ namespace Game
|
||||
{
|
||||
PreparedStatement stmt = DB.Characters.GetPreparedStatement(CharStatements.SEL_CHARACTER_GIFT_BY_ITEM);
|
||||
stmt.AddValue(0, item.GetGUID().GetCounter());
|
||||
_queryProcessor.AddQuery(DB.Characters.AsyncQuery(stmt)
|
||||
_queryProcessor.AddCallback(DB.Characters.AsyncQuery(stmt)
|
||||
.WithCallback(result => HandleOpenWrappedItemCallback(item.GetPos(), item.GetGUID(), result)));
|
||||
}
|
||||
else
|
||||
|
||||
@@ -65,7 +65,7 @@ namespace Game.Network
|
||||
stmt.AddValue(0, ip_address);
|
||||
stmt.AddValue(1, BitConverter.ToUInt32(GetRemoteIpAddress().GetAddressBytes(), 0));
|
||||
|
||||
_queryProcessor.AddQuery(DB.Login.AsyncQuery(stmt).WithCallback(CheckIpCallback));
|
||||
_queryProcessor.AddCallback(DB.Login.AsyncQuery(stmt).WithCallback(CheckIpCallback));
|
||||
}
|
||||
|
||||
void CheckIpCallback(SQLResult result)
|
||||
@@ -356,7 +356,7 @@ namespace Game.Network
|
||||
if (!base.Update())
|
||||
return false;
|
||||
|
||||
_queryProcessor.ProcessReadyQueries();
|
||||
_queryProcessor.ProcessReadyCallbacks();
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -378,7 +378,7 @@ namespace Game.Network
|
||||
stmt.AddValue(0, Global.WorldMgr.GetRealm().Id.Realm);
|
||||
stmt.AddValue(1, authSession.RealmJoinTicket);
|
||||
|
||||
_queryProcessor.AddQuery(DB.Login.AsyncQuery(stmt).WithCallback(HandleAuthSessionCallback, authSession));
|
||||
_queryProcessor.AddCallback(DB.Login.AsyncQuery(stmt).WithCallback(HandleAuthSessionCallback, authSession));
|
||||
}
|
||||
|
||||
void HandleAuthSessionCallback(AuthSession authSession, SQLResult result)
|
||||
@@ -559,7 +559,7 @@ namespace Game.Network
|
||||
//if (wardenActive)
|
||||
//_worldSession.InitWarden(_sessionKey);
|
||||
|
||||
_queryProcessor.AddQuery(_worldSession.LoadPermissionsAsync().WithCallback(LoadSessionPermissionsCallback));
|
||||
_queryProcessor.AddCallback(_worldSession.LoadPermissionsAsync().WithCallback(LoadSessionPermissionsCallback));
|
||||
}
|
||||
|
||||
void LoadSessionPermissionsCallback(SQLResult result)
|
||||
@@ -587,7 +587,7 @@ namespace Game.Network
|
||||
PreparedStatement stmt = DB.Login.GetPreparedStatement(LoginStatements.SEL_ACCOUNT_INFO_CONTINUED_SESSION);
|
||||
stmt.AddValue(0, accountId);
|
||||
|
||||
_queryProcessor.AddQuery(DB.Login.AsyncQuery(stmt).WithCallback(HandleAuthContinuedSessionCallback, authSession));
|
||||
_queryProcessor.AddCallback(DB.Login.AsyncQuery(stmt).WithCallback(HandleAuthContinuedSessionCallback, authSession));
|
||||
}
|
||||
|
||||
void HandleAuthContinuedSessionCallback(AuthContinuedSession authSession, SQLResult result)
|
||||
@@ -745,7 +745,7 @@ namespace Game.Network
|
||||
|
||||
ZLib.z_stream _compressionStream;
|
||||
|
||||
QueryCallbackProcessor _queryProcessor = new QueryCallbackProcessor();
|
||||
AsyncCallbackProcessor<QueryCallback> _queryProcessor = new AsyncCallbackProcessor<QueryCallback>();
|
||||
string _ipCountry;
|
||||
}
|
||||
|
||||
|
||||
@@ -1781,7 +1781,7 @@ namespace Game
|
||||
{
|
||||
PreparedStatement stmt = DB.Characters.GetPreparedStatement(CharStatements.SEL_CHARACTER_COUNT);
|
||||
stmt.AddValue(0, accountId);
|
||||
_queryProcessor.AddQuery(DB.Characters.AsyncQuery(stmt).WithCallback(_UpdateRealmCharCount));
|
||||
_queryProcessor.AddCallback(DB.Characters.AsyncQuery(stmt).WithCallback(_UpdateRealmCharCount));
|
||||
}
|
||||
|
||||
void _UpdateRealmCharCount(SQLResult result)
|
||||
@@ -2145,7 +2145,7 @@ namespace Game
|
||||
|
||||
void ProcessQueryCallbacks()
|
||||
{
|
||||
_queryProcessor.ProcessReadyQueries();
|
||||
_queryProcessor.ProcessReadyCallbacks();
|
||||
}
|
||||
|
||||
public void ReloadRBAC()
|
||||
@@ -2324,7 +2324,7 @@ namespace Game
|
||||
|
||||
ConcurrentQueue<Tuple<WorldSocket, ulong>> _linkSocketQueue = new ConcurrentQueue<Tuple<WorldSocket, ulong>>();
|
||||
|
||||
QueryCallbackProcessor _queryProcessor = new QueryCallbackProcessor();
|
||||
AsyncCallbackProcessor<QueryCallback> _queryProcessor = new AsyncCallbackProcessor<QueryCallback>();
|
||||
|
||||
Realm _realm;
|
||||
|
||||
|
||||
@@ -631,7 +631,7 @@ namespace Game
|
||||
|
||||
public ulong GetConnectToInstanceKey() { return _instanceConnectKey.Raw; }
|
||||
|
||||
public QueryCallbackProcessor GetQueryProcessor() { return _queryProcessor; }
|
||||
public AsyncCallbackProcessor<QueryCallback> GetQueryProcessor() { return _queryProcessor; }
|
||||
|
||||
void SetLogoutStartTime(long requestTime)
|
||||
{
|
||||
@@ -645,7 +645,8 @@ namespace Game
|
||||
|
||||
void ProcessQueryCallbacks()
|
||||
{
|
||||
_queryProcessor.ProcessReadyQueries();
|
||||
_queryProcessor.ProcessReadyCallbacks();
|
||||
_transactionCallbacks.ProcessReadyCallbacks();
|
||||
|
||||
if (_realmAccountLoginCallback != null && _realmAccountLoginCallback.IsCompleted && _accountLoginCallback != null && _accountLoginCallback.IsCompleted)
|
||||
{
|
||||
@@ -662,6 +663,11 @@ namespace Game
|
||||
}
|
||||
}
|
||||
|
||||
TransactionCallback AddTransactionCallback(TransactionCallback callback)
|
||||
{
|
||||
return _transactionCallbacks.AddCallback(callback);
|
||||
}
|
||||
|
||||
void InitWarden(BigInteger k)
|
||||
{
|
||||
if (_os == "Win")
|
||||
@@ -896,7 +902,8 @@ namespace Game
|
||||
Task<SQLQueryHolder<AccountInfoQueryLoad>> _accountLoginCallback;
|
||||
Task<SQLQueryHolder<PlayerLoginQueryLoad>> _charLoginCallback;
|
||||
|
||||
QueryCallbackProcessor _queryProcessor = new QueryCallbackProcessor();
|
||||
AsyncCallbackProcessor<QueryCallback> _queryProcessor = new AsyncCallbackProcessor<QueryCallback>();
|
||||
AsyncCallbackProcessor<TransactionCallback> _transactionCallbacks = new AsyncCallbackProcessor<TransactionCallback>();
|
||||
#endregion
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user