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