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