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