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