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