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