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