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