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