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