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