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