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