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