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