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