mirror of
https://github.com/galaxyhaxz/devilution
synced 2024-11-14 16:29:02 +00:00
149 lines
3 KiB
C++
149 lines
3 KiB
C++
|
#include "diablo.h"
|
||
|
#include "../3rdParty/Storm/Source/storm.h"
|
||
|
|
||
|
static CCritSect sgMemCrit; // idb
|
||
|
static unsigned int sgnThreadId; // idb
|
||
|
TDeltaInfo *sgpInfoHead;
|
||
|
static BOOLEAN sgbThreadIsActive; // weak
|
||
|
HANDLE sghWorkToDoEvent; // idb
|
||
|
|
||
|
/* rdata */
|
||
|
static HANDLE sghThread = INVALID_HANDLE_VALUE; // idb
|
||
|
|
||
|
void dthread_remove_player(int pnum)
|
||
|
{
|
||
|
TDeltaInfo *p;
|
||
|
|
||
|
sgMemCrit.Enter();
|
||
|
|
||
|
for(p = sgpInfoHead; p != NULL; p = p->pNext) {
|
||
|
if(p->pnum == pnum) {
|
||
|
p->pnum = 4;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
sgMemCrit.Leave();
|
||
|
}
|
||
|
|
||
|
void dthread_send_delta(int pnum, BYTE cmd, const BYTE *pbSrc, DWORD dwLen)
|
||
|
{
|
||
|
TDeltaInfo *pCurr, *p;
|
||
|
|
||
|
/// ASSERT: assert((DWORD) pnum < MAX_PLRS);
|
||
|
/// ASSERT: assert(pnum != myplr);
|
||
|
/// ASSERT: assert(pbSrc);
|
||
|
/// ASSERT: assert(dwLen);
|
||
|
|
||
|
if(gbMaxPlayers == 1) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
pCurr = (TDeltaInfo *)DiabloAllocPtr(sizeof(*pCurr) + dwLen);
|
||
|
pCurr->pNext = NULL;
|
||
|
pCurr->pnum = pnum;
|
||
|
pCurr->cmd = cmd;
|
||
|
pCurr->size = dwLen;
|
||
|
memcpy(pCurr->data, pbSrc, dwLen);
|
||
|
|
||
|
sgMemCrit.Enter();
|
||
|
|
||
|
p = (TDeltaInfo *)&sgpInfoHead;
|
||
|
while(p->pNext != NULL) {
|
||
|
p = p->pNext;
|
||
|
}
|
||
|
p->pNext = pCurr;
|
||
|
|
||
|
SetEvent(sghWorkToDoEvent);
|
||
|
|
||
|
sgMemCrit.Leave();
|
||
|
}
|
||
|
|
||
|
void dthread_start()
|
||
|
{
|
||
|
/// ASSERT: assert(sghThread == INVALID_HANDLE_VALUE);
|
||
|
|
||
|
if(gbMaxPlayers == 1) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
/// ASSERT: assert(! sgpInfoHead);
|
||
|
/// ASSERT: assert(! sghWorkToDoEvent);
|
||
|
sghWorkToDoEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||
|
if(sghWorkToDoEvent == NULL) {
|
||
|
app_fatal("dthread:1\n%s", TraceLastError());
|
||
|
}
|
||
|
|
||
|
sgbThreadIsActive = TRUE;
|
||
|
|
||
|
/// ASSERT: assert(sghThread == INVALID_HANDLE_VALUE);
|
||
|
sghThread = (HANDLE)_beginthreadex(NULL, 0, dthread_handler, NULL, 0, &sgnThreadId);
|
||
|
if(sghThread == INVALID_HANDLE_VALUE) {
|
||
|
app_fatal("dthread2:\n%s", TraceLastError());
|
||
|
}
|
||
|
}
|
||
|
|
||
|
unsigned int __stdcall dthread_handler(void *dummy)
|
||
|
{
|
||
|
DWORD dwTime;
|
||
|
TDeltaInfo *p;
|
||
|
|
||
|
while(sgbThreadIsActive) {
|
||
|
if(sgpInfoHead == NULL && WaitForSingleObject(sghWorkToDoEvent, INFINITE) == WAIT_FAILED) {
|
||
|
app_fatal("dthread4:\n%s", TraceLastError());
|
||
|
}
|
||
|
sgMemCrit.Enter();
|
||
|
p = sgpInfoHead;
|
||
|
if(p != NULL) {
|
||
|
sgpInfoHead = p->pNext;
|
||
|
} else {
|
||
|
ResetEvent(sghWorkToDoEvent);
|
||
|
}
|
||
|
sgMemCrit.Leave();
|
||
|
if(p != NULL) {
|
||
|
if(p->pnum != 4) {
|
||
|
multi_send_zero_packet(p->pnum, p->cmd, p->data, p->size);
|
||
|
}
|
||
|
/// ASSERT: assert(gdwDeltaBytesSec);
|
||
|
dwTime = 1000 * p->size / gdwDeltaBytesSec;
|
||
|
if(dwTime >= 1) {
|
||
|
dwTime = 1;
|
||
|
}
|
||
|
MemFreeDbg(p);
|
||
|
if(dwTime != 0) {
|
||
|
Sleep(dwTime);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
void dthread_cleanup()
|
||
|
{
|
||
|
TDeltaInfo *p;
|
||
|
|
||
|
if(sghWorkToDoEvent == NULL) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
sgbThreadIsActive = FALSE;
|
||
|
SetEvent(sghWorkToDoEvent);
|
||
|
|
||
|
if(sghThread != INVALID_HANDLE_VALUE && sgnThreadId != GetCurrentThreadId()) {
|
||
|
if(WaitForSingleObject(sghThread, INFINITE) == WAIT_FAILED) {
|
||
|
app_fatal("dthread3:\n(%s)", TraceLastError());
|
||
|
}
|
||
|
CloseHandle(sghThread);
|
||
|
sghThread = INVALID_HANDLE_VALUE;
|
||
|
}
|
||
|
|
||
|
CloseHandle(sghWorkToDoEvent);
|
||
|
sghWorkToDoEvent = NULL;
|
||
|
|
||
|
while(sgpInfoHead != NULL) {
|
||
|
p = sgpInfoHead->pNext;
|
||
|
MemFreeDbg(sgpInfoHead);
|
||
|
sgpInfoHead = p;
|
||
|
}
|
||
|
}
|