You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

146 lines
3.0 KiB

/**
* @file dthread.cpp
*
* Implementation of functions for updating game state from network commands.
*/
#include "nthread.h"
#include "storm/storm.h"
#include "utils/thread.h"
namespace devilution {
static CCritSect sgMemCrit;
SDL_threadID glpDThreadId;
TMegaPkt *sgpInfoHead; /* may not be right struct */
bool dthread_running;
event_emul *sghWorkToDoEvent;
/* rdata */
static SDL_Thread *sghThread = nullptr;
static unsigned int dthread_handler(void *data)
{
const char *error_buf;
TMegaPkt *pkt;
DWORD dwMilliseconds;
while (dthread_running) {
if (sgpInfoHead == nullptr && WaitForEvent(sghWorkToDoEvent) == -1) {
error_buf = SDL_GetError();
app_fatal("dthread4:\n%s", error_buf);
}
sgMemCrit.Enter();
pkt = sgpInfoHead;
if (sgpInfoHead != nullptr)
sgpInfoHead = sgpInfoHead->pNext;
else
ResetEvent(sghWorkToDoEvent);
sgMemCrit.Leave();
if (pkt != nullptr) {
if (pkt->dwSpaceLeft != MAX_PLRS)
multi_send_zero_packet(pkt->dwSpaceLeft, static_cast<_cmd_id>(pkt->data[0]), &pkt->data[8], *(DWORD *)&pkt->data[4]);
dwMilliseconds = 1000 * *(DWORD *)&pkt->data[4] / gdwDeltaBytesSec;
if (dwMilliseconds >= 1)
dwMilliseconds = 1;
mem_free_dbg(pkt);
if (dwMilliseconds != 0)
SDL_Delay(dwMilliseconds);
}
}
return 0;
}
void dthread_remove_player(uint8_t pnum)
{
TMegaPkt *pkt;
sgMemCrit.Enter();
for (pkt = sgpInfoHead; pkt != nullptr; pkt = pkt->pNext) {
if (pkt->dwSpaceLeft == pnum)
pkt->dwSpaceLeft = MAX_PLRS;
}
sgMemCrit.Leave();
}
void dthread_send_delta(int pnum, char cmd, void *pbSrc, int dwLen)
{
TMegaPkt *pkt;
TMegaPkt *p;
if (!gbIsMultiplayer) {
return;
}
pkt = (TMegaPkt *)DiabloAllocPtr(dwLen + 20);
pkt->pNext = nullptr;
pkt->dwSpaceLeft = pnum;
pkt->data[0] = cmd;
*(DWORD *)&pkt->data[4] = dwLen;
memcpy(&pkt->data[8], pbSrc, dwLen);
sgMemCrit.Enter();
p = (TMegaPkt *)&sgpInfoHead;
while (p->pNext != nullptr) {
p = p->pNext;
}
p->pNext = pkt;
SetEvent(sghWorkToDoEvent);
sgMemCrit.Leave();
}
void dthread_start()
{
const char *error_buf;
if (!gbIsMultiplayer) {
return;
}
sghWorkToDoEvent = StartEvent();
if (sghWorkToDoEvent == nullptr) {
error_buf = SDL_GetError();
app_fatal("dthread:1\n%s", error_buf);
}
dthread_running = true;
sghThread = CreateThread(dthread_handler, &glpDThreadId);
if (sghThread == nullptr) {
error_buf = SDL_GetError();
app_fatal("dthread2:\n%s", error_buf);
}
}
void dthread_cleanup()
{
TMegaPkt *tmp;
if (sghWorkToDoEvent == nullptr) {
return;
}
dthread_running = false;
SetEvent(sghWorkToDoEvent);
if (sghThread != nullptr && glpDThreadId != SDL_GetThreadID(nullptr)) {
SDL_WaitThread(sghThread, nullptr);
sghThread = nullptr;
}
EndEvent(sghWorkToDoEvent);
sghWorkToDoEvent = nullptr;
while (sgpInfoHead != nullptr) {
tmp = sgpInfoHead->pNext;
MemFreeDbg(sgpInfoHead);
sgpInfoHead = tmp;
}
}
} // namespace devilution