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