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