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