mirror of
https://github.com/rajkosto/mxoemu
synced 2026-08-14 02:26:05 -04:00
Movement processor, some fixes
This commit is contained in:
parent
5b4bed2502
commit
aa6007ded5
14 changed files with 2222 additions and 56 deletions
404
Reality/Source/CrashHandler.cpp
Normal file
404
Reality/Source/CrashHandler.cpp
Normal file
|
|
@ -0,0 +1,404 @@
|
|||
// *************************************************************************************************
|
||||
// --------------------------------------
|
||||
// Copyright (C) 2006-2010 Rajko Stojadinovic
|
||||
//
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Lesser General Public
|
||||
// License as published by the Free Software Foundation; either
|
||||
// version 2.1 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
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
//
|
||||
// *************************************************************************************************
|
||||
|
||||
#include "Common.h"
|
||||
#include "CrashHandler.h"
|
||||
#include "Log.h"
|
||||
|
||||
void OutputCrashLogLine(const char * format, ...)
|
||||
{
|
||||
std::string s = "ERRORS.LOG";
|
||||
FILE * m_file = fopen(s.c_str(), "a");
|
||||
if(!m_file) return;
|
||||
|
||||
va_list ap;
|
||||
va_start(ap, format);
|
||||
vfprintf(m_file, format, ap);
|
||||
fprintf(m_file, "\n");
|
||||
fclose(m_file);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
#ifdef WIN32
|
||||
|
||||
#include "Threading/NativeMutex.h"
|
||||
NativeMutex m_crashLock;
|
||||
|
||||
/* *
|
||||
@file CrashHandler.h
|
||||
Handles crashes/exceptions on a win32 based platform, writes a dump file,
|
||||
for later bug fixing.
|
||||
*/
|
||||
# pragma warning( disable : 4311 )
|
||||
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
//#include <windows.h>
|
||||
#include "Log.h"
|
||||
#include <tchar.h>
|
||||
|
||||
bool ON_CRASH_BREAK_DEBUGGER;
|
||||
|
||||
void StartCrashHandler()
|
||||
{
|
||||
// Firstly, check if there is a debugger present. There isn't any point in
|
||||
// handling crashes internally if we have a debugger attached, that would
|
||||
// just piss us off. :P
|
||||
|
||||
// Check for a debugger.
|
||||
#ifndef X64
|
||||
DWORD code;
|
||||
|
||||
__asm
|
||||
{
|
||||
MOV EAX, FS:[0x18]
|
||||
MOV EAX, DWORD PTR [EAX + 0x30]
|
||||
MOV ECX, DWORD PTR [EAX]
|
||||
MOV [DWORD PTR code], ECX
|
||||
}
|
||||
|
||||
if(code & 0x00010000)
|
||||
{
|
||||
// We got a debugger. We'll tell it to not exit on a crash but instead break into debugger.
|
||||
ON_CRASH_BREAK_DEBUGGER = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// No debugger. On crash, we'll call OnCrash to save etc.
|
||||
ON_CRASH_BREAK_DEBUGGER = false;
|
||||
}
|
||||
#else
|
||||
ON_CRASH_BREAK_DEBUGGER = (IsDebuggerPresent() == TRUE) ? true : false;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// GetExceptionDescription
|
||||
// Translate the exception code into something human readable
|
||||
static const TCHAR *GetExceptionDescription(DWORD ExceptionCode)
|
||||
{
|
||||
struct ExceptionNames
|
||||
{
|
||||
DWORD ExceptionCode;
|
||||
TCHAR * ExceptionName;
|
||||
};
|
||||
|
||||
#if 0 // from winnt.h
|
||||
#define STATUS_WAIT_0 ((DWORD )0x00000000L)
|
||||
#define STATUS_ABANDONED_WAIT_0 ((DWORD )0x00000080L)
|
||||
#define STATUS_USER_APC ((DWORD )0x000000C0L)
|
||||
#define STATUS_TIMEOUT ((DWORD )0x00000102L)
|
||||
#define STATUS_PENDING ((DWORD )0x00000103L)
|
||||
#define STATUS_SEGMENT_NOTIFICATION ((DWORD )0x40000005L)
|
||||
#define STATUS_GUARD_PAGE_VIOLATION ((DWORD )0x80000001L)
|
||||
#define STATUS_DATATYPE_MISALIGNMENT ((DWORD )0x80000002L)
|
||||
#define STATUS_BREAKPOINT ((DWORD )0x80000003L)
|
||||
#define STATUS_SINGLE_STEP ((DWORD )0x80000004L)
|
||||
#define STATUS_ACCESS_VIOLATION ((DWORD )0xC0000005L)
|
||||
#define STATUS_IN_PAGE_ERROR ((DWORD )0xC0000006L)
|
||||
#define STATUS_INVALID_HANDLE ((DWORD )0xC0000008L)
|
||||
#define STATUS_NO_MEMORY ((DWORD )0xC0000017L)
|
||||
#define STATUS_ILLEGAL_INSTRUCTION ((DWORD )0xC000001DL)
|
||||
#define STATUS_NONCONTINUABLE_EXCEPTION ((DWORD )0xC0000025L)
|
||||
#define STATUS_INVALID_DISPOSITION ((DWORD )0xC0000026L)
|
||||
#define STATUS_ARRAY_BOUNDS_EXCEEDED ((DWORD )0xC000008CL)
|
||||
#define STATUS_FLOAT_DENORMAL_OPERAND ((DWORD )0xC000008DL)
|
||||
#define STATUS_FLOAT_DIVIDE_BY_ZERO ((DWORD )0xC000008EL)
|
||||
#define STATUS_FLOAT_INEXACT_RESULT ((DWORD )0xC000008FL)
|
||||
#define STATUS_FLOAT_INVALID_OPERATION ((DWORD )0xC0000090L)
|
||||
#define STATUS_FLOAT_OVERFLOW ((DWORD )0xC0000091L)
|
||||
#define STATUS_FLOAT_STACK_CHECK ((DWORD )0xC0000092L)
|
||||
#define STATUS_FLOAT_UNDERFLOW ((DWORD )0xC0000093L)
|
||||
#define STATUS_INTEGER_DIVIDE_BY_ZERO ((DWORD )0xC0000094L)
|
||||
#define STATUS_INTEGER_OVERFLOW ((DWORD )0xC0000095L)
|
||||
#define STATUS_PRIVILEGED_INSTRUCTION ((DWORD )0xC0000096L)
|
||||
#define STATUS_STACK_OVERFLOW ((DWORD )0xC00000FDL)
|
||||
#define STATUS_CONTROL_C_EXIT ((DWORD )0xC000013AL)
|
||||
#define STATUS_FLOAT_MULTIPLE_FAULTS ((DWORD )0xC00002B4L)
|
||||
#define STATUS_FLOAT_MULTIPLE_TRAPS ((DWORD )0xC00002B5L)
|
||||
#define STATUS_ILLEGAL_VLM_REFERENCE ((DWORD )0xC00002C0L)
|
||||
#endif
|
||||
|
||||
ExceptionNames ExceptionMap[] =
|
||||
{
|
||||
{0x40010005, _T("a Control-C")},
|
||||
{0x40010008, _T("a Control-Break")},
|
||||
{0x80000002, _T("a Datatype Misalignment")},
|
||||
{0x80000003, _T("a Breakpoint")},
|
||||
{0xc0000005, _T("an Access Violation")},
|
||||
{0xc0000006, _T("an In Page Error")},
|
||||
{0xc0000017, _T("a No Memory")},
|
||||
{0xc000001d, _T("an Illegal Instruction")},
|
||||
{0xc0000025, _T("a Noncontinuable Exception")},
|
||||
{0xc0000026, _T("an Invalid Disposition")},
|
||||
{0xc000008c, _T("a Array Bounds Exceeded")},
|
||||
{0xc000008d, _T("a Float Denormal Operand")},
|
||||
{0xc000008e, _T("a Float Divide by Zero")},
|
||||
{0xc000008f, _T("a Float Inexact Result")},
|
||||
{0xc0000090, _T("a Float Invalid Operation")},
|
||||
{0xc0000091, _T("a Float Overflow")},
|
||||
{0xc0000092, _T("a Float Stack Check")},
|
||||
{0xc0000093, _T("a Float Underflow")},
|
||||
{0xc0000094, _T("an Integer Divide by Zero")},
|
||||
{0xc0000095, _T("an Integer Overflow")},
|
||||
{0xc0000096, _T("a Privileged Instruction")},
|
||||
{0xc00000fD, _T("a Stack Overflow")},
|
||||
{0xc0000142, _T("a DLL Initialization Failed")},
|
||||
{0xe06d7363, _T("a Microsoft C++ Exception")},
|
||||
};
|
||||
|
||||
for (int i = 0; i < sizeof(ExceptionMap) / sizeof(ExceptionMap[0]); i++)
|
||||
if (ExceptionCode == ExceptionMap[i].ExceptionCode)
|
||||
return ExceptionMap[i].ExceptionName;
|
||||
|
||||
return _T("an Unknown exception type");
|
||||
}
|
||||
|
||||
void spEcho(const char * format, ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap, format);
|
||||
vprintf(format, ap);
|
||||
std::string s = "SHAREDPTR.LOG";
|
||||
FILE * m_file = fopen(s.c_str(), "a");
|
||||
if(!m_file)
|
||||
{
|
||||
va_end(ap);
|
||||
return;
|
||||
}
|
||||
|
||||
vfprintf(m_file, format, ap);
|
||||
fclose(m_file);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
void __cdecl PrintSharedPtrInformation(bool m_sharedPtrDestructed, long references)
|
||||
{
|
||||
if(!m_sharedPtrDestructed)
|
||||
spEcho("Failure to call Destructor method on deletion.\n");
|
||||
if(references)
|
||||
spEcho("Destructor() called when it has %i references left in memory!\n", references);
|
||||
spEcho("-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-\n");
|
||||
spEcho("Call Stack: \n");
|
||||
CStackWalker sw;
|
||||
sw.ShowCallstack(TRUE);
|
||||
spEcho("-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-\n");
|
||||
}
|
||||
|
||||
void echo(const char * format, ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap, format);
|
||||
vprintf(format, ap);
|
||||
std::string s = "CRASH.LOG";
|
||||
FILE * m_file = fopen(s.c_str(), "a");
|
||||
if(!m_file)
|
||||
{
|
||||
va_end(ap);
|
||||
return;
|
||||
}
|
||||
|
||||
vfprintf(m_file, format, ap);
|
||||
fclose(m_file);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
void PrintCrashInformation(PEXCEPTION_POINTERS except)
|
||||
{
|
||||
echo("-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-\n");
|
||||
echo("Server has crashed. Reason was:\n");
|
||||
echo(" %s at 0x%08X\n", GetExceptionDescription(except->ExceptionRecord->ExceptionCode),
|
||||
(unsigned long)except->ExceptionRecord->ExceptionAddress);
|
||||
#ifdef REPACK
|
||||
echo("%s repack by %s has crashed. Visit %s for support.", REPACK, REPACK_AUTHOR, REPACK_WEBSITE);
|
||||
#endif
|
||||
echo("-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-\n");
|
||||
echo("Call Stack: \n");
|
||||
CStackWalker sw;
|
||||
sw.ShowCallstack();
|
||||
echo("-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-\n");
|
||||
}
|
||||
|
||||
void CStackWalker::OnSymInit(LPCSTR szSearchPath, DWORD symOptions, LPCSTR szUserName)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void CStackWalker::OnLoadModule(LPCSTR img, LPCSTR mod, DWORD64 baseAddr, DWORD size, DWORD result, LPCSTR symType, LPCSTR pdbName, ULONGLONG fileVersion)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void CStackWalker::OnDbgHelpErr(LPCSTR szFuncName, DWORD gle, DWORD64 addr)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void CStackWalker::OnCallstackEntry(CallstackEntryType eType, CallstackEntry &entry)
|
||||
{
|
||||
CHAR buffer[STACKWALK_MAX_NAMELEN];
|
||||
if ( (eType != lastEntry) && (entry.offset != 0) )
|
||||
{
|
||||
if (entry.name[0] == 0)
|
||||
strcpy(entry.name, "(function-name not available)");
|
||||
if (entry.undName[0] != 0)
|
||||
strcpy(entry.name, entry.undName);
|
||||
if (entry.undFullName[0] != 0)
|
||||
strcpy(entry.name, entry.undFullName);
|
||||
/* if(!stricmp(entry.symTypeString, "-exported-"))
|
||||
strcpy(entry.symTypeString, "dll");
|
||||
for(uint32 i = 0; i < strlen(entry.symTypeString); ++i)
|
||||
entry.symTypeString[i] = tolower(entry.symTypeString);*/
|
||||
|
||||
char * p = strrchr(entry.loadedImageName, '\\');
|
||||
if(!p)
|
||||
p = entry.loadedImageName;
|
||||
else
|
||||
++p;
|
||||
|
||||
if (entry.lineFileName[0] == 0)
|
||||
{
|
||||
//strcpy(entry.lineFileName, "(filename not available)");
|
||||
//if (entry.moduleName[0] == 0)
|
||||
//strcpy(entry.moduleName, "(module-name not available)");
|
||||
//sprintf(buffer, "%s): %s: %s\n", (LPVOID) entry.offset, entry.moduleName, entry.lineFileName, entry.name);
|
||||
//sprintf(buffer, "%s.
|
||||
if(entry.name[0] == 0)
|
||||
sprintf(entry.name, "%p", entry.offset);
|
||||
|
||||
sprintf(buffer, "%s!%s Line %u\n", p, entry.name, entry.lineNumber );
|
||||
}
|
||||
else
|
||||
sprintf(buffer, "%s!%s Line %u\n", p, entry.name, entry.lineNumber);
|
||||
//OnOutput(buffer);
|
||||
|
||||
/*if(p)
|
||||
OnOutput(p);
|
||||
else*/
|
||||
OnOutput(buffer);
|
||||
}
|
||||
}
|
||||
|
||||
void CStackWalker::OnOutput(LPCSTR szText)
|
||||
{
|
||||
std::string s;
|
||||
if(m_sharedptrlog)
|
||||
s = "SHAREDPTR.LOG";
|
||||
else
|
||||
s = "CRASH.LOG";
|
||||
FILE * m_file = fopen(s.c_str(), "a");
|
||||
if(!m_file) return;
|
||||
|
||||
printf(" %s", szText);
|
||||
fprintf(m_file, " %s", szText);
|
||||
fclose(m_file);
|
||||
}
|
||||
|
||||
bool died = false;
|
||||
|
||||
|
||||
int __cdecl HandleCrash(PEXCEPTION_POINTERS pExceptPtrs)
|
||||
{
|
||||
if(pExceptPtrs == 0)
|
||||
{
|
||||
// Raise an exception :P
|
||||
__try
|
||||
{
|
||||
RaiseException(EXCEPTION_BREAKPOINT, 0, 0, 0);
|
||||
}
|
||||
__except(HandleCrash(GetExceptionInformation()), EXCEPTION_CONTINUE_EXECUTION)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/* only allow one thread to crash. */
|
||||
if(!m_crashLock.AttemptAcquire())
|
||||
{
|
||||
TerminateThread(GetCurrentThread(),-1);
|
||||
// not reached
|
||||
}
|
||||
|
||||
if(died)
|
||||
{
|
||||
TerminateProcess(GetCurrentProcess(),-1);
|
||||
// not reached:P
|
||||
}
|
||||
|
||||
died=true;
|
||||
|
||||
// Create the date/time string
|
||||
time_t curtime = time(NULL);
|
||||
tm * pTime = localtime(&curtime);
|
||||
char filename[MAX_PATH];
|
||||
TCHAR modname[MAX_PATH*2];
|
||||
ZeroMemory(modname, sizeof(modname));
|
||||
if(GetModuleFileName(0, modname, MAX_PATH*2-2) <= 0)
|
||||
strcpy(modname, "UNKNOWN");
|
||||
|
||||
char * mname = strrchr(modname, '\\');
|
||||
(void*)mname++; // Remove the last
|
||||
|
||||
sprintf(filename, "CrashDumps\\dump-%s-%u-%u-%u-%u-%u-%u-%u.dmp",
|
||||
mname, pTime->tm_year+1900, pTime->tm_mon, pTime->tm_mday,
|
||||
pTime->tm_hour, pTime->tm_min, pTime->tm_sec, GetCurrentThreadId());
|
||||
|
||||
|
||||
HANDLE hDump = CreateFile(filename, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
|
||||
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_WRITE_THROUGH, 0);
|
||||
|
||||
if(hDump == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
// Create the directory first
|
||||
CreateDirectory("CrashDumps", 0);
|
||||
hDump = CreateFile(filename, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
|
||||
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_WRITE_THROUGH, 0);
|
||||
}
|
||||
|
||||
PrintCrashInformation(pExceptPtrs);
|
||||
// beep
|
||||
//printf("\x7");
|
||||
printf("\nCreating crash dump file %s\n", filename);
|
||||
|
||||
if(hDump == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
MessageBox(0, "Could not open crash dump file.", "Crash dump error.", MB_OK);
|
||||
}
|
||||
else
|
||||
{
|
||||
MINIDUMP_EXCEPTION_INFORMATION info;
|
||||
info.ClientPointers = FALSE;
|
||||
info.ExceptionPointers = pExceptPtrs;
|
||||
info.ThreadId = GetCurrentThreadId();
|
||||
|
||||
|
||||
MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(),
|
||||
hDump, MiniDumpWithIndirectlyReferencedMemory, &info, 0, 0);
|
||||
|
||||
CloseHandle(hDump);
|
||||
}
|
||||
SetPriorityClass(GetCurrentProcess(), BELOW_NORMAL_PRIORITY_CLASS);
|
||||
OnCrash(!ON_CRASH_BREAK_DEBUGGER);
|
||||
|
||||
return EXCEPTION_CONTINUE_SEARCH;
|
||||
}
|
||||
#endif
|
||||
69
Reality/Source/CrashHandler.h
Normal file
69
Reality/Source/CrashHandler.h
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
// *************************************************************************************************
|
||||
// --------------------------------------
|
||||
// Copyright (C) 2006-2010 Rajko Stojadinovic
|
||||
//
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Lesser General Public
|
||||
// License as published by the Free Software Foundation; either
|
||||
// version 2.1 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
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
//
|
||||
// *************************************************************************************************
|
||||
|
||||
#ifndef MXOSIM_CRASH_HANDLER_H
|
||||
#define MXOSIM_CRASH_HANDLER_H
|
||||
|
||||
bool HookCrashReporter(bool logon);
|
||||
void OutputCrashLogLine(const char* format, ...);
|
||||
|
||||
#ifdef WIN32
|
||||
|
||||
//#include <Windows.h>
|
||||
#include "Common.h"
|
||||
#include <DbgHelp.h>
|
||||
#include "StackWalker.h"
|
||||
|
||||
class CStackWalker : public StackWalker
|
||||
{
|
||||
public:
|
||||
void OnOutput(LPCSTR szText);
|
||||
void OnSymInit(LPCSTR szSearchPath, DWORD symOptions, LPCSTR szUserName);
|
||||
void OnLoadModule(LPCSTR img, LPCSTR mod, DWORD64 baseAddr, DWORD size, DWORD result, LPCSTR symType, LPCSTR pdbName, ULONGLONG fileVersion);
|
||||
void OnCallstackEntry(CallstackEntryType eType, CallstackEntry &entry);
|
||||
void OnDbgHelpErr(LPCSTR szFuncName, DWORD gle, DWORD64 addr);
|
||||
};
|
||||
|
||||
void StartCrashHandler();
|
||||
void OnCrash(bool Terminate);
|
||||
|
||||
typedef struct _EXCEPTION_POINTERS EXCEPTION_POINTERS, *PEXCEPTION_POINTERS;
|
||||
int __cdecl HandleCrash(PEXCEPTION_POINTERS pExceptPtrs);
|
||||
void __cdecl PrintSharedPtrInformation(bool m_sharedPtrDestructed, long references);
|
||||
|
||||
#define THREAD_TRY_EXECUTION __try
|
||||
#define THREAD_HANDLE_CRASH __except(HandleCrash(GetExceptionInformation())) {}
|
||||
|
||||
#define THREAD_TRY_EXECUTION2 __try {
|
||||
#define THREAD_HANDLE_CRASH2 } __except(HandleCrash(GetExceptionInformation())) {}
|
||||
|
||||
#else
|
||||
|
||||
// We dont wanna confuse nix ;p
|
||||
#define THREAD_TRY_EXECUTION
|
||||
#define THREAD_HANDLE_CRASH
|
||||
|
||||
#define THREAD_TRY_EXECUTION2 ;
|
||||
#define THREAD_HANDLE_CRASH2 ;
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
@ -395,16 +395,18 @@ void GameClient::PSSChanged( uint8 oldPSS,uint8 newPSS )
|
|||
sObjMgr.getGOPtr(m_playerGoId)->SpawnSelf();
|
||||
m_worldLoaded = true;
|
||||
}
|
||||
m_characterSpawned = true;
|
||||
sObjMgr.getGOPtr(m_playerGoId)->PopulateWorld();
|
||||
if (m_characterSpawned == false)
|
||||
{
|
||||
sObjMgr.getGOPtr(m_playerGoId)->PopulateWorld();
|
||||
m_characterSpawned = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GameClient::MoveMsgsToQueue()
|
||||
{
|
||||
std::sort(m_packetsToAck.begin(),m_packetsToAck.end());
|
||||
//first we send out all the 03
|
||||
for (queueType::iterator it=m_queuedStates.begin();it!=m_queuedStates.end();++it)
|
||||
for (stateQueueType::iterator it=m_queuedStates.begin();it!=m_queuedStates.end();++it)
|
||||
{
|
||||
//consume an ack if we can
|
||||
if (m_packetsToAck.size() > 0)
|
||||
|
|
@ -412,11 +414,11 @@ void GameClient::MoveMsgsToQueue()
|
|||
uint16 theClientSeq = m_packetsToAck.front();
|
||||
m_packetsToAck.pop_front();
|
||||
|
||||
AddPacketToQueue(theClientSeq,true,*it);
|
||||
AddPacketToQueue(theClientSeq,true,it->stateData,it->noResend);
|
||||
}
|
||||
else
|
||||
{
|
||||
AddPacketToQueue(*it);
|
||||
AddPacketToQueue(it->stateData,it->noResend);
|
||||
}
|
||||
}
|
||||
//all queued 03s have been transferred to packet queue, clear the 03 queue
|
||||
|
|
@ -551,8 +553,11 @@ void GameClient::FlushQueue()
|
|||
//mark packet as sent
|
||||
it->sent=true;
|
||||
it->msTimeSent=getMSTime();
|
||||
|
||||
++it;
|
||||
//if packet is non resendable, remove it
|
||||
if (it->noResends==true)
|
||||
it=m_sendQueue.erase(it);
|
||||
else
|
||||
++it;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -59,14 +59,14 @@ public:
|
|||
void HandleEncrypted(ByteBuffer &srcData);
|
||||
void HandleOther(ByteBuffer &otherData);
|
||||
void HandleOrdered(ByteBuffer &orderedData);
|
||||
void QueueState(msgBaseClassPtr theData)
|
||||
void QueueState(msgBaseClassPtr theData,bool immediateOnly=false)
|
||||
{
|
||||
msgBaseClassPtr &realPtr = theData;
|
||||
shared_ptr<ObjectUpdateMsg> amIObjectUpdate = dynamic_pointer_cast<ObjectUpdateMsg>(realPtr);
|
||||
if (amIObjectUpdate != NULL)
|
||||
amIObjectUpdate->setReceiver(this);
|
||||
|
||||
m_queuedStates.push_back(realPtr);
|
||||
m_queuedStates.push_back(queuedState(realPtr,immediateOnly));
|
||||
}
|
||||
void QueueCommand(msgBaseClassPtr theCmd)
|
||||
{
|
||||
|
|
@ -136,12 +136,23 @@ private:
|
|||
|
||||
typedef deque<msgBaseClassPtr> queueType;
|
||||
queueType m_queuedCommands;
|
||||
queueType m_queuedStates;
|
||||
struct queuedState
|
||||
{
|
||||
queuedState(msgBaseClassPtr theState, bool immediateOnly=false)
|
||||
{
|
||||
stateData = theState;
|
||||
noResend=immediateOnly;
|
||||
}
|
||||
bool noResend;
|
||||
msgBaseClassPtr stateData;
|
||||
};
|
||||
typedef deque<queuedState> stateQueueType;
|
||||
stateQueueType m_queuedStates;
|
||||
|
||||
struct PacketInQueue
|
||||
{
|
||||
//the packet will own the data pointer
|
||||
PacketInQueue(uint8 thePSS, uint16 serverSeq, uint16 clientSeq, bool ackPacket, msgBaseClassPtr dataToSend)
|
||||
PacketInQueue(uint8 thePSS, uint16 serverSeq, uint16 clientSeq, bool ackPacket, msgBaseClassPtr dataToSend, bool immediateOnly=false)
|
||||
{
|
||||
clientPSS = thePSS;
|
||||
server_sequence = serverSeq;
|
||||
|
|
@ -151,6 +162,7 @@ private:
|
|||
sent=false;
|
||||
msTimeSent=0;
|
||||
resentCounter=0;
|
||||
noResends=immediateOnly;
|
||||
}
|
||||
~PacketInQueue() {}
|
||||
|
||||
|
|
@ -162,10 +174,11 @@ private:
|
|||
bool sent;
|
||||
uint32 msTimeSent;
|
||||
uint32 resentCounter;
|
||||
bool noResends;
|
||||
};
|
||||
typedef list<PacketInQueue> sendQueueList;
|
||||
sendQueueList m_sendQueue;
|
||||
void AddPacketToQueue(uint16 clientSeq, bool ackPacket, msgBaseClassPtr dataToSend)
|
||||
void AddPacketToQueue(uint16 clientSeq, bool ackPacket, msgBaseClassPtr dataToSend, bool immediateOnly=false)
|
||||
{
|
||||
//if its a static packet of 0 bytes and no ack, no reason to send it
|
||||
if (ackPacket == false)
|
||||
|
|
@ -191,11 +204,11 @@ private:
|
|||
{
|
||||
DEBUG_LOG(format("(%s) Queue SSeq: %d CSeq: %d Ack: %d No Data") % Address() % theServerSeq % clientSeq % ackPacket);
|
||||
}
|
||||
m_sendQueue.push_back(PacketInQueue(m_clientPSS,theServerSeq,clientSeq,ackPacket,dataToSend));
|
||||
m_sendQueue.push_back(PacketInQueue(m_clientPSS,theServerSeq,clientSeq,ackPacket,dataToSend,immediateOnly));
|
||||
}
|
||||
void AddPacketToQueue(msgBaseClassPtr dataToSend)
|
||||
void AddPacketToQueue(msgBaseClassPtr dataToSend, bool immediateOnly=false)
|
||||
{
|
||||
AddPacketToQueue(m_lastClientSequence,false,dataToSend);
|
||||
AddPacketToQueue(m_lastClientSequence,false,dataToSend,immediateOnly);
|
||||
}
|
||||
|
||||
void MoveMsgsToQueue();
|
||||
|
|
|
|||
|
|
@ -219,13 +219,13 @@ void GameServer::CheckAndResend()
|
|||
}
|
||||
}
|
||||
|
||||
void GameServer::AnnounceStateUpdate( class GameClient* clFrom,msgBaseClassPtr theMsg )
|
||||
void GameServer::AnnounceStateUpdate( class GameClient* clFrom,msgBaseClassPtr theMsg, bool immediateOnly )
|
||||
{
|
||||
for (GClientList::iterator it=m_clients.begin();it!=m_clients.end();++it)
|
||||
{
|
||||
if (it->second!=clFrom)
|
||||
{
|
||||
it->second->QueueState(theMsg);
|
||||
it->second->QueueState(theMsg,immediateOnly);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ public:
|
|||
class GameClient *GetClientWithSessionId(uint32 sessionId);
|
||||
void CheckAndResend();
|
||||
void Broadcast(const ByteBuffer &message);
|
||||
void AnnounceStateUpdate(class GameClient* clFrom,msgBaseClassPtr theMsg);
|
||||
void AnnounceStateUpdate(class GameClient* clFrom,msgBaseClassPtr theMsg, bool immediateOnly=false);
|
||||
void AnnounceCommand(class GameClient* clFrom,msgBaseClassPtr theCmd);
|
||||
ObjectMgr &getObjMgr() { return m_objMgr; }
|
||||
|
||||
|
|
|
|||
|
|
@ -26,12 +26,33 @@
|
|||
#include "Common.h"
|
||||
#include <cmath>
|
||||
|
||||
#ifndef M_PI
|
||||
#define M_PI 3.14159265358979323846264338327
|
||||
#endif
|
||||
|
||||
class LocationVector
|
||||
{
|
||||
public:
|
||||
LocationVector(double X, double Y, double Z) : x(X), y(Y), z(Z) {}
|
||||
LocationVector() : x(0), y(0), z(0) {}
|
||||
|
||||
LocationVector(double X, double Y, double Z, uint8 O) : x(x), y(Y), z(Z), rot(MxoToDoubleRot(O)) {}
|
||||
LocationVector(double X, double Y, double Z) : x(X), y(Y), z(Z), rot(0) {}
|
||||
LocationVector() : x(0), y(0), z(0), rot(0) {}
|
||||
private:
|
||||
inline double MxoToDoubleRot(uint8 mxoRot)
|
||||
{
|
||||
double normalizedRot = (double(mxoRot)/double(256)); //range from 0 to 1
|
||||
normalizedRot-=0.5f; //range from -0.5 to 0.5
|
||||
normalizedRot*=2*M_PI; //range from -pi to +pi
|
||||
return normalizedRot;
|
||||
}
|
||||
inline uint8 DoubleToMxoRot(double rot)
|
||||
{
|
||||
//start range in -pi to +pi
|
||||
double normalizedRot = rot/(2*M_PI); //range from -0.5 to 0.5
|
||||
normalizedRot+=0.5f; //range from 0 to 1
|
||||
normalizedRot*=255; //range from 0 to 255
|
||||
return uint8(normalizedRot);
|
||||
}
|
||||
public:
|
||||
// (dx * dx + dy * dy + dz * dz)
|
||||
double DistanceSq(const LocationVector & comp)
|
||||
{
|
||||
|
|
@ -97,13 +118,46 @@ public:
|
|||
double delta_y = Y - y;
|
||||
return sqrt(delta_x*delta_x + delta_y*delta_y);
|
||||
}
|
||||
|
||||
// atan2(dx / dy)
|
||||
double CalcAngTo(const LocationVector & dest)
|
||||
{
|
||||
double dx = dest.x - x;
|
||||
double dy = dest.y - y;
|
||||
if(dy != 0.0f)
|
||||
return atan2(dy, dx);
|
||||
else
|
||||
return 0.0f;
|
||||
}
|
||||
inline uint8 CalcAngToMxo(const LocationVector & dest)
|
||||
{
|
||||
return DoubleToMxoRot(CalcAngTo(dest));
|
||||
}
|
||||
double CalcAngFrom(const LocationVector & src)
|
||||
{
|
||||
double dx = x - src.x;
|
||||
double dy = y - src.y;
|
||||
if(dy != 0.0f)
|
||||
return atan2(dy, dx);
|
||||
else
|
||||
return 0.0f;
|
||||
}
|
||||
inline uint8 CalcAngFromMxo(const LocationVector & dest)
|
||||
{
|
||||
return DoubleToMxoRot(CalcAngFrom(dest));
|
||||
}
|
||||
void ChangeCoords(double X, double Y, double Z)
|
||||
{
|
||||
x = X;
|
||||
y = Y;
|
||||
z = Z;
|
||||
}
|
||||
void ChangeCoords(double X, double Y, double Z, uint8 O)
|
||||
{
|
||||
x = X;
|
||||
y = Y;
|
||||
z = Z;
|
||||
rot = O;
|
||||
}
|
||||
|
||||
// add/subtract/equality vectors
|
||||
LocationVector & operator += (const LocationVector & add)
|
||||
|
|
@ -111,6 +165,7 @@ public:
|
|||
x += add.x;
|
||||
y += add.y;
|
||||
z += add.z;
|
||||
rot += add.rot;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
|
@ -119,6 +174,7 @@ public:
|
|||
x -= sub.x;
|
||||
y -= sub.y;
|
||||
z -= sub.z;
|
||||
rot -= sub.rot;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
|
@ -127,6 +183,7 @@ public:
|
|||
x = eq.x;
|
||||
y = eq.y;
|
||||
z = eq.z;
|
||||
rot = eq.rot;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
|
@ -137,7 +194,14 @@ public:
|
|||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
uint8 getMxoRot()
|
||||
{
|
||||
return DoubleToMxoRot(rot);
|
||||
}
|
||||
void setMxoRot(uint8 theRot)
|
||||
{
|
||||
rot=MxoToDoubleRot(theRot);
|
||||
}
|
||||
bool fromDoubleBuf(ByteBuffer &sourceBuf)
|
||||
{
|
||||
if (sourceBuf.remaining() < sizeof(double)*3)
|
||||
|
|
@ -198,6 +262,7 @@ public:
|
|||
double x;
|
||||
double y;
|
||||
double z;
|
||||
double rot;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -192,4 +192,39 @@ void Master::_UnhookSignals()
|
|||
signal(SIGBREAK, 0);
|
||||
#endif
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef WIN32
|
||||
|
||||
NativeMutex m_crashedMutex;
|
||||
|
||||
// Crash Handler
|
||||
void OnCrash( bool Terminate )
|
||||
{
|
||||
ERROR_LOG( "Advanced crash handler initialized." );
|
||||
|
||||
if( !m_crashedMutex.AttemptAcquire() )
|
||||
TerminateThread( GetCurrentThread(), 0 );
|
||||
|
||||
try
|
||||
{
|
||||
ERROR_LOG( "Waiting for all database queries to finish..." );
|
||||
sDatabase.EndThreads();
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
ERROR_LOG( "Threw an exception while attempting to save all data." );
|
||||
}
|
||||
|
||||
ERROR_LOG( "Closing." );
|
||||
|
||||
// Terminate Entire Application
|
||||
if( Terminate )
|
||||
{
|
||||
HANDLE pH = OpenProcess( PROCESS_TERMINATE, TRUE, GetCurrentProcessId() );
|
||||
TerminateProcess( pH, 1 );
|
||||
CloseHandle( pH );
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@
|
|||
#include "MessageTypes.h"
|
||||
#include "Log.h"
|
||||
#include "GameClient.h"
|
||||
#include "Timer.h"
|
||||
|
||||
PlayerObject::PlayerObject( GameClient &parent,uint64 charUID ) :m_parent(parent),m_characterUID(charUID),m_spawnedInWorld(false)
|
||||
{
|
||||
|
|
@ -34,7 +35,7 @@ PlayerObject::PlayerObject( GameClient &parent,uint64 charUID ) :m_parent(parent
|
|||
{
|
||||
scoped_ptr<QueryResult> result(sDatabase.Query(format("SELECT `handle`,\
|
||||
`firstName`, `lastName`, `background`,\
|
||||
`x`, `y`, `z`,\
|
||||
`x`, `y`, `z`, `rot`, \
|
||||
`healthC`, `healthM`, `innerStrC`, `innerStrM`,\
|
||||
`level`, `profession`, `alignment`, `pvpflag`, `exp`, `cash`, `district`\
|
||||
FROM `characters` WHERE `charId` = '%1%' LIMIT 1") % m_characterUID) );
|
||||
|
|
@ -52,17 +53,19 @@ PlayerObject::PlayerObject( GameClient &parent,uint64 charUID ) :m_parent(parent
|
|||
m_pos.ChangeCoords( field[4].GetDouble(),
|
||||
field[5].GetDouble(),
|
||||
field[6].GetDouble());
|
||||
m_healthC = field[7].GetUInt16();
|
||||
m_healthM = field[8].GetUInt16();
|
||||
m_innerStrC = field[9].GetUInt16();
|
||||
m_innerStrM = field[10].GetUInt16();
|
||||
m_lvl = field[11].GetUInt8();
|
||||
m_prof = field[12].GetUInt8();
|
||||
m_alignment = field[13].GetUInt8();
|
||||
m_pvpflag = field[14].GetBool();
|
||||
m_exp = field[15].GetUInt64();
|
||||
m_cash = field[16].GetUInt64();
|
||||
m_district = field[17].GetUInt8();
|
||||
m_pos.rot = field[7].GetDouble();
|
||||
m_savedPos = m_pos;
|
||||
m_healthC = field[8].GetUInt16();
|
||||
m_healthM = field[9].GetUInt16();
|
||||
m_innerStrC = field[10].GetUInt16();
|
||||
m_innerStrM = field[11].GetUInt16();
|
||||
m_lvl = field[12].GetUInt8();
|
||||
m_prof = field[13].GetUInt8();
|
||||
m_alignment = field[14].GetUInt8();
|
||||
m_pvpflag = field[15].GetBool();
|
||||
m_exp = field[16].GetUInt64();
|
||||
m_cash = field[17].GetUInt64();
|
||||
m_district = field[18].GetUInt8();
|
||||
}
|
||||
//grab data from rsi table
|
||||
{
|
||||
|
|
@ -124,6 +127,7 @@ PlayerObject::PlayerObject( GameClient &parent,uint64 charUID ) :m_parent(parent
|
|||
m_goId=0;
|
||||
INFO_LOG(format("Player object for %1% constructed") % m_handle);
|
||||
testCount=0;
|
||||
m_lastStore = getTime();
|
||||
}
|
||||
|
||||
void PlayerObject::initGoId(uint32 theGoId)
|
||||
|
|
@ -138,8 +142,10 @@ PlayerObject::~PlayerObject()
|
|||
{
|
||||
INFO_LOG(format("Player object for %1%:%2% deconstructing") % m_handle % m_goId);
|
||||
sGame.AnnounceStateUpdate(&m_parent,make_shared<DeletePlayerMsg>(m_goId));
|
||||
|
||||
m_spawnedInWorld=false;
|
||||
|
||||
//commit position changes
|
||||
saveDataToDB();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -151,6 +157,36 @@ uint8 PlayerObject::getRsiData( byte* outputBuf,uint32 maxBufLen ) const
|
|||
return m_rsi->ToBytes(outputBuf,maxBufLen);
|
||||
}
|
||||
|
||||
void PlayerObject::checkAndStore()
|
||||
{
|
||||
if (getTime() - m_lastStore > 60) //every 60 seconds
|
||||
{
|
||||
saveDataToDB();
|
||||
m_lastStore = getTime();
|
||||
}
|
||||
}
|
||||
|
||||
void PlayerObject::saveDataToDB()
|
||||
{
|
||||
if (m_savedPos == m_pos)
|
||||
return;
|
||||
|
||||
bool storeSuccess = sDatabase.Execute(format("UPDATE `characters` SET `x` = '%1%', `y` = '%2%', `z` = '%3%', `rot` = '%4%' WHERE `charId` = '%5%'")
|
||||
% m_pos.x
|
||||
% m_pos.y
|
||||
% m_pos.z
|
||||
% m_pos.rot
|
||||
% m_characterUID );
|
||||
|
||||
if (!storeSuccess)
|
||||
WARNING_LOG(format("%1%:%2% failed to save data to database") % m_handle % m_goId );
|
||||
else
|
||||
{
|
||||
m_savedPos = m_pos;
|
||||
m_parent.QueueCommand(boost::make_shared<SystemChatMsg>( (format("Character data for %1% has been written to the database.") % m_handle).str() ));
|
||||
}
|
||||
}
|
||||
|
||||
void PlayerObject::InitializeWorld()
|
||||
{
|
||||
m_parent.QueueCommand(make_shared<LoadWorldCmd>((LoadWorldCmd::mxoLocation)m_district,"SatiSky"));
|
||||
|
|
@ -219,8 +255,8 @@ void PlayerObject::PopulateWorld()
|
|||
|
||||
void PlayerObject::HandleStateUpdate( ByteBuffer &srcData )
|
||||
{
|
||||
srcData.rpos(0);
|
||||
DEBUG_LOG(format("(%1%) 03 data: %2%") % m_parent.Address() % Bin2Hex(srcData) );
|
||||
checkAndStore();
|
||||
|
||||
uint8 zeroThree;
|
||||
if (srcData.remaining() < sizeof(zeroThree))
|
||||
return;
|
||||
|
|
@ -236,14 +272,108 @@ void PlayerObject::HandleStateUpdate( ByteBuffer &srcData )
|
|||
WARNING_LOG(format("Client %1% Player %2%:%3% trying to update someone else's object view %4%") % m_parent.Address() % m_handle % m_goId % viewIdToUpdate);
|
||||
return;
|
||||
}
|
||||
//otherwise just propagate update to all other players
|
||||
ByteBuffer theStateData;
|
||||
theStateData.append(&srcData.contents()[srcData.rpos()],srcData.remaining());
|
||||
sGame.AnnounceStateUpdate(&m_parent,make_shared<StateUpdateMsg>(m_goId,theStateData));
|
||||
size_t restOfDataPos = srcData.rpos();
|
||||
uint8 shouldBeOne;
|
||||
if (srcData.remaining() < sizeof(shouldBeOne))
|
||||
return;
|
||||
srcData >> shouldBeOne;
|
||||
if (shouldBeOne != 1)
|
||||
{
|
||||
WARNING_LOG(format("Client %1% Player %2%:%3% 03 doesn't have number 1 after viewId") % m_parent.Address() % m_handle % m_goId);
|
||||
return;
|
||||
}
|
||||
uint8 updateType;
|
||||
if (srcData.remaining() < sizeof(updateType))
|
||||
return;
|
||||
srcData >> updateType;
|
||||
bool validUpdate=false;
|
||||
switch (updateType)
|
||||
{
|
||||
//change angle
|
||||
case 0x04:
|
||||
{
|
||||
uint8 theRotByte;
|
||||
if (srcData.remaining() < sizeof(theRotByte))
|
||||
return;
|
||||
srcData >> theRotByte;
|
||||
|
||||
m_pos.setMxoRot(theRotByte);
|
||||
validUpdate=true;
|
||||
break;
|
||||
}
|
||||
//change angle with extra param
|
||||
case 0x06:
|
||||
{
|
||||
uint8 theAnimation;
|
||||
if (srcData.remaining() < sizeof(theAnimation))
|
||||
return;
|
||||
srcData >> theAnimation;
|
||||
//we will just ignore the animation for now
|
||||
uint8 theRotByte;
|
||||
if (srcData.remaining() < sizeof(theRotByte))
|
||||
return;
|
||||
srcData >> theRotByte;
|
||||
|
||||
m_pos.setMxoRot(theRotByte);
|
||||
validUpdate=true;
|
||||
break;
|
||||
}
|
||||
//update xyz
|
||||
case 0x08:
|
||||
{
|
||||
validUpdate = m_pos.fromFloatBuf(srcData);
|
||||
break;
|
||||
}
|
||||
//update xyz, extra byte before xyz
|
||||
case 0x0A:
|
||||
case 0x0C:
|
||||
{
|
||||
uint8 extraByte;
|
||||
if (srcData.remaining() < sizeof(extraByte))
|
||||
return;
|
||||
srcData >> extraByte;
|
||||
|
||||
validUpdate = m_pos.fromFloatBuf(srcData);
|
||||
break;
|
||||
}
|
||||
//update xyz, extra 2 bytes before xyz
|
||||
case 0x0E:
|
||||
{
|
||||
uint8 extraByte1,extraByte2;
|
||||
if (srcData.remaining() < sizeof(uint8)*2)
|
||||
return;
|
||||
srcData >> extraByte1;
|
||||
srcData >> extraByte2;
|
||||
|
||||
validUpdate = m_pos.fromFloatBuf(srcData);
|
||||
break;
|
||||
}
|
||||
//sometimes happens, no info inside
|
||||
case 0x02:
|
||||
{
|
||||
validUpdate = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (validUpdate)
|
||||
{
|
||||
//propagate state to all other players
|
||||
srcData.rpos(restOfDataPos);
|
||||
ByteBuffer theStateData;
|
||||
theStateData.append(&srcData.contents()[srcData.rpos()],srcData.remaining());
|
||||
sGame.AnnounceStateUpdate(&m_parent,make_shared<StateUpdateMsg>(m_goId,theStateData),true);
|
||||
}
|
||||
else
|
||||
{
|
||||
srcData.rpos(0);
|
||||
DEBUG_LOG(format("(%1%) %2%:%3% 03 data: %4%") % m_parent.Address() % m_handle % m_goId % Bin2Hex(srcData) );
|
||||
}
|
||||
}
|
||||
|
||||
void PlayerObject::HandleCommand( ByteBuffer &srcCmd )
|
||||
{
|
||||
checkAndStore();
|
||||
|
||||
uint8 firstByte;
|
||||
if (srcCmd.remaining() < sizeof(firstByte) )
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -59,6 +59,9 @@ public:
|
|||
uint8 getAlignment() const {return m_alignment;}
|
||||
bool getPvpFlag() const {return m_pvpflag;}
|
||||
|
||||
void checkAndStore();
|
||||
void saveDataToDB();
|
||||
|
||||
vector<msgBaseClassPtr> getCurrentStatePackets();
|
||||
private:
|
||||
class GameClient &m_parent;
|
||||
|
|
@ -73,7 +76,7 @@ private:
|
|||
uint32 m_goId;
|
||||
uint64 m_exp,m_cash;
|
||||
uint8 m_district;
|
||||
LocationVector m_pos;
|
||||
LocationVector m_pos,m_savedPos;
|
||||
shared_ptr<class RsiData> m_rsi;
|
||||
uint16 m_healthC,m_healthM,m_innerStrC,m_innerStrM;
|
||||
uint8 m_prof,m_lvl,m_alignment;
|
||||
|
|
@ -81,6 +84,7 @@ private:
|
|||
uint32 testCount;
|
||||
|
||||
bool m_spawnedInWorld;
|
||||
uint32 m_lastStore;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -21,7 +21,7 @@
|
|||
OutputDirectory="..\$(ConfigurationName)"
|
||||
IntermediateDirectory="..\$(ConfigurationName)"
|
||||
ConfigurationType="1"
|
||||
CharacterSet="1"
|
||||
CharacterSet="0"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
|
|
@ -62,7 +62,7 @@
|
|||
/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
AdditionalDependencies="ws2_32.lib libmysql.lib cryptlib.lib Sockets.lib"
|
||||
AdditionalDependencies="Dbghelp.lib ws2_32.lib libmysql.lib cryptlib.lib Sockets.lib"
|
||||
OutputFile="..\Binaries\RealityD.exe"
|
||||
LinkIncremental="2"
|
||||
AdditionalLibraryDirectories="..\..\Dependencies\CryptoPP\Win32\Output\Debug;..\..\Dependencies\MySQL\lib\32;..\..\Dependencies\Sockets\Project.net\lib\D;..\..\Dependencies\ZThread\lib\D"
|
||||
|
|
@ -100,7 +100,7 @@
|
|||
OutputDirectory="..\$(ConfigurationName)"
|
||||
IntermediateDirectory="..\$(ConfigurationName)"
|
||||
ConfigurationType="1"
|
||||
CharacterSet="1"
|
||||
CharacterSet="0"
|
||||
WholeProgramOptimization="1"
|
||||
>
|
||||
<Tool
|
||||
|
|
@ -139,7 +139,7 @@
|
|||
/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
AdditionalDependencies="ws2_32.lib libmysql.lib cryptlib.lib Sockets.lib"
|
||||
AdditionalDependencies="Dbghelp.lib ws2_32.lib libmysql.lib cryptlib.lib Sockets.lib"
|
||||
OutputFile="..\Binaries\Reality.exe"
|
||||
LinkIncremental="1"
|
||||
AdditionalLibraryDirectories="..\..\Dependencies\CryptoPP\Win32\Output\Release;..\..\Dependencies\MySQL\lib\32;..\..\Dependencies\Sockets\Project.net\lib\R;..\..\Dependencies\ZThread\lib\R"
|
||||
|
|
@ -184,7 +184,11 @@
|
|||
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
|
||||
>
|
||||
<File
|
||||
RelativePath=".\CryptoTest.h"
|
||||
RelativePath=".\CrashHandler.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\CrashHandler.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
|
|
@ -200,11 +204,11 @@
|
|||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\seqchecktest.h"
|
||||
RelativePath=".\StackWalker.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\SubPacketsTest.h"
|
||||
RelativePath=".\StackWalker.h"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
|
|
@ -575,6 +579,18 @@
|
|||
<Filter
|
||||
Name="Tests"
|
||||
>
|
||||
<File
|
||||
RelativePath=".\CryptoTest.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\seqchecktest.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\SubPacketsTest.h"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
</Files>
|
||||
<Globals>
|
||||
|
|
|
|||
|
|
@ -19,12 +19,12 @@
|
|||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
<CharacterSet>NotSet</CharacterSet>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
<CharacterSet>NotSet</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
|
|
@ -59,7 +59,7 @@
|
|||
<DebugInformationFormat>EditAndContinue</DebugInformationFormat>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>ws2_32.lib;libmysql.lib;cryptlib.lib;Sockets.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalDependencies>Dbghelp.lib;ws2_32.lib;libmysql.lib;cryptlib.lib;Sockets.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<OutputFile>..\Binaries\RealityD.exe</OutputFile>
|
||||
<AdditionalLibraryDirectories>..\..\Dependencies10\CryptoPP\Win32\Output\Debug;..\..\Dependencies10\MySQL\lib\32;..\..\Dependencies10\Sockets\Project.net\lib\D;..\..\Dependencies10\ZThread\lib\D;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<IgnoreSpecificDefaultLibraries>%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>
|
||||
|
|
@ -83,7 +83,7 @@
|
|||
</DebugInformationFormat>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>ws2_32.lib;libmysql.lib;cryptlib.lib;Sockets.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalDependencies>Dbghelp.lib;ws2_32.lib;libmysql.lib;cryptlib.lib;Sockets.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<OutputFile>..\Binaries\Reality.exe</OutputFile>
|
||||
<AdditionalLibraryDirectories>..\..\Dependencies10\CryptoPP\Win32\Output\Release;..\..\Dependencies10\MySQL\lib\32;..\..\Dependencies10\Sockets\Project.net\lib\R;..\..\Dependencies10\ZThread\lib\R;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<IgnoreSpecificDefaultLibraries>%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>
|
||||
|
|
@ -98,9 +98,11 @@
|
|||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="CrashHandler.h" />
|
||||
<ClInclude Include="CryptoTest.h" />
|
||||
<ClInclude Include="Master.h" />
|
||||
<ClInclude Include="seqchecktest.h" />
|
||||
<ClInclude Include="StackWalker.h" />
|
||||
<ClInclude Include="SubPacketsTest.h" />
|
||||
<ClInclude Include="DotConfPP\dotconfpp.h" />
|
||||
<ClInclude Include="DotConfPP\mempool.h" />
|
||||
|
|
@ -154,6 +156,7 @@
|
|||
<ClInclude Include="ConsoleThread.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="CrashHandler.cpp" />
|
||||
<ClCompile Include="Main.cpp" />
|
||||
<ClCompile Include="Master.cpp" />
|
||||
<ClCompile Include="DotConfPP\dotconfpp.cpp" />
|
||||
|
|
@ -162,6 +165,7 @@
|
|||
<ClCompile Include="Config.cpp" />
|
||||
<ClCompile Include="Log.cpp" />
|
||||
<ClCompile Include="MersenneTwister.cpp" />
|
||||
<ClCompile Include="StackWalker.cpp" />
|
||||
<ClCompile Include="Util.cpp" />
|
||||
<ClCompile Include="Database\Database.cpp" />
|
||||
<ClCompile Include="GameClient.cpp" />
|
||||
|
|
|
|||
1220
Reality/Source/StackWalker.cpp
Normal file
1220
Reality/Source/StackWalker.cpp
Normal file
File diff suppressed because it is too large
Load diff
201
Reality/Source/StackWalker.h
Normal file
201
Reality/Source/StackWalker.h
Normal file
|
|
@ -0,0 +1,201 @@
|
|||
// *************************************************************************************************
|
||||
// --------------------------------------
|
||||
// Copyright (C) 2006-2010 Rajko Stojadinovic
|
||||
//
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Lesser General Public
|
||||
// License as published by the Free Software Foundation; either
|
||||
// version 2.1 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
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
//
|
||||
// *************************************************************************************************
|
||||
|
||||
// #pragma once is supported starting with _MCS_VER 1000,
|
||||
// so we need not to check the version (because we only support _MSC_VER >= 1100)!
|
||||
#pragma once
|
||||
|
||||
//#include <windows.h>
|
||||
|
||||
// special defines for VC5/6 (if no actual PSDK is installed):
|
||||
#if _MSC_VER < 1300
|
||||
typedef unsigned __int64 DWORD64, *PDWORD64;
|
||||
#if defined(_WIN64)
|
||||
typedef unsigned __int64 SIZE_T, *PSIZE_T;
|
||||
#else
|
||||
typedef unsigned long SIZE_T, *PSIZE_T;
|
||||
#endif
|
||||
#endif // _MSC_VER < 1300
|
||||
|
||||
class __declspec(dllexport) StackWalkerInternal; // forward
|
||||
class __declspec(dllexport) StackWalker
|
||||
{
|
||||
public:
|
||||
typedef enum StackWalkOptions
|
||||
{
|
||||
// No addition info will be retrived
|
||||
// (only the address is available)
|
||||
RetrieveNone = 0,
|
||||
|
||||
// Try to get the symbol-name
|
||||
RetrieveSymbol = 1,
|
||||
|
||||
// Try to get the line for this symbol
|
||||
RetrieveLine = 2,
|
||||
|
||||
// Try to retrieve the module-infos
|
||||
RetrieveModuleInfo = 4,
|
||||
|
||||
// Also retrieve the version for the DLL/EXE
|
||||
RetrieveFileVersion = 8,
|
||||
|
||||
// Contains all the abouve
|
||||
RetrieveVerbose = 0xF,
|
||||
|
||||
// Generate a "good" symbol-search-path
|
||||
SymBuildPath = 0x10,
|
||||
|
||||
// Also use the public Microsoft-Symbol-Server
|
||||
SymUseSymSrv = 0x20,
|
||||
|
||||
// Contains all the abouve "Sym"-options
|
||||
SymAll = 0x30,
|
||||
|
||||
// Contains all options (default)
|
||||
OptionsAll = 0x3F
|
||||
} StackWalkOptions;
|
||||
|
||||
StackWalker(
|
||||
int options = OptionsAll, // 'int' is by design, to combine the enum-flags
|
||||
LPCSTR szSymPath = NULL,
|
||||
DWORD dwProcessId = GetCurrentProcessId(),
|
||||
HANDLE hProcess = GetCurrentProcess()
|
||||
);
|
||||
StackWalker(DWORD dwProcessId, HANDLE hProcess);
|
||||
virtual ~StackWalker();
|
||||
|
||||
typedef BOOL (__stdcall *PReadProcessMemoryRoutine)(
|
||||
HANDLE hProcess,
|
||||
DWORD64 qwBaseAddress,
|
||||
PVOID lpBuffer,
|
||||
DWORD nSize,
|
||||
LPDWORD lpNumberOfBytesRead,
|
||||
LPVOID pUserData // optional data, which was passed in "ShowCallstack"
|
||||
);
|
||||
|
||||
BOOL LoadModules();
|
||||
|
||||
BOOL m_sharedptrlog;
|
||||
BOOL ShowCallstack(BOOL issharedptrlog = FALSE,
|
||||
HANDLE hThread = GetCurrentThread(),
|
||||
const CONTEXT *context = NULL,
|
||||
PReadProcessMemoryRoutine readMemoryFunction = NULL,
|
||||
LPVOID pUserData = NULL // optional to identify some data in the 'readMemoryFunction'-callback
|
||||
);
|
||||
|
||||
#if _MSC_VER >= 1300
|
||||
// due to some reasons, the "STACKWALK_MAX_NAMELEN" must be declared as "public"
|
||||
// in older compilers in order to use it... starting with VC7 we can declare it as "protected"
|
||||
protected:
|
||||
#endif
|
||||
enum { STACKWALK_MAX_NAMELEN = 1024 }; // max name length for found symbols
|
||||
|
||||
protected:
|
||||
// Entry for each Callstack-Entry
|
||||
typedef struct CallstackEntry
|
||||
{
|
||||
DWORD64 offset; // if 0, we have no valid entry
|
||||
CHAR name[STACKWALK_MAX_NAMELEN];
|
||||
CHAR undName[STACKWALK_MAX_NAMELEN];
|
||||
CHAR undFullName[STACKWALK_MAX_NAMELEN];
|
||||
DWORD64 offsetFromSmybol;
|
||||
DWORD offsetFromLine;
|
||||
DWORD lineNumber;
|
||||
CHAR lineFileName[STACKWALK_MAX_NAMELEN];
|
||||
DWORD symType;
|
||||
LPCSTR symTypeString;
|
||||
CHAR moduleName[STACKWALK_MAX_NAMELEN];
|
||||
DWORD64 baseOfImage;
|
||||
CHAR loadedImageName[STACKWALK_MAX_NAMELEN];
|
||||
} CallstackEntry;
|
||||
|
||||
typedef enum CallstackEntryType {firstEntry, nextEntry, lastEntry};
|
||||
|
||||
virtual void OnSymInit(LPCSTR szSearchPath, DWORD symOptions, LPCSTR szUserName);
|
||||
virtual void OnLoadModule(LPCSTR img, LPCSTR mod, DWORD64 baseAddr, DWORD size, DWORD result, LPCSTR symType, LPCSTR pdbName, ULONGLONG fileVersion);
|
||||
virtual void OnCallstackEntry(CallstackEntryType eType, CallstackEntry &entry);
|
||||
virtual void OnDbgHelpErr(LPCSTR szFuncName, DWORD gle, DWORD64 addr);
|
||||
virtual void OnOutput(LPCSTR szText);
|
||||
|
||||
StackWalkerInternal *m_sw;
|
||||
HANDLE m_hProcess;
|
||||
DWORD m_dwProcessId;
|
||||
BOOL m_modulesLoaded;
|
||||
LPSTR m_szSymPath;
|
||||
|
||||
int m_options;
|
||||
|
||||
static BOOL __stdcall myReadProcMem(HANDLE hProcess, DWORD64 qwBaseAddress, PVOID lpBuffer, DWORD nSize, LPDWORD lpNumberOfBytesRead);
|
||||
|
||||
friend StackWalkerInternal;
|
||||
};
|
||||
|
||||
|
||||
// The "ugly" assembler-implementation is needed for systems before XP
|
||||
// If you have a new PSDK and you only compile for XP and later, then you can use
|
||||
// the "RtlCaptureContext"
|
||||
// Currently there is no define which determines the PSDK-Version...
|
||||
// So we just use the compiler-version (and assumes that the PSDK is
|
||||
// the one which was installed by the VS-IDE)
|
||||
|
||||
// INFO: If you want, you can use the RtlCaptureContext if you only target XP and later...
|
||||
// But I currently use it in x64/IA64 environments...
|
||||
//#if defined(_M_IX86) && (_WIN32_WINNT <= 0x0500) && (_MSC_VER < 1400)
|
||||
|
||||
#if defined(_M_IX86)
|
||||
#ifdef CURRENT_THREAD_VIA_EXCEPTION
|
||||
// TODO: The following is not a "good" implementation,
|
||||
// because the callstack is only valid in the "__except" block...
|
||||
#define GET_CURRENT_CONTEXT(c, contextFlags) \
|
||||
do { \
|
||||
memset(&c, 0, sizeof(CONTEXT)); \
|
||||
EXCEPTION_POINTERS *pExp = NULL; \
|
||||
__try { \
|
||||
throw 0; \
|
||||
} __except( ( (pExp = GetExceptionInformation()) ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_EXECUTE_HANDLER)) {} \
|
||||
if (pExp != NULL) \
|
||||
memcpy(&c, pExp->ContextRecord, sizeof(CONTEXT)); \
|
||||
c.ContextFlags = contextFlags; \
|
||||
} while(0);
|
||||
#else
|
||||
// The following should be enough for walking the callstack...
|
||||
#define GET_CURRENT_CONTEXT(c, contextFlags) \
|
||||
do { \
|
||||
memset(&c, 0, sizeof(CONTEXT)); \
|
||||
c.ContextFlags = contextFlags; \
|
||||
__asm call x \
|
||||
__asm x: pop eax \
|
||||
__asm mov c.Eip, eax \
|
||||
__asm mov c.Ebp, ebp \
|
||||
__asm mov c.Esp, esp \
|
||||
} while(0);
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
// The following is defined for x86 (XP and higher), x64 and IA64:
|
||||
#define GET_CURRENT_CONTEXT(c, contextFlags) \
|
||||
do { \
|
||||
memset(&c, 0, sizeof(CONTEXT)); \
|
||||
c.ContextFlags = contextFlags; \
|
||||
RtlCaptureContext(&c); \
|
||||
} while(0);
|
||||
#endif
|
||||
Loading…
Add table
Add a link
Reference in a new issue