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