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