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