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