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