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