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