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