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