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