- 在线时间
- 1957 小时
- 最后登录
- 2024-6-29
- 注册时间
- 2004-4-26
- 听众数
- 49
- 收听数
- 0
- 能力
- 60 分
- 体力
- 40960 点
- 威望
- 6 点
- 阅读权限
- 255
- 积分
- 23863
- 相册
- 0
- 日志
- 0
- 记录
- 0
- 帖子
- 20501
- 主题
- 18182
- 精华
- 5
- 分享
- 0
- 好友
- 140
TA的每日心情 | 奋斗 2024-6-23 05:14 |
|---|
签到天数: 1043 天 [LV.10]以坛为家III
 群组: 万里江山 群组: sas讨论小组 群组: 长盛证券理财有限公司 群组: C 语言讨论组 群组: Matlab讨论组 |
<DIV class=HtmlCode>
: o/ h) c8 m. o2 w; s' o< >// File: mazeserver.cpp
& c9 G9 V9 F' ?* I# L6 ~, T$ O) b//
\4 K2 p$ K b. F) b$ a& H// Desc: see main.cpp
9 c. Q& c( c+ t//: k; Y& z6 c) c& f/ O+ H2 G
// Copyright (c) 1999-2001 Microsoft Corp. All rights reserved.
$ t. L4 ^1 m- f( p# s//-----------------------------------------------------------------------------
/ {) [% c; n) L8 O; n#define STRICT8 K& G# ]' [; y6 h
#define D3D_OVERLOADS
' o8 o2 f8 U" p( r/ i4 R#include <windows.h>( V- E8 }4 Z! b, K% N P
#include <d3dx.h>
* ]0 e& ? O5 ?. V#include <stdio.h>
) \# O* c( v% l) m% r9 h" N#include <math.h>9 J; O* l( x8 d, |8 s% r) U4 i1 Q+ k
#include <mmsystem.h>4 D4 Z: |3 N3 c! R' B4 Z6 J
#include <dplay8.h>
' E. [* C" A/ }$ w/ W* {#include <dpaddr.h>
2 ~& c0 Y6 `9 l8 _' i! G0 s$ n#include <dxerr8.h>
" X' P- d; I3 U( W3 Y. _+ S#include "DXUtil.h"
q3 |1 V5 ^* H: |5 {+ p#include "MazeServer.h"
. c$ U( M R' o+ Y' q#include " ackets.h"5 ?, j% k$ R. L6 ]
#include "Maze.h"
% h; @ [6 W( s |9 h#include <malloc.h>! X4 |, h' k6 {/ v$ j5 h
#include <tchar.h></P>
5 K# \3 K* W' r. n, u. k3 M- T, t% M" V, l/ w; A5 N
< >//-----------------------------------------------------------------------------
2 ?* z( K9 B7 Q6 ]9 S8 y0 Q# E6 J// Name: . C8 t) b& Q" I& Q
// Desc: 1 O6 G7 O; @ U% {4 l6 J
//-----------------------------------------------------------------------------; [5 r" w9 X9 @0 o* \4 x
CMazeServer::CMazeServer()
. \) B' Y3 k! @7 u4 w" A& Y3 @{7 \: g0 b8 F( I% U! }1 v0 B
m_dwPlayerCount = 0;! m8 y/ J- u8 ~! `
; \$ \7 V# r6 u: d
m_wActiveThreadCount = 0;$ R' y; D/ I" W, n# U) q' ^! E
m_wMaxThreadCount = 0;- |& _2 f6 |: T# i$ ~ N. m1 M
m_fAvgThreadCount = 0;0 e* H0 W# s6 L( I
m_fAvgThreadTime = 0;
( [8 S* i7 D0 r- n4 c" n4 B) G) h m_fMaxThreadTime = 0;</P>, l4 Z8 }, {1 r/ }- }
< > m_dwServerReliableRate = 15;
; J0 }9 g1 z, f! d m_dwServerTimeout = 150;( u v% @, a) Q7 l' o' ?
m_dwLogLevel = 2;
6 `" d5 E/ B7 x% d& | m_pMaze = NULL;</P>
& e. S# K, }5 D _! t< > m_ClientNetConfig.ubReliableRate = 15;4 Z7 N9 L8 y1 z* c
m_ClientNetConfig.wUpdateRate = 150;3 ]2 q% z" K& L/ v
m_ClientNetConfig.wTimeout = 150;</P>
# h( x' n2 G, c& L* x9 q2 h- {% N2 m< > m_ClientNetConfig.dwThreadWait = 0;</P>/ f9 e. P9 I3 p3 J- T
< > m_ClientNetConfig.ubClientPackIndex = 0;+ C1 q' c8 ?/ p% _) }
m_ClientNetConfig.ubServerPackIndex = 0;
# D; `9 i: L* B, a$ z% p9 P for(WORD x = 0; x < PACK_ARRAY_SIZE; x++)- }" m) W- s1 e
{$ f: Q2 @2 n/ I3 r0 ~
m_ClientNetConfig.wClientPackSizeArray[x] = 0;' \9 ^4 _+ M, x) B1 L
m_ClientNetConfig.wServerPackSizeArray[x] = 0;
0 b8 K9 W5 z$ m# Q. ]$ l }) p3 W! y" ~; S) V
}</P>
3 q/ l% X0 E$ O8 J0 l }3 S
% d, f- n4 v4 `; \+ B |; Z5 f< >9 m7 ?0 f. I5 o, V% b/ C
//-----------------------------------------------------------------------------
+ c- N, M( s6 s M. J# e// Name: & G* l1 [; s2 j8 M
// Desc: : M+ \; K2 t8 J
//-----------------------------------------------------------------------------9 @; J. O# r u
HRESULT CMazeServer::Init( BOOL bLocalLoopback, const CMaze* pMaze )) u* a0 A( C! E5 W( r- L! y3 _% p
{5 ^/ B7 a2 F! A, Z! k
m_bLocalLoopback = bLocalLoopback;7 z+ p1 V. P/ k6 ^$ c( M
m_pMaze = pMaze;
! r ?& @8 @ w9 I7 |) X0 ` if( m_pMaze == NULL )
) W4 F. G& F: O return DXTRACE_ERR( TEXT(" aram"), E_FAIL );</P>* Q) l3 _ {8 R4 H. m% K" f
< > // Grab height and width of maze. O( [3 {+ N& D- f! H, p6 A- o/ o5 e
m_dwWidth = m_pMaze->GetWidth();" Z; n! M+ k* Y' h; X
m_dwHeight = m_pMaze->GetHeight();</P>
8 Z' N4 F$ }* Q4 P0 V z< > m_ClientNetConfig.dwMazeWidth = m_dwWidth;
8 C# z8 b! N5 G/ k# _6 U m_ClientNetConfig.dwMazeHeight = m_dwHeight;</P>0 \) [2 ]/ T, J+ s6 b
< > // Validate size. Must be a power-of-2 times LOCK_GRID_SIZE. Compute the shifts.* d* a8 [1 p2 C( y4 p& m+ m% S: \
if( m_dwWidth > SERVER_MAX_WIDTH || m_dwHeight > SERVER_MAX_HEIGHT )
6 a9 u6 R" q* s) p2 b return DXTRACE_ERR( TEXT("Maze height and width need to be less than 128"), E_INVALIDARG );
# {9 _' r9 c' n6 u if( (m_dwWidth % LOCK_GRID_SIZE) != 0 || (m_dwHeight % LOCK_GRID_SIZE) != 0 )' Y8 t, x' \( S- t" d" \8 T. l
return DXTRACE_ERR( TEXT("Maze height and width need to be divisable by 16"), E_INVALIDARG );</P>
# h# o3 R4 B. ^( F< > DWORD scale = m_dwWidth / LOCK_GRID_SIZE;
2 ?. B7 G. b3 M5 x8 c m_dwMazeXShift = 0;
1 U* z! o/ L5 K while ( (scale >>= 1) )
/ c5 p" n6 {, w r, ] m_dwMazeXShift++;</P>- p5 U) R: o9 @) {. a0 H
< > scale = m_dwHeight / LOCK_GRID_SIZE;# |" f" e5 U% L3 C6 _$ G3 j$ j
m_dwMazeYShift = 0;. a6 C4 u0 T! c0 t; i! S
while ( (scale >>= 1) )8 d5 C3 {9 B" l6 d+ O1 u
m_dwMazeYShift++;</P>+ G8 H7 y" q# E$ W+ _/ X
< > if( ((DWORD(LOCK_GRID_SIZE) << m_dwMazeXShift) != m_dwWidth) ||* I# Y/ l3 y! m2 _2 l: V: R( m
((DWORD(LOCK_GRID_SIZE) << m_dwMazeYShift) != m_dwHeight) )
, b! q8 Z% e1 C: L/ t! o4 {; L5 y return DXTRACE_ERR( TEXT("Maze height and width need to be power of 2"), E_INVALIDARG );</P>! ~6 \* g/ T+ J" i- k5 z
< > // Initialise the player list/ I0 u, r5 J$ X9 J1 k
ZeroMemory( m_PlayerDatas, sizeof(m_PlayerDatas) );
$ n8 a, s5 C# |0 D m_pFirstActivePlayerData = NULL;" i5 W3 r, k& }8 Y) i9 w
m_pFirstFreePlayerData = m_PlayerDatas;
5 u& G$ ~1 v8 W. | for( DWORD i = 1; i < MAX_PLAYER_OBJECTS-1; i++ ): U5 c: u& s @! s4 Y I
{
/ G, |3 `6 t: O- V! ?8 u m_PlayerDatas.pNext = &m_PlayerDatas[i+1];$ l1 J) u% j1 w
m_PlayerDatas.pPrevious = &m_PlayerDatas[i-1];
; \; }3 }! p0 m+ S. q. c! ` }</P>
7 |6 [3 U: S. F< > m_PlayerDatas[0].pNext = &m_PlayerDatas[1];. r+ ]* T% p! E6 d$ g" e) X1 B
m_PlayerDatas[MAX_PLAYER_OBJECTS-1].pPrevious = &m_PlayerDatas[MAX_PLAYER_OBJECTS-2];6 X" I, ^9 R/ X- Z6 X
m_dwActivePlayerDataCount = 0;- I+ Z# ~6 n: ~& ]
m_dwPlayerDataUniqueValue = 0;</P>
/ B( w5 G0 P! b: d< > // Initialise the cells% S; r9 @3 ^7 G; Z* p9 S; D
ZeroMemory( m_Cells, sizeof(m_Cells) );# a" g2 Q! U4 k+ s) }) V
ZeroMemory( &m_OffMapCell, sizeof(m_OffMapCell) );</P>
) t8 W0 J. O3 p* o: z5 f< > return S_OK;
4 P' c0 O% W1 I1 }% t j}</P>
3 C# b( ^9 L0 c' Y5 a+ F, \/ g; H2 _& }$ K
< >
$ b; o2 t1 [6 l; Q: x+ h//-----------------------------------------------------------------------------0 Z& B% S% ?4 x: a
// Name: 2 Q5 t& Q" d$ K0 j& {& w& L
// Desc:
: @) l0 x4 D* w% N T//-----------------------------------------------------------------------------5 ]. p, M1 |+ f0 a7 V7 [ O! ?
void CMazeServer::Shutdown()
5 k! B* k e5 S" c& {/ N{% U/ K) ]5 y0 X$ a3 W' |( y
}</P>
2 Q! O) l4 A$ X/ M& n, n
; b6 K) r; i9 Q# }< >
" h( c2 I0 h7 }' w: b. [; U//-----------------------------------------------------------------------------
* T2 s/ Y' y w/ j C% j// Name:
% A: N- v" t4 }5 d- J' |// Desc:
7 b/ E6 _9 K- h) v//-----------------------------------------------------------------------------" P0 }3 M1 ?; V
void CMazeServer: ockRange( DWORD x1, DWORD y1, DWORD x2, DWORD y2 )
b: s; |! g4 N& h* q: s& [- u6 U{
8 |6 I3 Z/ \2 J k; | m_LockGrid.LockRange( x1>>m_dwMazeXShift, y1>>m_dwMazeYShift ,
6 S( S3 i& a% l" w5 K* \( F x2>>m_dwMazeXShift, y2>>m_dwMazeYShift );
; B0 u7 [$ i! d2 p/ }# H}</P>: e) t* P: V2 }7 c7 H9 C2 K# G
1 D7 V7 ^- u- \
< >5 x, V( k* P0 A! P5 V) E9 y
//-----------------------------------------------------------------------------
; h [$ v! Z1 o// Name: ; v! Q( f$ V" Z$ l; t
// Desc:
, u% j- U1 O7 p: Y- ]//-----------------------------------------------------------------------------
; U/ p2 W6 p( Q# L* M( Q# }! Jvoid CMazeServer::UnlockRange( DWORD x1, DWORD y1, DWORD x2, DWORD y2 ); V" J) K2 r6 d' X
{
T p3 B) G1 H9 F3 o" y1 I m_LockGrid.UnlockRange( x1>>m_dwMazeXShift, y1>>m_dwMazeYShift , F5 f1 {+ R* x$ J1 l$ ~! \# d) q1 I0 p
x2>>m_dwMazeXShift, y2>>m_dwMazeYShift );0 p4 _! f3 v# M" _) Y( l
}</P>9 |3 u" ]' k0 C% h6 o
* {; K( s( v/ e" R$ ^: h
< >
/ W# v, P) k" F; N- I) N! ~- d//-----------------------------------------------------------------------------
# t3 I4 l; ^, N( l( M- R+ ]! f// Name:
+ E$ ~* ]- g% v* o+ d: i7 m. i H// Desc: 3 F2 L8 p0 c4 d0 J
//-----------------------------------------------------------------------------
; ~3 [ M4 R: |& T$ z6 u0 f% Fvoid CMazeServer: ockCell( DWORD x, DWORD y )
0 K% |& R2 Q& U, S6 y{. D/ F5 r! G% [4 i
if( x == 0xffff )) E: b8 O- i6 A ^
m_OffMapLock.Enter();) U! n9 G4 O1 R' C* [1 _
else6 p4 P0 T6 `' \* }
m_LockGrid.LockCell(x>>m_dwMazeXShift,y>>m_dwMazeYShift);
2 \( h0 O! k# N J" {0 `0 ?}</P>
6 u, w- L2 o$ U3 B7 ~( P5 W' {' w. H9 s; w* W9 I2 f
< >9 a+ n7 k$ }5 ]
//-----------------------------------------------------------------------------
# j8 ]' ~/ H* ]( I! i1 d0 a8 b7 ~// Name: 3 {) t3 q" N5 j7 v
// Desc: 1 c" B c) w" P2 I- q
//-----------------------------------------------------------------------------
& }4 L, j' k& D3 J( C/ Bvoid CMazeServer::UnlockCell( DWORD x, DWORD y )8 A9 k( w( H. \0 G
{! s* Y8 D1 ]4 T' l, p# }$ c
if( x == 0xffff )! x, W% t. ?; r9 g0 `
m_OffMapLock.Leave();' U: W1 b$ v8 S; q. w
else- y5 O# ] e. I* ~
m_LockGrid.UnlockCell(x>>m_dwMazeXShift,y>>m_dwMazeYShift);
" O" T8 O. p. n0 I9 S2 t* d8 U}</P>( `0 n' o3 z: B$ T0 U" h5 Z
/ e; ]& x& l4 Y7 p: `< >
: q. z e# o& ?8 i//-----------------------------------------------------------------------------
/ b( D5 `: i2 ?// Name:
5 f; T/ K# }& l3 `// Desc: 9 o) L2 R8 j8 R$ T
//-----------------------------------------------------------------------------$ T2 d, _& C2 U$ Z4 R) D
void CMazeServer: ockCellPair( DWORD x1, DWORD y1, DWORD x2, DWORD y2 )) _; J: w. ?+ i( i1 D/ k
{
( \/ [% i7 R: ~. F; j, F if( x1 == x2 && y1 == y2 )
' S' ^( N6 n+ a# g# Y {# T9 x2 T0 v3 ] b" i% K
if( x1 != 0xffff && y2 != 0xffff )) p9 P7 v5 ]0 R
LockCell( x1, y1 );5 h4 Z% v4 J4 X' p& _0 H" `. _6 k
else9 z, ^: H7 J( p( k0 x. x1 d' K
m_OffMapLock.Enter();</P>
7 ?. [( o) E# C4 B# r< > return;
, G5 N) X5 m+ B* Q5 E! x! d }</P>* C! r0 ^7 v+ t9 O7 G) o4 O
< > DWORD x1shift = x1>>m_dwMazeXShift;* @" g3 Q% B% r# A
DWORD x2shift = x2>>m_dwMazeXShift;9 C# s6 s+ [/ q* Y f
DWORD y1shift = y1>>m_dwMazeYShift;# l E! W% @0 V
DWORD y2shift = y2>>m_dwMazeYShift;</P>
1 I [( q7 d& b+ H< > if( x1 == 0xffff )7 E7 |) t% r) {8 G/ l0 Z2 P
{% k) o/ |) F) p/ G
m_OffMapLock.Enter();. U! Z# t# U2 c1 F6 Y
m_LockGrid.LockCell(x2shift,y2shift);
2 q2 T" {2 a" l# b0 W+ s }& G9 W- F) O1 a7 s: M
else if( x2 == 0xffff )0 e/ y( H* P' h% d$ F
{
2 C9 A8 q( e' t. |* [/ q m_OffMapLock.Enter();
( l1 w; T: h3 p8 V8 { m_LockGrid.LockCell(x1shift,y1shift);
* m4 w5 }4 ~; ? }
# A$ O% a; s8 X4 I$ Y- Q else $ ?4 |5 q2 E7 g% j& ]
{% G, {5 k4 U, B* r' O
m_LockGrid.LockCellPair(x1shift,y1shift,x2shift,y2shift);
3 o& w3 c' G. g/ f }4 [8 z' F3 C6 a9 L
}</P>
' @6 ~& }! ~0 f: S: e9 F+ o; G. B) q& P9 M7 q
< >$ z% e t# f; l* [, _
//-----------------------------------------------------------------------------
1 E' V! @' n H( @// Name:
7 \* o7 ^0 y: W$ M8 j% b// Desc: 2 o# h5 y$ X1 y9 w
//----------------------------------------------------------------------------- Y+ A5 A2 B3 _) F4 U
void CMazeServer::UnlockCellPair( DWORD x1, DWORD y1, DWORD x2, DWORD y2 )
' B/ O5 a- {; C9 {8 j! v{
( z5 u5 Y( m+ M if( x1 == x2 && y1 == y2 )
$ G; i7 G7 e. p! ]0 h$ P {7 Q2 _# F) @; [( V* R
if( x1 != 0xffff && y2 != 0xffff )
3 h5 I1 p4 K% C4 j* X2 K# J3 R UnlockCell( x1, y1 );
2 s( _1 Z+ ?5 n) i: X! l else5 D9 c: O: T0 R; Q
m_OffMapLock.Leave();</P>
9 O/ N0 b6 P0 J, {6 P5 ?+ ~< > return;
* J3 b; ^8 m# V- W& ` }</P>
4 N: m: ?. v/ O, W<P> DWORD x1shift = x1>>m_dwMazeXShift;
4 \$ O, g# `7 c- a: g DWORD x2shift = x2>>m_dwMazeXShift;
, _, v) e7 F' j" n5 H( E8 Q; p DWORD y1shift = y1>>m_dwMazeYShift;9 ?6 Q3 r) b7 H$ [9 Y3 Q" _! A
DWORD y2shift = y2>>m_dwMazeYShift;</P>
( F/ I x! C; Z% H: z<P> if( x1 == 0xffff )/ P( \0 Z& d4 X' e6 b/ ^ l) ~
{
) s. x, r0 M: i/ Z7 Y* x m_LockGrid.UnlockCell(x2shift,y2shift);
* O% R8 L# {. n5 @+ T2 @, H. j# j m_OffMapLock.Leave();& V' B5 {% }$ W3 Z0 ^( T
}: l4 @! L2 Q* S! T8 J6 ?# t( f# Q$ r
else if( x2 == 0xffff )' ~% H' I: Z9 ?1 e( n* z! X/ M
{
; i0 q3 O6 Q3 a9 H$ R0 J m_LockGrid.UnlockCell(x1shift,y1shift);
; s, a$ ?" ~. R1 p0 h+ ?2 z* v m_OffMapLock.Leave();
0 y9 ]8 a2 _4 ?' b- D3 n }" N: F% P0 r0 N3 D. w: M
else
/ F3 K% r+ k1 I- a, g# V- x% f {
% E m7 G9 [* l |0 K3 o m_LockGrid.UnlockCellPair(x1shift,y1shift,x2shift,y2shift);
' K* U5 g' l0 Q2 G$ | }
. R' H4 {# o6 t# L}</P>
) x6 X: h) K9 q& _
( J4 ^( i$ p4 K2 S2 d6 o n<P>
4 c3 H9 S7 @$ y//-----------------------------------------------------------------------------
: L0 f+ ]/ _% M( D0 ~// Name:
( v) r: k9 u3 w g- h& N- |# v// Desc: ; s, p! R' j& ?9 N8 I
//-----------------------------------------------------------------------------
3 g l. N7 D, X# A2 m/ Uvoid CMazeServer::OnAddConnection( DWORD id )% k$ G5 O" m% D8 s$ `3 K: y
{
8 ]. G& j% |$ k d m_AddRemoveLock.Enter();</P>
! y$ C5 \7 Y0 _$ B1 }0 G<P> // Increment our count of players3 J' i" T4 i) B5 b+ a$ m; p
m_dwPlayerCount++;7 f5 ~. v/ H7 S* W5 ]7 L
if( m_dwLogLevel > 0 ) }7 @7 k0 e9 Q& z# n
{
3 f5 U- m5 e- o( \; M ConsolePrintf( SLINE_LOG, TEXT("Adding player DPNID %0.8x"), id );
, T3 `. Y" p7 D1 c n ConsolePrintf( SLINE_LOG, TEXT("Players connected = %d"), m_dwPlayerCount );
1 r0 d4 k; H: F& _) Q5 a }</P>
. p6 g/ k3 q7 F9 M7 }' B) w# H<P> if( m_dwPlayerCount > m_dwPeakPlayerCount )! F8 _8 N2 n1 x5 s2 h* y: M& x
m_dwPeakPlayerCount = m_dwPlayerCount;</P>
! v; E) l+ {( \ f5 [<P> // Create a player for this client: v2 u; A# U# X+ L$ m' y6 Q
PlayerData* pPlayerData = CreatePlayerData();# A9 @# m7 S& V/ ^2 p! E
if( pPlayerData == NULL ). {9 X1 N b) ~ }( q6 V
{' T- ^. Q4 r. G! Y& L
ConsolePrintf( SLINE_LOG, TEXT("ERROR! Unable to create new PlayerData for client!") );
' L. W% S1 `, J1 b DXTRACE_ERR( TEXT("CreatePlayerData"), E_FAIL );9 P7 w0 o+ t7 a" I
m_AddRemoveLock.Leave();
+ }* S# `( E" o8 N' j+ r return;% j ?- h; b; S. U6 O3 ^4 M
}</P>. y; X- Z6 ?5 B5 K
<P> // Store that pointer as local player data
0 M- y* C3 L; [ B; q% l SetPlayerDataForID( id, pPlayerData );</P>
" u j+ I' ~5 q' R! N" G; k U<P> // Grab net config into to send to client3 \/ m1 [$ q1 ]
m_ClientNetConfigLock.Enter();0 D: L6 O3 b6 i' {! h$ D1 o7 p6 C
ServerConfigPacket packet( m_ClientNetConfig );
' W( A- `: m6 F! a m_ClientNetConfigLock.Leave();</P>
5 \/ x8 G! M* j0 G% ]5 X: b) w% y<P> // Send it
5 Q* _$ t! \ k7 g* I+ I( ] SendPacket( id, &packet, sizeof(packet), TRUE, 0 );</P>
1 d# v. o& r1 d; a# ]5 _<P> m_AddRemoveLock.Leave();
( L$ q# F* }7 a- P}</P>
+ h2 a4 k; t: f# _$ f& Z% ]* U" H* b- z3 i/ {4 f9 l' [4 I
<P>, x& b" k0 h P
//-----------------------------------------------------------------------------: V; M A+ d9 t8 F9 J4 U: e
// Name:
2 Q8 ~9 K; I0 L4 E// Desc:
" `6 |1 @6 m* M7 o7 s//-----------------------------------------------------------------------------% \- I+ F- g( z, {0 p% P5 V7 h2 l
void CMazeServer::OnRemoveConnection( DWORD id )
$ D- a6 U% x! S' {; i7 r{. C; [$ n' j1 O$ S
m_AddRemoveLock.Enter();</P>: p7 M% W- ]+ @5 V* Y5 A1 N
<P> // Decrement count of players
4 |& W7 _% k/ a/ \6 r' ^ m_dwPlayerCount--;</P>
$ T8 A) w1 @) i! }<P> if( m_dwLogLevel > 0 )
( |% T3 O- q$ f2 t( T# H {
8 c/ o( c2 v; M5 u& ?9 o5 ]' ^ ConsolePrintf( SLINE_LOG, TEXT("Removing player DPNID %0.8x"), id );( K5 u/ V& O; S4 u6 {( U4 i, J* a0 `& Q
ConsolePrintf( SLINE_LOG, TEXT("Players connected = %d"), m_dwPlayerCount );
1 c5 o" n& g# ~& U }</P>
- [- {0 E# G/ C8 A% i& O3 f$ d<P> // Find playerdata for this client2 A ^0 S1 S* k2 m, E: t
PlayerData* pPlayerData = GetPlayerDataForID( id );
; A( A' ]3 _0 p) X+ u if( pPlayerData != NULL ), x( ~# g9 t; L5 G/ v0 O
{( a+ o+ o/ d1 V! L) w! B8 s: S
// Destroy it
, h Z6 Y4 c/ _) q RemovePlayerDataID( pPlayerData );( k& t) v+ G+ u5 }& T+ k% g
DestroyPlayerData( pPlayerData );
8 M3 V+ J' `8 F' z# M' ^. U% o }</P>/ ]# e3 k& I, H9 E( M7 `
<P> m_AddRemoveLock.Leave();
) T* u7 A4 d, V% {' k}</P>
- }9 `. H n$ z; p& ~4 M7 a5 h5 p/ U+ W& w T
<P>. x4 x2 r* p0 @# x# a/ _; ]
//-----------------------------------------------------------------------------
$ o- f# s( y: U! x9 L! E) u// Name: ! Z9 h E8 D# E, S G# J0 j: U
// Desc: ( `- O$ z& y+ N9 ?8 @, v
//-----------------------------------------------------------------------------
1 C; G0 U7 \. j( g8 K6 K# GHRESULT CMazeServer::OnPacket( DWORD dwFrom, void* pData, DWORD size )
5 G; ]/ A; _: D, v. P% v{
. U& v7 [, D! ?! ~# e BOOL fFoundSize = FALSE;</P>
. P" H) L U1 v, S9 l, y<P> // Increment the number of thread we have in this process.) e' p2 O' U/ h7 p! q! v
m_csThreadCountLock.Enter();</P>* Z3 h" n$ |- a- M! i
<P> //Get the start time of when we entered the message handler.
: c- p, `& E( B0 { T FLOAT fStartTime = DXUtil_Timer( TIMER_GETAPPTIME );</P> W& y' O+ t! e' U
<P> m_wActiveThreadCount++;
7 Y! C0 q n; g- Q- O( E# Z1 K if(m_wActiveThreadCount > m_wMaxThreadCount)$ c& C' F# `1 ]2 n/ u1 u
m_wMaxThreadCount = m_wActiveThreadCount;7 y( I* @0 F/ f2 [; _
: U7 j0 w3 K4 r+ B2 |# ^$ W // Calculate and average.
5 A; ^' g8 W$ K5 d/ C8 W; S& {6 ~; \& q FLOAT fdiff = m_wActiveThreadCount - m_fAvgThreadCount;# ^8 H, T9 ` P, H& b5 p
m_fAvgThreadCount += fdiff/32;
% x) }; S( r. a' A 3 O2 u7 k7 x- n8 l& T2 J
m_csThreadCountLock.Leave();</P>
3 h% K: h/ z% l _5 u- N3 F |8 D<P>( ^' H! s, U* I2 D2 s4 F: j$ B. ^
ClientPacket* pClientPack = (ClientPacket*)pData;
' f+ D$ [% h+ B' C8 H5 c switch( pClientPack->wType )
( r, N5 W% l. v( W {
" A- d) o! V: e4 b; [3 ~ case PACKETTYPE_CLIENT_POS:" ~3 {9 n s9 _" u2 r0 _
( z6 ?2 c4 o, M, M# F
// Check to see if the packet has a valid size. Including % t7 n( N; a# U5 V, _
// the custom pack size.
# T0 r# o: X8 h n1 E if( size < sizeof(ClientPosPacket))' s6 Z* I4 j3 ^- S( |0 {
fFoundSize = FALSE;
* [9 W0 x, b. S' c else if( ! IsValidPackSize(size - sizeof(ClientPosPacket)))
* X+ y2 i8 q, z; r2 J fFoundSize = FALSE;
1 s9 z2 A. Z+ O; d1 `- O# P else
2 X; f; X1 L0 P" H! S) e fFoundSize = TRUE;</P>
% S$ q) i, G& |' a- s5 c0 c<P> // If valid sized packet, handle the position.9 L B5 ?. ~* s- m# D$ ]- G% S
if(fFoundSize)
% z' G9 x& V$ b9 w% ^ Q, I HandleClientPosPacket( dwFrom, (ClientPosPacket*)pClientPack );
) A) k: C; y7 M# e# R7 x else
+ N1 T/ u4 e1 g8 X+ N8 x/ W; s m_pNet->RejectClient( dwFrom, DISCONNNECT_REASON_CLIENT_OUT_OF_DATE );</P>
9 `4 X& R/ m! K( |# R<P> break;</P>+ H9 N7 e- G6 c& G6 l+ _3 I
<P> case PACKETTYPE_CLIENT_VERSION:
/ n8 ]2 W' h# S if( size == sizeof(ClientVersionPacket) )
4 [3 v* L7 f6 y% q1 Z2 p, J HandleClientVersionPacket( dwFrom, (ClientVersionPacket*)pClientPack );& i+ T6 g% y& K2 h( S( ~4 U
else
, H9 _, P, H |" [ m_pNet->RejectClient( dwFrom, DISCONNNECT_REASON_CLIENT_OUT_OF_DATE );0 @0 B- I8 P% x `0 }% K
break;</P>) n6 C- z" G, a3 y' s m/ e. `6 I
<P> case PACKETTYPE_SERVER_CONFIG:</P>$ P$ m- y/ w/ j( W- {/ S4 C
<P> // Server config packet sent to all users (including server). Just ignore and continue.</P>. y4 b# L% G, m& `
<P> break;7 O- U r4 F/ ]
default:6 x2 J; v4 {- Q4 O& @( x' J" o
HandleUnknownPacket( dwFrom, pClientPack, size );. B/ v4 d3 Y/ ~5 S% r3 q
break;
# a+ }" V4 A) K }</P>8 R7 G# E7 {- D
<P> //If the user wants to hold the thread, Sleep for given amount of time.. G4 h' x9 w. ]" z" @
if ( m_dwServerThreadWait > 0 )7 j+ u* L4 P4 B2 R
{. q8 a' `8 h! t' [9 ]
Sleep( m_dwServerThreadWait );2 f7 X& R% p7 }& F
}# S( _. N, }4 @& M. g0 @
+ g$ ]5 L E; W. z // Retrieve thread data for this process.
5 m2 o" b% j5 L: f8 i4 e m_csThreadCountLock.Enter();</P>
# w1 k% H- M7 Q0 N) @. q<P> m_wActiveThreadCount--;</P>8 E) N; y3 U3 ^
<P> FLOAT fDiffTime = (DXUtil_Timer( TIMER_GETAPPTIME ) - fStartTime) - m_fAvgThreadTime;
( s3 H4 F1 z* P" I m_fAvgThreadTime += fDiffTime/32;</P>' I, ~8 X' Y% M+ I8 N
<P> //Get the Max time in the thread.
3 a, C ^# q7 b5 u( Z+ ^6 ?& l if ( fDiffTime > m_fMaxThreadTime )3 W5 r! [1 Y0 q3 u5 x% \( K& C
{
8 H6 C2 d8 u) y9 C& b* U5 E m_fMaxThreadTime = fDiffTime;" h8 U4 {3 X$ [3 I/ e7 m
}</P>
* F: G" k3 U( ^8 X! o) }+ K, @<P> m_csThreadCountLock.Leave();</P>
* j) q0 S) x7 M0 Q/ m* O, Q% {' F<P> return S_OK;
" ]- @9 Q: Q( ?# N u}</P>! Y# i; f% ^2 Y+ i3 `# p
" p$ g; n$ ?' M
<P>//-----------------------------------------------------------------------------/ X( a; j5 k7 b
// Name:
$ h( |' L) G/ g' Q1 `: z. Y// Desc: % U4 e# W5 K$ z+ x% w
//-----------------------------------------------------------------------------/ S. R! _! ^# y9 z% O. ^* A
BOOL CMazeServer::IsValidPackSize( DWORD dwSize )
" l8 t( j; c9 f, G5 M" l{
8 B0 f5 e' g* _; q8 T3 r) R BOOL fFoundSize = FALSE;
! ~" f# ~6 g- g BYTE ubPackLocation = m_ClientNetConfig.ubClientPackIndex;* K/ l6 ~" C7 d3 f8 y8 t
5 x$ e3 j5 \: Y3 l: L, x1 G
// Check through the array of valid pack sizes.+ A8 }* Y) u: M% b5 D) \
if(dwSize != m_ClientNetConfig.wClientPackSizeArray[ubPackLocation])# H3 d" {" i2 G" W9 W
{
C) h1 Z p' C' [4 Q for( --ubPackLocation; ubPackLocation != m_ClientNetConfig.ubClientPackIndex; ubPackLocation--)0 V2 A' O' _" H' [
{
" \+ }. U& r) U4 @7 H6 ] if(dwSize == m_ClientNetConfig.wClientPackSizeArray[ubPackLocation])! ]2 h8 T! O, y. e
{4 I6 U) M) g; U9 X, r( X) H
// Found valid size in the array.
2 x% F. G( D& I' z9 c fFoundSize = TRUE;; B8 ]* X4 F8 h
break;# r3 R, O, E! L5 @5 q
} B7 Y9 _2 n9 k1 K e ?$ ~
if(ubPackLocation >= PACK_ARRAY_SIZE) ubPackLocation = PACK_ARRAY_SIZE; //Wrap the array.
. Y3 L6 `% P `( b2 ?1 b7 ~ }
( P6 p# ^: g- V" T( w }
; [/ |; j U5 t: j- Z else
7 O1 F s1 Q4 H3 y6 v, b {
* P: i# R1 {' T2 Z' H( q fFoundSize = TRUE;
+ s2 e1 \5 L ]2 N }</P>1 s- f0 B( K/ Q
<P> return fFoundSize;9 `6 m( K, M2 ~1 ]) y1 [. [
}</P>) _% b* @. z: U( V) ~. U8 h. c
<P>
9 D" L5 G& ?2 S7 G//-----------------------------------------------------------------------------
^. r8 k- u! B3 Y- W( _6 g: W// Name:
8 g8 I, o8 D6 j6 }6 Z// Desc: / X5 q a' n- \! |( @6 m
//-----------------------------------------------------------------------------/ X1 {; |. q( {, z2 `! `
void CMazeServer::OnSessionLost( DWORD dwReason )
7 d! J1 M+ s {' _: C# ^& P# {{
p/ ?: V) V5 M& t ConsolePrintf( SLINE_LOG, TEXT("ERROR! Session was lost") );
& S* L- v' Y8 s& G1 K}</P>4 [- p9 _* q$ U# \: U
- E$ g; | X) M1 p# V0 d3 q<P>. H, {% D- m2 D
//-----------------------------------------------------------------------------
5 j/ w* [; s/ ^2 {/ |% i6 Z, L3 O// Name:
* t( V/ f1 ^7 {9 O; i! V# s" V- `// Desc: 4 |5 y0 B1 x1 l, u% u
//-----------------------------------------------------------------------------2 u( v* @* [2 F' S
PlayerData* CMazeServer::CreatePlayerData()
3 w( y1 B R% @4 y9 y" v{
- @6 l4 Z5 L) ?: [2 Z8 o m_PlayerDataListLock.Enter();</P> `! r5 o) Q3 u6 F' [0 F- \. w
<P> // Grab first free player in the list
8 f" R) n- l; p6 I' K5 d3 p PlayerData* pPlayerData = m_pFirstFreePlayerData;</P>, C$ M; ?. }# y4 {0 Y& ]
<P> if( pPlayerData )7 {) i1 A+ U8 ~% F1 C6 n
{( T1 ?) V3 B: q" V4 g
LockPlayerData( pPlayerData );</P>
( ]8 H) ]1 r7 \0 M2 }<P> // Got one, so remove it from the free list& @7 P/ _8 V' I6 {2 ]
if( pPlayerData->pPrevious )" F. g0 W8 o/ U6 Z4 E3 z: @
pPlayerData->pPrevious->pNext = pPlayerData->pNext;3 E3 i6 v( u9 o* J& t
if( pPlayerData->pNext )
+ h2 F/ V6 _6 i' E5 w pPlayerData->pNext->pPrevious = pPlayerData->pPrevious;
' c: Y/ R: L" I! y( u7 |. Y& ^" B m_pFirstFreePlayerData = pPlayerData->pNext;</P>* R' n2 Q7 R& {% P4 i" K
<P> // Add it to the active list
# v2 T5 ]: b, Z8 X if( m_pFirstActivePlayerData )0 a8 d; C# F& v8 C6 {$ G) \
m_pFirstActivePlayerData->pPrevious = pPlayerData;# \% c, h6 l! I' @& u
pPlayerData->pNext = m_pFirstActivePlayerData;
! M* y2 v( ~ j h6 @+ d pPlayerData->pPrevious = NULL;8 v$ x' z" G% Y7 y1 `0 Y1 I) c1 P, ^- \9 Z
m_pFirstActivePlayerData = pPlayerData;</P>
& p5 }3 @( d' q/ y<P> // Update count of players) k" d/ @/ F% ^$ }3 B3 C4 t; D# g
m_dwActivePlayerDataCount++;</P>
' ~) a# z2 T8 o2 F1 P* T<P> // Generate the ID for this player
: _* A1 |$ s$ r& s: N m_dwPlayerDataUniqueValue++;
/ V ?4 L% }, k1 Y pPlayerData->dwID = (DWORD) ((pPlayerData-m_PlayerDatas)|(m_dwPlayerDataUniqueValue<<PLAYER_OBJECT_SLOT_BITS));</P>
% }8 @& G# f& g) A7 i+ d<P> pPlayerData->pNextInIDHashBucket = NULL;8 o. Y% W; l* n2 H4 M
pPlayerData->NetID = 0;* p# n* N4 s/ c* N! c5 B @& I
pPlayerData->dwNumNearbyPlayers = 0;</P>
% A" Y' H: `# I0 H<P> // Insert into the "off-map" cell" g1 f j: F! M0 x2 I" x5 P
pPlayerData->fPosX = pPlayerData->fPosY = -1;. Q( G& D( ~8 X: U
pPlayerData->wCellX = pPlayerData->wCellY = 0xffff;. x- h* Z. T: r5 v# ?2 U1 W
m_OffMapLock.Enter();2 n, O2 f9 J" e8 t
pPlayerData->pNextInCell = m_OffMapCell.pFirstPlayerData;+ ~3 B! i- Z; d5 V+ i; V
m_OffMapCell.pFirstPlayerData = pPlayerData;8 f$ P& M n+ V$ U- [5 T( W
m_OffMapLock.Leave();</P>
: B ^ V& E( ]8 k! c<P> // Mark as active, E1 T. i) s/ p7 s
pPlayerData->bActive = TRUE;</P># [, Z ~/ b* N+ e2 `0 O
<P> UnlockPlayerData( pPlayerData );
( l7 i+ T1 x( x1 b) c+ t }</P> p: f, _4 k V. x1 r/ O" _
<P> m_PlayerDataListLock.Leave();</P>' _( o" P: }9 L N: v
<P> return pPlayerData;
, d% ?) J9 W" N: K) I}</P>
" k$ _7 t# \' h# @6 g4 b' j7 \, ]: B3 s+ O( z1 a; o y; u
<P>& c! ]- \5 u1 Q6 s
//-----------------------------------------------------------------------------
9 X) I5 N: m/ z, S0 T4 T// Name:
. A- j8 ~4 L) `2 @* \// Desc:
8 T* X L- w3 a//-----------------------------------------------------------------------------+ R8 J! H% f& R _
void CMazeServer: estroyPlayerData( PlayerData* pPlayerData )
$ r" r2 F; m! C# L6 r' A{
6 o# _: t8 `' ^. j7 C4 } m_PlayerDataListLock.Enter();- J; P0 }2 a) O$ m1 v& b
LockPlayerData( pPlayerData );</P>4 B$ X- M. F; V$ z& r" G
<P> // Remove the player from its cell
- q6 o# _+ w9 X; O2 X RemovePlayerDataFromCell( pPlayerData );</P>2 J$ c/ h9 @3 c: T& G" r H
<P> // Mark as inactive1 u! P# h# ^9 \9 Q
pPlayerData->bActive = FALSE;</P>
# ` g1 }; x2 |" k) g+ `+ u<P> // Remove player from active list
' ~- |, A) w) C' N& P; w if( pPlayerData->pPrevious )7 O0 c* t/ r1 {! G" u! D6 m6 a
pPlayerData->pPrevious->pNext = pPlayerData->pNext;
4 E6 s; [- m5 N3 i if( pPlayerData->pNext ); L) T: f8 p2 t: b0 y$ E( |# R
pPlayerData->pNext->pPrevious = pPlayerData->pPrevious;</P>
5 Q5 M6 s1 X- g1 A N, P<P> if( m_pFirstActivePlayerData == pPlayerData ), L3 c( d* h P9 P6 D2 O
m_pFirstActivePlayerData = pPlayerData->pNext;</P>" K6 W2 i- T6 M4 G
<P> // Add it to the free list
( Q2 F& s) g! z+ I( m# T if( m_pFirstFreePlayerData )! ~. `% S3 M; k$ Q% Q2 f) t" \* F
m_pFirstFreePlayerData->pPrevious = pPlayerData;
" J7 Z' E8 I7 S$ Y pPlayerData->pNext = m_pFirstFreePlayerData;
( P5 @% K! v6 Z Z' y6 M( j pPlayerData->pPrevious = NULL;+ Z# M2 I# q9 A9 x( f0 h/ Z
m_pFirstFreePlayerData = pPlayerData;</P>
& s/ z/ T) T+ I, `- j. }/ j; d<P> // Update count of players
/ P1 ~& `, M/ t9 ^7 I$ F6 |! x; c m_dwActivePlayerDataCount--;</P>
1 ^5 }# N& X5 b0 B3 W% h: c; j<P> UnlockPlayerData( pPlayerData );
7 h, Y" F( @ M, Q# W; x' J m_PlayerDataListLock.Leave();' U F# C% F% g
}</P>
" c! J& \: l: p: S' L4 G- R8 X, _+ B9 v6 L' s" Y& q: k: ]% S
<P>1 z, m( V, f1 J, ]$ R
//-----------------------------------------------------------------------------
6 s3 k- _5 _0 W1 d* [- V// Name:
6 n0 @8 ^* V; S( D) Q9 x0 _) M// Desc:
9 \+ B: u, U9 v8 y' A//-----------------------------------------------------------------------------
! K! p. B0 y( vvoid CMazeServer::RemovePlayerDataFromCell( PlayerData* pPlayerData )4 i# ~- @$ R* n: [' O5 f2 w3 f$ L
{' J3 x& m) V" r" s8 M8 p
// Lock the player
1 Q, B; f" n, U l$ l LockPlayerData( pPlayerData );</P>6 M( E& Y! Y6 ?& `% I
<P> // Lock the cell the player is in# m9 {& v: N0 h" n" V4 o/ A8 M7 d. }
ServerCell* pCell;
# _+ |- |* r. H) d5 U! ~ if( pPlayerData->wCellX == 0xffff )8 C# N& j5 B* \
{% q8 W1 s3 I, @ J
m_OffMapLock.Enter();
7 t# n9 A( [2 ^: @5 S pCell = &m_OffMapCell;
8 |0 |/ d! ]! H2 }0 Y& n }: r2 u( @! N7 d9 {0 R1 k4 c
else
* e4 M3 N9 [/ \$ ~ {5 M$ @- O% Q8 ?
LockCell( pPlayerData->wCellX, pPlayerData->wCellY );
9 [' n$ X4 w2 m( ~4 R pCell = &m_Cells[pPlayerData->wCellY][pPlayerData->wCellX];6 B$ E/ N3 Q9 h/ r4 c( c3 z; z
}</P>
- q8 P, R& c5 U<P> // Remove it from the cell
+ N8 J3 m3 y" C, ~3 Y! _ PlayerData* pPt = pCell->pFirstPlayerData;
/ }) o! r3 y3 x' g% X+ ^ PlayerData* pPrev = NULL;
1 H2 ]8 Q: g5 P1 L; \. L" M1 Q0 W while ( pPt )0 Y) U( F5 l$ T/ J% @0 \
{
. J. v, g; l' o: y if( pPt == pPlayerData ): }3 |# `0 M1 s4 {' ^
{
: H T3 T+ V! ]' E; _4 a! f if( pPrev )
/ F! v+ d, o4 b4 H2 ?+ i5 S2 c+ r pPrev->pNextInCell = pPlayerData->pNextInCell;4 R- V) t/ a( C, X7 ~ S5 C! n! \ H
else
0 w; Z c; w! S6 ^0 m" g8 a pCell->pFirstPlayerData = pPlayerData->pNextInCell;</P>: M) r3 I. {! @; l. @
<P> pPlayerData->pNextInCell = NULL;2 Y6 [+ U* A6 W2 v# r' T$ I
break;
2 x( i3 e4 ] P2 T3 x }# Z' C: m3 Z9 o) _
pPrev = pPt;
2 p u, {5 g6 @% |- }6 K1 T h9 ~ pPt = pPt->pNextInCell;( r. {7 \( p- j$ L
}</P>
0 L7 \9 d' q! i* s: x<P> // Unlock the cell
' B, H" X( K, x if( pPlayerData->wCellX == 0xffff )) t+ p' x" \5 N9 j5 @4 g; k
m_OffMapLock.Leave();
. `: \0 K* Z d' a. x- O else
8 ]+ m8 H" J) Z: k# A- F8 F% _7 G UnlockCell( pPlayerData->wCellX, pPlayerData->wCellY );</P>
1 B) | q; U5 w<P> // Unlock the player+ E: s5 p1 j: p% s3 o
UnlockPlayerData( pPlayerData );2 I! m* l& v a9 J2 g+ z/ y
}</P>
6 A9 E' c. b6 @2 n P- k6 K2 g0 J! D
5 a. s$ C8 d8 s! b& P<P>3 ~7 m. F. s- M. z3 z
//-----------------------------------------------------------------------------
2 y6 c4 T5 ^" X5 _% c# Z3 z// Name: 1 I' D* u; r; P# J. B1 x9 ?, x0 M
// Desc:
8 x' a! {5 v1 V% Z$ o//-----------------------------------------------------------------------------: Z$ M1 ~: ]% E! d* w6 p
void CMazeServer::UnsafeRemovePlayerDataFromCell( PlayerData* pPlayerData )) x( q6 j$ c; Q' U$ D9 d* g0 l Q1 |
{# m6 `) o6 a2 O& g1 i* ~
ServerCell* pCell = GetCell( pPlayerData );3 r9 m: W4 ^% C* o# `* d4 V
PlayerData* pPt = pCell->pFirstPlayerData;- I" m2 O6 [3 W. d2 N
PlayerData* pPrev = NULL;% |0 s& G5 G, k% t# ^; |
while ( pPt )& I/ z: M& S/ I0 D# U) N, u( I
{
& c, T5 }' B/ w- i$ t6 @3 [9 y0 ~ if( pPt == pPlayerData )$ R" \! b1 I4 X/ W3 n8 k: N
{
6 Q1 K2 L9 {; b/ g1 ~& ? if( pPrev )
# R, ]! p$ b7 k+ V& I pPrev->pNextInCell = pPlayerData->pNextInCell;
4 n& l3 Y8 ? u1 f else
; G+ X% s- X# J( ?, R+ Z2 n pCell->pFirstPlayerData = pPlayerData->pNextInCell;! \% z" B3 X3 a! W' S7 E! F
pPlayerData->pNextInCell = NULL; V1 |2 E! s+ {8 [9 G# H
break;; ?: P3 O& t/ p) T' t* v
}* b* H4 w! a E% R" I( z2 r
pPrev = pPt;( Q8 L+ G9 s4 g/ [3 R0 O
pPt = pPt->pNextInCell;, b i1 L! I( P+ J! R3 N9 M* _
}5 D# F) n; `5 e% {( i C) H' x
}</P>9 I: Q) `, [6 [) V/ v f( s
' p3 q/ b* [1 _
<P>3 K( y! s6 _: }" k
//-----------------------------------------------------------------------------9 N6 X1 N5 Z: J" r% F4 M5 ^
// Name:
" w. C9 p9 v% b+ W! ^// Desc:
" O0 A* O9 R4 d1 `//-----------------------------------------------------------------------------5 S+ y$ D1 u# M. T' J
void CMazeServer::UnsafeAddPlayerDataToCell( PlayerData* pPlayerData )
8 U5 l. g! E% ~5 O4 |{& L7 p, P+ N. y& {
ServerCell* pCell = GetCell( pPlayerData );; \" N. X* y% t; j s/ W
pPlayerData->pNextInCell = pCell->pFirstPlayerData;
9 e& Z% a. D+ u4 u pCell->pFirstPlayerData = pPlayerData;
7 L- x( P! G- O- o' j4 j" ?# E( t}</P>
- E3 `+ [8 U# i9 M
' A9 v4 E0 u X$ C. \<P>
$ i% f0 ~2 j' _+ w# H+ L//-----------------------------------------------------------------------------
9 P. \/ u2 a1 C2 b7 w0 x) w7 r// Name: : t; N6 M8 q1 q7 b* Y% Q% Y4 ?4 g
// Desc: 9 o: [, T. y% z6 w
//-----------------------------------------------------------------------------$ k+ E8 @. \4 i9 P; P0 u: E! q
void CMazeServer::HandleClientPosPacket( DWORD dwFrom, ClientPosPacket* pClientPosPack )' N$ R) M k. ^; ?( V& s( v6 g
{! x" W, V# E$ Z& N& B6 g$ F
// Grab player for this client and lock it
, z/ e5 F5 r% K7 X% J PlayerData* pFromPlayer = GetPlayerDataForID( dwFrom );. m! S$ {- P$ X
if( pFromPlayer == NULL )' l, k0 y o: s% V. q+ f, z
{
$ W6 ^% W# K/ {- `# j7 w& p$ F) f if( m_dwLogLevel > 1 )$ s8 g7 x0 a9 x
ConsolePrintf( SLINE_LOG, TEXT("DPNID %0.8x: Could not find data structure for this player"), pFromPlayer->NetID );
4 O% A" \# N6 ^ return;8 o g \ O: f: D
}</P> `0 Q' T( J$ _' M( t& a& ^# X
<P> LockPlayerData( pFromPlayer );</P>9 V+ o6 ~- u; T- `7 n1 Y8 M) F" z; z0 F3 }
<P> if( FALSE == pFromPlayer->bAllow ), p6 Y2 j# _* ~/ C
{" l9 D4 Z# } M: v e! E5 d3 j
if( m_dwLogLevel > 0 )
) |, F* P+ d9 j# W* K3 P6 } ConsolePrintf( SLINE_LOG, TEXT("DPNID %0.8x: Got position packet from bad client. Rejecting client"), pFromPlayer->NetID );</P>5 w% H) D3 \: N" x p+ B) _' e
<P> m_pNet->RejectClient( dwFrom, DISCONNNECT_REASON_CLIENT_OUT_OF_DATE );& q- f6 U6 r5 H# \* r0 v! H
UnlockPlayerData( pFromPlayer );6 m# k; ~8 B* F# J$ `, s
return;: I' j8 z3 [( \ Y
}</P>
* j) r) P1 s0 b4 A5 \! K<P> // Compute the cell the player should be in now
8 @8 Y5 [- ^ p! W3 x- `! d& a DWORD newcellx = int(pClientPosPack->fX);
5 A* _! p4 z, ^ DWORD newcelly = int(pClientPosPack->fY);
' V1 [4 I& [' M* b DWORD oldcellx = pFromPlayer->wCellX;
. R5 E7 J& Z" @7 a8 p: S DWORD oldcelly = pFromPlayer->wCellY;</P>8 Z7 Z0 n, A. ~
<P> // Have we moved cell?
: P% R2 g3 o- r( w0 p- G if( newcellx != oldcellx || newcelly != oldcelly )" }( p, D q/ F2 _3 I s1 ~
{; l0 H2 j2 R, W& g. B4 q
// Yes, so lock the pair of cells in question
; s$ u1 I& e6 L& s6 @+ T LockCellPair( oldcellx, oldcelly, newcellx, newcelly );</P>
0 w: @; U3 t3 S% s. D7 G( ~<P> // Remove from old cell and add to new cell
4 }1 a7 o* ]1 j- i; M! R4 p UnsafeRemovePlayerDataFromCell( pFromPlayer );0 W0 j% [) z4 f7 p& ?
pFromPlayer->wCellX = WORD(newcellx); pFromPlayer->wCellY = WORD(newcelly);
7 L! r- I' y" A- v% h$ m6 n. P/ { UnsafeAddPlayerDataToCell( pFromPlayer );</P>
0 B! o+ B9 E# C8 ?<P> // Unlock cells' x5 M- k+ @7 ^7 k2 I
UnlockCellPair( oldcellx, oldcelly, newcellx, newcelly );4 H7 S: o: k* w7 i5 X
}</P>5 ]2 E8 E5 r! \; t
<P> // Update player position
6 n% t) ?/ q# Z! h; S pFromPlayer->fPosX = pClientPosPack->fX;5 B1 Q7 C8 l: p! i) R- W
pFromPlayer->fPosY = pClientPosPack->fY;
8 ]; b! [ S6 } pFromPlayer->aCameraYaw = pClientPosPack->aCameraYaw;</P>
9 L' U, b0 Y' O K9 E<P> // Allocate space to build the reply packet, and fill in header
2 C" }" Q: S* d; v: t8 I DWORD dwAllocSize;
7 D, [6 \! J9 L0 H, S6 V, M) T4 h ServerAckPacket* pSvrAckPack = NULL;</P>
7 D# h8 E6 r* [- W0 l<P> // Begin by allocating a buffer sized according to
?3 S( w! B1 N% }$ D // the current number of nearby players + 4. This will give ( S" R4 l" \3 z' R9 [; x
// a little room for more players to come 'near' without resize
$ K8 N% R" S$ ^+ k // the buffer.
; a) K0 }: |% A* Q DWORD dwMaxPlayerStatePackets = pFromPlayer->dwNumNearbyPlayers + 4;</P>" ?* i5 ]$ R$ h
<P> dwAllocSize = sizeof(ServerAckPacket) + dwMaxPlayerStatePackets*sizeof(PlayerStatePacket);- b7 O- w/ \$ o8 r) U3 p9 t% E. a
pSvrAckPack = (ServerAckPacket*) realloc( pSvrAckPack, dwAllocSize ); {' S% p7 C# x
if( NULL == pSvrAckPack )
" }& [ l- w& C1 z# `: T {# r$ A2 `# D& ~) S8 L
// Out of mem. Cleanup and return2 }$ p* n# T9 T% w2 ]: ?
UnlockPlayerData( pFromPlayer ); M X" e2 C9 }( B! [; T
return; / K+ j& C; v9 w+ n0 Q; i
}' _$ z: q2 U1 h6 w4 b4 P
ZeroMemory( pSvrAckPack, dwAllocSize );</P>
4 Q% S" e; }9 v% i<P> *pSvrAckPack = ServerAckPacket(m_dwPlayerCount);
, ^4 ?* n' g- _# W% V pSvrAckPack->wPlayerStatePacketCount = 0;
1 I* B y, o0 ^% z7 q! v4 { PlayerStatePacket* pChunk = (PlayerStatePacket*)(pSvrAckPack+1);</P># ~2 N" [* O; z7 T3 P9 K- i
<P> // Compute range of cells we're going to scan for players to send, D- m; B1 U2 ?8 I# n$ M
DWORD minx = (newcellx > 7) ? (newcellx - 7) : 0;8 I& r! c" T4 K, l( F0 E% b
DWORD miny = (newcelly > 7) ? (newcelly - 7) : 0;; | x( X5 q! a
DWORD maxx = (newcellx+7 >= m_dwWidth) ? m_dwWidth-1 : newcellx+7;
- h5 G3 Q$ X+ r% Q DWORD maxy = (newcelly+7 >= m_dwHeight) ? m_dwHeight-1 : newcelly+7;</P>4 G+ w, {* m2 n T" s
<P> // Lock that range of cells
( l8 p; Z9 T) P# y: k& H e LockRange( minx, miny, maxx, maxy );</P>
; B- h6 m* s8 s D<P> // Scan through the cells, tagging player data onto the end of
5 |( F, S* @7 E // our pSvrAckPacket until we run out of room& }0 N/ r/ A5 R$ G
for( DWORD y = miny; y <= maxy; y++ )
4 q8 z2 p) ]! R {
6 C0 u" e& g8 E9 l7 a7 F for( DWORD x = minx; x <= maxx; x++ ) Y' j+ s% q& ~
{8 ~! [# z1 [) J' T+ Y- _' w
PlayerData* pCurPlayerData = m_Cells[y][x].pFirstPlayerData;
0 O# x+ g. n/ C% w' K while ( pCurPlayerData )+ R4 N. H- z) |* F
{2 w! [6 L1 ]8 q6 X+ B
if( pCurPlayerData != pFromPlayer )
% @. Y# }* B: x. X1 N. p/ O {4 A: c) S5 f( K
if( pSvrAckPack->wPlayerStatePacketCount >= dwMaxPlayerStatePackets )
$ D1 r# [- [2 T7 m {
; G7 V7 G7 X6 H // Make sure pChunk is where we think it is
7 x) j$ E3 Q/ N) ^0 O assert( (BYTE*) pChunk == (BYTE*) ((BYTE*)pSvrAckPack + sizeof(ServerAckPacket) + pSvrAckPack->wPlayerStatePacketCount*sizeof(PlayerStatePacket)) );</P>7 H+ [4 x1 \4 q: w0 [2 o1 B
<P> // There are more than just 4 new nearby players, so resize the 2 O) V) h T# p* b& e7 m
// buffer pSvrAckPack to allow 16 more PlayerStatePacket's.% n4 f$ y+ K# E1 J/ ~5 G0 {
dwMaxPlayerStatePackets += 16;7 \% b- [9 |9 _$ c T& G% d* ~* k# J
dwAllocSize = sizeof(ServerAckPacket) + dwMaxPlayerStatePackets*sizeof(PlayerStatePacket);
' r6 u! N, v" d n7 \7 _6 Y X9 w ServerAckPacket* pNewSvrAckPack = NULL;: z. `: w' p$ l) v. g
pNewSvrAckPack = (ServerAckPacket*) realloc( pSvrAckPack, dwAllocSize );2 Q$ t5 n* e* S
if( NULL == pNewSvrAckPack )7 \: l2 K6 p- L1 [9 [& m( R( g
{
: c `$ x7 ^9 u; E8 V // Out of mem. Cleanup and return( b9 Y; L5 V5 I" O% ~/ q
free( pSvrAckPack );, P4 n8 L2 c) @7 K2 T# a; U4 |/ G
UnlockRange( minx, miny, maxx, maxy );
1 T; A& j% i0 @8 _0 } UnlockPlayerData( pFromPlayer );
* ?3 L, O+ G+ Z' Z% E* |, { return;
; e2 L9 l) \0 w& e+ T }</P>, A, {. a7 c1 E* d
<P> pSvrAckPack = pNewSvrAckPack;
7 A; w" P' d4 h4 n' _ pChunk = (PlayerStatePacket*) ((BYTE*) ((BYTE*)pSvrAckPack + sizeof(ServerAckPacket) + pSvrAckPack->wPlayerStatePacketCount*sizeof(PlayerStatePacket) ) );</P>
1 E' \8 Z6 ?7 K<P> // Make sure pChunk is still where its supposed to be6 Q) d5 i, S+ `+ a
assert( (BYTE*) pChunk == (BYTE*) ((BYTE*)pSvrAckPack + sizeof(ServerAckPacket) + pSvrAckPack->wPlayerStatePacketCount*sizeof(PlayerStatePacket)) );3 E6 I) Q5 [/ D& v, x: E
}</P>% s. E0 R, U2 t" F4 E
<P> pChunk->dwID = pCurPlayerData->dwID;- }2 V: ]- l7 R" X# @1 ]
pChunk->fX = pCurPlayerData->fPosX;
2 N* _2 ^* }) b# w pChunk->fY = pCurPlayerData->fPosY;
6 C0 J T4 a& u9 [' Y2 B7 s2 l pChunk->aCameraYaw = pCurPlayerData->aCameraYaw;* M6 z* i- ?( R0 z: c
pChunk++;% h6 o; U# [' H6 A1 w$ H
pSvrAckPack->wPlayerStatePacketCount++;
6 x" K! |+ c, X% g: p& o* ?! @ }
) j* l! _* d6 C: z& F* w8 \4 x* } pCurPlayerData = pCurPlayerData->pNextInCell;$ b0 a4 J; `) u* E# _
}$ I3 f8 H/ t" I( L+ A3 V( j4 g! B
}
3 F1 p4 x- M+ Y }</P>/ A! Z! _ ^9 V$ z
<P> // Update the dwNumNearbyPlayers for this player
8 }. F4 Y3 U( S' L5 P pFromPlayer->dwNumNearbyPlayers = pSvrAckPack->wPlayerStatePacketCount;</P>
, s8 O+ _3 y" X" l, W1 ^" u3 }<P> // Unlock range of cells9 Y/ f8 i$ \0 u9 A4 u& }( {
UnlockRange( minx, miny, maxx, maxy );</P>
( a' P+ o, m/ J( R t$ B0 g1 w<P> if( m_dwLogLevel > 2 )
; N3 r- ~1 g) r. _) L4 ^7 s {
4 G8 T0 |. ~0 j9 Y" @ ConsolePrintf( SLINE_LOG, TEXT("DPNID %0.8x: Position is (%0.2f,%0.2f)"), pFromPlayer->NetID, pFromPlayer->fPosX, pFromPlayer->fPosY );; C$ s7 x7 ^, m. `1 O# N
}( G$ ]5 n9 ~1 M1 x& K
else if( m_dwLogLevel == 2 )
0 k4 _% ]. I- b( {& ~, [- J {% L5 U! w4 m3 A, N* Q" ?& @
FLOAT fTime = DXUtil_Timer( TIMER_GETAPPTIME );
' X# b7 F2 n& h8 ~3 j! b if( fTime - pFromPlayer->fLastDisplayTime > 60.0f )
: t4 p4 v% }2 i5 N {8 r/ D; l0 y; p
ConsolePrintf( SLINE_LOG, TEXT("DPNID %0.8x: Position is (%0.2f,%0.2f)"), pFromPlayer->NetID, pFromPlayer->fPosX, pFromPlayer->fPosY );5 T3 L( J/ g# x$ U; R6 {, X
pFromPlayer->fLastDisplayTime = fTime;
% x" s5 {! M! V3 L4 I }+ I |9 `. q2 Y+ X
}</P>
8 R+ K$ u8 n! S9 R, O' E<P> // Unlock the playerdata
?0 y, L9 m1 o U5 D8 g UnlockPlayerData( pFromPlayer );</P>9 f! |$ s; F) a, L9 a, C
<P> // Send acknowledgement back to client, including list of nearby players 9 v2 T# | N/ k2 @7 W
DWORD acksize = sizeof(ServerAckPacket) + (pSvrAckPack->wPlayerStatePacketCount * sizeof(PlayerStatePacket));5 r$ q2 i6 V) v- S! b
2 u$ n! Y- M; y6 c0 t) W // Pack the buffer with dummy data.2 o k* T2 p; y* W7 t
if(m_ClientNetConfig.wServerPackSizeArray[m_ClientNetConfig.ubServerPackIndex] > 0)0 K) {4 \( i8 Z& b+ p7 u
{2 K5 {! T; }" C3 ?. Y1 Z
DWORD dwBufferSize = acksize + m_ClientNetConfig.wServerPackSizeArray[m_ClientNetConfig.ubServerPackIndex];
+ ` L5 f; B# Z4 o" H. j: G VOID* pTempBuffer = 0;</P>/ d3 o# Q) D9 o+ L: O
<P> pTempBuffer = malloc(dwBufferSize); x9 I3 F0 Z+ b7 C
if( NULL == pTempBuffer )% J% E0 l% C p: A0 J# l
{
" c/ u. Y3 z# d! t //Out of memory
S( g/ A' c; z* Z6 k. l DXTRACE_ERR_NOMSGBOX( TEXT("System out of Memory!"), E_OUTOFMEMORY );3 ?/ c) K0 J! W
free( pSvrAckPack );
/ |/ z0 L U; x) R9 W! n: F: P return;
$ F$ n! g4 F8 n5 {7 r9 J }</P>
, M3 p& X- `7 P6 ?<P> FillMemory(pTempBuffer, dwBufferSize, 'Z');
' e7 l% q; d7 C& z: E) C J e* s memcpy(pTempBuffer, pSvrAckPack, acksize);</P>, J& s9 E5 O* Y! ~9 j
<P> SendPacket( dwFrom, pTempBuffer, dwBufferSize, FALSE, m_dwServerTimeout );! K2 J9 t o g p! R* J- m3 D- j, Y
1 R2 C* k2 i/ x1 k* ~) w
free(pTempBuffer);
% _- Y0 o& {7 A5 u }
# K, T- v: \8 }1 t5 U c W) D else
/ r5 x& r- m. g2 C {6 {8 F/ y, U8 z# F
SendPacket( dwFrom, pSvrAckPack, acksize, FALSE, m_dwServerTimeout );7 X4 p7 M S2 l0 |
}</P>0 i5 w3 B$ y; Z+ \
<P> free( pSvrAckPack );</P>
. @+ {2 F' N$ e1 \- y<P>}</P>3 O7 d% g; j8 S, `
# W' n6 M/ T- b5 i8 }- ?" K0 K, B# c
<P>
* A3 C1 {5 K' c0 C//-----------------------------------------------------------------------------
+ f4 \: X; f: `, p+ ?+ |// Name:
6 |; p0 Z3 x% C// Desc:
. d6 p! d) S% m' j//-----------------------------------------------------------------------------( L1 O1 z* k5 ?; F3 }6 p0 ]
void CMazeServer::HandleClientVersionPacket( DWORD dwFrom, ClientVersionPacket* pClientVersionPack )
3 z$ m) E8 y& \' u) z' ]{
* N" X8 @, \7 a2 E5 ]: P // Grab playerdata for this client and lock it* c) [( A( F7 S& @0 U
PlayerData* pPlayerData = GetPlayerDataForID( dwFrom );
# t, R6 ~" W2 V6 ?. M+ b if( pPlayerData == NULL )* ?- [. d d' R: R0 S' {
return;/ h4 f/ W( A. l
LockPlayerData( pPlayerData );</P>* k: e9 R# [: X5 k: g9 ^" Z
<P> // Record the version number ) R+ T+ U9 q0 n# e7 \. j) C" h* E! F; a
pPlayerData->dwVersion = pClientVersionPack->dwVersion;</P>
$ x" l8 ?% i8 s- ?) o<P> if( m_bLocalLoopback )* b% Q& p* B- O6 T
pPlayerData->bAllow = TRUE;; M# w$ ], j4 y4 Y; k& C1 U5 _
else, U* i& K( h$ s
pPlayerData->bAllow = IsClientVersionSupported( pClientVersionPack->dwVersion );</P>
) D3 J9 l! @1 C<P> if( m_dwLogLevel > 0 ): \: c5 M+ T* ~
ConsolePrintf( SLINE_LOG, TEXT("DPNID %0.8x: Client version=%d (%s)"), pPlayerData->NetID, pPlayerData->dwVersion, pPlayerData->bAllow ? TEXT("Accepted") : TEXT("Rejected") );</P>+ O. G4 }8 E( M9 U: ^
<P> if( FALSE == pPlayerData->bAllow )1 I# c5 L: [4 |; X
{
4 O8 S C7 [- c8 L1 ?! m if( m_dwLogLevel > 0 ); R4 m) X0 o& l. E9 b, [
ConsolePrintf( SLINE_LOG, TEXT("DPNID %0.8x: Rejecting client"), pPlayerData->NetID );</P>/ X6 m E: F" v3 t
<P> m_pNet->RejectClient( dwFrom, DISCONNNECT_REASON_CLIENT_OUT_OF_DATE );- @& d! X- M( H( }& K5 @0 j
UnlockPlayerData( pPlayerData );
+ [, U2 v( e% v w3 W return;
" U1 `+ h7 q1 B# x2 j9 T }</P>
" I& n3 [& m4 o# ^9 P; x" C: o* H<P> // Unlock the playerdata. T' k# C& R0 t S% a
UnlockPlayerData( pPlayerData );</P>
* N! d+ o$ q0 j- _3 M<P> // Send acknowledgement to client that the client was either accepted or rejected! B8 z- V! y. w5 F7 \$ O A* S, {! ?5 L
ServerAckVersionPacket packet( pPlayerData->bAllow, dwFrom );/ u0 F: E; M, K% }
SendPacket( dwFrom, &packet, sizeof(packet), TRUE, 0 );' M2 K" e% r! S1 M' B
}</P>
5 w: E! e, D) T' H+ `( `; e" {, I! _$ X: a
<P>/ M( T% i% F1 w8 E; T
//-----------------------------------------------------------------------------
6 d0 C6 g$ m% Z. E: H2 x% H// Name:
1 O: B; b3 ^8 p- R0 s! E- z// Desc: " ^, y% V% U6 ]3 C4 R
//-----------------------------------------------------------------------------) ~! @4 G t! R( F" n
BOOL CMazeServer::IsClientVersionSupported( DWORD dwClientVersion )
$ L$ b# Q" G! n{' @1 ]9 L7 N0 ~& o/ K
switch( dwClientVersion )
2 o. O+ B# N8 Y* }% n9 m {8 f7 w2 n6 k1 k* P( }- p$ [6 J$ U; P
case 107: // only v107 is supported
" z9 a8 j( E; E( W4 N1 D' K return TRUE;
6 R: l( o: ]3 W+ a8 D. X9 ~+ j default:
' s% s: v8 `# M2 O4 Y return FALSE;) n% ]3 b/ J# b1 A
}6 I8 e$ Z z2 A& k. d- ]
}</P>8 L$ d N) ?% W: l+ r, i
6 J) D" T( U4 D- @& b' a. i1 w<P> ]* S) j6 Y- c% E: K( x. L ^
//-----------------------------------------------------------------------------* F J" o1 ~5 P7 P
// Name:
+ W* V' N3 w. w! _7 @! E- Y// Desc:
! Q# S% F& f/ ?' {$ D, ^- K//-----------------------------------------------------------------------------3 b L( [1 {0 A
void CMazeServer::HandleUnknownPacket( DWORD dwFrom, ClientPacket* pClientPack, DWORD size )
! g N5 ^6 @% X" g{
5 k! Y: \ C6 J8 T. _- { if( m_dwLogLevel > 1 )
+ D7 Z. ?/ Z$ X9 i, X# V; h ConsolePrintf( SLINE_LOG, TEXT("ERROR! Unknown %d byte packet from player %0.8x"), size, dwFrom );</P>8 v3 @3 @. a; R, s" ]
<P> m_pNet->RejectClient( dwFrom, DISCONNNECT_REASON_CLIENT_OUT_OF_DATE );2 t7 c4 O+ J' ]$ b
}</P>- Y$ A9 e; ~* j& P& R$ |8 g
( T- p: r- } C# A
<P>
, r1 R. X9 T9 F- S6 X//-----------------------------------------------------------------------------
: m7 z2 t0 D8 x% q" S// Name: & y! R* X) A) e* M" h& a, d3 ^
// Desc: 8 h0 X9 A9 k" b/ ^! h& H
//-----------------------------------------------------------------------------
1 N6 g4 q6 U- T( r( Q8 q, KDWORD CMazeServer::IDHash( DWORD id )
# }- g! G# B' S{
, V6 Y' }( I" { DWORD hash = ((id) + (id>>8) + (id>>16) + (id>>24)) & (NUM_ID_HASH_BUCKETS-1);
" g: o5 Z9 [0 ~! J) A9 N& f+ P return hash;$ v! G/ a1 Y4 h
}</P>
% D# n/ V& g Z* d7 y% `3 B0 A# B( ]( T2 q( y& j
<P>* ^: C5 p2 E" a: _2 N# Q6 l
//------------------------------------------------------------------------------ h8 k, E+ ]+ N5 j
// Name:
/ V1 l& q: ^* a! ]/ q. `// Desc:
' |5 m4 ], g9 G' n- n- Z$ o//-----------------------------------------------------------------------------; k# T3 K* M! ?4 b3 [" [/ n
void CMazeServer::RemovePlayerDataID( PlayerData* pPlayerData )
3 A. ?& E6 Z! ~2 F{
3 M) e7 x1 N3 i // Hash the ID to a bucket number0 o! W, D1 H& N( I% j" h
DWORD bucket = IDHash( pPlayerData->NetID );</P>
1 @7 S; Z6 @/ X+ ^8 t<P> // Lock that hash bucket
2 J( A% C- l. m' }; H const DWORD buckets_per_lock = NUM_ID_HASH_BUCKETS / NUM_ID_HASH_BUCKET_LOCKS;/ k+ } ?& }( w/ I/ ~) o2 t
m_IDHashBucketLocks[bucket/buckets_per_lock].Enter();</P>& F* z/ k; A6 @, I3 ^
<P> // Loop though players in bucket until we find the right one
# ^$ x+ r( d! T6 C0 F PlayerData* pPt = m_pstIDHashBucket[bucket];; r0 u& h; [ S/ Y# J% Q: U0 M
PlayerData* pPrev = NULL;& R9 R Z; m+ H! p" Z, |# f
while( pPt )+ Q- ?7 X$ A2 [8 d; C: Z, m
{( k9 v: s" q5 \/ Q; O3 z0 _
if( pPt == pPlayerData )
4 @3 _% V" }: @2 g( x/ |& |( g break;
$ U3 G% |6 b! `8 q" v- o pPrev = pPt;
9 K0 m0 m+ o! \5 R5 K: } pPt = pPt->pNextInIDHashBucket;
. V% g( D! t) z }</P>% Z. t% Y0 v1 \) L1 A8 k
<P> if( pPt )
5 Y& ]' |9 w6 J! R* v' ]7 X! ` {
4 a* J8 s: v I if( pPrev )# {% b' i+ L4 `
pPrev->pNextInIDHashBucket = pPt->pNextInIDHashBucket;
$ ^9 r# N& l2 C7 \$ X- ` else5 `7 J8 `& i/ H P# q* I9 P+ k" k
m_pstIDHashBucket[bucket] = pPt->pNextInIDHashBucket;% ~$ x; Z3 I( A2 D3 H' H! f# b5 y C
pPt->pNextInIDHashBucket = NULL;7 J3 c; [) R) |% J: ?) g
}</P>
, y, l4 j7 x, e. Y1 {: Z6 q1 V<P> // Unlock the hash bucket$ k2 b, L) r/ `7 K0 [: p
m_IDHashBucketLocks[bucket/buckets_per_lock].Leave();5 n0 [+ e. Q3 ?' V
}</P>
& m4 Q5 g I% n: m( C. i/ `2 `6 I7 i: v1 [) a; E2 i4 j$ J7 Z6 ^
<P>
5 Z4 @, W4 @( _" ~//-----------------------------------------------------------------------------7 ` |6 ?' s9 L) S; R7 p
// Name: ) ~/ x \3 J& T4 U8 P' {( b
// Desc:
' d0 s! H$ D ]9 \//-----------------------------------------------------------------------------
# z1 U6 Q, N! @- Vvoid CMazeServer::SetPlayerDataForID( DWORD id, PlayerData* pPlayerData )
, p- r# A6 Q1 F: ~8 S. m{3 }( _9 R1 ` B" i
// Make sure this player isn't added twice to the m_pstIDHashBucket[]
5 B& t6 Q* ?% L' F# T5 r k // otherwise there will be a circular reference5 r/ G$ _& c+ X8 p0 E
PlayerData* pSearch = GetPlayerDataForID( id );
; d; g# r" y; [% G1 h if( pSearch != NULL )
1 `3 J2 T+ _2 ^! T3 k2 |+ P return;</P>
, Y7 O1 i) Q: `0 L4 ]( m( {& v<P> // Hash the ID to a bucket number% x- W. v. I1 ^+ Q3 J& m6 D' i
DWORD bucket = IDHash( id );</P>, v- E. w% Q7 _* f% f% C
<P> // Lock that hash bucket
. j9 `( c3 ^0 ?/ d8 [& n const DWORD buckets_per_lock = NUM_ID_HASH_BUCKETS / NUM_ID_HASH_BUCKET_LOCKS;" \$ C) D& |- a1 ^6 @# I% j3 Y0 W
m_IDHashBucketLocks[bucket/buckets_per_lock].Enter();</P>
( t8 Y& i* A7 o, K<P> // Add player onto hash bucket chain9 x Q8 y# e" i" z
pPlayerData->pNextInIDHashBucket = m_pstIDHashBucket[bucket];& _) ?6 b; U3 M. C% Z
m_pstIDHashBucket[bucket] = pPlayerData;</P>
, c2 h( |1 s- M9 c- L7 O<P> // Store net id in player
4 w" E* o4 W1 N4 B6 B3 u3 _/ g6 Z pPlayerData->NetID = id;</P>
; ~; C! V3 J- l/ S5 z" L, u) t3 ?9 r {<P> // Unlock the hash bucket
- _% W5 D1 N! p* i5 ^7 ^ m_IDHashBucketLocks[bucket/buckets_per_lock].Leave();- E1 t! f- G: f r' e6 l& `* K
}</P>0 M) Z9 k+ U3 L
+ \+ t$ p+ b5 i) {8 }$ P<P>. B1 y6 |1 O( \( u x
//-----------------------------------------------------------------------------. ]2 k7 y6 W- K' V
// Name:
2 W& }6 x# c* `! d$ \0 m( l6 t// Desc:
- S2 W5 T( ]4 P* d: l; O. L//-----------------------------------------------------------------------------: y+ _; Z# X) m1 @
PlayerData* CMazeServer::GetPlayerDataForID( DWORD id )
' h2 j: S6 b2 R) D/ l# _1 A{
& n, l+ Y. \3 w. d/ P) \2 S: M" \ // Hash the ID to a bucket number; c5 d% J! H+ V# E, B8 p/ D
DWORD bucket = IDHash( id );</P>- {$ l3 u# `% ^! O5 Z
<P> // Lock that hash bucket
2 x' S/ |" E6 \; ?/ x3 m( ] const DWORD buckets_per_lock = NUM_ID_HASH_BUCKETS / NUM_ID_HASH_BUCKET_LOCKS;
8 e: C' S) h( H# j2 }' P* {" s m_IDHashBucketLocks[bucket/buckets_per_lock].Enter();</P>
5 m3 ~7 D {; j4 ~5 a<P> // Loop though players in bucket until we find the right one
# q% g) i F8 a/ F! d PlayerData* pPlayerData = m_pstIDHashBucket[bucket];4 P h2 X6 W8 m5 ?
while ( pPlayerData )
+ G9 X. b' c' D/ \ {
. X3 t- m1 S% ~6 N! `( x* ` w if( pPlayerData->NetID == id )
6 d8 E D2 N0 ^+ @; `( o* a break; T/ L) b ^* _# D# \
pPlayerData = pPlayerData->pNextInIDHashBucket;
0 y9 I3 B. ~4 O: U, m3 K }</P>3 F0 B2 ?' J+ ^2 [
<P> // Unlock the hash bucket' K T# O# n% v2 ]+ T
m_IDHashBucketLocks[bucket/buckets_per_lock].Leave();</P>
, l& G7 o+ ]5 P# n! _+ O T/ c1 n) u<P> // Return the player we found (will be NULL if we couldn't find it)
$ d) f' P, g- W; T/ I3 \4 ` return pPlayerData;
8 t9 p: E# q0 e3 d k P: b}</P>
; c+ A3 F5 @5 Q; u% C t Z' `3 q. Y. s: g2 M& Z7 b. O/ x' d H
<P>
0 r4 z q5 ]" n0 E! M//-----------------------------------------------------------------------------
8 [8 k3 L8 p8 K J4 A: |% r// Name: 3 f s! l' q. l4 m2 R# o) m
// Desc: calls DisplayConnectionInfo for each connection in a round-robin manner
, n* H2 |; X/ O8 Z9 f1 Z7 i$ ~ @//-----------------------------------------------------------------------------. s2 s+ d8 Z3 g8 s
void CMazeServer: isplayNextConnectionInfo()7 k5 }5 O4 R* c% e0 y: ~
{# \5 B4 u' w$ o+ M! Q
if( m_pNet )
, W6 _2 m2 C7 j' x' N! F {6 L% v+ F( O- u0 U; {
// Find the player that was displayed the longest time ago, and display it.# H% o* d, \- x+ k! f
FLOAT fCurTime = DXUtil_Timer( TIMER_GETAPPTIME );
4 U3 b/ h$ X. Z2 Y, ] PlayerData* pOldestPlayerData = NULL;4 j) @6 k) G" `: Y, [
FLOAT fOldestTime = 0.0f;</P>
) D& i7 P4 C0 Y4 N$ J! j+ A<P> m_PlayerDataListLock.Enter();</P>
' e7 t: H: \1 h2 X: c3 @<P> PlayerData* pPlayerData = m_pFirstActivePlayerData;- `8 D! v, L, L6 y* W: j6 t2 h
while ( pPlayerData )# g/ N$ Z- R& S! S" h4 _4 f P; u& |
{! E3 y6 y4 M0 C( H$ p
if( fCurTime - pPlayerData->fLastCITime > fOldestTime )
4 p" y% B2 s2 R {
1 Q" M( S1 W; D fOldestTime = fCurTime - pPlayerData->fLastCITime;2 B% v- `( R* K8 G; Q
pOldestPlayerData = pPlayerData;& G. b1 l: d+ `0 Z0 R, z
}</P>+ g1 b/ `2 {0 V& b
<P> pPlayerData = pPlayerData->pNext;
' t: J F4 J' u- E4 \, H }</P>+ e* C5 k/ r n; j3 M. s# i; ?
<P> // Display the player with the oldest CI field, and update its CI field.7 _2 {1 B, u6 }/ M0 W
if( pOldestPlayerData ); p& z( T# f! h$ g$ R
{9 ]( e0 v" C8 w, \
ConsolePrintf( SLINE_LOG, TEXT("Displaying connection info for next player") );
7 n5 ]2 u* E3 {2 T6 D0 E3 Y DisplayConnectionInfo( pOldestPlayerData->NetID );
T3 x6 p1 i+ V, b pOldestPlayerData->fLastCITime = fCurTime;8 [6 j* N$ A; w+ w
}
: ]& A j( L5 b$ R; j8 l else
2 `' v- q4 ]7 A: Z {: u. a# t% G5 w0 P
ConsolePrintf( SLINE_LOG, TEXT("No players found") ); X" g* L) @/ S, f( Y ~9 @
}</P>
% _+ X3 g; j' _! ^<P> m_PlayerDataListLock.Leave();
% j. f. f* E! C) d& v1 L5 i5 l( w& C0 I }' P: O0 P: g( d: j" E5 y8 I) I& T
}</P>
2 z y4 B5 w0 ]" j6 n
8 ^$ I0 n7 Z5 m$ ?& B! s<P>
* d, N9 L: f% j }- l/ v//------------------------------------------------------------------------------ v+ X4 n4 S) g4 b; a2 a: e! W
// Name:
/ l+ Z' \1 l& t& [) G" n// Desc:
8 d- I/ m& d$ ?. Y; e( `& r//-----------------------------------------------------------------------------
: p8 R0 y/ J# g4 c- j) Z7 l- [% gvoid CMazeServer: rintStats()
/ `1 o" W: R& w0 ^{: a/ K# e8 Y8 ~) X
ConsolePrintf( SLINE_LOG, TEXT("Thread count: Active=%d Avg=%.2f Max=%d"), 3 H9 G! H! s. }: d' W6 i; N
m_wActiveThreadCount, m_fAvgThreadCount, m_wMaxThreadCount );
7 h0 y0 a8 m- `! B ConsolePrintf( SLINE_LOG, TEXT("Thread Time: Avg=%.4f Max=%.4f(s)"),
8 N& c( O' t2 j& \/ X m_fAvgThreadTime, m_fMaxThreadTime );
& J8 r+ n% U& P) t) [ ConsolePrintf( SLINE_LOG, TEXT("Players online (not including server player): %d"), m_dwPlayerCount ); E) K7 f% c# {5 U
ConsolePrintf( SLINE_LOG, TEXT("Peak player count: %d"), m_dwPeakPlayerCount );& B5 s1 [/ d* I# A1 [( ^( X6 P" ]+ z
}</P>
! o: N L1 p! ~8 a0 T1 p' M9 t! e6 G" y3 w, u a
<P>
) y% m$ P' @; D+ X6 e9 k2 q//-----------------------------------------------------------------------------/ }0 d3 b% }* i2 V7 S- M
// Name:
% I B/ t. A4 X& T// Desc:
`9 `( r5 k. d//-----------------------------------------------------------------------------
, f, ~5 J' K# n$ e- hvoid CMazeServer: isplayConnectionInfo( DWORD dwID )
+ E0 l7 k t9 ^4 l. D/ Z0 S{
: ?; s! _% ^ p, f9 L7 P4 ]6 g/ m TCHAR strInfo[5000];
+ K. }" T% o2 G$ U; Y TCHAR* strEndOfLine;. x; v/ G8 U c, d2 W4 w* F
TCHAR* strStartOfLine;</P>
5 {1 p& v0 v! ?' y) j! u3 q5 C/ C<P> // Query the IOutboudNet for info about the connection to this user' R: @4 b7 J5 v8 Y; ^' q
m_pNet->GetConnectionInfo( dwID, strInfo );</P>
, X, F& j* W1 ?<P> ConsolePrintf( SLINE_LOG, TEXT("Displaying connection info for %0.8x"), dwID );
6 V( L* Z9 v4 H9 Q0 z# i ConsolePrintf( SLINE_LOG, TEXT("(Key: G=Guaranteed NG=Non-Guaranteed B=Bytes P=Packets)") );</P>
! S# ~$ l2 Z* g6 \<P> // Display each line seperately
' P( c) z# u7 n2 ~ strStartOfLine = strInfo;
4 x5 e# T! N, E) r while( TRUE )1 I/ A! D5 l3 l6 F( R
{
. V N- [6 l3 G d strEndOfLine = _tcschr( strStartOfLine, '\n' );
/ b% l- ]4 R( J0 w2 V d if( strEndOfLine == NULL )
" J7 Y9 F' Y9 x( }) n" }, H break;</P>
( u8 Y* D( T& n- p8 i2 S<P> *strEndOfLine = 0;' z) N6 R( a6 W8 @2 h# s
ConsolePrintf( SLINE_LOG, strStartOfLine );: W( e' _) ]& F% P+ f3 K2 N J
strStartOfLine = strEndOfLine + 1;
S) O/ G# `) H7 k7 z# [5 R }) W- T( t' P, _7 C" K: P
}</P>
' x3 l, y7 G' E! i4 j( l; E2 u2 r: S8 W c' |
<P>1 _4 I8 Z7 a0 Y! g7 I4 G3 m
//-----------------------------------------------------------------------------* r1 z. P' Z' }$ D9 r
// Name:
" W: `4 Y5 k. n' J+ ^4 f/ w) B// Desc:
1 m: @) L8 R1 N: ?//-----------------------------------------------------------------------------. s% a$ \; [; i9 d" I' Y" ~
HRESULT CMazeServer::SendPacket( DWORD to, void* pData, : J) x. _4 t( M0 x
DWORD size, BOOL reliable, DWORD dwTimeout )6 x, i t3 \* b- v b1 g3 A8 @/ ]
{$ l6 f' u3 V5 o1 @' o4 O y! g) x
// Chance of forcing any packet to be delivered reliably2 [7 h3 M( @0 G) H% m9 O0 E+ ^
if( m_Rand.Get( 100 ) < m_dwServerReliableRate )7 f: _2 ]& B v5 B
reliable = TRUE;</P>* e& W& @. p v7 W: c. c. l$ {
<P> return m_pNet->SendPacket( to, pData, size, reliable, dwTimeout );2 E- ?4 `6 g( V S. E% `8 K
}</P>
6 _/ w* ^: z: w3 i2 |; `
4 O3 b! n; W2 {6 i7 T- a! I, e<P>% s# }& X. u7 S+ O8 D8 X$ u
//-----------------------------------------------------------------------------/ H3 u* Y* q+ ~2 @1 e
// Name: 5 ~) X/ ~- P C3 T5 r: P% T
// Desc:
; m0 O, p+ X. c3 {( ?$ Z. i [//-----------------------------------------------------------------------------) j* l4 T b' n
void CMazeServer::SendConfigPacketToAll( ServerConfigPacket* pPacket )3 ^* P8 l+ {3 v* u; s5 C: Z
{
& N! ?3 d6 A2 |' \8 }* u3 i/ A // If we're up and running, then send this new information to all clients
- m8 z& e1 s. X b8 R! N if( m_pNet )3 D" d9 p: X; B6 I# s% c+ b8 v. u
{
6 q& V! S1 B' k4 X n. z //Use the AllPlayers ID
# i1 J* R2 ^* {2 c+ } SendPacket( DPNID_ALL_PLAYERS_GROUP, pPacket, sizeof(ServerConfigPacket), TRUE, 0 );
* o# x4 g, i; W1 o. p4 K+ i+ K* T }. ^. P. J9 W' r3 o, I0 U$ J5 b2 X3 F
}</P>1 Z9 U. B) R$ e8 D# h
4 n7 a0 n% K$ {/ {
<P>
& v$ Y' r6 ]* ?) L5 G! c3 S. Z//-----------------------------------------------------------------------------
; `3 ^* D* q9 V/ D8 E0 ]: \$ [// Name: 2 E' @! r4 i# a3 r
// Desc:
3 I6 Y& k' l3 t& j5 x: x" c//-----------------------------------------------------------------------------4 a! V% Q6 Q; R' u4 Z( j8 H$ q0 f
void CMazeServer::SetClientReliableRate( DWORD percent )
J9 D9 V6 ]3 m5 e& g{* u4 ]3 g+ K, [
// Update client config, and build packet containing that data
1 |! t' r3 X$ o2 ~8 ^ m_ClientNetConfigLock.Enter();( s$ M) S9 [3 t% b9 g
m_ClientNetConfig.ubReliableRate = BYTE(percent);
2 @) k- B$ J0 J6 k ServerConfigPacket packet( m_ClientNetConfig );$ d: I- s- [6 S1 A7 H" D- ?
m_ClientNetConfigLock.Leave();</P>( T' ^8 V% F( A& @+ y3 C
<P> SendConfigPacketToAll( &packet );
7 p# q, {8 k! v2 `# F% T) j' r}</P>, ]3 Y% a9 n1 ^
: h; s5 h( ^2 i) a- u9 n<P>5 E3 T1 x$ `' [5 U& a+ F
//-----------------------------------------------------------------------------1 M% |! ` B6 P+ T: s6 j5 l( _
// Name: ) ]0 r u% ?; P# s* S6 n
// Desc: 6 s) |) [% P$ Z; t* {4 G6 w) `
//-----------------------------------------------------------------------------2 L* F3 d4 p. f) W! T( ]$ T2 R, Y
void CMazeServer::SetClientUpdateRate( DWORD rate )
- |* c8 r0 r8 b3 L& g{, ~' W+ P5 b, C- M2 R3 c% ?: s
// Update client config, and build packet containing that data- d) I; t, b2 R- U. T" R/ H
m_ClientNetConfigLock.Enter();: N2 }9 @! F' j1 A2 B+ V3 T
m_ClientNetConfig.wUpdateRate = WORD(rate);
: I4 ~2 ~2 S1 e- q, q) j ServerConfigPacket packet( m_ClientNetConfig );
. j5 {( m# P* Y8 u4 W3 e m_ClientNetConfigLock.Leave();</P>
1 w# N! U j* ~1 W; ~7 ]<P> SendConfigPacketToAll( &packet );3 n" m* k; P1 ]5 u4 O. R3 [
}</P>: Q, a$ k ]( P% ?% [
9 G% ^) {5 |8 R! G" {+ O/ Q: l/ B# _<P>8 m- z$ y" Z% d- H
//-----------------------------------------------------------------------------
8 s4 q9 k0 i ~5 T( s6 a// Name: * _5 ?. Z4 i* G' ?3 ~ w8 V8 ?+ ?0 f$ j
// Desc:
, \) Z d) M1 b* z3 A8 [1 q5 J//-----------------------------------------------------------------------------5 M! g7 r. w$ G' D0 c4 Z! w& E
void CMazeServer::SetClientTimeout( DWORD timeout )
# J! `# E& i2 U2 k$ x: e2 K{
5 n* q, v3 D; L9 _. Q // Update client config, and build packet containing that data
+ {+ d/ P& q2 } m_ClientNetConfigLock.Enter();$ T1 R! n: ?3 T' n' W( ^0 y$ o
m_ClientNetConfig.wTimeout = WORD(timeout);+ B' w" O+ O- U: y$ t
ServerConfigPacket packet( m_ClientNetConfig );
; o) W9 O# X# R m+ l# O m_ClientNetConfigLock.Leave();</P>
' T- b! K: B3 w% g5 o<P> SendConfigPacketToAll( &packet );7 _5 q0 w" B' x
}</P>( W7 X- x" f& `0 c4 _. C
$ g: {+ K' {# y3 m( n<P>9 D3 W3 q: l! c( ^& {" k
//-----------------------------------------------------------------------------
0 P6 |' Q6 {: y1 e# B7 B4 |& V. X// Name: + I C; }+ `0 c( d& a( }9 s, d* t- I
// Desc: : V' m! K+ p b% r- W- i% P- a
//-----------------------------------------------------------------------------! i6 t3 z# ~9 \
void CMazeServer::SetClientPackSize( DWORD size )! @+ b ^6 w W% o1 |
{
* P. n/ I; [6 [6 H$ r // Update client config, and build packet containing that data
2 C5 S2 l1 j! p0 i/ H" U m_ClientNetConfigLock.Enter();, C; Z" H5 F. y; F
3 _' D1 k8 \0 }/ h" f' \
m_ClientNetConfig.ubClientPackIndex++; //Increase index and verify location in array.; u( C2 t- ?4 ~1 c: I8 e8 ^
if(m_ClientNetConfig.ubClientPackIndex >= PACK_ARRAY_SIZE)
" X& d9 s. ]7 q: j! M m_ClientNetConfig.ubClientPackIndex = 0;</P>
5 |* @$ T4 F6 l# ~8 b<P> m_ClientNetConfig.wClientPackSizeArray[m_ClientNetConfig.ubClientPackIndex] = WORD(size);
( j/ `. B. }$ O* F& i% ~ c% u$ T x ServerConfigPacket packet( m_ClientNetConfig );
: V( \2 M v( ~ m_ClientNetConfigLock.Leave();</P>% l3 e' b3 B7 G5 C% G+ r
<P> SendConfigPacketToAll( &packet );( h! R; I" H) g: I! a
}</P>
j, ^. f/ {4 w; j' a3 O& L
2 U2 T5 N. A2 k! Y) [<P>/ f5 [% ?1 b8 C" s$ }9 ], p4 M: K
//-----------------------------------------------------------------------------5 {# U, r3 U$ E; T
// Name: + x- Q0 c2 Y; J* ?- |, M
// Desc:
; C4 S; N U4 P, m& Z//-----------------------------------------------------------------------------, t# M( k7 a4 p7 w( R: d9 E+ ?
void CMazeServer::SetServerPackSize( DWORD size ) W' ^9 Y# X, \5 k0 b4 Y
{
4 C) {9 ^. W4 L ]& A& p( k- O // Update client config, and build packet containing that data) m! J/ B# Z* f7 B" s
m_ClientNetConfigLock.Enter();
( }2 B& m q, q0 t8 y1 W( e9 V
. R( V7 R2 B* ]$ U m_ClientNetConfig.ubServerPackIndex++; //Increase index and verify location in array.
, L: L* O$ M1 s% X$ s if(m_ClientNetConfig.ubServerPackIndex >= PACK_ARRAY_SIZE)
/ v @- H7 `0 Y. h" u1 Q" B m_ClientNetConfig.ubServerPackIndex = 0;</P>/ ?' t9 d6 H4 V, ?, [( u% R* |
<P> m_ClientNetConfig.wServerPackSizeArray[m_ClientNetConfig.ubServerPackIndex] = WORD(size);
/ ]7 g- P# e T5 e9 R& m, F6 \ ServerConfigPacket packet( m_ClientNetConfig );0 ?# w+ K* N8 P- M8 E6 i8 f
m_ClientNetConfigLock.Leave();</P>& C2 D2 v4 x7 |8 A" J4 k
<P> SendConfigPacketToAll( &packet );
6 d, q' z+ T6 G7 x5 E3 f# g}</P>
, B: Q) a' p, F+ O<P>
, t- N. f; ] S! w//-----------------------------------------------------------------------------# [ X# y E# {+ g0 ]5 l
// Name:
! G, Z; f$ X: N' E// Desc: ' E$ q; P+ i; E5 _! f$ a8 f; W+ B) \
//-----------------------------------------------------------------------------3 W/ W: e" q2 P: V! L' r. ]. _* _
void CMazeServer::SetClientThreadWait( DWORD dwThreadWait )
) V7 A% N3 ~- n2 N6 W{
; H" L% e( _1 t // Update client config, and build packet containing that data
4 Y3 Z3 y# w y, P0 k m_ClientNetConfigLock.Enter();8 m- ?1 L# z) X. n- t# C
" r2 M5 X# Q: K
m_ClientNetConfig.dwThreadWait = dwThreadWait;" d( ^, P! M, B% z3 @7 f
ServerConfigPacket packet( m_ClientNetConfig );: v7 Z# i" P' O) g
m_ClientNetConfigLock.Leave();</P>2 I9 k+ j O9 t) @' X. [( U
<P> SendConfigPacketToAll( &packet );* ~# Y3 e/ K1 M/ ^
}</P></DIV> |
zan
|