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