1 /**
2  * @file msg.cpp
3  *
4  * Implementation of function for sending and reciving network messages.
5  */
6 #include "all.h"
7 #include "../3rdParty/Storm/Source/storm.h"
8 #include "../DiabloUI/diabloui.h"
9 #include "options.h"
10 
11 DEVILUTION_BEGIN_NAMESPACE
12 
13 static DWORD sgdwOwnerWait;
14 static DWORD sgdwRecvOffset;
15 static int sgnCurrMegaPlayer;
16 static DLevel sgLevels[NUMLEVELS];
17 static BYTE sbLastCmd;
18 static TMegaPkt *sgpCurrPkt;
19 static BYTE sgRecvBuf[sizeof(DLevel) + 1];
20 static BYTE sgbRecvCmd;
21 static LocalLevel sgLocals[NUMLEVELS];
22 static DJunk sgJunk;
23 static TMegaPkt *sgpMegaPkt;
24 static BOOLEAN sgbDeltaChanged;
25 static BYTE sgbDeltaChunks;
26 BOOL deltaload;
27 BYTE gbBufferMsgs;
28 int dwRecCount;
29 
msg_get_next_packet()30 static void msg_get_next_packet()
31 {
32 	TMegaPkt *result;
33 
34 	sgpCurrPkt = (TMegaPkt *)DiabloAllocPtr(sizeof(TMegaPkt));
35 	sgpCurrPkt->pNext = NULL;
36 	sgpCurrPkt->dwSpaceLeft = sizeof(result->data);
37 
38 	result = (TMegaPkt *)&sgpMegaPkt;
39 	while (result->pNext)
40 		result = result->pNext;
41 
42 	result->pNext = sgpCurrPkt;
43 }
44 
msg_free_packets()45 static void msg_free_packets()
46 {
47 	while (sgpMegaPkt) {
48 		sgpCurrPkt = sgpMegaPkt->pNext;
49 		MemFreeDbg(sgpMegaPkt);
50 		sgpMegaPkt = sgpCurrPkt;
51 	}
52 }
53 
msg_pre_packet()54 static void msg_pre_packet()
55 {
56 	int i;
57 
58 	i = -1;
59 	for (TMegaPkt *pkt = sgpMegaPkt; pkt != NULL; pkt = pkt->pNext) {
60 		BYTE *data = pkt->data;
61 		int spaceLeft = sizeof(pkt->data);
62 		while (spaceLeft != pkt->dwSpaceLeft) {
63 			if (*data == FAKE_CMD_SETID) {
64 				TFakeCmdPlr *cmd = (TFakeCmdPlr *)data;
65 				data += sizeof(*cmd);
66 				spaceLeft -= sizeof(*cmd);
67 				i = cmd->bPlr;
68 			} else if (*data == FAKE_CMD_DROPID) {
69 				TFakeDropPlr *cmd = (TFakeDropPlr *)data;
70 				data += sizeof(*cmd);
71 				spaceLeft -= sizeof(*cmd);
72 				multi_player_left(cmd->bPlr, cmd->dwReason);
73 			} else {
74 				int pktSize = ParseCmd(i, (TCmd *)data);
75 				data += pktSize;
76 				spaceLeft -= pktSize;
77 			}
78 		}
79 	}
80 }
81 
msg_send_packet(int pnum,const void * packet,DWORD dwSize)82 static void msg_send_packet(int pnum, const void *packet, DWORD dwSize)
83 {
84 	TFakeCmdPlr cmd;
85 
86 	if (pnum != sgnCurrMegaPlayer) {
87 		sgnCurrMegaPlayer = pnum;
88 		cmd.bCmd = FAKE_CMD_SETID;
89 		cmd.bPlr = pnum;
90 		msg_send_packet(pnum, &cmd, sizeof(cmd));
91 	}
92 	if (sgpCurrPkt->dwSpaceLeft < dwSize)
93 		msg_get_next_packet();
94 
95 	memcpy(sgpCurrPkt->data + sizeof(sgpCurrPkt->data) - sgpCurrPkt->dwSpaceLeft, packet, dwSize);
96 	sgpCurrPkt->dwSpaceLeft -= dwSize;
97 }
98 
msg_send_drop_pkt(int pnum,int reason)99 void msg_send_drop_pkt(int pnum, int reason)
100 {
101 	TFakeDropPlr cmd;
102 
103 	cmd.dwReason = reason;
104 	cmd.bCmd = FAKE_CMD_DROPID;
105 	cmd.bPlr = pnum;
106 	msg_send_packet(pnum, &cmd, sizeof(cmd));
107 }
108 
msg_wait_for_turns()109 static int msg_wait_for_turns()
110 {
111 	BOOL received;
112 	DWORD turns;
113 
114 	if (sgbDeltaChunks == 0) {
115 		nthread_send_and_recv_turn(0, 0);
116 		if (!SNetGetOwnerTurnsWaiting(&turns) && SErrGetLastError() == STORM_ERROR_NOT_IN_GAME)
117 			return 100;
118 		if (SDL_GetTicks() - sgdwOwnerWait <= 2000 && turns < gdwTurnsInTransit)
119 			return 0;
120 		sgbDeltaChunks++;
121 	}
122 	multi_process_network_packets();
123 	nthread_send_and_recv_turn(0, 0);
124 	if (nthread_has_500ms_passed())
125 		nthread_recv_turns(&received);
126 
127 	if (gbGameDestroyed)
128 		return 100;
129 	if (gbDeltaSender >= MAX_PLRS) {
130 		sgbDeltaChunks = 0;
131 		sgbRecvCmd = CMD_DLEVEL_END;
132 		gbDeltaSender = myplr;
133 		nthread_set_turn_upper_bit();
134 	}
135 	if (sgbDeltaChunks == MAX_CHUNKS - 1) {
136 		sgbDeltaChunks = MAX_CHUNKS;
137 		return 99;
138 	}
139 	return 100 * sgbDeltaChunks / MAX_CHUNKS;
140 }
141 
msg_wait_resync()142 BOOL msg_wait_resync()
143 {
144 	BOOL success;
145 
146 	msg_get_next_packet();
147 	sgbDeltaChunks = 0;
148 	sgnCurrMegaPlayer = -1;
149 	sgbRecvCmd = CMD_DLEVEL_END;
150 	gbBufferMsgs = 1;
151 	sgdwOwnerWait = SDL_GetTicks();
152 	success = UiProgressDialog("Waiting for game data...", 1, msg_wait_for_turns, 20);
153 	gbBufferMsgs = 0;
154 	if (!success) {
155 		msg_free_packets();
156 		return FALSE;
157 	}
158 
159 	if (gbGameDestroyed) {
160 		DrawDlg("The game ended");
161 		msg_free_packets();
162 		return FALSE;
163 	}
164 
165 	if (sgbDeltaChunks != MAX_CHUNKS) {
166 		DrawDlg("Unable to get level data");
167 		msg_free_packets();
168 		return FALSE;
169 	}
170 
171 	return TRUE;
172 }
173 
run_delta_info()174 void run_delta_info()
175 {
176 	if (!gbIsMultiplayer)
177 		return;
178 
179 	gbBufferMsgs = 2;
180 	msg_pre_packet();
181 	gbBufferMsgs = 0;
182 	msg_free_packets();
183 }
184 
DeltaExportItem(BYTE * dst,TCmdPItem * src)185 static BYTE *DeltaExportItem(BYTE *dst, TCmdPItem *src)
186 {
187 	for (int i = 0; i < MAXITEMS; i++, src++) {
188 		if (src->bCmd == 0xFF)
189 			*dst++ = 0xFF;
190 		else {
191 			memcpy(dst, src, sizeof(TCmdPItem));
192 			dst += sizeof(TCmdPItem);
193 		}
194 	}
195 
196 	return dst;
197 }
198 
DeltaImportItem(BYTE * src,TCmdPItem * dst)199 static BYTE *DeltaImportItem(BYTE *src, TCmdPItem *dst)
200 {
201 	for (int i = 0; i < MAXITEMS; i++, dst++) {
202 		if (*src == 0xFF) {
203 			memset(dst, 0xFF, sizeof(TCmdPItem));
204 			src++;
205 		} else {
206 			memcpy(dst, src, sizeof(TCmdPItem));
207 			src += sizeof(TCmdPItem);
208 		}
209 	}
210 
211 	return src;
212 }
213 
DeltaExportObject(BYTE * dst,DObjectStr * src)214 static BYTE *DeltaExportObject(BYTE *dst, DObjectStr *src)
215 {
216 	memcpy(dst, src, sizeof(DObjectStr) * MAXOBJECTS);
217 	return dst + sizeof(DObjectStr) * MAXOBJECTS;
218 }
219 
DeltaImportObject(BYTE * src,DObjectStr * dst)220 static BYTE *DeltaImportObject(BYTE *src, DObjectStr *dst)
221 {
222 	memcpy(dst, src, sizeof(DObjectStr) * MAXOBJECTS);
223 	return src + sizeof(DObjectStr) * MAXOBJECTS;
224 }
225 
DeltaExportMonster(BYTE * dst,DMonsterStr * src)226 static BYTE *DeltaExportMonster(BYTE *dst, DMonsterStr *src)
227 {
228 	for (int i = 0; i < MAXMONSTERS; i++, src++) {
229 		if (src->_mx == 0xFF)
230 			*dst++ = 0xFF;
231 		else {
232 			memcpy(dst, src, sizeof(DMonsterStr));
233 			dst += sizeof(DMonsterStr);
234 		}
235 	}
236 
237 	return dst;
238 }
239 
DeltaImportMonster(BYTE * src,DMonsterStr * dst)240 static BYTE *DeltaImportMonster(BYTE *src, DMonsterStr *dst)
241 {
242 	for (int i = 0; i < MAXMONSTERS; i++, dst++) {
243 		if (*src == 0xFF) {
244 			memset(dst, 0xFF, sizeof(DMonsterStr));
245 			src++;
246 		} else {
247 			memcpy(dst, src, sizeof(DMonsterStr));
248 			src += sizeof(DMonsterStr);
249 		}
250 	}
251 
252 	return src;
253 }
254 
DeltaExportJunk(BYTE * dst)255 static BYTE *DeltaExportJunk(BYTE *dst)
256 {
257 	int i, q;
258 
259 	for (i = 0; i < MAXPORTAL; i++) {
260 		if (sgJunk.portal[i].x == 0xFF) {
261 			*dst++ = 0xFF;
262 		} else {
263 			memcpy(dst, &sgJunk.portal[i], sizeof(DPortal));
264 			dst += sizeof(DPortal);
265 		}
266 	}
267 
268 	for (i = 0, q = 0; i < MAXQUESTS; i++) {
269 		if (questlist[i]._qflags & QUEST_ANY) {
270 			sgJunk.quests[q].qlog = quests[i]._qlog;
271 			sgJunk.quests[q].qstate = quests[i]._qactive;
272 			sgJunk.quests[q].qvar1 = quests[i]._qvar1;
273 			memcpy(dst, &sgJunk.quests[q], sizeof(MultiQuests));
274 			dst += sizeof(MultiQuests);
275 			q++;
276 		}
277 	}
278 
279 	return dst;
280 }
281 
DeltaImportJunk(BYTE * src)282 static void DeltaImportJunk(BYTE *src)
283 {
284 	int i, q;
285 
286 	for (i = 0; i < MAXPORTAL; i++) {
287 		if (*src == 0xFF) {
288 			memset(&sgJunk.portal[i], 0xFF, sizeof(DPortal));
289 			src++;
290 			SetPortalStats(i, FALSE, 0, 0, 0, DTYPE_TOWN);
291 		} else {
292 			memcpy(&sgJunk.portal[i], src, sizeof(DPortal));
293 			src += sizeof(DPortal);
294 			SetPortalStats(
295 			    i,
296 			    TRUE,
297 			    sgJunk.portal[i].x,
298 			    sgJunk.portal[i].y,
299 			    sgJunk.portal[i].level,
300 			    (dungeon_type)sgJunk.portal[i].ltype);
301 		}
302 	}
303 
304 	for (i = 0, q = 0; i < MAXQUESTS; i++) {
305 		if (questlist[i]._qflags & QUEST_ANY) {
306 			memcpy(&sgJunk.quests[q], src, sizeof(MultiQuests));
307 			src += sizeof(MultiQuests);
308 			quests[i]._qlog = sgJunk.quests[q].qlog;
309 			quests[i]._qactive = sgJunk.quests[q].qstate;
310 			quests[i]._qvar1 = sgJunk.quests[q].qvar1;
311 			q++;
312 		}
313 	}
314 }
315 
msg_comp_level(BYTE * buffer,BYTE * end)316 static DWORD msg_comp_level(BYTE *buffer, BYTE *end)
317 {
318 	DWORD size = end - buffer - 1;
319 	DWORD pkSize = PkwareCompress(buffer + 1, size);
320 
321 	*buffer = size != pkSize;
322 
323 	return pkSize + 1;
324 }
325 
DeltaExportData(int pnum)326 void DeltaExportData(int pnum)
327 {
328 	if (sgbDeltaChanged) {
329 		int size;
330 		BYTE *dstEnd, *dst = (BYTE *)DiabloAllocPtr(sizeof(DLevel) + 1);
331 		for (int i = 0; i < NUMLEVELS; i++) {
332 			dstEnd = dst + 1;
333 			dstEnd = DeltaExportItem(dstEnd, sgLevels[i].item);
334 			dstEnd = DeltaExportObject(dstEnd, sgLevels[i].object);
335 			dstEnd = DeltaExportMonster(dstEnd, sgLevels[i].monster);
336 			size = msg_comp_level(dst, dstEnd);
337 			dthread_send_delta(pnum, i + CMD_DLEVEL_0, dst, size);
338 		}
339 		dstEnd = dst + 1;
340 		dstEnd = DeltaExportJunk(dstEnd);
341 		size = msg_comp_level(dst, dstEnd);
342 		dthread_send_delta(pnum, CMD_DLEVEL_JUNK, dst, size);
343 		mem_free_dbg(dst);
344 	}
345 	char src = 0;
346 	dthread_send_delta(pnum, CMD_DLEVEL_END, &src, 1);
347 }
348 
DeltaImportData(BYTE cmd,DWORD recv_offset)349 static void DeltaImportData(BYTE cmd, DWORD recv_offset)
350 {
351 	if (sgRecvBuf[0] != 0)
352 		PkwareDecompress(&sgRecvBuf[1], recv_offset, sizeof(sgRecvBuf) - 1);
353 
354 	BYTE *src = &sgRecvBuf[1];
355 	if (cmd == CMD_DLEVEL_JUNK) {
356 		DeltaImportJunk(src);
357 	} else if (cmd >= CMD_DLEVEL_0 && cmd <= CMD_DLEVEL_24) {
358 		BYTE i = cmd - CMD_DLEVEL_0;
359 		src = DeltaImportItem(src, sgLevels[i].item);
360 		src = DeltaImportObject(src, sgLevels[i].object);
361 		DeltaImportMonster(src, sgLevels[i].monster);
362 	} else {
363 		app_fatal("Unkown network message type: %d", cmd);
364 	}
365 
366 	sgbDeltaChunks++;
367 	sgbDeltaChanged = TRUE;
368 }
369 
On_DLEVEL(int pnum,TCmd * pCmd)370 static DWORD On_DLEVEL(int pnum, TCmd *pCmd)
371 {
372 	TCmdPlrInfoHdr *p = (TCmdPlrInfoHdr *)pCmd;
373 
374 	if (gbDeltaSender != pnum) {
375 		if (p->bCmd == CMD_DLEVEL_END) {
376 			gbDeltaSender = pnum;
377 			sgbRecvCmd = CMD_DLEVEL_END;
378 		} else if (p->bCmd == CMD_DLEVEL_0 && p->wOffset == 0) {
379 			gbDeltaSender = pnum;
380 			sgbRecvCmd = CMD_DLEVEL_END;
381 		} else {
382 			return p->wBytes + sizeof(*p);
383 		}
384 	}
385 	if (sgbRecvCmd == CMD_DLEVEL_END) {
386 		if (p->bCmd == CMD_DLEVEL_END) {
387 			sgbDeltaChunks = MAX_CHUNKS - 1;
388 			return p->wBytes + sizeof(*p);
389 		} else if (p->bCmd == CMD_DLEVEL_0 && p->wOffset == 0) {
390 			sgdwRecvOffset = 0;
391 			sgbRecvCmd = p->bCmd;
392 		} else {
393 			return p->wBytes + sizeof(*p);
394 		}
395 	} else if (sgbRecvCmd != p->bCmd) {
396 		DeltaImportData(sgbRecvCmd, sgdwRecvOffset);
397 		if (p->bCmd == CMD_DLEVEL_END) {
398 			sgbDeltaChunks = MAX_CHUNKS - 1;
399 			sgbRecvCmd = CMD_DLEVEL_END;
400 			return p->wBytes + sizeof(*p);
401 		} else {
402 			sgdwRecvOffset = 0;
403 			sgbRecvCmd = p->bCmd;
404 		}
405 	}
406 
407 	/// ASSERT: assert(p->wOffset == sgdwRecvOffset);
408 	memcpy(&sgRecvBuf[p->wOffset], &p[1], p->wBytes);
409 	sgdwRecvOffset += p->wBytes;
410 	return p->wBytes + sizeof(*p);
411 }
412 
delta_init()413 void delta_init()
414 {
415 	sgbDeltaChanged = FALSE;
416 	memset(&sgJunk, 0xFF, sizeof(sgJunk));
417 	memset(sgLevels, 0xFF, sizeof(sgLevels));
418 	memset(sgLocals, 0, sizeof(sgLocals));
419 	deltaload = FALSE;
420 }
421 
delta_kill_monster(int mi,BYTE x,BYTE y,BYTE bLevel)422 void delta_kill_monster(int mi, BYTE x, BYTE y, BYTE bLevel)
423 {
424 	if (!gbIsMultiplayer)
425 		return;
426 
427 	sgbDeltaChanged = TRUE;
428 	DMonsterStr *pD = &sgLevels[bLevel].monster[mi];
429 	pD->_mx = x;
430 	pD->_my = y;
431 	pD->_mdir = monster[mi]._mdir;
432 	pD->_mhitpoints = 0;
433 }
434 
delta_monster_hp(int mi,int hp,BYTE bLevel)435 void delta_monster_hp(int mi, int hp, BYTE bLevel)
436 {
437 	if (!gbIsMultiplayer)
438 		return;
439 
440 	sgbDeltaChanged = TRUE;
441 	DMonsterStr *pD = &sgLevels[bLevel].monster[mi];
442 	if (pD->_mhitpoints > hp)
443 		pD->_mhitpoints = hp;
444 }
445 
delta_sync_monster(const TSyncMonster * pSync,BYTE bLevel)446 void delta_sync_monster(const TSyncMonster *pSync, BYTE bLevel)
447 {
448 	if (!gbIsMultiplayer)
449 		return;
450 
451 	/// ASSERT: assert(pSync != NULL);
452 	/// ASSERT: assert(bLevel < NUMLEVELS);
453 	sgbDeltaChanged = TRUE;
454 
455 	DMonsterStr *pD = &sgLevels[bLevel].monster[pSync->_mndx];
456 	if (pD->_mhitpoints == 0)
457 		return;
458 
459 	pD->_mx = pSync->_mx;
460 	pD->_my = pSync->_my;
461 	pD->_mactive = UCHAR_MAX;
462 	pD->_menemy = pSync->_menemy;
463 }
464 
delta_sync_golem(TCmdGolem * pG,int pnum,BYTE bLevel)465 void delta_sync_golem(TCmdGolem *pG, int pnum, BYTE bLevel)
466 {
467 	if (!gbIsMultiplayer)
468 		return;
469 
470 	sgbDeltaChanged = TRUE;
471 	DMonsterStr *pD = &sgLevels[bLevel].monster[pnum];
472 	pD->_mx = pG->_mx;
473 	pD->_my = pG->_my;
474 	pD->_mactive = UCHAR_MAX;
475 	pD->_menemy = pG->_menemy;
476 	pD->_mdir = pG->_mdir;
477 	pD->_mhitpoints = pG->_mhitpoints;
478 }
479 
delta_leave_sync(BYTE bLevel)480 void delta_leave_sync(BYTE bLevel)
481 {
482 	if (!gbIsMultiplayer)
483 		return;
484 	if (currlevel == 0)
485 		glSeedTbl[0] = AdvanceRndSeed();
486 	if (currlevel <= 0)
487 		return;
488 
489 	for (int i = 0; i < nummonsters; i++) {
490 		int ma = monstactive[i];
491 		if (monster[ma]._mhitpoints == 0)
492 			continue;
493 		sgbDeltaChanged = TRUE;
494 		DMonsterStr *pD = &sgLevels[bLevel].monster[ma];
495 		pD->_mx = monster[ma]._mx;
496 		pD->_my = monster[ma]._my;
497 		pD->_mdir = monster[ma]._mdir;
498 		pD->_menemy = encode_enemy(ma);
499 		pD->_mhitpoints = monster[ma]._mhitpoints;
500 		pD->_mactive = monster[ma]._msquelch;
501 	}
502 	memcpy(&sgLocals[bLevel].automapsv, automapview, sizeof(automapview));
503 }
504 
delta_sync_object(int oi,BYTE bCmd,BYTE bLevel)505 static void delta_sync_object(int oi, BYTE bCmd, BYTE bLevel)
506 {
507 	if (!gbIsMultiplayer)
508 		return;
509 
510 	sgbDeltaChanged = TRUE;
511 	sgLevels[bLevel].object[oi].bCmd = bCmd;
512 }
513 
delta_get_item(TCmdGItem * pI,BYTE bLevel)514 static BOOL delta_get_item(TCmdGItem *pI, BYTE bLevel)
515 {
516 	int i;
517 
518 	if (!gbIsMultiplayer)
519 		return TRUE;
520 
521 	TCmdPItem *pD = sgLevels[bLevel].item;
522 	for (i = 0; i < MAXITEMS; i++, pD++) {
523 		if (pD->bCmd == 0xFF || pD->wIndx != pI->wIndx || pD->wCI != pI->wCI || pD->dwSeed != pI->dwSeed)
524 			continue;
525 
526 		if (pD->bCmd == CMD_WALKXY) {
527 			return TRUE;
528 		}
529 		if (pD->bCmd == CMD_STAND) {
530 			sgbDeltaChanged = TRUE;
531 			pD->bCmd = CMD_WALKXY;
532 			return TRUE;
533 		}
534 		if (pD->bCmd == CMD_ACK_PLRINFO) {
535 			sgbDeltaChanged = TRUE;
536 			pD->bCmd = 0xFF;
537 			return TRUE;
538 		}
539 
540 		app_fatal("delta:1");
541 	}
542 
543 	if ((pI->wCI & CF_PREGEN) == 0)
544 		return FALSE;
545 
546 	pD = sgLevels[bLevel].item;
547 	for (i = 0; i < MAXITEMS; i++, pD++) {
548 		if (pD->bCmd == 0xFF) {
549 			sgbDeltaChanged = TRUE;
550 			pD->bCmd = CMD_WALKXY;
551 			pD->x = pI->x;
552 			pD->y = pI->y;
553 			pD->wIndx = pI->wIndx;
554 			pD->wCI = pI->wCI;
555 			pD->dwSeed = pI->dwSeed;
556 			pD->bId = pI->bId;
557 			pD->bDur = pI->bDur;
558 			pD->bMDur = pI->bMDur;
559 			pD->bCh = pI->bCh;
560 			pD->bMCh = pI->bMCh;
561 			pD->wValue = pI->wValue;
562 			pD->dwBuff = pI->dwBuff;
563 			pD->wToHit = pI->wToHit;
564 			pD->wMaxDam = pI->wMaxDam;
565 			pD->bMinStr = pI->bMinStr;
566 			pD->bMinMag = pI->bMinMag;
567 			pD->bMinDex = pI->bMinDex;
568 			pD->bAC = pI->bAC;
569 			break;
570 		}
571 	}
572 	return TRUE;
573 }
574 
delta_put_item(TCmdPItem * pI,int x,int y,BYTE bLevel)575 static void delta_put_item(TCmdPItem *pI, int x, int y, BYTE bLevel)
576 {
577 	int i;
578 
579 	if (!gbIsMultiplayer)
580 		return;
581 
582 	TCmdPItem *pD = sgLevels[bLevel].item;
583 	for (i = 0; i < MAXITEMS; i++, pD++) {
584 		if (pD->bCmd != CMD_WALKXY
585 		    && pD->bCmd != 0xFF
586 		    && pD->wIndx == pI->wIndx
587 		    && pD->wCI == pI->wCI
588 		    && pD->dwSeed == pI->dwSeed) {
589 			if (pD->bCmd == CMD_ACK_PLRINFO)
590 				return;
591 			app_fatal("Trying to drop a floor item?");
592 		}
593 	}
594 
595 	pD = sgLevels[bLevel].item;
596 	for (i = 0; i < MAXITEMS; i++, pD++) {
597 		if (pD->bCmd == 0xFF) {
598 			sgbDeltaChanged = TRUE;
599 			memcpy(pD, pI, sizeof(TCmdPItem));
600 			pD->bCmd = CMD_ACK_PLRINFO;
601 			pD->x = x;
602 			pD->y = y;
603 			return;
604 		}
605 	}
606 }
607 
delta_portal_inited(int i)608 BOOL delta_portal_inited(int i)
609 {
610 	return sgJunk.portal[i].x == 0xFF;
611 }
612 
delta_quest_inited(int i)613 BOOL delta_quest_inited(int i)
614 {
615 	return sgJunk.quests[i].qstate != 0xFF;
616 }
617 
DeltaAddItem(int ii)618 void DeltaAddItem(int ii)
619 {
620 	int i;
621 
622 	if (!gbIsMultiplayer)
623 		return;
624 
625 	TCmdPItem *pD = sgLevels[currlevel].item;
626 	for (i = 0; i < MAXITEMS; i++, pD++) {
627 		if (pD->bCmd != 0xFF
628 		    && pD->wIndx == item[ii].IDidx
629 		    && pD->wCI == item[ii]._iCreateInfo
630 		    && pD->dwSeed == item[ii]._iSeed
631 		    && (pD->bCmd == CMD_WALKXY || pD->bCmd == CMD_STAND)) {
632 			return;
633 		}
634 	}
635 
636 	pD = sgLevels[currlevel].item;
637 	for (i = 0; i < MAXITEMS; i++, pD++) {
638 		if (pD->bCmd == 0xFF) {
639 			sgbDeltaChanged = TRUE;
640 			pD->bCmd = CMD_STAND;
641 			pD->x = item[ii]._ix;
642 			pD->y = item[ii]._iy;
643 			pD->wIndx = item[ii].IDidx;
644 			pD->wCI = item[ii]._iCreateInfo;
645 			pD->dwSeed = item[ii]._iSeed;
646 			pD->bId = item[ii]._iIdentified;
647 			pD->bDur = item[ii]._iDurability;
648 			pD->bMDur = item[ii]._iMaxDur;
649 			pD->bCh = item[ii]._iCharges;
650 			pD->bMCh = item[ii]._iMaxCharges;
651 			pD->wValue = item[ii]._ivalue;
652 			pD->wToHit = item[ii]._iPLToHit;
653 			pD->wMaxDam = item[ii]._iMaxDam;
654 			pD->bMinStr = item[ii]._iMinStr;
655 			pD->bMinMag = item[ii]._iMinMag;
656 			pD->bMinDex = item[ii]._iMinDex;
657 			pD->bAC = item[ii]._iAC;
658 			pD->dwBuff = item[ii].dwBuff;
659 			return;
660 		}
661 	}
662 }
663 
DeltaSaveLevel()664 void DeltaSaveLevel()
665 {
666 	if (!gbIsMultiplayer)
667 		return;
668 
669 	for (int i = 0; i < MAX_PLRS; i++) {
670 		if (i != myplr)
671 			plr[i]._pGFXLoad = 0;
672 	}
673 	plr[myplr]._pLvlVisited[currlevel] = TRUE;
674 	delta_leave_sync(currlevel);
675 }
676 
DeltaLoadLevel()677 void DeltaLoadLevel()
678 {
679 	int ot;
680 	int i, j, k, l;
681 	int x, y, xx, yy;
682 	BOOL done;
683 
684 	if (!gbIsMultiplayer)
685 		return;
686 
687 	deltaload = TRUE;
688 	if (currlevel != 0) {
689 		for (i = 0; i < nummonsters; i++) {
690 			if (sgLevels[currlevel].monster[i]._mx != 0xFF) {
691 				M_ClearSquares(i);
692 				x = sgLevels[currlevel].monster[i]._mx;
693 				y = sgLevels[currlevel].monster[i]._my;
694 				monster[i]._mx = x;
695 				monster[i]._my = y;
696 				monster[i]._moldx = x;
697 				monster[i]._moldy = y;
698 				monster[i]._mfutx = x;
699 				monster[i]._mfuty = y;
700 				if (sgLevels[currlevel].monster[i]._mhitpoints != -1)
701 					monster[i]._mhitpoints = sgLevels[currlevel].monster[i]._mhitpoints;
702 				if (sgLevels[currlevel].monster[i]._mhitpoints == 0) {
703 					monster[i]._moldx = sgLevels[currlevel].monster[i]._mx; // CODEFIX: useless assignment
704 					monster[i]._moldy = sgLevels[currlevel].monster[i]._my; // CODEFIX: useless assignment
705 					M_ClearSquares(i);
706 					if (monster[i]._mAi != AI_DIABLO) {
707 						if (monster[i]._uniqtype == 0)
708 							/// ASSERT: assert(monster[i].MType != NULL);
709 							AddDead(monster[i]._mx, monster[i]._my, monster[i].MType->mdeadval, (direction)monster[i]._mdir);
710 						else
711 							AddDead(monster[i]._mx, monster[i]._my, monster[i]._udeadval, (direction)monster[i]._mdir);
712 					}
713 					monster[i]._mDelFlag = TRUE;
714 					M_UpdateLeader(i);
715 				} else {
716 					decode_enemy(i, sgLevels[currlevel].monster[i]._menemy);
717 					if ((monster[i]._mx && monster[i]._mx != 1) || monster[i]._my)
718 						dMonster[monster[i]._mx][monster[i]._my] = i + 1;
719 					if (i < MAX_PLRS) {
720 						MAI_Golum(i);
721 						monster[i]._mFlags |= (MFLAG_TARGETS_MONSTER | MFLAG_GOLEM);
722 					} else {
723 						M_StartStand(i, monster[i]._mdir);
724 					}
725 					monster[i]._msquelch = sgLevels[currlevel].monster[i]._mactive;
726 				}
727 			}
728 		}
729 		memcpy(automapview, &sgLocals[currlevel], sizeof(automapview));
730 	}
731 
732 	for (i = 0; i < MAXITEMS; i++) {
733 		if (sgLevels[currlevel].item[i].bCmd != 0xFF) {
734 			if (sgLevels[currlevel].item[i].bCmd == CMD_WALKXY) {
735 				int ii = FindGetItem(
736 				    sgLevels[currlevel].item[i].wIndx,
737 				    sgLevels[currlevel].item[i].wCI,
738 				    sgLevels[currlevel].item[i].dwSeed);
739 				if (ii != -1) {
740 					if (dItem[item[ii]._ix][item[ii]._iy] == ii + 1)
741 						dItem[item[ii]._ix][item[ii]._iy] = 0;
742 					DeleteItem(ii, i);
743 				}
744 			}
745 			if (sgLevels[currlevel].item[i].bCmd == CMD_ACK_PLRINFO) {
746 				int ii = AllocateItem();
747 
748 				if (sgLevels[currlevel].item[i].wIndx == IDI_EAR) {
749 					RecreateEar(
750 					    ii,
751 					    sgLevels[currlevel].item[i].wCI,
752 					    sgLevels[currlevel].item[i].dwSeed,
753 					    sgLevels[currlevel].item[i].bId,
754 					    sgLevels[currlevel].item[i].bDur,
755 					    sgLevels[currlevel].item[i].bMDur,
756 					    sgLevels[currlevel].item[i].bCh,
757 					    sgLevels[currlevel].item[i].bMCh,
758 					    sgLevels[currlevel].item[i].wValue,
759 					    sgLevels[currlevel].item[i].dwBuff);
760 				} else {
761 					RecreateItem(
762 					    ii,
763 					    sgLevels[currlevel].item[i].wIndx,
764 					    sgLevels[currlevel].item[i].wCI,
765 					    sgLevels[currlevel].item[i].dwSeed,
766 					    sgLevels[currlevel].item[i].wValue,
767 					    (sgLevels[currlevel].item[i].dwBuff & CF_HELLFIRE) != 0);
768 					if (sgLevels[currlevel].item[i].bId)
769 						item[ii]._iIdentified = TRUE;
770 					item[ii]._iDurability = sgLevels[currlevel].item[i].bDur;
771 					item[ii]._iMaxDur = sgLevels[currlevel].item[i].bMDur;
772 					item[ii]._iCharges = sgLevels[currlevel].item[i].bCh;
773 					item[ii]._iMaxCharges = sgLevels[currlevel].item[i].bMCh;
774 					item[ii]._iPLToHit = sgLevels[currlevel].item[i].wToHit;
775 					item[ii]._iMaxDam = sgLevels[currlevel].item[i].wMaxDam;
776 					item[ii]._iMinStr = sgLevels[currlevel].item[i].bMinStr;
777 					item[ii]._iMinMag = sgLevels[currlevel].item[i].bMinMag;
778 					item[ii]._iMinDex = sgLevels[currlevel].item[i].bMinDex;
779 					item[ii]._iAC = sgLevels[currlevel].item[i].bAC;
780 					item[ii].dwBuff = sgLevels[currlevel].item[i].dwBuff;
781 				}
782 				x = sgLevels[currlevel].item[i].x;
783 				y = sgLevels[currlevel].item[i].y;
784 				if (!CanPut(x, y)) {
785 					done = FALSE;
786 					for (k = 1; k < 50 && !done; k++) {
787 						for (j = -k; j <= k && !done; j++) {
788 							yy = y + j;
789 							for (l = -k; l <= k && !done; l++) {
790 								xx = x + l;
791 								if (CanPut(xx, yy)) {
792 									done = TRUE;
793 									x = xx;
794 									y = yy;
795 								}
796 							}
797 						}
798 					}
799 				}
800 				item[ii]._ix = x;
801 				item[ii]._iy = y;
802 				dItem[item[ii]._ix][item[ii]._iy] = ii + 1;
803 				RespawnItem(ii, FALSE);
804 			}
805 		}
806 	}
807 
808 	if (currlevel != 0) {
809 		for (i = 0; i < MAXOBJECTS; i++) {
810 			switch (sgLevels[currlevel].object[i].bCmd) {
811 			case CMD_OPENDOOR:
812 			case CMD_CLOSEDOOR:
813 			case CMD_OPERATEOBJ:
814 			case CMD_PLROPOBJ:
815 				SyncOpObject(-1, sgLevels[currlevel].object[i].bCmd, i);
816 				break;
817 			case CMD_BREAKOBJ:
818 				SyncBreakObj(-1, i);
819 				break;
820 			}
821 		}
822 
823 		for (i = 0; i < nobjects; i++) {
824 			ot = object[objectactive[i]]._otype;
825 			if (ot == OBJ_TRAPL || ot == OBJ_TRAPR)
826 				Obj_Trap(objectactive[i]);
827 		}
828 	}
829 	deltaload = FALSE;
830 }
831 
NetSendCmd(BOOL bHiPri,BYTE bCmd)832 void NetSendCmd(BOOL bHiPri, BYTE bCmd)
833 {
834 	TCmd cmd;
835 
836 	cmd.bCmd = bCmd;
837 	if (bHiPri)
838 		NetSendHiPri((BYTE *)&cmd, sizeof(cmd));
839 	else
840 		NetSendLoPri((BYTE *)&cmd, sizeof(cmd));
841 }
842 
NetSendCmdGolem(BYTE mx,BYTE my,BYTE dir,BYTE menemy,int hp,BYTE cl)843 void NetSendCmdGolem(BYTE mx, BYTE my, BYTE dir, BYTE menemy, int hp, BYTE cl)
844 {
845 	TCmdGolem cmd;
846 
847 	cmd.bCmd = CMD_AWAKEGOLEM;
848 	cmd._mx = mx;
849 	cmd._my = my;
850 	cmd._mdir = dir;
851 	cmd._menemy = menemy;
852 	cmd._mhitpoints = hp;
853 	cmd._currlevel = cl;
854 	NetSendLoPri((BYTE *)&cmd, sizeof(cmd));
855 }
856 
NetSendCmdLoc(BOOL bHiPri,BYTE bCmd,BYTE x,BYTE y)857 void NetSendCmdLoc(BOOL bHiPri, BYTE bCmd, BYTE x, BYTE y)
858 {
859 	ALIGN_BY_1 TCmdLoc cmd;
860 
861 	cmd.bCmd = bCmd;
862 	cmd.x = x;
863 	cmd.y = y;
864 	if (bHiPri)
865 		NetSendHiPri((BYTE *)&cmd, sizeof(cmd));
866 	else
867 		NetSendLoPri((BYTE *)&cmd, sizeof(cmd));
868 }
869 
NetSendCmdLocParam1(BOOL bHiPri,BYTE bCmd,BYTE x,BYTE y,WORD wParam1)870 void NetSendCmdLocParam1(BOOL bHiPri, BYTE bCmd, BYTE x, BYTE y, WORD wParam1)
871 {
872 	TCmdLocParam1 cmd;
873 
874 	cmd.bCmd = bCmd;
875 	cmd.x = x;
876 	cmd.y = y;
877 	cmd.wParam1 = wParam1;
878 	if (bHiPri)
879 		NetSendHiPri((BYTE *)&cmd, sizeof(cmd));
880 	else
881 		NetSendLoPri((BYTE *)&cmd, sizeof(cmd));
882 }
883 
NetSendCmdLocParam2(BOOL bHiPri,BYTE bCmd,BYTE x,BYTE y,WORD wParam1,WORD wParam2)884 void NetSendCmdLocParam2(BOOL bHiPri, BYTE bCmd, BYTE x, BYTE y, WORD wParam1, WORD wParam2)
885 {
886 	TCmdLocParam2 cmd;
887 
888 	cmd.bCmd = bCmd;
889 	cmd.x = x;
890 	cmd.y = y;
891 	cmd.wParam1 = wParam1;
892 	cmd.wParam2 = wParam2;
893 	if (bHiPri)
894 		NetSendHiPri((BYTE *)&cmd, sizeof(cmd));
895 	else
896 		NetSendLoPri((BYTE *)&cmd, sizeof(cmd));
897 }
898 
NetSendCmdLocParam3(BOOL bHiPri,BYTE bCmd,BYTE x,BYTE y,WORD wParam1,WORD wParam2,WORD wParam3)899 void NetSendCmdLocParam3(BOOL bHiPri, BYTE bCmd, BYTE x, BYTE y, WORD wParam1, WORD wParam2, WORD wParam3)
900 {
901 	TCmdLocParam3 cmd;
902 
903 	cmd.bCmd = bCmd;
904 	cmd.x = x;
905 	cmd.y = y;
906 	cmd.wParam1 = wParam1;
907 	cmd.wParam2 = wParam2;
908 	cmd.wParam3 = wParam3;
909 	if (bHiPri)
910 		NetSendHiPri((BYTE *)&cmd, sizeof(cmd));
911 	else
912 		NetSendLoPri((BYTE *)&cmd, sizeof(cmd));
913 }
914 
NetSendCmdParam1(BOOL bHiPri,BYTE bCmd,WORD wParam1)915 void NetSendCmdParam1(BOOL bHiPri, BYTE bCmd, WORD wParam1)
916 {
917 	ALIGN_BY_1 TCmdParam1 cmd;
918 
919 	cmd.bCmd = bCmd;
920 	cmd.wParam1 = wParam1;
921 	if (bHiPri)
922 		NetSendHiPri((BYTE *)&cmd, sizeof(cmd));
923 	else
924 		NetSendLoPri((BYTE *)&cmd, sizeof(cmd));
925 }
926 
NetSendCmdParam2(BOOL bHiPri,BYTE bCmd,WORD wParam1,WORD wParam2)927 void NetSendCmdParam2(BOOL bHiPri, BYTE bCmd, WORD wParam1, WORD wParam2)
928 {
929 	TCmdParam2 cmd;
930 
931 	cmd.bCmd = bCmd;
932 	cmd.wParam1 = wParam1;
933 	cmd.wParam2 = wParam2;
934 	if (bHiPri)
935 		NetSendHiPri((BYTE *)&cmd, sizeof(cmd));
936 	else
937 		NetSendLoPri((BYTE *)&cmd, sizeof(cmd));
938 }
939 
NetSendCmdParam3(BOOL bHiPri,BYTE bCmd,WORD wParam1,WORD wParam2,WORD wParam3)940 void NetSendCmdParam3(BOOL bHiPri, BYTE bCmd, WORD wParam1, WORD wParam2, WORD wParam3)
941 {
942 	TCmdParam3 cmd;
943 
944 	cmd.bCmd = bCmd;
945 	cmd.wParam1 = wParam1;
946 	cmd.wParam2 = wParam2;
947 	cmd.wParam3 = wParam3;
948 	if (bHiPri)
949 		NetSendHiPri((BYTE *)&cmd, sizeof(cmd));
950 	else
951 		NetSendLoPri((BYTE *)&cmd, sizeof(cmd));
952 }
953 
NetSendCmdQuest(BOOL bHiPri,BYTE q)954 void NetSendCmdQuest(BOOL bHiPri, BYTE q)
955 {
956 	TCmdQuest cmd;
957 
958 	cmd.q = q;
959 	cmd.bCmd = CMD_SYNCQUEST;
960 	cmd.qstate = quests[q]._qactive;
961 	cmd.qlog = quests[q]._qlog;
962 	cmd.qvar1 = quests[q]._qvar1;
963 	if (bHiPri)
964 		NetSendHiPri((BYTE *)&cmd, sizeof(cmd));
965 	else
966 		NetSendLoPri((BYTE *)&cmd, sizeof(cmd));
967 }
968 
NetSendCmdGItem(BOOL bHiPri,BYTE bCmd,BYTE mast,BYTE pnum,BYTE ii)969 void NetSendCmdGItem(BOOL bHiPri, BYTE bCmd, BYTE mast, BYTE pnum, BYTE ii)
970 {
971 	TCmdGItem cmd;
972 
973 	cmd.bCmd = bCmd;
974 	cmd.bPnum = pnum;
975 	cmd.bMaster = mast;
976 	cmd.bLevel = currlevel;
977 	cmd.bCursitem = ii;
978 	cmd.dwTime = 0;
979 	cmd.x = item[ii]._ix;
980 	cmd.y = item[ii]._iy;
981 	cmd.wIndx = item[ii].IDidx;
982 
983 	if (item[ii].IDidx == IDI_EAR) {
984 		cmd.wCI = item[ii]._iName[8] | (item[ii]._iName[7] << 8);
985 		cmd.dwSeed = item[ii]._iName[12] | ((item[ii]._iName[11] | ((item[ii]._iName[10] | (item[ii]._iName[9] << 8)) << 8)) << 8);
986 		cmd.bId = item[ii]._iName[13];
987 		cmd.bDur = item[ii]._iName[14];
988 		cmd.bMDur = item[ii]._iName[15];
989 		cmd.bCh = item[ii]._iName[16];
990 		cmd.bMCh = item[ii]._iName[17];
991 		cmd.wValue = item[ii]._ivalue | (item[ii]._iName[18] << 8) | ((item[ii]._iCurs - ICURS_EAR_SORCERER) << 6);
992 		cmd.dwBuff = item[ii]._iName[22] | ((item[ii]._iName[21] | ((item[ii]._iName[20] | (item[ii]._iName[19] << 8)) << 8)) << 8);
993 	} else {
994 		cmd.wCI = item[ii]._iCreateInfo;
995 		cmd.dwSeed = item[ii]._iSeed;
996 		cmd.bId = item[ii]._iIdentified;
997 		cmd.bDur = item[ii]._iDurability;
998 		cmd.bMDur = item[ii]._iMaxDur;
999 		cmd.bCh = item[ii]._iCharges;
1000 		cmd.bMCh = item[ii]._iMaxCharges;
1001 		cmd.wValue = item[ii]._ivalue;
1002 		cmd.wToHit = item[ii]._iPLToHit;
1003 		cmd.wMaxDam = item[ii]._iMaxDam;
1004 		cmd.bMinStr = item[ii]._iMinStr;
1005 		cmd.bMinMag = item[ii]._iMinMag;
1006 		cmd.bMinDex = item[ii]._iMinDex;
1007 		cmd.bAC = item[ii]._iAC;
1008 		cmd.dwBuff = item[ii].dwBuff;
1009 	}
1010 
1011 	if (bHiPri)
1012 		NetSendHiPri((BYTE *)&cmd, sizeof(cmd));
1013 	else
1014 		NetSendLoPri((BYTE *)&cmd, sizeof(cmd));
1015 }
1016 
NetSendCmdGItem2(BOOL usonly,BYTE bCmd,BYTE mast,BYTE pnum,TCmdGItem * p)1017 void NetSendCmdGItem2(BOOL usonly, BYTE bCmd, BYTE mast, BYTE pnum, TCmdGItem *p)
1018 {
1019 	TCmdGItem cmd;
1020 
1021 	memcpy(&cmd, p, sizeof(cmd));
1022 	cmd.bPnum = pnum;
1023 	cmd.bCmd = bCmd;
1024 	cmd.bMaster = mast;
1025 
1026 	if (!usonly) {
1027 		cmd.dwTime = 0;
1028 		NetSendHiPri((BYTE *)&cmd, sizeof(cmd));
1029 		return;
1030 	}
1031 
1032 	int ticks = SDL_GetTicks();
1033 	if (cmd.dwTime == 0) {
1034 		cmd.dwTime = ticks;
1035 	} else if (ticks - cmd.dwTime > 5000) {
1036 		return;
1037 	}
1038 
1039 	multi_msg_add((BYTE *)&cmd.bCmd, sizeof(cmd));
1040 }
1041 
NetSendCmdReq2(BYTE bCmd,BYTE mast,BYTE pnum,TCmdGItem * p)1042 BOOL NetSendCmdReq2(BYTE bCmd, BYTE mast, BYTE pnum, TCmdGItem *p)
1043 {
1044 	TCmdGItem cmd;
1045 
1046 	memcpy(&cmd, p, sizeof(cmd));
1047 	cmd.bCmd = bCmd;
1048 	cmd.bPnum = pnum;
1049 	cmd.bMaster = mast;
1050 
1051 	int ticks = SDL_GetTicks();
1052 	if (cmd.dwTime == 0)
1053 		cmd.dwTime = ticks;
1054 	else if (ticks - cmd.dwTime > 5000)
1055 		return FALSE;
1056 
1057 	multi_msg_add((BYTE *)&cmd.bCmd, sizeof(cmd));
1058 
1059 	return TRUE;
1060 }
1061 
NetSendCmdExtra(TCmdGItem * p)1062 void NetSendCmdExtra(TCmdGItem *p)
1063 {
1064 	TCmdGItem cmd;
1065 
1066 	memcpy(&cmd, p, sizeof(cmd));
1067 	cmd.dwTime = 0;
1068 	cmd.bCmd = CMD_ITEMEXTRA;
1069 	NetSendHiPri((BYTE *)&cmd, sizeof(cmd));
1070 }
1071 
NetSendCmdPItem(BOOL bHiPri,BYTE bCmd,BYTE x,BYTE y)1072 void NetSendCmdPItem(BOOL bHiPri, BYTE bCmd, BYTE x, BYTE y)
1073 {
1074 	TCmdPItem cmd;
1075 
1076 	cmd.bCmd = bCmd;
1077 	cmd.x = x;
1078 	cmd.y = y;
1079 	cmd.wIndx = plr[myplr].HoldItem.IDidx;
1080 
1081 	if (plr[myplr].HoldItem.IDidx == IDI_EAR) {
1082 		cmd.wCI = plr[myplr].HoldItem._iName[8] | (plr[myplr].HoldItem._iName[7] << 8);
1083 		cmd.dwSeed = plr[myplr].HoldItem._iName[12] | ((plr[myplr].HoldItem._iName[11] | ((plr[myplr].HoldItem._iName[10] | (plr[myplr].HoldItem._iName[9] << 8)) << 8)) << 8);
1084 		cmd.bId = plr[myplr].HoldItem._iName[13];
1085 		cmd.bDur = plr[myplr].HoldItem._iName[14];
1086 		cmd.bMDur = plr[myplr].HoldItem._iName[15];
1087 		cmd.bCh = plr[myplr].HoldItem._iName[16];
1088 		cmd.bMCh = plr[myplr].HoldItem._iName[17];
1089 		cmd.wValue = plr[myplr].HoldItem._ivalue | (plr[myplr].HoldItem._iName[18] << 8) | ((plr[myplr].HoldItem._iCurs - ICURS_EAR_SORCERER) << 6);
1090 		cmd.dwBuff = plr[myplr].HoldItem._iName[22] | ((plr[myplr].HoldItem._iName[21] | ((plr[myplr].HoldItem._iName[20] | (plr[myplr].HoldItem._iName[19] << 8)) << 8)) << 8);
1091 	} else {
1092 		cmd.wCI = plr[myplr].HoldItem._iCreateInfo;
1093 		cmd.dwSeed = plr[myplr].HoldItem._iSeed;
1094 		cmd.bId = plr[myplr].HoldItem._iIdentified;
1095 		cmd.bDur = plr[myplr].HoldItem._iDurability;
1096 		cmd.bMDur = plr[myplr].HoldItem._iMaxDur;
1097 		cmd.bCh = plr[myplr].HoldItem._iCharges;
1098 		cmd.bMCh = plr[myplr].HoldItem._iMaxCharges;
1099 		cmd.wValue = plr[myplr].HoldItem._ivalue;
1100 		cmd.wToHit = plr[myplr].HoldItem._iPLToHit;
1101 		cmd.wMaxDam = plr[myplr].HoldItem._iMaxDam;
1102 		cmd.bMinStr = plr[myplr].HoldItem._iMinStr;
1103 		cmd.bMinMag = plr[myplr].HoldItem._iMinMag;
1104 		cmd.bMinDex = plr[myplr].HoldItem._iMinDex;
1105 		cmd.bAC = plr[myplr].HoldItem._iAC;
1106 		cmd.dwBuff = plr[myplr].HoldItem.dwBuff;
1107 	}
1108 
1109 	if (bHiPri)
1110 		NetSendHiPri((BYTE *)&cmd, sizeof(cmd));
1111 	else
1112 		NetSendLoPri((BYTE *)&cmd, sizeof(cmd));
1113 }
1114 
NetSendCmdChItem(BOOL bHiPri,BYTE bLoc)1115 void NetSendCmdChItem(BOOL bHiPri, BYTE bLoc)
1116 {
1117 	TCmdChItem cmd;
1118 
1119 	cmd.bCmd = CMD_CHANGEPLRITEMS;
1120 	cmd.bLoc = bLoc;
1121 	cmd.wIndx = plr[myplr].HoldItem.IDidx;
1122 	cmd.wCI = plr[myplr].HoldItem._iCreateInfo;
1123 	cmd.dwSeed = plr[myplr].HoldItem._iSeed;
1124 	cmd.bId = plr[myplr].HoldItem._iIdentified;
1125 	cmd.dwBuff = plr[myplr].HoldItem.dwBuff;
1126 
1127 	if (bHiPri)
1128 		NetSendHiPri((BYTE *)&cmd, sizeof(cmd));
1129 	else
1130 		NetSendLoPri((BYTE *)&cmd, sizeof(cmd));
1131 }
1132 
NetSendCmdDelItem(BOOL bHiPri,BYTE bLoc)1133 void NetSendCmdDelItem(BOOL bHiPri, BYTE bLoc)
1134 {
1135 	TCmdDelItem cmd;
1136 
1137 	cmd.bLoc = bLoc;
1138 	cmd.bCmd = CMD_DELPLRITEMS;
1139 	if (bHiPri)
1140 		NetSendHiPri((BYTE *)&cmd, sizeof(cmd));
1141 	else
1142 		NetSendLoPri((BYTE *)&cmd, sizeof(cmd));
1143 }
1144 
NetSendCmdDItem(BOOL bHiPri,int ii)1145 void NetSendCmdDItem(BOOL bHiPri, int ii)
1146 {
1147 	TCmdPItem cmd;
1148 
1149 	cmd.bCmd = CMD_DROPITEM;
1150 	cmd.x = item[ii]._ix;
1151 	cmd.y = item[ii]._iy;
1152 	cmd.wIndx = item[ii].IDidx;
1153 
1154 	if (item[ii].IDidx == IDI_EAR) {
1155 		cmd.wCI = item[ii]._iName[8] | (item[ii]._iName[7] << 8);
1156 		cmd.dwSeed = item[ii]._iName[12] | ((item[ii]._iName[11] | ((item[ii]._iName[10] | (item[ii]._iName[9] << 8)) << 8)) << 8);
1157 		cmd.bId = item[ii]._iName[13];
1158 		cmd.bDur = item[ii]._iName[14];
1159 		cmd.bMDur = item[ii]._iName[15];
1160 		cmd.bCh = item[ii]._iName[16];
1161 		cmd.bMCh = item[ii]._iName[17];
1162 		cmd.wValue = item[ii]._ivalue | (item[ii]._iName[18] << 8) | ((item[ii]._iCurs - ICURS_EAR_SORCERER) << 6);
1163 		cmd.dwBuff = item[ii]._iName[22] | ((item[ii]._iName[21] | ((item[ii]._iName[20] | (item[ii]._iName[19] << 8)) << 8)) << 8);
1164 	} else {
1165 		cmd.wCI = item[ii]._iCreateInfo;
1166 		cmd.dwSeed = item[ii]._iSeed;
1167 		cmd.bId = item[ii]._iIdentified;
1168 		cmd.bDur = item[ii]._iDurability;
1169 		cmd.bMDur = item[ii]._iMaxDur;
1170 		cmd.bCh = item[ii]._iCharges;
1171 		cmd.bMCh = item[ii]._iMaxCharges;
1172 		cmd.wValue = item[ii]._ivalue;
1173 		cmd.wToHit = item[ii]._iPLToHit;
1174 		cmd.wMaxDam = item[ii]._iMaxDam;
1175 		cmd.bMinStr = item[ii]._iMinStr;
1176 		cmd.bMinMag = item[ii]._iMinMag;
1177 		cmd.bMinDex = item[ii]._iMinDex;
1178 		cmd.bAC = item[ii]._iAC;
1179 		cmd.dwBuff = item[ii].dwBuff;
1180 	}
1181 
1182 	if (bHiPri)
1183 		NetSendHiPri((BYTE *)&cmd, sizeof(cmd));
1184 	else
1185 		NetSendLoPri((BYTE *)&cmd, sizeof(cmd));
1186 }
1187 
i_own_level(int nReqLevel)1188 static BOOL i_own_level(int nReqLevel)
1189 {
1190 	int i;
1191 
1192 	for (i = 0; i < MAX_PLRS; i++) {
1193 		if (!plr[i].plractive)
1194 			continue;
1195 		if (plr[i]._pLvlChanging)
1196 			continue;
1197 		if (plr[i].plrlevel != nReqLevel)
1198 			continue;
1199 		if (i == myplr && gbBufferMsgs != 0)
1200 			continue;
1201 		break;
1202 	}
1203 	return i == myplr;
1204 }
1205 
NetSendCmdDamage(BOOL bHiPri,BYTE bPlr,DWORD dwDam)1206 void NetSendCmdDamage(BOOL bHiPri, BYTE bPlr, DWORD dwDam)
1207 {
1208 	TCmdDamage cmd;
1209 
1210 	cmd.bCmd = CMD_PLRDAMAGE;
1211 	cmd.bPlr = bPlr;
1212 	cmd.dwDam = dwDam;
1213 	if (bHiPri)
1214 		NetSendHiPri((BYTE *)&cmd, sizeof(cmd));
1215 	else
1216 		NetSendLoPri((BYTE *)&cmd, sizeof(cmd));
1217 }
1218 
NetSendCmdMonDmg(BOOL bHiPri,WORD wMon,DWORD dwDam)1219 void NetSendCmdMonDmg(BOOL bHiPri, WORD wMon, DWORD dwDam)
1220 {
1221 	TCmdMonDamage cmd;
1222 
1223 	cmd.bCmd = CMD_MONSTDAMAGE;
1224 	cmd.wMon = wMon;
1225 	cmd.dwDam = dwDam;
1226 	if (bHiPri)
1227 		NetSendHiPri((BYTE *)&cmd, sizeof(cmd));
1228 	else
1229 		NetSendLoPri((BYTE *)&cmd, sizeof(cmd));
1230 }
1231 
NetSendCmdString(int pmask,const char * pszStr)1232 void NetSendCmdString(int pmask, const char *pszStr)
1233 {
1234 	int dwStrLen;
1235 	TCmdString cmd;
1236 
1237 	dwStrLen = strlen(pszStr);
1238 	cmd.bCmd = CMD_STRING;
1239 	strcpy(cmd.str, pszStr);
1240 	multi_send_msg_packet(pmask, (BYTE *)&cmd.bCmd, dwStrLen + 2);
1241 }
1242 
On_STRING2(int pnum,TCmd * pCmd)1243 static DWORD On_STRING2(int pnum, TCmd *pCmd)
1244 {
1245 	TCmdString *p = (TCmdString *)pCmd;
1246 
1247 	int len = strlen(p->str);
1248 	if (!gbBufferMsgs)
1249 		SendPlrMsg(pnum, p->str);
1250 
1251 	return len + 2; // length of string + nul terminator + sizeof(p->bCmd)
1252 }
1253 
delta_open_portal(int pnum,BYTE x,BYTE y,BYTE bLevel,dungeon_type bLType,BYTE bSetLvl)1254 static void delta_open_portal(int pnum, BYTE x, BYTE y, BYTE bLevel, dungeon_type bLType, BYTE bSetLvl)
1255 {
1256 	sgbDeltaChanged = TRUE;
1257 	sgJunk.portal[pnum].x = x;
1258 	sgJunk.portal[pnum].y = y;
1259 	sgJunk.portal[pnum].level = bLevel;
1260 	sgJunk.portal[pnum].ltype = bLType;
1261 	sgJunk.portal[pnum].setlvl = bSetLvl;
1262 }
1263 
delta_close_portal(int pnum)1264 void delta_close_portal(int pnum)
1265 {
1266 	memset(&sgJunk.portal[pnum], 0xFF, sizeof(sgJunk.portal[pnum]));
1267 	sgbDeltaChanged = TRUE;
1268 }
1269 
check_update_plr(int pnum)1270 static void check_update_plr(int pnum)
1271 {
1272 	if (gbIsMultiplayer && pnum == myplr)
1273 		pfile_update(true);
1274 }
1275 
msg_errorf(const char * pszFmt,...)1276 static void msg_errorf(const char *pszFmt, ...)
1277 {
1278 	static DWORD msg_err_timer;
1279 	DWORD ticks;
1280 	char msg[256];
1281 	va_list va;
1282 
1283 	va_start(va, pszFmt);
1284 	ticks = SDL_GetTicks();
1285 	if (ticks - msg_err_timer >= 5000) {
1286 		msg_err_timer = ticks;
1287 		vsprintf(msg, pszFmt, va);
1288 		ErrorPlrMsg(msg);
1289 	}
1290 	va_end(va);
1291 }
1292 
On_SYNCDATA(TCmd * pCmd,int pnum)1293 static DWORD On_SYNCDATA(TCmd *pCmd, int pnum)
1294 {
1295 	return sync_update(pnum, (const BYTE *)pCmd);
1296 }
1297 
On_WALKXY(TCmd * pCmd,int pnum)1298 static DWORD On_WALKXY(TCmd *pCmd, int pnum)
1299 {
1300 	TCmdLoc *p = (TCmdLoc *)pCmd;
1301 
1302 	if (gbBufferMsgs != 1 && currlevel == plr[pnum].plrlevel) {
1303 		ClrPlrPath(pnum);
1304 		MakePlrPath(pnum, p->x, p->y, TRUE);
1305 		plr[pnum].destAction = ACTION_NONE;
1306 	}
1307 
1308 	return sizeof(*p);
1309 }
1310 
On_ADDSTR(TCmd * pCmd,int pnum)1311 static DWORD On_ADDSTR(TCmd *pCmd, int pnum)
1312 {
1313 	TCmdParam1 *p = (TCmdParam1 *)pCmd;
1314 
1315 	if (gbBufferMsgs == 1)
1316 		msg_send_packet(pnum, p, sizeof(*p));
1317 	else if (p->wParam1 <= 256)
1318 		ModifyPlrStr(pnum, p->wParam1);
1319 
1320 	return sizeof(*p);
1321 }
1322 
On_ADDMAG(TCmd * pCmd,int pnum)1323 static DWORD On_ADDMAG(TCmd *pCmd, int pnum)
1324 {
1325 	TCmdParam1 *p = (TCmdParam1 *)pCmd;
1326 
1327 	if (gbBufferMsgs == 1)
1328 		msg_send_packet(pnum, p, sizeof(*p));
1329 	else if (p->wParam1 <= 256)
1330 		ModifyPlrMag(pnum, p->wParam1);
1331 
1332 	return sizeof(*p);
1333 }
1334 
On_ADDDEX(TCmd * pCmd,int pnum)1335 static DWORD On_ADDDEX(TCmd *pCmd, int pnum)
1336 {
1337 	TCmdParam1 *p = (TCmdParam1 *)pCmd;
1338 
1339 	if (gbBufferMsgs == 1)
1340 		msg_send_packet(pnum, p, sizeof(*p));
1341 	else if (p->wParam1 <= 256)
1342 		ModifyPlrDex(pnum, p->wParam1);
1343 
1344 	return sizeof(*p);
1345 }
1346 
On_ADDVIT(TCmd * pCmd,int pnum)1347 static DWORD On_ADDVIT(TCmd *pCmd, int pnum)
1348 {
1349 	TCmdParam1 *p = (TCmdParam1 *)pCmd;
1350 
1351 	if (gbBufferMsgs == 1)
1352 		msg_send_packet(pnum, p, sizeof(*p));
1353 	else if (p->wParam1 <= 256)
1354 		ModifyPlrVit(pnum, p->wParam1);
1355 
1356 	return sizeof(*p);
1357 }
1358 
On_SBSPELL(TCmd * pCmd,int pnum)1359 static DWORD On_SBSPELL(TCmd *pCmd, int pnum)
1360 {
1361 	TCmdParam1 *p = (TCmdParam1 *)pCmd;
1362 
1363 	if (gbBufferMsgs != 1) {
1364 		spell_id spell = (spell_id)p->wParam1;
1365 		if (currlevel != 0 || spelldata[spell].sTownSpell) {
1366 			plr[pnum]._pSpell = spell;
1367 			plr[pnum]._pSplType = plr[pnum]._pSBkSplType;
1368 			plr[pnum]._pSplFrom = 1;
1369 			plr[pnum].destAction = ACTION_SPELL;
1370 		} else
1371 			msg_errorf("%s has cast an illegal spell.", plr[pnum]._pName);
1372 	}
1373 
1374 	return sizeof(*p);
1375 }
1376 
On_GOTOGETITEM(TCmd * pCmd,int pnum)1377 static DWORD On_GOTOGETITEM(TCmd *pCmd, int pnum)
1378 {
1379 	TCmdLocParam1 *p = (TCmdLocParam1 *)pCmd;
1380 
1381 	if (gbBufferMsgs != 1 && currlevel == plr[pnum].plrlevel) {
1382 		MakePlrPath(pnum, p->x, p->y, FALSE);
1383 		plr[pnum].destAction = ACTION_PICKUPITEM;
1384 		plr[pnum].destParam1 = p->wParam1;
1385 	}
1386 
1387 	return sizeof(*p);
1388 }
1389 
On_REQUESTGITEM(TCmd * pCmd,int pnum)1390 static DWORD On_REQUESTGITEM(TCmd *pCmd, int pnum)
1391 {
1392 	TCmdGItem *p = (TCmdGItem *)pCmd;
1393 
1394 	if (gbBufferMsgs != 1 && i_own_level(plr[pnum].plrlevel)) {
1395 		if (GetItemRecord(p->dwSeed, p->wCI, p->wIndx)) {
1396 			int ii = FindGetItem(p->wIndx, p->wCI, p->dwSeed);
1397 			if (ii != -1) {
1398 				NetSendCmdGItem2(FALSE, CMD_GETITEM, myplr, p->bPnum, p);
1399 				if (p->bPnum != myplr)
1400 					SyncGetItem(p->x, p->y, p->wIndx, p->wCI, p->dwSeed);
1401 				else
1402 					InvGetItem(myplr, ii);
1403 				SetItemRecord(p->dwSeed, p->wCI, p->wIndx);
1404 			} else if (!NetSendCmdReq2(CMD_REQUESTGITEM, myplr, p->bPnum, p))
1405 				NetSendCmdExtra(p);
1406 		}
1407 	}
1408 
1409 	return sizeof(*p);
1410 }
1411 
On_GETITEM(TCmd * pCmd,int pnum)1412 static DWORD On_GETITEM(TCmd *pCmd, int pnum)
1413 {
1414 	TCmdGItem *p = (TCmdGItem *)pCmd;
1415 
1416 	if (gbBufferMsgs == 1)
1417 		msg_send_packet(pnum, p, sizeof(*p));
1418 	else {
1419 		int ii = FindGetItem(p->wIndx, p->wCI, p->dwSeed);
1420 		if (delta_get_item(p, p->bLevel)) {
1421 			if ((currlevel == p->bLevel || p->bPnum == myplr) && p->bMaster != myplr) {
1422 				if (p->bPnum == myplr) {
1423 					if (currlevel != p->bLevel) {
1424 						ii = SyncPutItem(myplr, plr[myplr]._px, plr[myplr]._py, p->wIndx, p->wCI, p->dwSeed, p->bId, p->bDur, p->bMDur, p->bCh, p->bMCh, p->wValue, p->dwBuff, p->wToHit, p->wMaxDam, p->bMinStr, p->bMinMag, p->bMinDex, p->bAC);
1425 						if (ii != -1)
1426 							InvGetItem(myplr, ii);
1427 					} else
1428 						InvGetItem(myplr, ii);
1429 				} else
1430 					SyncGetItem(p->x, p->y, p->wIndx, p->wCI, p->dwSeed);
1431 			}
1432 		} else
1433 			NetSendCmdGItem2(TRUE, CMD_GETITEM, p->bMaster, p->bPnum, p);
1434 	}
1435 
1436 	return sizeof(*p);
1437 }
1438 
On_GOTOAGETITEM(TCmd * pCmd,int pnum)1439 static DWORD On_GOTOAGETITEM(TCmd *pCmd, int pnum)
1440 {
1441 	TCmdLocParam1 *p = (TCmdLocParam1 *)pCmd;
1442 
1443 	if (gbBufferMsgs != 1 && currlevel == plr[pnum].plrlevel) {
1444 		MakePlrPath(pnum, p->x, p->y, FALSE);
1445 		plr[pnum].destAction = ACTION_PICKUPAITEM;
1446 		plr[pnum].destParam1 = p->wParam1;
1447 	}
1448 
1449 	return sizeof(*p);
1450 }
1451 
On_REQUESTAGITEM(TCmd * pCmd,int pnum)1452 static DWORD On_REQUESTAGITEM(TCmd *pCmd, int pnum)
1453 {
1454 	TCmdGItem *p = (TCmdGItem *)pCmd;
1455 
1456 	if (gbBufferMsgs != 1 && i_own_level(plr[pnum].plrlevel)) {
1457 		if (GetItemRecord(p->dwSeed, p->wCI, p->wIndx)) {
1458 			int ii = FindGetItem(p->wIndx, p->wCI, p->dwSeed);
1459 			if (ii != -1) {
1460 				NetSendCmdGItem2(FALSE, CMD_AGETITEM, myplr, p->bPnum, p);
1461 				if (p->bPnum != myplr)
1462 					SyncGetItem(p->x, p->y, p->wIndx, p->wCI, p->dwSeed);
1463 				else
1464 					AutoGetItem(myplr, p->bCursitem);
1465 				SetItemRecord(p->dwSeed, p->wCI, p->wIndx);
1466 			} else if (!NetSendCmdReq2(CMD_REQUESTAGITEM, myplr, p->bPnum, p))
1467 				NetSendCmdExtra(p);
1468 		}
1469 	}
1470 
1471 	return sizeof(*p);
1472 }
1473 
On_AGETITEM(TCmd * pCmd,int pnum)1474 static DWORD On_AGETITEM(TCmd *pCmd, int pnum)
1475 {
1476 	TCmdGItem *p = (TCmdGItem *)pCmd;
1477 
1478 	if (gbBufferMsgs == 1)
1479 		msg_send_packet(pnum, p, sizeof(*p));
1480 	else {
1481 		FindGetItem(p->wIndx, p->wCI, p->dwSeed);
1482 		if (delta_get_item(p, p->bLevel)) {
1483 			if ((currlevel == p->bLevel || p->bPnum == myplr) && p->bMaster != myplr) {
1484 				if (p->bPnum == myplr) {
1485 					if (currlevel != p->bLevel) {
1486 						int ii = SyncPutItem(myplr, plr[myplr]._px, plr[myplr]._py, p->wIndx, p->wCI, p->dwSeed, p->bId, p->bDur, p->bMDur, p->bCh, p->bMCh, p->wValue, p->dwBuff, p->wToHit, p->wMaxDam, p->bMinStr, p->bMinMag, p->bMinDex, p->bAC);
1487 						if (ii != -1)
1488 							AutoGetItem(myplr, ii);
1489 					} else
1490 						AutoGetItem(myplr, p->bCursitem);
1491 				} else
1492 					SyncGetItem(p->x, p->y, p->wIndx, p->wCI, p->dwSeed);
1493 			}
1494 		} else
1495 			NetSendCmdGItem2(TRUE, CMD_AGETITEM, p->bMaster, p->bPnum, p);
1496 	}
1497 
1498 	return sizeof(*p);
1499 }
1500 
On_ITEMEXTRA(TCmd * pCmd,int pnum)1501 static DWORD On_ITEMEXTRA(TCmd *pCmd, int pnum)
1502 {
1503 	TCmdGItem *p = (TCmdGItem *)pCmd;
1504 
1505 	if (gbBufferMsgs == 1)
1506 		msg_send_packet(pnum, p, sizeof(*p));
1507 	else {
1508 		delta_get_item(p, p->bLevel);
1509 		if (currlevel == plr[pnum].plrlevel)
1510 			SyncGetItem(p->x, p->y, p->wIndx, p->wCI, p->dwSeed);
1511 	}
1512 
1513 	return sizeof(*p);
1514 }
1515 
On_PUTITEM(TCmd * pCmd,int pnum)1516 static DWORD On_PUTITEM(TCmd *pCmd, int pnum)
1517 {
1518 	TCmdPItem *p = (TCmdPItem *)pCmd;
1519 
1520 	if (gbBufferMsgs == 1)
1521 		msg_send_packet(pnum, p, sizeof(*p));
1522 	else if (currlevel == plr[pnum].plrlevel) {
1523 		int ii;
1524 		if (pnum == myplr)
1525 			ii = InvPutItem(pnum, p->x, p->y);
1526 		else
1527 			ii = SyncPutItem(pnum, p->x, p->y, p->wIndx, p->wCI, p->dwSeed, p->bId, p->bDur, p->bMDur, p->bCh, p->bMCh, p->wValue, p->dwBuff, p->wToHit, p->wMaxDam, p->bMinStr, p->bMinMag, p->bMinDex, p->bAC);
1528 		if (ii != -1) {
1529 			PutItemRecord(p->dwSeed, p->wCI, p->wIndx);
1530 			delta_put_item(p, item[ii]._ix, item[ii]._iy, plr[pnum].plrlevel);
1531 			check_update_plr(pnum);
1532 		}
1533 		return sizeof(*p);
1534 	} else {
1535 		PutItemRecord(p->dwSeed, p->wCI, p->wIndx);
1536 		delta_put_item(p, p->x, p->y, plr[pnum].plrlevel);
1537 		check_update_plr(pnum);
1538 	}
1539 
1540 	return sizeof(*p);
1541 }
1542 
On_SYNCPUTITEM(TCmd * pCmd,int pnum)1543 static DWORD On_SYNCPUTITEM(TCmd *pCmd, int pnum)
1544 {
1545 	TCmdPItem *p = (TCmdPItem *)pCmd;
1546 
1547 	if (gbBufferMsgs == 1)
1548 		msg_send_packet(pnum, p, sizeof(*p));
1549 	else if (currlevel == plr[pnum].plrlevel) {
1550 		int ii = SyncPutItem(pnum, p->x, p->y, p->wIndx, p->wCI, p->dwSeed, p->bId, p->bDur, p->bMDur, p->bCh, p->bMCh, p->wValue, p->dwBuff, p->wToHit, p->wMaxDam, p->bMinStr, p->bMinMag, p->bMinDex, p->bAC);
1551 		if (ii != -1) {
1552 			PutItemRecord(p->dwSeed, p->wCI, p->wIndx);
1553 			delta_put_item(p, item[ii]._ix, item[ii]._iy, plr[pnum].plrlevel);
1554 			check_update_plr(pnum);
1555 		}
1556 		return sizeof(*p);
1557 	} else {
1558 		PutItemRecord(p->dwSeed, p->wCI, p->wIndx);
1559 		delta_put_item(p, p->x, p->y, plr[pnum].plrlevel);
1560 		check_update_plr(pnum);
1561 	}
1562 
1563 	return sizeof(*p);
1564 }
1565 
On_RESPAWNITEM(TCmd * pCmd,int pnum)1566 static DWORD On_RESPAWNITEM(TCmd *pCmd, int pnum)
1567 {
1568 	TCmdPItem *p = (TCmdPItem *)pCmd;
1569 
1570 	if (gbBufferMsgs == 1)
1571 		msg_send_packet(pnum, p, sizeof(*p));
1572 	else {
1573 		if (currlevel == plr[pnum].plrlevel && pnum != myplr) {
1574 			SyncPutItem(pnum, p->x, p->y, p->wIndx, p->wCI, p->dwSeed, p->bId, p->bDur, p->bMDur, p->bCh, p->bMCh, p->wValue, p->dwBuff, p->wToHit, p->wMaxDam, p->bMinStr, p->bMinMag, p->bMinDex, p->bAC);
1575 		}
1576 		PutItemRecord(p->dwSeed, p->wCI, p->wIndx);
1577 		delta_put_item(p, p->x, p->y, plr[pnum].plrlevel);
1578 	}
1579 
1580 	return sizeof(*p);
1581 }
1582 
On_ATTACKXY(TCmd * pCmd,int pnum)1583 static DWORD On_ATTACKXY(TCmd *pCmd, int pnum)
1584 {
1585 	TCmdLoc *p = (TCmdLoc *)pCmd;
1586 
1587 	if (gbBufferMsgs != 1 && currlevel == plr[pnum].plrlevel) {
1588 		MakePlrPath(pnum, p->x, p->y, FALSE);
1589 		plr[pnum].destAction = ACTION_ATTACK;
1590 		plr[pnum].destParam1 = p->x;
1591 		plr[pnum].destParam2 = p->y;
1592 	}
1593 
1594 	return sizeof(*p);
1595 }
1596 
On_SATTACKXY(TCmd * pCmd,int pnum)1597 static DWORD On_SATTACKXY(TCmd *pCmd, int pnum)
1598 {
1599 	TCmdLoc *p = (TCmdLoc *)pCmd;
1600 
1601 	if (gbBufferMsgs != 1 && currlevel == plr[pnum].plrlevel) {
1602 		ClrPlrPath(pnum);
1603 		plr[pnum].destAction = ACTION_ATTACK;
1604 		plr[pnum].destParam1 = p->x;
1605 		plr[pnum].destParam2 = p->y;
1606 	}
1607 
1608 	return sizeof(*p);
1609 }
1610 
On_RATTACKXY(TCmd * pCmd,int pnum)1611 static DWORD On_RATTACKXY(TCmd *pCmd, int pnum)
1612 {
1613 	TCmdLoc *p = (TCmdLoc *)pCmd;
1614 
1615 	if (gbBufferMsgs != 1 && currlevel == plr[pnum].plrlevel) {
1616 		ClrPlrPath(pnum);
1617 		plr[pnum].destAction = ACTION_RATTACK;
1618 		plr[pnum].destParam1 = p->x;
1619 		plr[pnum].destParam2 = p->y;
1620 	}
1621 
1622 	return sizeof(*p);
1623 }
1624 
On_SPELLXYD(TCmd * pCmd,int pnum)1625 static DWORD On_SPELLXYD(TCmd *pCmd, int pnum)
1626 {
1627 	TCmdLocParam3 *p = (TCmdLocParam3 *)pCmd;
1628 
1629 	if (gbBufferMsgs != 1 && currlevel == plr[pnum].plrlevel) {
1630 		spell_id spell = (spell_id)p->wParam1;
1631 		if (currlevel != 0 || spelldata[spell].sTownSpell) {
1632 			ClrPlrPath(pnum);
1633 			plr[pnum].destAction = ACTION_SPELLWALL;
1634 			plr[pnum].destParam1 = p->x;
1635 			plr[pnum].destParam2 = p->y;
1636 			plr[pnum].destParam3 = (direction)p->wParam2;
1637 			plr[pnum].destParam4 = p->wParam3;
1638 			plr[pnum]._pSpell = spell;
1639 			plr[pnum]._pSplType = plr[pnum]._pRSplType;
1640 			plr[pnum]._pSplFrom = 0;
1641 		} else
1642 			msg_errorf("%s has cast an illegal spell.", plr[pnum]._pName);
1643 	}
1644 
1645 	return sizeof(*p);
1646 }
1647 
On_SPELLXY(TCmd * pCmd,int pnum)1648 static DWORD On_SPELLXY(TCmd *pCmd, int pnum)
1649 {
1650 	TCmdLocParam2 *p = (TCmdLocParam2 *)pCmd;
1651 
1652 	if (gbBufferMsgs != 1 && currlevel == plr[pnum].plrlevel) {
1653 		spell_id spell = (spell_id)p->wParam1;
1654 		if (currlevel != 0 || spelldata[spell].sTownSpell) {
1655 			ClrPlrPath(pnum);
1656 			plr[pnum].destAction = ACTION_SPELL;
1657 			plr[pnum].destParam1 = p->x;
1658 			plr[pnum].destParam2 = p->y;
1659 			plr[pnum].destParam3 = (direction)p->wParam2;
1660 			plr[pnum]._pSpell = spell;
1661 			plr[pnum]._pSplType = plr[pnum]._pRSplType;
1662 			plr[pnum]._pSplFrom = 0;
1663 		} else
1664 			msg_errorf("%s has cast an illegal spell.", plr[pnum]._pName);
1665 	}
1666 
1667 	return sizeof(*p);
1668 }
1669 
On_TSPELLXY(TCmd * pCmd,int pnum)1670 static DWORD On_TSPELLXY(TCmd *pCmd, int pnum)
1671 {
1672 	TCmdLocParam2 *p = (TCmdLocParam2 *)pCmd;
1673 
1674 	if (gbBufferMsgs != 1 && currlevel == plr[pnum].plrlevel) {
1675 		spell_id spell = (spell_id)p->wParam1;
1676 		if (currlevel != 0 || spelldata[spell].sTownSpell) {
1677 			ClrPlrPath(pnum);
1678 			plr[pnum].destAction = ACTION_SPELL;
1679 			plr[pnum].destParam1 = p->x;
1680 			plr[pnum].destParam2 = p->y;
1681 			plr[pnum].destParam3 = (direction)p->wParam2;
1682 			plr[pnum]._pSpell = spell;
1683 			plr[pnum]._pSplType = plr[pnum]._pTSplType;
1684 			plr[pnum]._pSplFrom = 2;
1685 		} else
1686 			msg_errorf("%s has cast an illegal spell.", plr[pnum]._pName);
1687 	}
1688 
1689 	return sizeof(*p);
1690 }
1691 
On_OPOBJXY(TCmd * pCmd,int pnum)1692 static DWORD On_OPOBJXY(TCmd *pCmd, int pnum)
1693 {
1694 	TCmdLocParam1 *p = (TCmdLocParam1 *)pCmd;
1695 
1696 	if (gbBufferMsgs != 1 && currlevel == plr[pnum].plrlevel) {
1697 		if (object[p->wParam1]._oSolidFlag || object[p->wParam1]._oDoorFlag)
1698 			MakePlrPath(pnum, p->x, p->y, FALSE);
1699 		else
1700 			MakePlrPath(pnum, p->x, p->y, TRUE);
1701 		plr[pnum].destAction = ACTION_OPERATE;
1702 		plr[pnum].destParam1 = p->wParam1;
1703 	}
1704 
1705 	return sizeof(*p);
1706 }
1707 
On_DISARMXY(TCmd * pCmd,int pnum)1708 static DWORD On_DISARMXY(TCmd *pCmd, int pnum)
1709 {
1710 	TCmdLocParam1 *p = (TCmdLocParam1 *)pCmd;
1711 
1712 	if (gbBufferMsgs != 1 && currlevel == plr[pnum].plrlevel) {
1713 		if (object[p->wParam1]._oSolidFlag || object[p->wParam1]._oDoorFlag)
1714 			MakePlrPath(pnum, p->x, p->y, FALSE);
1715 		else
1716 			MakePlrPath(pnum, p->x, p->y, TRUE);
1717 		plr[pnum].destAction = ACTION_DISARM;
1718 		plr[pnum].destParam1 = p->wParam1;
1719 	}
1720 
1721 	return sizeof(*p);
1722 }
1723 
On_OPOBJT(TCmd * pCmd,int pnum)1724 static DWORD On_OPOBJT(TCmd *pCmd, int pnum)
1725 {
1726 	TCmdParam1 *p = (TCmdParam1 *)pCmd;
1727 
1728 	if (gbBufferMsgs != 1 && currlevel == plr[pnum].plrlevel) {
1729 		plr[pnum].destAction = ACTION_OPERATETK;
1730 		plr[pnum].destParam1 = p->wParam1;
1731 	}
1732 
1733 	return sizeof(*p);
1734 }
1735 
On_ATTACKID(TCmd * pCmd,int pnum)1736 static DWORD On_ATTACKID(TCmd *pCmd, int pnum)
1737 {
1738 	TCmdParam1 *p = (TCmdParam1 *)pCmd;
1739 
1740 	if (gbBufferMsgs != 1 && currlevel == plr[pnum].plrlevel) {
1741 		int distx = abs(plr[pnum]._px - monster[p->wParam1]._mfutx);
1742 		int disty = abs(plr[pnum]._py - monster[p->wParam1]._mfuty);
1743 		if (distx > 1 || disty > 1)
1744 			MakePlrPath(pnum, monster[p->wParam1]._mfutx, monster[p->wParam1]._mfuty, FALSE);
1745 		plr[pnum].destAction = ACTION_ATTACKMON;
1746 		plr[pnum].destParam1 = p->wParam1;
1747 	}
1748 
1749 	return sizeof(*p);
1750 }
1751 
On_ATTACKPID(TCmd * pCmd,int pnum)1752 static DWORD On_ATTACKPID(TCmd *pCmd, int pnum)
1753 {
1754 	TCmdParam1 *p = (TCmdParam1 *)pCmd;
1755 
1756 	if (gbBufferMsgs != 1 && currlevel == plr[pnum].plrlevel) {
1757 		MakePlrPath(pnum, plr[p->wParam1]._pfutx, plr[p->wParam1]._pfuty, FALSE);
1758 		plr[pnum].destAction = ACTION_ATTACKPLR;
1759 		plr[pnum].destParam1 = p->wParam1;
1760 	}
1761 
1762 	return sizeof(*p);
1763 }
1764 
On_RATTACKID(TCmd * pCmd,int pnum)1765 static DWORD On_RATTACKID(TCmd *pCmd, int pnum)
1766 {
1767 	TCmdParam1 *p = (TCmdParam1 *)pCmd;
1768 
1769 	if (gbBufferMsgs != 1 && currlevel == plr[pnum].plrlevel) {
1770 		ClrPlrPath(pnum);
1771 		plr[pnum].destAction = ACTION_RATTACKMON;
1772 		plr[pnum].destParam1 = p->wParam1;
1773 	}
1774 
1775 	return sizeof(*p);
1776 }
1777 
On_RATTACKPID(TCmd * pCmd,int pnum)1778 static DWORD On_RATTACKPID(TCmd *pCmd, int pnum)
1779 {
1780 	TCmdParam1 *p = (TCmdParam1 *)pCmd;
1781 
1782 	if (gbBufferMsgs != 1 && currlevel == plr[pnum].plrlevel) {
1783 		ClrPlrPath(pnum);
1784 		plr[pnum].destAction = ACTION_RATTACKPLR;
1785 		plr[pnum].destParam1 = p->wParam1;
1786 	}
1787 
1788 	return sizeof(*p);
1789 }
1790 
On_SPELLID(TCmd * pCmd,int pnum)1791 static DWORD On_SPELLID(TCmd *pCmd, int pnum)
1792 {
1793 	TCmdParam3 *p = (TCmdParam3 *)pCmd;
1794 
1795 	if (gbBufferMsgs != 1 && currlevel == plr[pnum].plrlevel) {
1796 		spell_id spell = (spell_id)p->wParam2;
1797 		if (currlevel != 0 || spelldata[spell].sTownSpell) {
1798 			ClrPlrPath(pnum);
1799 			plr[pnum].destAction = ACTION_SPELLMON;
1800 			plr[pnum].destParam1 = p->wParam1;
1801 			plr[pnum].destParam2 = p->wParam3;
1802 			plr[pnum]._pSpell = spell;
1803 			plr[pnum]._pSplType = plr[pnum]._pRSplType;
1804 			plr[pnum]._pSplFrom = 0;
1805 		} else
1806 			msg_errorf("%s has cast an illegal spell.", plr[pnum]._pName);
1807 	}
1808 
1809 	return sizeof(*p);
1810 }
1811 
On_SPELLPID(TCmd * pCmd,int pnum)1812 static DWORD On_SPELLPID(TCmd *pCmd, int pnum)
1813 {
1814 	TCmdParam3 *p = (TCmdParam3 *)pCmd;
1815 
1816 	if (gbBufferMsgs != 1 && currlevel == plr[pnum].plrlevel) {
1817 		spell_id spell = (spell_id)p->wParam2;
1818 		if (currlevel != 0 || spelldata[spell].sTownSpell) {
1819 			ClrPlrPath(pnum);
1820 			plr[pnum].destAction = ACTION_SPELLPLR;
1821 			plr[pnum].destParam1 = p->wParam1;
1822 			plr[pnum].destParam2 = p->wParam3;
1823 			plr[pnum]._pSpell = spell;
1824 			plr[pnum]._pSplType = plr[pnum]._pRSplType;
1825 			plr[pnum]._pSplFrom = 0;
1826 		} else
1827 			msg_errorf("%s has cast an illegal spell.", plr[pnum]._pName);
1828 	}
1829 
1830 	return sizeof(*p);
1831 }
1832 
On_TSPELLID(TCmd * pCmd,int pnum)1833 static DWORD On_TSPELLID(TCmd *pCmd, int pnum)
1834 {
1835 	TCmdParam3 *p = (TCmdParam3 *)pCmd;
1836 
1837 	if (gbBufferMsgs != 1 && currlevel == plr[pnum].plrlevel) {
1838 		spell_id spell = (spell_id)p->wParam2;
1839 		if (currlevel != 0 || spelldata[spell].sTownSpell) {
1840 			ClrPlrPath(pnum);
1841 			plr[pnum].destAction = ACTION_SPELLMON;
1842 			plr[pnum].destParam1 = p->wParam1;
1843 			plr[pnum].destParam2 = p->wParam3;
1844 			plr[pnum]._pSpell = spell;
1845 			plr[pnum]._pSplType = plr[pnum]._pTSplType;
1846 			plr[pnum]._pSplFrom = 2;
1847 		} else
1848 			msg_errorf("%s has cast an illegal spell.", plr[pnum]._pName);
1849 	}
1850 
1851 	return sizeof(*p);
1852 }
1853 
On_TSPELLPID(TCmd * pCmd,int pnum)1854 static DWORD On_TSPELLPID(TCmd *pCmd, int pnum)
1855 {
1856 	TCmdParam3 *p = (TCmdParam3 *)pCmd;
1857 
1858 	if (gbBufferMsgs != 1 && currlevel == plr[pnum].plrlevel) {
1859 		spell_id spell = (spell_id)p->wParam2;
1860 		if (currlevel != 0 || spelldata[spell].sTownSpell) {
1861 			ClrPlrPath(pnum);
1862 			plr[pnum].destAction = ACTION_SPELLPLR;
1863 			plr[pnum].destParam1 = p->wParam1;
1864 			plr[pnum].destParam2 = p->wParam3;
1865 			plr[pnum]._pSpell = spell;
1866 			plr[pnum]._pSplType = plr[pnum]._pTSplType;
1867 			plr[pnum]._pSplFrom = 2;
1868 		} else
1869 			msg_errorf("%s has cast an illegal spell.", plr[pnum]._pName);
1870 	}
1871 
1872 	return sizeof(*p);
1873 }
1874 
On_KNOCKBACK(TCmd * pCmd,int pnum)1875 static DWORD On_KNOCKBACK(TCmd *pCmd, int pnum)
1876 {
1877 	TCmdParam1 *p = (TCmdParam1 *)pCmd;
1878 
1879 	if (gbBufferMsgs != 1 && currlevel == plr[pnum].plrlevel) {
1880 		M_GetKnockback(p->wParam1);
1881 		M_StartHit(p->wParam1, pnum, 0);
1882 	}
1883 
1884 	return sizeof(*p);
1885 }
1886 
On_RESURRECT(TCmd * pCmd,int pnum)1887 static DWORD On_RESURRECT(TCmd *pCmd, int pnum)
1888 {
1889 	TCmdParam1 *p = (TCmdParam1 *)pCmd;
1890 
1891 	if (gbBufferMsgs == 1)
1892 		msg_send_packet(pnum, p, sizeof(*p));
1893 	else {
1894 		DoResurrect(pnum, p->wParam1);
1895 		check_update_plr(pnum);
1896 	}
1897 
1898 	return sizeof(*p);
1899 }
1900 
On_HEALOTHER(TCmd * pCmd,int pnum)1901 static DWORD On_HEALOTHER(TCmd *pCmd, int pnum)
1902 {
1903 	TCmdParam1 *p = (TCmdParam1 *)pCmd;
1904 
1905 	if (gbBufferMsgs != 1 && currlevel == plr[pnum].plrlevel)
1906 		DoHealOther(pnum, p->wParam1);
1907 
1908 	return sizeof(*p);
1909 }
1910 
On_TALKXY(TCmd * pCmd,int pnum)1911 static DWORD On_TALKXY(TCmd *pCmd, int pnum)
1912 {
1913 	TCmdLocParam1 *p = (TCmdLocParam1 *)pCmd;
1914 
1915 	if (gbBufferMsgs != 1 && currlevel == plr[pnum].plrlevel) {
1916 		MakePlrPath(pnum, p->x, p->y, FALSE);
1917 		plr[pnum].destAction = ACTION_TALK;
1918 		plr[pnum].destParam1 = p->wParam1;
1919 	}
1920 
1921 	return sizeof(*p);
1922 }
1923 
On_NEWLVL(TCmd * pCmd,int pnum)1924 static DWORD On_NEWLVL(TCmd *pCmd, int pnum)
1925 {
1926 	TCmdParam2 *p = (TCmdParam2 *)pCmd;
1927 
1928 	if (gbBufferMsgs == 1)
1929 		msg_send_packet(pnum, p, sizeof(*p));
1930 	else if (pnum != myplr)
1931 		StartNewLvl(pnum, p->wParam1, p->wParam2);
1932 
1933 	return sizeof(*p);
1934 }
1935 
On_WARP(TCmd * pCmd,int pnum)1936 static DWORD On_WARP(TCmd *pCmd, int pnum)
1937 {
1938 	TCmdParam1 *p = (TCmdParam1 *)pCmd;
1939 
1940 	if (gbBufferMsgs == 1)
1941 		msg_send_packet(pnum, p, sizeof(*p));
1942 	else {
1943 		StartWarpLvl(pnum, p->wParam1);
1944 	}
1945 
1946 	return sizeof(*p);
1947 }
1948 
On_MONSTDEATH(TCmd * pCmd,int pnum)1949 static DWORD On_MONSTDEATH(TCmd *pCmd, int pnum)
1950 {
1951 	TCmdLocParam1 *p = (TCmdLocParam1 *)pCmd;
1952 
1953 	if (gbBufferMsgs == 1)
1954 		msg_send_packet(pnum, p, sizeof(*p));
1955 	else if (pnum != myplr) {
1956 		if (currlevel == plr[pnum].plrlevel)
1957 			M_SyncStartKill(p->wParam1, p->x, p->y, pnum);
1958 		delta_kill_monster(p->wParam1, p->x, p->y, plr[pnum].plrlevel);
1959 	}
1960 
1961 	return sizeof(*p);
1962 }
1963 
On_KILLGOLEM(TCmd * pCmd,int pnum)1964 static DWORD On_KILLGOLEM(TCmd *pCmd, int pnum)
1965 {
1966 	TCmdLocParam1 *p = (TCmdLocParam1 *)pCmd;
1967 
1968 	if (gbBufferMsgs == 1)
1969 		msg_send_packet(pnum, p, sizeof(*p));
1970 	else if (pnum != myplr) {
1971 		if (currlevel == p->wParam1)
1972 			M_SyncStartKill(pnum, p->x, p->y, pnum);
1973 		delta_kill_monster(pnum, p->x, p->y, plr[pnum].plrlevel);
1974 	}
1975 
1976 	return sizeof(*p);
1977 }
1978 
On_AWAKEGOLEM(TCmd * pCmd,int pnum)1979 static DWORD On_AWAKEGOLEM(TCmd *pCmd, int pnum)
1980 {
1981 	TCmdGolem *p = (TCmdGolem *)pCmd;
1982 
1983 	if (gbBufferMsgs == 1)
1984 		msg_send_packet(pnum, p, sizeof(*p));
1985 	else if (currlevel != plr[pnum].plrlevel)
1986 		delta_sync_golem(p, pnum, p->_currlevel);
1987 	else if (pnum != myplr) {
1988 		int i;
1989 		// check if this player already has an active golem
1990 		BOOL addGolem = TRUE;
1991 		for (i = 0; i < nummissiles; i++) {
1992 			int mi = missileactive[i];
1993 			if (missile[mi]._mitype == MIS_GOLEM && missile[mi]._misource == pnum) {
1994 				addGolem = FALSE;
1995 				// BUGFIX: break, don't need to check the rest
1996 			}
1997 		}
1998 		if (addGolem)
1999 			AddMissile(plr[pnum]._px, plr[pnum]._py, p->_mx, p->_my, p->_mdir, MIS_GOLEM, TARGET_MONSTERS, pnum, 0, 1);
2000 	}
2001 
2002 	return sizeof(*p);
2003 }
2004 
On_MONSTDAMAGE(TCmd * pCmd,int pnum)2005 static DWORD On_MONSTDAMAGE(TCmd *pCmd, int pnum)
2006 {
2007 	TCmdMonDamage *p = (TCmdMonDamage *)pCmd;
2008 
2009 	if (gbBufferMsgs == 1)
2010 		msg_send_packet(pnum, p, sizeof(*p)); // BUGFIX: change to sizeof(*p) or it still uses TCmdParam2 size for hellfire (fixed)
2011 	else if (pnum != myplr) {
2012 		if (currlevel == plr[pnum].plrlevel) {
2013 			monster[p->wMon].mWhoHit |= 1 << pnum;
2014 			if (monster[p->wMon]._mhitpoints > 0) {
2015 				monster[p->wMon]._mhitpoints -= p->dwDam;
2016 				if ((monster[p->wMon]._mhitpoints >> 6) < 1)
2017 					monster[p->wMon]._mhitpoints = 1 << 6;
2018 				delta_monster_hp(p->wMon, monster[p->wMon]._mhitpoints, plr[pnum].plrlevel);
2019 			}
2020 		}
2021 	}
2022 
2023 	return sizeof(*p);
2024 }
2025 
On_PLRDEAD(TCmd * pCmd,int pnum)2026 static DWORD On_PLRDEAD(TCmd *pCmd, int pnum)
2027 {
2028 	TCmdParam1 *p = (TCmdParam1 *)pCmd;
2029 
2030 	if (gbBufferMsgs == 1)
2031 		msg_send_packet(pnum, p, sizeof(*p));
2032 	else if (pnum != myplr)
2033 		StartPlayerKill(pnum, p->wParam1);
2034 	else
2035 		check_update_plr(pnum);
2036 
2037 	return sizeof(*p);
2038 }
2039 
On_PLRDAMAGE(TCmd * pCmd,int pnum)2040 static DWORD On_PLRDAMAGE(TCmd *pCmd, int pnum)
2041 {
2042 	TCmdDamage *p = (TCmdDamage *)pCmd;
2043 
2044 	if (p->bPlr == myplr && currlevel != 0 && gbBufferMsgs != 1) {
2045 		if (currlevel == plr[pnum].plrlevel && p->dwDam <= 192000 && plr[myplr]._pHitPoints >> 6 > 0) {
2046 			drawhpflag = TRUE;
2047 			plr[myplr]._pHitPoints -= p->dwDam;
2048 			plr[myplr]._pHPBase -= p->dwDam;
2049 			if (plr[myplr]._pHitPoints > plr[myplr]._pMaxHP) {
2050 				plr[myplr]._pHitPoints = plr[myplr]._pMaxHP;
2051 				plr[myplr]._pHPBase = plr[myplr]._pMaxHPBase;
2052 			}
2053 			if (plr[myplr]._pHitPoints >> 6 <= 0) {
2054 				SyncPlrKill(myplr, 1);
2055 			}
2056 		}
2057 	}
2058 
2059 	return sizeof(*p);
2060 }
2061 
On_OPENDOOR(TCmd * pCmd,int pnum)2062 static DWORD On_OPENDOOR(TCmd *pCmd, int pnum)
2063 {
2064 	TCmdParam1 *p = (TCmdParam1 *)pCmd;
2065 
2066 	if (gbBufferMsgs == 1)
2067 		msg_send_packet(pnum, p, sizeof(*p));
2068 	else {
2069 		if (currlevel == plr[pnum].plrlevel)
2070 			SyncOpObject(pnum, CMD_OPENDOOR, p->wParam1);
2071 		delta_sync_object(p->wParam1, CMD_OPENDOOR, plr[pnum].plrlevel);
2072 	}
2073 
2074 	return sizeof(*p);
2075 }
2076 
On_CLOSEDOOR(TCmd * pCmd,int pnum)2077 static DWORD On_CLOSEDOOR(TCmd *pCmd, int pnum)
2078 {
2079 	TCmdParam1 *p = (TCmdParam1 *)pCmd;
2080 
2081 	if (gbBufferMsgs == 1)
2082 		msg_send_packet(pnum, p, sizeof(*p));
2083 	else {
2084 		if (currlevel == plr[pnum].plrlevel)
2085 			SyncOpObject(pnum, CMD_CLOSEDOOR, p->wParam1);
2086 		delta_sync_object(p->wParam1, CMD_CLOSEDOOR, plr[pnum].plrlevel);
2087 	}
2088 
2089 	return sizeof(*p);
2090 }
2091 
On_OPERATEOBJ(TCmd * pCmd,int pnum)2092 static DWORD On_OPERATEOBJ(TCmd *pCmd, int pnum)
2093 {
2094 	TCmdParam1 *p = (TCmdParam1 *)pCmd;
2095 
2096 	if (gbBufferMsgs == 1)
2097 		msg_send_packet(pnum, p, sizeof(*p));
2098 	else {
2099 		if (currlevel == plr[pnum].plrlevel)
2100 			SyncOpObject(pnum, CMD_OPERATEOBJ, p->wParam1);
2101 		delta_sync_object(p->wParam1, CMD_OPERATEOBJ, plr[pnum].plrlevel);
2102 	}
2103 
2104 	return sizeof(*p);
2105 }
2106 
On_PLROPOBJ(TCmd * pCmd,int pnum)2107 static DWORD On_PLROPOBJ(TCmd *pCmd, int pnum)
2108 {
2109 	TCmdParam2 *p = (TCmdParam2 *)pCmd;
2110 
2111 	if (gbBufferMsgs == 1)
2112 		msg_send_packet(pnum, p, sizeof(*p));
2113 	else {
2114 		if (currlevel == plr[pnum].plrlevel)
2115 			SyncOpObject(p->wParam1, CMD_PLROPOBJ, p->wParam2);
2116 		delta_sync_object(p->wParam2, CMD_PLROPOBJ, plr[pnum].plrlevel);
2117 	}
2118 
2119 	return sizeof(*p);
2120 }
2121 
On_BREAKOBJ(TCmd * pCmd,int pnum)2122 static DWORD On_BREAKOBJ(TCmd *pCmd, int pnum)
2123 {
2124 	TCmdParam2 *p = (TCmdParam2 *)pCmd;
2125 
2126 	if (gbBufferMsgs == 1)
2127 		msg_send_packet(pnum, p, sizeof(*p));
2128 	else {
2129 		if (currlevel == plr[pnum].plrlevel)
2130 			SyncBreakObj(p->wParam1, p->wParam2);
2131 		delta_sync_object(p->wParam2, CMD_BREAKOBJ, plr[pnum].plrlevel);
2132 	}
2133 
2134 	return sizeof(*p);
2135 }
2136 
On_CHANGEPLRITEMS(TCmd * pCmd,int pnum)2137 static DWORD On_CHANGEPLRITEMS(TCmd *pCmd, int pnum)
2138 {
2139 	TCmdChItem *p = (TCmdChItem *)pCmd;
2140 
2141 	if (gbBufferMsgs == 1)
2142 		msg_send_packet(pnum, p, sizeof(*p));
2143 	else if (pnum != myplr)
2144 		CheckInvSwap(pnum, p->bLoc, p->wIndx, p->wCI, p->dwSeed, p->bId, p->dwBuff);
2145 
2146 	return sizeof(*p);
2147 }
2148 
On_DELPLRITEMS(TCmd * pCmd,int pnum)2149 static DWORD On_DELPLRITEMS(TCmd *pCmd, int pnum)
2150 {
2151 	TCmdDelItem *p = (TCmdDelItem *)pCmd;
2152 
2153 	if (gbBufferMsgs == 1)
2154 		msg_send_packet(pnum, p, sizeof(*p));
2155 	else if (pnum != myplr)
2156 		inv_update_rem_item(pnum, p->bLoc);
2157 
2158 	return sizeof(*p);
2159 }
2160 
On_PLRLEVEL(TCmd * pCmd,int pnum)2161 static DWORD On_PLRLEVEL(TCmd *pCmd, int pnum)
2162 {
2163 	TCmdParam1 *p = (TCmdParam1 *)pCmd;
2164 
2165 	if (gbBufferMsgs == 1)
2166 		msg_send_packet(pnum, p, sizeof(*p));
2167 	else if (p->wParam1 <= MAXCHARLEVEL && pnum != myplr)
2168 		plr[pnum]._pLevel = p->wParam1;
2169 
2170 	return sizeof(*p);
2171 }
2172 
On_DROPITEM(TCmd * pCmd,int pnum)2173 static DWORD On_DROPITEM(TCmd *pCmd, int pnum)
2174 {
2175 	TCmdPItem *p = (TCmdPItem *)pCmd;
2176 
2177 	if (gbBufferMsgs == 1)
2178 		msg_send_packet(pnum, p, sizeof(*p));
2179 	else
2180 		delta_put_item(p, p->x, p->y, plr[pnum].plrlevel);
2181 
2182 	return sizeof(*p);
2183 }
2184 
On_SEND_PLRINFO(TCmd * pCmd,int pnum)2185 static DWORD On_SEND_PLRINFO(TCmd *pCmd, int pnum)
2186 {
2187 	TCmdPlrInfoHdr *p = (TCmdPlrInfoHdr *)pCmd;
2188 
2189 	if (gbBufferMsgs == 1)
2190 		msg_send_packet(pnum, p, p->wBytes + sizeof(*p));
2191 	else
2192 		recv_plrinfo(pnum, p, p->bCmd == CMD_ACK_PLRINFO);
2193 
2194 	return p->wBytes + sizeof(*p);
2195 }
2196 
On_ACK_PLRINFO(TCmd * pCmd,int pnum)2197 static DWORD On_ACK_PLRINFO(TCmd *pCmd, int pnum)
2198 {
2199 	return On_SEND_PLRINFO(pCmd, pnum);
2200 }
2201 
On_PLAYER_JOINLEVEL(TCmd * pCmd,int pnum)2202 static DWORD On_PLAYER_JOINLEVEL(TCmd *pCmd, int pnum)
2203 {
2204 	TCmdLocParam1 *p = (TCmdLocParam1 *)pCmd;
2205 
2206 	if (gbBufferMsgs == 1)
2207 		msg_send_packet(pnum, p, sizeof(*p));
2208 	else {
2209 		plr[pnum]._pLvlChanging = FALSE;
2210 		if (plr[pnum]._pName[0] != 0 && !plr[pnum].plractive) {
2211 			plr[pnum].plractive = TRUE;
2212 			gbActivePlayers++;
2213 			EventPlrMsg("Player '%s' (level %d) just joined the game", plr[pnum]._pName, plr[pnum]._pLevel);
2214 		}
2215 
2216 		if (plr[pnum].plractive && myplr != pnum) {
2217 			plr[pnum]._px = p->x;
2218 			plr[pnum]._py = p->y;
2219 			plr[pnum].plrlevel = p->wParam1;
2220 			plr[pnum]._pGFXLoad = 0;
2221 			if (currlevel == plr[pnum].plrlevel) {
2222 				LoadPlrGFX(pnum, PFILE_STAND);
2223 				SyncInitPlr(pnum);
2224 				if ((plr[pnum]._pHitPoints >> 6) > 0)
2225 					StartStand(pnum, DIR_S);
2226 				else {
2227 					plr[pnum]._pgfxnum = 0;
2228 					LoadPlrGFX(pnum, PFILE_DEATH);
2229 					plr[pnum]._pmode = PM_DEATH;
2230 					NewPlrAnim(pnum, plr[pnum]._pDAnim[DIR_S], plr[pnum]._pDFrames, 1, plr[pnum]._pDWidth);
2231 					plr[pnum]._pAnimFrame = plr[pnum]._pAnimLen - 1;
2232 					plr[pnum]._pVar8 = plr[pnum]._pAnimLen << 1;
2233 					dFlags[plr[pnum]._px][plr[pnum]._py] |= BFLAG_DEAD_PLAYER;
2234 				}
2235 
2236 				plr[pnum]._pvid = AddVision(plr[pnum]._px, plr[pnum]._py, plr[pnum]._pLightRad, pnum == myplr);
2237 				plr[pnum]._plid = NO_LIGHT;
2238 			}
2239 		}
2240 	}
2241 
2242 	return sizeof(*p);
2243 }
2244 
On_ACTIVATEPORTAL(TCmd * pCmd,int pnum)2245 static DWORD On_ACTIVATEPORTAL(TCmd *pCmd, int pnum)
2246 {
2247 	TCmdLocParam3 *p = (TCmdLocParam3 *)pCmd;
2248 
2249 	if (gbBufferMsgs == 1)
2250 		msg_send_packet(pnum, p, sizeof(*p));
2251 	else {
2252 		ActivatePortal(pnum, p->x, p->y, p->wParam1, (dungeon_type)p->wParam2, p->wParam3);
2253 		if (pnum != myplr) {
2254 			if (currlevel == 0)
2255 				AddInTownPortal(pnum);
2256 			else if (currlevel == plr[pnum].plrlevel) {
2257 				BOOL addPortal = TRUE;
2258 				for (int i = 0; i < nummissiles; i++) {
2259 					int mi = missileactive[i];
2260 					if (missile[mi]._mitype == MIS_TOWN && missile[mi]._misource == pnum) {
2261 						addPortal = FALSE;
2262 						// CODEFIX: break
2263 					}
2264 				}
2265 				if (addPortal)
2266 					AddWarpMissile(pnum, p->x, p->y);
2267 			} else
2268 				RemovePortalMissile(pnum);
2269 		}
2270 		delta_open_portal(pnum, p->x, p->y, p->wParam1, (dungeon_type)p->wParam2, p->wParam3);
2271 	}
2272 
2273 	return sizeof(*p);
2274 }
2275 
On_DEACTIVATEPORTAL(TCmd * pCmd,int pnum)2276 static DWORD On_DEACTIVATEPORTAL(TCmd *pCmd, int pnum)
2277 {
2278 	if (gbBufferMsgs == 1)
2279 		msg_send_packet(pnum, pCmd, sizeof(*pCmd));
2280 	else {
2281 		if (PortalOnLevel(pnum))
2282 			RemovePortalMissile(pnum);
2283 		DeactivatePortal(pnum);
2284 		delta_close_portal(pnum);
2285 	}
2286 
2287 	return sizeof(*pCmd);
2288 }
2289 
On_RETOWN(TCmd * pCmd,int pnum)2290 static DWORD On_RETOWN(TCmd *pCmd, int pnum)
2291 {
2292 	if (gbBufferMsgs == 1)
2293 		msg_send_packet(pnum, pCmd, sizeof(*pCmd));
2294 	else {
2295 		if (pnum == myplr) {
2296 			deathflag = FALSE;
2297 			gamemenu_off();
2298 		}
2299 		RestartTownLvl(pnum);
2300 	}
2301 
2302 	return sizeof(*pCmd);
2303 }
2304 
On_SETSTR(TCmd * pCmd,int pnum)2305 static DWORD On_SETSTR(TCmd *pCmd, int pnum)
2306 {
2307 	TCmdParam1 *p = (TCmdParam1 *)pCmd;
2308 
2309 	if (gbBufferMsgs == 1)
2310 		msg_send_packet(pnum, p, sizeof(*p));
2311 	else if (p->wParam1 <= 750 && pnum != myplr)
2312 		SetPlrStr(pnum, p->wParam1);
2313 
2314 	return sizeof(*p);
2315 }
2316 
On_SETDEX(TCmd * pCmd,int pnum)2317 static DWORD On_SETDEX(TCmd *pCmd, int pnum)
2318 {
2319 	TCmdParam1 *p = (TCmdParam1 *)pCmd;
2320 
2321 	if (gbBufferMsgs == 1)
2322 		msg_send_packet(pnum, p, sizeof(*p));
2323 	else if (p->wParam1 <= 750 && pnum != myplr)
2324 		SetPlrDex(pnum, p->wParam1);
2325 
2326 	return sizeof(*p);
2327 }
2328 
On_SETMAG(TCmd * pCmd,int pnum)2329 static DWORD On_SETMAG(TCmd *pCmd, int pnum)
2330 {
2331 	TCmdParam1 *p = (TCmdParam1 *)pCmd;
2332 
2333 	if (gbBufferMsgs == 1)
2334 		msg_send_packet(pnum, p, sizeof(*p));
2335 	else if (p->wParam1 <= 750 && pnum != myplr)
2336 		SetPlrMag(pnum, p->wParam1);
2337 
2338 	return sizeof(*p);
2339 }
2340 
On_SETVIT(TCmd * pCmd,int pnum)2341 static DWORD On_SETVIT(TCmd *pCmd, int pnum)
2342 {
2343 	TCmdParam1 *p = (TCmdParam1 *)pCmd;
2344 
2345 	if (gbBufferMsgs == 1)
2346 		msg_send_packet(pnum, p, sizeof(*p));
2347 	else if (p->wParam1 <= 750 && pnum != myplr)
2348 		SetPlrVit(pnum, p->wParam1);
2349 
2350 	return sizeof(*p);
2351 }
2352 
On_STRING(TCmd * pCmd,int pnum)2353 static DWORD On_STRING(TCmd *pCmd, int pnum)
2354 {
2355 	return On_STRING2(pnum, pCmd);
2356 }
2357 
On_SYNCQUEST(TCmd * pCmd,int pnum)2358 static DWORD On_SYNCQUEST(TCmd *pCmd, int pnum)
2359 {
2360 	TCmdQuest *p = (TCmdQuest *)pCmd;
2361 
2362 	if (gbBufferMsgs == 1)
2363 		msg_send_packet(pnum, p, sizeof(*p));
2364 	else {
2365 		if (pnum != myplr)
2366 			SetMultiQuest(p->q, p->qstate, p->qlog, p->qvar1);
2367 		sgbDeltaChanged = TRUE;
2368 	}
2369 
2370 	return sizeof(*p);
2371 }
2372 
On_ENDREFLECT(TCmd * pCmd,int pnum)2373 static DWORD On_ENDREFLECT(TCmd *pCmd, int pnum)
2374 {
2375 	if (gbBufferMsgs != 1 && pnum != myplr && currlevel == plr[pnum].plrlevel) {
2376 		for (int i = 0; i < nummissiles; i++) {
2377 			int mi = missileactive[i];
2378 			if (missile[mi]._mitype == MIS_REFLECT && missile[mi]._misource == pnum) {
2379 				ClearMissileSpot(mi);
2380 				DeleteMissile(mi, i);
2381 			}
2382 		}
2383 	}
2384 
2385 	return sizeof(*pCmd);
2386 }
2387 
On_ENDSHIELD(TCmd * pCmd,int pnum)2388 static DWORD On_ENDSHIELD(TCmd *pCmd, int pnum)
2389 {
2390 	if (gbBufferMsgs != 1 && pnum != myplr && currlevel == plr[pnum].plrlevel) {
2391 		for (int i = 0; i < nummissiles; i++) {
2392 			int mi = missileactive[i];
2393 			if (missile[mi]._mitype == MIS_MANASHIELD && missile[mi]._misource == pnum) {
2394 				ClearMissileSpot(mi);
2395 				DeleteMissile(mi, i);
2396 			}
2397 		}
2398 	}
2399 
2400 	return sizeof(*pCmd);
2401 }
2402 
On_CHEAT_EXPERIENCE(TCmd * pCmd,int pnum)2403 static DWORD On_CHEAT_EXPERIENCE(TCmd *pCmd, int pnum)
2404 {
2405 #ifdef _DEBUG
2406 	if (gbBufferMsgs == 1)
2407 		msg_send_packet(pnum, pCmd, sizeof(*pCmd));
2408 	else if (plr[pnum]._pLevel < MAXCHARLEVEL - 1) {
2409 		plr[pnum]._pExperience = plr[pnum]._pNextExper;
2410 		if (sgOptions.Gameplay.bExperienceBar) {
2411 			force_redraw = 255;
2412 		}
2413 		NextPlrLevel(pnum);
2414 	}
2415 #endif
2416 	return sizeof(*pCmd);
2417 }
2418 
On_CHEAT_SPELL_LEVEL(TCmd * pCmd,int pnum)2419 static DWORD On_CHEAT_SPELL_LEVEL(TCmd *pCmd, int pnum)
2420 {
2421 #ifdef _DEBUG
2422 	if (gbBufferMsgs == 1)
2423 		msg_send_packet(pnum, pCmd, sizeof(*pCmd));
2424 	else
2425 		plr[pnum]._pSplLvl[plr[pnum]._pRSpell]++;
2426 #endif
2427 	return sizeof(*pCmd);
2428 }
2429 
On_DEBUG(TCmd * pCmd,int pnum)2430 static DWORD On_DEBUG(TCmd *pCmd, int pnum)
2431 {
2432 	return sizeof(*pCmd);
2433 }
2434 
On_NOVA(TCmd * pCmd,int pnum)2435 static DWORD On_NOVA(TCmd *pCmd, int pnum)
2436 {
2437 	TCmdLoc *p = (TCmdLoc *)pCmd;
2438 
2439 	if (gbBufferMsgs != 1 && currlevel == plr[pnum].plrlevel && pnum != myplr) {
2440 		ClrPlrPath(pnum);
2441 		plr[pnum]._pSpell = SPL_NOVA;
2442 		plr[pnum]._pSplType = RSPLTYPE_INVALID;
2443 		plr[pnum]._pSplFrom = 3;
2444 		plr[pnum].destAction = ACTION_SPELL;
2445 		plr[pnum].destParam1 = p->x;
2446 		plr[pnum].destParam2 = p->y;
2447 	}
2448 
2449 	return sizeof(*p);
2450 }
2451 
On_SETSHIELD(TCmd * pCmd,int pnum)2452 static DWORD On_SETSHIELD(TCmd *pCmd, int pnum)
2453 {
2454 	if (gbBufferMsgs != 1)
2455 		plr[pnum].pManaShield = TRUE;
2456 
2457 	return sizeof(*pCmd);
2458 }
2459 
On_REMSHIELD(TCmd * pCmd,int pnum)2460 static DWORD On_REMSHIELD(TCmd *pCmd, int pnum)
2461 {
2462 	if (gbBufferMsgs != 1)
2463 		plr[pnum].pManaShield = FALSE;
2464 
2465 	return sizeof(*pCmd);
2466 }
2467 
On_REFLECT(TCmd * pCmd,int pnum)2468 static DWORD On_REFLECT(TCmd *pCmd, int pnum)
2469 {
2470 	if (gbBufferMsgs != 1 && pnum != myplr && currlevel == plr[pnum].plrlevel) {
2471 		for (int i = 0; i < nummissiles; i++) {
2472 			int mx = missileactive[i];
2473 			if (missile[mx]._mitype == MIS_REFLECT && missile[mx]._misource == pnum) {
2474 				ClearMissileSpot(mx);
2475 				DeleteMissile(mx, i);
2476 			}
2477 		}
2478 	}
2479 
2480 	return sizeof(*pCmd);
2481 }
2482 
On_NAKRUL(TCmd * pCmd,int pnum)2483 static DWORD On_NAKRUL(TCmd *pCmd, int pnum)
2484 {
2485 	if (gbBufferMsgs != 1) {
2486 		operate_lv24_lever();
2487 		IsUberRoomOpened = 1;
2488 		quests[Q_NAKRUL]._qactive = 3;
2489 		monster_some_crypt();
2490 	}
2491 	return sizeof(*pCmd);
2492 }
2493 
On_OPENHIVE(TCmd * pCmd,int pnum)2494 static DWORD On_OPENHIVE(TCmd *pCmd, int pnum)
2495 {
2496 	TCmdLocParam2 *p = (TCmdLocParam2 *)pCmd;
2497 	if (gbBufferMsgs != 1) {
2498 		AddMissile(p->x, p->y, p->wParam1, p->wParam2, 0, MIS_HIVEEXP2, TARGET_MONSTERS, pnum, 0, 0);
2499 		TownOpenHive();
2500 	}
2501 	return sizeof(*p);
2502 }
2503 
On_OPENCRYPT(TCmd * pCmd,int pnum)2504 static DWORD On_OPENCRYPT(TCmd *pCmd, int pnum)
2505 {
2506 	if (gbBufferMsgs != 1) {
2507 		TownOpenGrave();
2508 		InitTownTriggers();
2509 		if (currlevel == 0)
2510 			PlaySFX(IS_SARC);
2511 	}
2512 	return sizeof(*pCmd);
2513 }
2514 
ParseCmd(int pnum,TCmd * pCmd)2515 DWORD ParseCmd(int pnum, TCmd *pCmd)
2516 {
2517 	sbLastCmd = pCmd->bCmd;
2518 	if (sgwPackPlrOffsetTbl[pnum] != 0 && sbLastCmd != CMD_ACK_PLRINFO && sbLastCmd != CMD_SEND_PLRINFO)
2519 		return 0;
2520 
2521 	switch (pCmd->bCmd) {
2522 	case CMD_SYNCDATA:
2523 		return On_SYNCDATA(pCmd, pnum);
2524 	case CMD_WALKXY:
2525 		return On_WALKXY(pCmd, pnum);
2526 	case CMD_ADDSTR:
2527 		return On_ADDSTR(pCmd, pnum);
2528 	case CMD_ADDDEX:
2529 		return On_ADDDEX(pCmd, pnum);
2530 	case CMD_ADDMAG:
2531 		return On_ADDMAG(pCmd, pnum);
2532 	case CMD_ADDVIT:
2533 		return On_ADDVIT(pCmd, pnum);
2534 	case CMD_SBSPELL:
2535 		return On_SBSPELL(pCmd, pnum);
2536 	case CMD_GOTOGETITEM:
2537 		return On_GOTOGETITEM(pCmd, pnum);
2538 	case CMD_REQUESTGITEM:
2539 		return On_REQUESTGITEM(pCmd, pnum);
2540 	case CMD_GETITEM:
2541 		return On_GETITEM(pCmd, pnum);
2542 	case CMD_GOTOAGETITEM:
2543 		return On_GOTOAGETITEM(pCmd, pnum);
2544 	case CMD_REQUESTAGITEM:
2545 		return On_REQUESTAGITEM(pCmd, pnum);
2546 	case CMD_AGETITEM:
2547 		return On_AGETITEM(pCmd, pnum);
2548 	case CMD_ITEMEXTRA:
2549 		return On_ITEMEXTRA(pCmd, pnum);
2550 	case CMD_PUTITEM:
2551 		return On_PUTITEM(pCmd, pnum);
2552 	case CMD_SYNCPUTITEM:
2553 		return On_SYNCPUTITEM(pCmd, pnum);
2554 	case CMD_RESPAWNITEM:
2555 		return On_RESPAWNITEM(pCmd, pnum);
2556 	case CMD_ATTACKXY:
2557 		return On_ATTACKXY(pCmd, pnum);
2558 	case CMD_SATTACKXY:
2559 		return On_SATTACKXY(pCmd, pnum);
2560 	case CMD_RATTACKXY:
2561 		return On_RATTACKXY(pCmd, pnum);
2562 	case CMD_SPELLXYD:
2563 		return On_SPELLXYD(pCmd, pnum);
2564 	case CMD_SPELLXY:
2565 		return On_SPELLXY(pCmd, pnum);
2566 	case CMD_TSPELLXY:
2567 		return On_TSPELLXY(pCmd, pnum);
2568 	case CMD_OPOBJXY:
2569 		return On_OPOBJXY(pCmd, pnum);
2570 	case CMD_DISARMXY:
2571 		return On_DISARMXY(pCmd, pnum);
2572 	case CMD_OPOBJT:
2573 		return On_OPOBJT(pCmd, pnum);
2574 	case CMD_ATTACKID:
2575 		return On_ATTACKID(pCmd, pnum);
2576 	case CMD_ATTACKPID:
2577 		return On_ATTACKPID(pCmd, pnum);
2578 	case CMD_RATTACKID:
2579 		return On_RATTACKID(pCmd, pnum);
2580 	case CMD_RATTACKPID:
2581 		return On_RATTACKPID(pCmd, pnum);
2582 	case CMD_SPELLID:
2583 		return On_SPELLID(pCmd, pnum);
2584 	case CMD_SPELLPID:
2585 		return On_SPELLPID(pCmd, pnum);
2586 	case CMD_TSPELLID:
2587 		return On_TSPELLID(pCmd, pnum);
2588 	case CMD_TSPELLPID:
2589 		return On_TSPELLPID(pCmd, pnum);
2590 	case CMD_KNOCKBACK:
2591 		return On_KNOCKBACK(pCmd, pnum);
2592 	case CMD_RESURRECT:
2593 		return On_RESURRECT(pCmd, pnum);
2594 	case CMD_HEALOTHER:
2595 		return On_HEALOTHER(pCmd, pnum);
2596 	case CMD_TALKXY:
2597 		return On_TALKXY(pCmd, pnum);
2598 	case CMD_DEBUG:
2599 		return On_DEBUG(pCmd, pnum);
2600 	case CMD_NEWLVL:
2601 		return On_NEWLVL(pCmd, pnum);
2602 	case CMD_WARP:
2603 		return On_WARP(pCmd, pnum);
2604 	case CMD_MONSTDEATH:
2605 		return On_MONSTDEATH(pCmd, pnum);
2606 	case CMD_KILLGOLEM:
2607 		return On_KILLGOLEM(pCmd, pnum);
2608 	case CMD_AWAKEGOLEM:
2609 		return On_AWAKEGOLEM(pCmd, pnum);
2610 	case CMD_MONSTDAMAGE:
2611 		return On_MONSTDAMAGE(pCmd, pnum);
2612 	case CMD_PLRDEAD:
2613 		return On_PLRDEAD(pCmd, pnum);
2614 	case CMD_PLRDAMAGE:
2615 		return On_PLRDAMAGE(pCmd, pnum);
2616 	case CMD_OPENDOOR:
2617 		return On_OPENDOOR(pCmd, pnum);
2618 	case CMD_CLOSEDOOR:
2619 		return On_CLOSEDOOR(pCmd, pnum);
2620 	case CMD_OPERATEOBJ:
2621 		return On_OPERATEOBJ(pCmd, pnum);
2622 	case CMD_PLROPOBJ:
2623 		return On_PLROPOBJ(pCmd, pnum);
2624 	case CMD_BREAKOBJ:
2625 		return On_BREAKOBJ(pCmd, pnum);
2626 	case CMD_CHANGEPLRITEMS:
2627 		return On_CHANGEPLRITEMS(pCmd, pnum);
2628 	case CMD_DELPLRITEMS:
2629 		return On_DELPLRITEMS(pCmd, pnum);
2630 	case CMD_PLRLEVEL:
2631 		return On_PLRLEVEL(pCmd, pnum);
2632 	case CMD_DROPITEM:
2633 		return On_DROPITEM(pCmd, pnum);
2634 	case CMD_ACK_PLRINFO:
2635 		return On_ACK_PLRINFO(pCmd, pnum);
2636 	case CMD_SEND_PLRINFO:
2637 		return On_SEND_PLRINFO(pCmd, pnum);
2638 	case CMD_PLAYER_JOINLEVEL:
2639 		return On_PLAYER_JOINLEVEL(pCmd, pnum);
2640 	case CMD_ACTIVATEPORTAL:
2641 		return On_ACTIVATEPORTAL(pCmd, pnum);
2642 	case CMD_DEACTIVATEPORTAL:
2643 		return On_DEACTIVATEPORTAL(pCmd, pnum);
2644 	case CMD_RETOWN:
2645 		return On_RETOWN(pCmd, pnum);
2646 	case CMD_SETSTR:
2647 		return On_SETSTR(pCmd, pnum);
2648 	case CMD_SETMAG:
2649 		return On_SETMAG(pCmd, pnum);
2650 	case CMD_SETDEX:
2651 		return On_SETDEX(pCmd, pnum);
2652 	case CMD_SETVIT:
2653 		return On_SETVIT(pCmd, pnum);
2654 	case CMD_STRING:
2655 		return On_STRING(pCmd, pnum);
2656 	case CMD_SYNCQUEST:
2657 		return On_SYNCQUEST(pCmd, pnum);
2658 	case CMD_ENDSHIELD:
2659 		return On_ENDSHIELD(pCmd, pnum);
2660 	case CMD_CHEAT_EXPERIENCE:
2661 		return On_CHEAT_EXPERIENCE(pCmd, pnum);
2662 	case CMD_CHEAT_SPELL_LEVEL:
2663 		return On_CHEAT_SPELL_LEVEL(pCmd, pnum);
2664 	case CMD_NOVA:
2665 		return On_NOVA(pCmd, pnum);
2666 	case CMD_SETSHIELD:
2667 		return On_SETSHIELD(pCmd, pnum);
2668 	case CMD_REMSHIELD:
2669 		return On_REMSHIELD(pCmd, pnum);
2670 	case CMD_REFLECT:
2671 		return On_REFLECT(pCmd, pnum);
2672 	case CMD_NAKRUL:
2673 		return On_NAKRUL(pCmd, pnum);
2674 	case CMD_OPENHIVE:
2675 		return On_OPENHIVE(pCmd, pnum);
2676 	case CMD_OPENCRYPT:
2677 		return On_OPENCRYPT(pCmd, pnum);
2678 	}
2679 
2680 	if (pCmd->bCmd < CMD_DLEVEL_0 || pCmd->bCmd > CMD_DLEVEL_END) {
2681 		SNetDropPlayer(pnum, LEAVE_DROP);
2682 		return 0;
2683 	}
2684 
2685 	return On_DLEVEL(pnum, pCmd);
2686 }
2687 
2688 DEVILUTION_END_NAMESPACE
2689