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