QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 4203|回复: 0
打印 上一主题 下一主题

[分享]MazeServer源码示例

[复制链接]
字体大小: 正常 放大
ilikenba 实名认证       

1万

主题

49

听众

2万

积分

  • TA的每日心情
    奋斗
    2024-6-23 05:14
  • 签到天数: 1043 天

    [LV.10]以坛为家III

    社区QQ达人 新人进步奖 优秀斑竹奖 发帖功臣

    群组万里江山

    群组sas讨论小组

    群组长盛证券理财有限公司

    群组C 语言讨论组

    群组Matlab讨论组

    跳转到指定楼层
    1#
    发表于 2005-1-31 11:52 |只看该作者 |倒序浏览
    |招呼Ta 关注Ta
    <DIV class=HtmlCode>& P+ k# P& Z, J% x" C5 F
    <>// File: mazeserver.cpp
    # }, R  I2 M4 B0 r/ l6 n  q//$ H$ x  X. M8 |& Q" `
    // Desc: see main.cpp
    . `" B6 j7 K% A9 x) a$ f% z) R//( t  Y. @/ ]( Z( m
    // Copyright (c) 1999-2001 Microsoft Corp. All rights reserved.
    1 P0 Z: L/ r; s3 E% ^; N! f, h  D) u//-----------------------------------------------------------------------------
    $ Z1 {6 f: R# q- S# G1 i#define STRICT
    $ X. C' A( r! ?#define D3D_OVERLOADS
    . S! D7 r! ^- P9 d#include &lt;windows.h&gt;
    ' Q& H% j6 V! r. ^) A#include &lt;d3dx.h&gt;
    - ]% N! f9 w* V" f2 C. [% k. t#include &lt;stdio.h&gt;
    + A) q2 j$ d' G' k  j' p$ e#include &lt;math.h&gt;% L7 a- M- I) s4 Q" h4 b
    #include &lt;mmsystem.h&gt;
    7 @3 {7 y1 B1 W' h* W/ I#include &lt;dplay8.h&gt;8 E+ b# H" S. {! {
    #include &lt;dpaddr.h&gt;7 H: ?9 Q7 C& Y% C
    #include &lt;dxerr8.h&gt;
    2 B8 x! i# t/ N: `0 T7 k#include "DXUtil.h"
    ) J* s% e* G  p) _) z#include "MazeServer.h"% F* G; X- X" g4 z8 H/ W
    #include "ackets.h"
    ( b( _  @3 X0 u6 l#include "Maze.h"9 Q* W! ]0 y% n9 M8 p
    #include &lt;malloc.h&gt;3 j, Y- T: g- x. M  W
    #include &lt;tchar.h&gt;</P>
    - ]% q: Z* ^% i7 }) [& y& g; F- K4 T' z
    <>//-----------------------------------------------------------------------------
    # b9 y: ?1 T" U1 M7 n7 m% d) ^// Name: 9 F7 q5 J0 Y5 l6 J: ^7 H1 K) s
    // Desc: 3 T8 j( [" }7 k8 P" a" v( J
    //-----------------------------------------------------------------------------0 S+ ?) e+ D; Y- B5 X, R" N
    CMazeServer::CMazeServer()( t( H! Z, C3 W6 P0 K# J
    {8 o4 t2 |2 X4 u
        m_dwPlayerCount         = 0;
    / a  b7 h5 ?) Y! Q" d   
    4 [$ W& b  J) n0 m4 y. U2 M  D    m_wActiveThreadCount   = 0;: \4 I8 W1 |0 i
        m_wMaxThreadCount      = 0;
    1 x* e- d% ^, c8 s    m_fAvgThreadCount      = 0;
    4 L! S8 F' {0 P5 ]- T" q$ x    m_fAvgThreadTime       = 0;
    $ M" I! t9 a3 W    m_fMaxThreadTime       = 0;</P>1 ~# U# N0 ]9 V7 ~/ r+ ]
    <>    m_dwServerReliableRate  = 15;  W' a& h' h' k
        m_dwServerTimeout       = 150;, o0 q; k1 O  s" @; R
        m_dwLogLevel            = 2;
    # {. x# w) C+ O; {3 ?    m_pMaze                 = NULL;</P>: G- l2 o' U. l6 }8 @! S1 R
    <>    m_ClientNetConfig.ubReliableRate = 15;
    ) C: F" F$ l! `. |) U    m_ClientNetConfig.wUpdateRate    = 150;- y! @" B. i- c5 z
        m_ClientNetConfig.wTimeout       = 150;</P>
    4 h2 M# Z' i( u" M<>    m_ClientNetConfig.dwThreadWait = 0;</P>
    + J9 F! [. L- i) T5 \8 a<>    m_ClientNetConfig.ubClientPackIndex = 0;
    2 }) J& I9 Q1 M8 h    m_ClientNetConfig.ubServerPackIndex = 0;$ N/ K9 a- e1 a/ o0 N, X% n% q6 O
        for(WORD x = 0; x &lt; PACK_ARRAY_SIZE; x++)
    7 A; D8 ?2 t  [! A* p    {( N8 Q, u$ I) f) c3 j* \- W) A
            m_ClientNetConfig.wClientPackSizeArray[x] = 0;2 ^# o. w9 b+ Y# Q+ I
            m_ClientNetConfig.wServerPackSizeArray[x] = 0;
    ( X2 h+ s+ I2 l; `, D! E) p    }/ l( h; P1 h! w$ a9 o
    }</P>
    , I  }  Y$ O, O8 C
    % a9 E( h$ f4 L! @3 h; U- d<>
    + n+ P, l* D% R& Q" n6 M  b- ~! Z% @//-----------------------------------------------------------------------------
    % v3 j7 p, X" Z7 y// Name: 4 |% K5 w( ~$ K2 _6 `7 g& G
    // Desc: 6 E& V7 G9 A+ @3 A2 K& `5 @
    //-----------------------------------------------------------------------------
    $ C# W' p. W6 B  F# dHRESULT CMazeServer::Init( BOOL bLocalLoopback, const CMaze* pMaze )
    ; c, ]1 h- q. f1 f$ x7 A7 z7 ?{
    " F6 k, U* y2 f& k    m_bLocalLoopback = bLocalLoopback;
    . b: X* ]/ j# F) x! y    m_pMaze = pMaze;$ P& F" E6 h( s; F
        if( m_pMaze == NULL )
    ! ?  Z- Z( g( _& c4 N        return DXTRACE_ERR( TEXT("aram"), E_FAIL );</P>
    7 O- ^; y5 B( H<>    // Grab height and width of maze
    - U! B: H" k5 P2 y& A    m_dwWidth = m_pMaze-&gt;GetWidth();9 _; ^( T. g( X. `
        m_dwHeight = m_pMaze-&gt;GetHeight();</P>
    : O" R& G# _  m9 ^' |<>    m_ClientNetConfig.dwMazeWidth  = m_dwWidth;& t( ^/ i4 E2 b% p( T0 W- o
        m_ClientNetConfig.dwMazeHeight = m_dwHeight;</P>
    6 s/ [2 V$ V' `* u1 b<>    // Validate size. Must be a power-of-2 times LOCK_GRID_SIZE. Compute the shifts.( {! G) Z# E! d  d. d5 Y6 |% g2 [
        if( m_dwWidth &gt; SERVER_MAX_WIDTH || m_dwHeight &gt; SERVER_MAX_HEIGHT )
    / P6 ~" H, _' h8 F        return DXTRACE_ERR( TEXT("Maze height and width need to be less than 128"), E_INVALIDARG );
    % \) F/ J& x, g1 P' O: D4 L( n    if( (m_dwWidth % LOCK_GRID_SIZE) != 0 || (m_dwHeight % LOCK_GRID_SIZE) != 0 )+ a; _/ h- i; q5 h  t4 ^
            return DXTRACE_ERR( TEXT("Maze height and width need to be divisable by 16"), E_INVALIDARG );</P>
    ' U0 o- Y: T" w, @; u. d<>    DWORD scale = m_dwWidth / LOCK_GRID_SIZE;" T4 H$ w% N* B) o- O! h
        m_dwMazeXShift = 0;1 f7 {; v: J$ I
        while ( (scale &gt;&gt;= 1) )
    / A5 N) W2 d: f, m* v        m_dwMazeXShift++;</P>9 k: c& C5 `4 U2 l$ @: d+ Z3 _
    <>    scale = m_dwHeight / LOCK_GRID_SIZE;
    ) M% O) \+ M' w) ~8 D# n- l% i; e  z    m_dwMazeYShift = 0;
    ; y1 M! i- R: U; P3 C, z, Z    while ( (scale &gt;&gt;= 1) )% O7 H5 T" O' i: l- P
            m_dwMazeYShift++;</P>5 V6 x/ k/ e" a! v
    <>    if( ((DWORD(LOCK_GRID_SIZE) &lt;&lt; m_dwMazeXShift) != m_dwWidth) ||
    ( M8 ^+ q0 g% z9 X3 N2 J' m        ((DWORD(LOCK_GRID_SIZE) &lt;&lt; m_dwMazeYShift) != m_dwHeight) )9 a! G" J8 Q2 k
            return DXTRACE_ERR( TEXT("Maze height and width need to be power of 2"), E_INVALIDARG );</P>
    1 W" a% g' T$ L# ?" k/ b7 `<>    // Initialise the player list0 a7 Q4 u9 m  A2 e$ o
        ZeroMemory( m_PlayerDatas, sizeof(m_PlayerDatas) );' t5 O# d9 S! S# y4 i
        m_pFirstActivePlayerData = NULL;  A7 y/ g9 t7 z2 O( p
        m_pFirstFreePlayerData = m_PlayerDatas;
    2 }0 w- ^6 d9 U    for( DWORD i = 1; i &lt; MAX_PLAYER_OBJECTS-1; i++ ). n- n6 V. I4 e# ~6 q3 c: ^
        {0 M4 F; A' ^* {3 W* M& c# s) }+ a5 |- K
            m_PlayerDatas.pNext = &amp;m_PlayerDatas[i+1];" U% \' ?$ R5 C6 f9 N% C
            m_PlayerDatas.pPrevious = &amp;m_PlayerDatas[i-1];- ^% k/ ^9 ~! ~+ v+ _6 z
        }</P>/ r4 y2 [% G0 C% u6 i( \5 G
    <>    m_PlayerDatas[0].pNext = &amp;m_PlayerDatas[1];! ~+ m( u' _/ ]' m% a" }
        m_PlayerDatas[MAX_PLAYER_OBJECTS-1].pPrevious = &amp;m_PlayerDatas[MAX_PLAYER_OBJECTS-2];8 a  A! K% t$ ]4 G
        m_dwActivePlayerDataCount = 0;
    8 e% u1 V% b0 h! b: q7 m& F5 q8 \* _2 [# u    m_dwPlayerDataUniqueValue = 0;</P>& ?8 L2 g" j; A, h+ [2 `
    <>    // Initialise the cells
    1 z3 j7 z9 h  b; \    ZeroMemory( m_Cells, sizeof(m_Cells) );
    0 I  o6 V  I: _$ D8 b* [7 Z    ZeroMemory( &amp;m_OffMapCell, sizeof(m_OffMapCell) );</P>3 F. H+ [: M. Y, O# Z
    <>    return S_OK;% I" D3 O1 I4 [. r3 t
    }</P>
      d7 W; p% B( a" f/ b, w4 J0 ]; H) w4 M$ C
    <>2 S0 Q8 ]' X. K, a, _8 z5 G2 u
    //-----------------------------------------------------------------------------
    8 V+ `: v( ~8 ^  a// Name:
    8 s2 T' }" y5 ?. f" c  n! t7 J// Desc: , H! F$ q$ i  c
    //-----------------------------------------------------------------------------* P3 A* \8 @- B: C
    void CMazeServer::Shutdown()
    ( }% |& y6 I+ t& b9 E. H1 L! ]{
    7 B* B$ {, m  [+ W: e- z, d}</P>
    ; `1 X! L' w/ |8 I+ ?
    6 n3 z: ?6 z2 p% D/ I<>
    2 l, p* W/ C  @" ]+ w0 ]//-----------------------------------------------------------------------------
    & l" ^+ k8 F" K1 ?' P// Name:
    ; m/ ^, W3 P; {& [// Desc:
    ; T7 Y% X2 G1 M! o/ o. I; c1 }7 u//-----------------------------------------------------------------------------
    5 p; D1 L2 u. `2 G+ b6 uvoid CMazeServer:ockRange( DWORD x1, DWORD y1, DWORD x2, DWORD y2 )% k1 }, r/ a, k5 q& C/ ~+ V- j6 T, f
    {
    8 f1 ~  Y4 z- {# ?    m_LockGrid.LockRange( x1&gt;&gt;m_dwMazeXShift, y1&gt;&gt;m_dwMazeYShift ,
    5 w! `; a3 U+ `1 D+ g1 m( K7 u% g* _                          x2&gt;&gt;m_dwMazeXShift, y2&gt;&gt;m_dwMazeYShift );
      q" ^/ A& y- ?% j5 j}</P>$ \; f7 V: Q: Q+ A8 K: u4 E# a
    ) K! ?. K) S9 ?' v, w; M5 R% s
    <>
    + {) n) U& P" G' N9 z//-----------------------------------------------------------------------------
    / p6 V: }! T* r. l5 j& a) e2 J// Name: # p0 d( E' L+ _- z! _, w+ o
    // Desc: " J) d  f" j+ g7 ?3 e3 [
    //-----------------------------------------------------------------------------
    ! m3 i5 C+ c  n8 ]void CMazeServer::UnlockRange( DWORD x1, DWORD y1, DWORD x2, DWORD y2 )
    ! N; Z1 w! |% v# m- R9 H/ e, E{
    : D' ~1 a, C! Y* v  u    m_LockGrid.UnlockRange( x1&gt;&gt;m_dwMazeXShift, y1&gt;&gt;m_dwMazeYShift ,$ p4 W9 f+ p+ w1 l' E- e8 q0 I
                                x2&gt;&gt;m_dwMazeXShift, y2&gt;&gt;m_dwMazeYShift );0 N" w, L% w4 _8 L4 d5 x/ ^
    }</P>
    5 p! l+ f% [# _' ~: H
    * T4 H, ?- q3 g# X9 m/ x<>4 s* P! j% m+ D6 q& R
    //-----------------------------------------------------------------------------2 f) K$ m- S. v$ _5 s- |1 V9 h+ D
    // Name:
    " p) L/ h$ ?4 X  A% i0 v1 o5 p# v// Desc:
    5 C6 b4 A8 V5 z- _4 d! N( A3 S//-----------------------------------------------------------------------------
    , h6 Z' v& S- J1 d5 h$ }void CMazeServer:ockCell( DWORD x, DWORD y )
    7 ~8 S! j/ c$ W& I. g{! c+ V9 s8 K0 \, l- y+ k' l
        if( x == 0xffff )
    0 e7 E/ O+ g  X+ ]6 `) O) d        m_OffMapLock.Enter();8 |7 {& d; N0 ]# [& F& b
        else; q# j: @5 [* t
            m_LockGrid.LockCell(x&gt;&gt;m_dwMazeXShift,y&gt;&gt;m_dwMazeYShift);8 p* E( o3 V0 I  g7 t1 h, B
    }</P>
    : z) J1 p* i% z" y2 I* d5 E1 }. I) ]1 q8 r8 _' L0 g
    <>
    ; z1 U; \4 n/ [1 Q//-----------------------------------------------------------------------------
    & h+ L; z! m! _: E// Name:
    ! _: {. K) @) z) }8 u! Y5 R  D# \// Desc: ) w) M7 h4 e# F
    //-----------------------------------------------------------------------------9 ]$ z7 E$ p& i2 \9 q7 d2 P
    void CMazeServer::UnlockCell( DWORD x, DWORD y )
    1 q/ u$ G/ R' a8 ^{- S' ?, o& ^. m1 t+ P8 K
        if( x == 0xffff )4 F8 q3 _" a) ^, c2 M2 b7 M( y" V1 D
            m_OffMapLock.Leave();6 ?/ T, i/ v% h4 l
        else
    6 S0 {' F  ~! h" y2 m4 N# P+ I        m_LockGrid.UnlockCell(x&gt;&gt;m_dwMazeXShift,y&gt;&gt;m_dwMazeYShift);3 [$ i8 I7 [; U5 n# `& I& H1 }- M
    }</P>, ^1 s' N: s# M) D

    6 ]) E$ B$ F  `! k- [0 t<>( T. _& D9 F5 t) r% b
    //-----------------------------------------------------------------------------  B- Q' {5 i1 U: l* j5 @
    // Name:
    & z% E! B9 A0 l& r; c0 b// Desc:
    / L$ |& D0 K: \2 w! ?0 @//-----------------------------------------------------------------------------% a- {( _/ p2 j3 g
    void CMazeServer:ockCellPair( DWORD x1, DWORD y1, DWORD x2, DWORD y2 )3 S, W! Z! Q  G, A  q4 h
    {
    2 e: A! ^( b$ @+ K' W- h    if( x1 == x2 &amp;&amp; y1 == y2 )$ M8 e. z8 J% {# }) x
        {
    , ]) \, y. y' ?2 w1 o/ }        if( x1 != 0xffff &amp;&amp; y2 != 0xffff )
    9 A! F7 B  R& F            LockCell( x1, y1 );& C, N+ A! @6 v6 r8 r3 a, C# U
            else) V2 s" [. o  r7 W
                m_OffMapLock.Enter();</P>! V- r; V# J5 E, V( V
    <>        return;. k5 M! h4 n, G
        }</P>
    . f1 I4 P' O; K<>    DWORD x1shift = x1&gt;&gt;m_dwMazeXShift;+ n" {' S: }0 V3 G) h' a: O
        DWORD x2shift = x2&gt;&gt;m_dwMazeXShift;9 v' J3 a5 h, d& t& i$ o  ~, Y$ k
        DWORD y1shift = y1&gt;&gt;m_dwMazeYShift;
    2 c1 y. S9 k* C* D/ P$ [& q$ w    DWORD y2shift = y2&gt;&gt;m_dwMazeYShift;</P>
    ' [* X% v$ t- j4 \7 f& ~<>    if( x1 == 0xffff )
    ) k4 B" a% a; c; T( R6 S! o    {
    . s" w( h1 M; H) k- c3 L        m_OffMapLock.Enter();: s% a4 F: R" p: Q! j7 s+ D  f
            m_LockGrid.LockCell(x2shift,y2shift);
    6 i3 u: y+ p) ~6 ^. Z- Q    }! n( K9 w& `7 D, d% _
        else if( x2 == 0xffff )
    , k# r& n$ s# [$ Y6 {    {: z0 Z2 f( L* C
            m_OffMapLock.Enter();
    * Z) g' b3 e; `$ L4 q. V        m_LockGrid.LockCell(x1shift,y1shift);
    ( K* p$ \9 }0 b" P3 V    }! z3 D1 d7 B- L: i5 r! w. {% A
        else ; m% u! Y1 V0 K6 f6 ]* n
        {1 V5 ], M; d6 d# j& g
            m_LockGrid.LockCellPair(x1shift,y1shift,x2shift,y2shift);
    3 Y$ G4 P/ {: \) i! _2 N    }
    , p- v: a7 v8 O; I6 Y}</P>
    7 D# e2 V, a  v: H
    % F$ c3 _7 ^: a8 ]<>5 b" ^3 |9 t4 ^0 L$ @
    //-----------------------------------------------------------------------------
    / o) \6 }' ?+ f4 ^% C) W" Q// Name:
    - Q' W7 d5 Q5 g) t// Desc: + Z$ [7 |5 x! W, L/ W" |6 Q% Y
    //-----------------------------------------------------------------------------8 S6 V& s! C; Y! P# C9 e4 F
    void CMazeServer::UnlockCellPair( DWORD x1, DWORD y1, DWORD x2, DWORD y2 )
    5 A( a0 j( r  Y/ w1 Q* @) D4 ?0 g' p{
    7 U& L4 E6 k6 N& k: X    if( x1 == x2 &amp;&amp; y1 == y2 )
    2 e  J# _- \- Y  x) Y    {
    3 D3 x" p( o6 n0 O9 W        if( x1 != 0xffff &amp;&amp; y2 != 0xffff )
    8 e) V$ M# O& m/ L7 P            UnlockCell( x1, y1 );, u3 }9 K6 j% _& H
            else- ^" }) d  h7 x" q2 ^" |
                m_OffMapLock.Leave();</P>
    % \8 s9 V& F( ]% p  z- l$ ?<>        return;5 Q8 T+ e& W; T, x
        }</P>' @& }. b# M9 ?7 E
    <P>    DWORD x1shift = x1&gt;&gt;m_dwMazeXShift;
    6 e- w1 w- M, P/ S/ U/ X( U* g    DWORD x2shift = x2&gt;&gt;m_dwMazeXShift;
    : a8 u5 A% q$ }" X0 k# p. w    DWORD y1shift = y1&gt;&gt;m_dwMazeYShift;
    4 \, G# _" y. m' z/ O. T    DWORD y2shift = y2&gt;&gt;m_dwMazeYShift;</P>
    5 m% {& Q( P2 V. Z<P>    if( x1 == 0xffff )8 s$ |* U# p. C; f; P1 a
        {
    8 R# d0 b7 F5 X' n3 a4 L        m_LockGrid.UnlockCell(x2shift,y2shift);+ U/ S' c; F1 p! h; ]5 F4 T( {
            m_OffMapLock.Leave();
    1 v& ?0 K3 k1 D1 p  ^- j8 j/ {5 g5 @8 p    }
    ( {, g: N( Q( f/ X  H2 u    else if( x2 == 0xffff )
    " }6 q0 z( f% `% ~6 i5 T    {$ {2 y; M$ \3 @
            m_LockGrid.UnlockCell(x1shift,y1shift);- c7 r9 r( D2 a' Y8 \
            m_OffMapLock.Leave();
    - X* w7 f+ a( c- m! @; K    }. a+ J5 n% H  M& J
        else $ H/ C; V! T  H: r/ A/ z( ^6 M! w
        {
    , Y7 e! \$ W9 Q$ U8 q( i        m_LockGrid.UnlockCellPair(x1shift,y1shift,x2shift,y2shift);
    ' u) C  q) K1 d    }; J3 M! |5 o) D. O! i3 P! j
    }</P>2 |6 W. e1 ^: U+ i+ @& ?

    ) L' Y. ^  T  ^" V5 \<P>
    5 G9 A; P- b; M" I! P& S0 `/ {//-----------------------------------------------------------------------------/ @2 u/ f5 Q: E) T3 L
    // Name: ; P' L: D6 i  ?! g" `( J4 g- y( m
    // Desc:
    ; p4 z" F; Z* E' j% Y6 [% L& X//-----------------------------------------------------------------------------$ v' B& b% b  r. @+ y
    void CMazeServer::OnAddConnection( DWORD id )
    ) i0 e8 E8 Y, f( @- u7 d5 ]  ?9 F* Q& S{3 O& H; o, z  `, |3 ]
        m_AddRemoveLock.Enter();</P>
    / u6 G% |) b1 Q' p1 r' }4 H9 a<P>    // Increment our count of players" a2 o/ C% j6 _$ _# \
        m_dwPlayerCount++;
    ' Z. u) U2 B( d4 k) ?    if( m_dwLogLevel &gt; 0 )* W) J$ d$ y$ G5 p* [3 V' u& M
        {
    ( A( d2 K  J. v% j3 q5 P- v        ConsolePrintf( SLINE_LOG, TEXT("Adding player DPNID %0.8x"), id );
    2 S* ~, T2 g2 B! y  V# ?( r; L        ConsolePrintf( SLINE_LOG, TEXT("Players connected = %d"), m_dwPlayerCount );# y2 I' l/ E4 G3 Q+ c! X+ w
        }</P>
    - {2 G1 i5 }. k$ c% \3 c4 d' x" `! R<P>    if( m_dwPlayerCount &gt; m_dwPeakPlayerCount )) q. _1 S( G" y' D; h4 H- t0 C
            m_dwPeakPlayerCount = m_dwPlayerCount;</P>1 d0 c( L8 s4 V
    <P>    // Create a player for this client( A9 W- X' F+ }9 u. p- v
        PlayerData* pPlayerData = CreatePlayerData();/ [5 y3 P8 R( _1 d
        if( pPlayerData == NULL )2 {! H. k* O! ^7 g; l
        {# o6 Z% d1 H* C9 B
            ConsolePrintf( SLINE_LOG, TEXT("ERROR! Unable to create new PlayerData for client!") );
    & a" Q' t/ d4 F        DXTRACE_ERR( TEXT("CreatePlayerData"), E_FAIL );3 ?  g; z: q. G- ^6 a& e0 ~9 S' d
            m_AddRemoveLock.Leave();. E3 J! W" ~; h  s/ V$ n
            return;& ^4 I/ \, |7 M
        }</P>& d) E. K/ ~0 @# _3 d3 {
    <P>    // Store that pointer as local player data
    , z# O. c1 L: M    SetPlayerDataForID( id, pPlayerData );</P>' z5 ~- c, L& E! w6 C* X
    <P>    // Grab net config into to send to client
    ! Y  E# m5 W, ~- F3 J    m_ClientNetConfigLock.Enter();! ]( C& n3 Z* P" @
        ServerConfigPacket packet( m_ClientNetConfig );" j% F8 G6 j& C+ R  K5 Y
        m_ClientNetConfigLock.Leave();</P>
    + {( w9 O' ?0 `8 k<P>    // Send it
    % q+ E; l! W( l8 l    SendPacket( id, &amp;packet, sizeof(packet), TRUE, 0 );</P>9 i6 M' B, J! p1 }# k
    <P>    m_AddRemoveLock.Leave();0 i8 V. v, J) h5 P% w8 j
    }</P>
    ( |: H( a) T* J" V
    ) G- i( ^% X2 x: j0 O$ X/ ^<P>8 c' w% C9 \! @7 I, b- {
    //-----------------------------------------------------------------------------2 N# e: b2 k; h  j$ Q; A% M
    // Name:
    1 t, G: M7 x& k$ G1 P, n% A// Desc:
    % O6 A6 w3 ^% t' e5 u# @  z//-----------------------------------------------------------------------------
    $ P% h, q" {4 y! xvoid CMazeServer::OnRemoveConnection( DWORD id )4 V$ S7 m$ I' e& F$ L
    {
    5 X# H  o) ~, k& \9 ~    m_AddRemoveLock.Enter();</P>
    3 q: s( M8 X& t2 @* \<P>    // Decrement count of players, d( |% ?# w, `- J+ |" t8 l7 M  V
        m_dwPlayerCount--;</P>4 V) {; S, S4 J! m
    <P>    if( m_dwLogLevel &gt; 0 ), Z8 Z1 M: R! a# @0 g" F1 o* [) j
        {+ _8 O6 f4 H  Z0 K: \% B# @
            ConsolePrintf( SLINE_LOG, TEXT("Removing player DPNID %0.8x"), id );
    6 N0 w4 B0 l) H$ Y        ConsolePrintf( SLINE_LOG, TEXT("Players connected = %d"), m_dwPlayerCount );. W9 ^# t( J. f
        }</P>5 w4 h" c" W) L+ a: `5 x
    <P>    // Find playerdata for this client
    & j* a1 Z* ]) x8 J    PlayerData* pPlayerData = GetPlayerDataForID( id );
    2 q# V, K! s; i4 ]$ a" u- M- v/ \    if( pPlayerData != NULL ), x" e- y1 h) g2 M$ c! t' i
        {
    7 _& j: ?( v8 u$ m3 z9 J% _        // Destroy it0 S5 n# c5 w' m) \$ {$ u
            RemovePlayerDataID( pPlayerData );
      e# U% ~6 G3 r  Y4 a: q        DestroyPlayerData( pPlayerData );
    ; @- E7 O) x/ K! U# x& [1 V    }</P>: H$ O6 g" K" ]# |! [
    <P>    m_AddRemoveLock.Leave();% m1 b+ }. G$ T1 R' x2 X1 x
    }</P>7 n' N+ }7 o% {& Z* T
    1 o$ n/ M* c, J5 p0 n
    <P>
    9 z# I7 S/ S) L* d//-----------------------------------------------------------------------------
    8 n" R5 V  ?( x( `# i8 ]% M# x+ u! W// Name:
    ! g9 N4 l6 ]6 w- z// Desc:
    $ Y9 O$ N, w* h; h//-----------------------------------------------------------------------------
    5 \' g: e: {1 b9 N4 X. HHRESULT CMazeServer::OnPacket( DWORD dwFrom, void* pData, DWORD size )
    ; L5 M2 e7 `- S$ H2 w{
    0 b5 t* D  X$ Q) C3 w    BOOL fFoundSize = FALSE;</P>
      W- I$ D' M4 x1 d1 O<P>    // Increment the number of thread we have in this process.( b$ N# Q; g+ o9 _; x9 m
        m_csThreadCountLock.Enter();</P>
    9 V; \5 m7 p. ]9 _: T) t8 n<P>    //Get the start time of when we entered the message handler.
      t. h6 b4 i0 t) C$ v    FLOAT   fStartTime = DXUtil_Timer( TIMER_GETAPPTIME );</P>+ e. q0 m; c2 a; M
    <P>    m_wActiveThreadCount++;: I! n7 S8 W# G5 L, i5 [
        if(m_wActiveThreadCount &gt; m_wMaxThreadCount)
    3 |# r+ |" r( {* |* ~        m_wMaxThreadCount = m_wActiveThreadCount;
    / X& a$ R& S) {0 y    % s4 }% C1 O2 ]2 x+ y
        // Calculate and average.! Q* m+ h" S3 @. w3 X
        FLOAT fdiff = m_wActiveThreadCount - m_fAvgThreadCount;; A( C0 N7 k$ `4 @% y' m
        m_fAvgThreadCount += fdiff/32;
    , j3 U% E* W* w    * p0 ?! y& q: }2 I
        m_csThreadCountLock.Leave();</P>
    + M" p1 V# E. A  ~& y<P>
    * T7 J: o) N2 Q. j5 L9 Z8 b    ClientPacket* pClientPack = (ClientPacket*)pData;
    # R& \* C; F# y    switch( pClientPack-&gt;wType ). A9 y6 x0 }% ]8 ]; z3 _/ N. O
        {  T% V3 G# H* ]1 i
            case PACKETTYPE_CLIENT_POS:
    7 ~0 C$ Z- m" H! e& w* Z            
    , M! l9 x7 Z8 ^( H            // Check to see if the packet has a valid size. Including # L4 d9 }1 O: V
                // the custom pack size.5 ~# O/ O! U3 _1 P2 n( [1 D
                if( size &lt; sizeof(ClientPosPacket))
    ! |# [8 Z+ L+ D4 Y# o                fFoundSize = FALSE;: `- F$ h) f5 u9 w4 J
                else if( ! IsValidPackSize(size - sizeof(ClientPosPacket)))4 ]0 b; a' \. O" |2 j0 t
                    fFoundSize = FALSE;! I3 @6 O6 s! v9 @6 f# t( C
                else% y8 v8 j. P& Z0 R3 f
                    fFoundSize = TRUE;</P>
    ! e3 i7 U6 F+ g8 O  x* {. h6 o<P>            // If valid sized packet, handle the position.
      @+ M; |, P' R! q  G. t! T            if(fFoundSize)
    $ B: i4 f5 f, C/ ]/ T                HandleClientPosPacket( dwFrom, (ClientPosPacket*)pClientPack );
    * o- |( I9 p8 u5 [2 _8 W, x) o/ y& D            else
    : @$ [2 R7 M5 a  ]& ?                m_pNet-&gt;RejectClient( dwFrom, DISCONNNECT_REASON_CLIENT_OUT_OF_DATE );</P>
    # m4 F5 y; T  Q9 `; Q<P>            break;</P>
    ( T. V4 c" A/ |0 W3 k7 f<P>        case PACKETTYPE_CLIENT_VERSION:
    # }' A! j4 B/ w' ~            if( size == sizeof(ClientVersionPacket) )
    5 h- J( J0 O/ @9 O1 u, U- G                HandleClientVersionPacket( dwFrom, (ClientVersionPacket*)pClientPack );  S; v$ n( d7 [1 o* I
                else3 g4 Y9 x4 g2 u: e( C4 H
                    m_pNet-&gt;RejectClient( dwFrom, DISCONNNECT_REASON_CLIENT_OUT_OF_DATE );& x( Q% J! ^, e0 |  ^( ^8 I: n7 Q) ?
                break;</P>/ I5 @/ F8 O& t$ h1 r$ @2 w
    <P>        case PACKETTYPE_SERVER_CONFIG:</P>/ \3 \7 G2 Y) n6 u
    <P>            // Server config packet sent to all users (including server). Just ignore and continue.</P>! X. R0 P/ ~& s7 u; Y9 i' z
    <P>            break;5 t% q: D2 [) d9 G! @/ S8 a" @
            default:0 v# ^# h$ G6 g* |" q1 ~
                HandleUnknownPacket( dwFrom, pClientPack, size );/ O! p+ q! R1 ?2 s$ t0 \
                break;& {, b# n; F9 u9 W4 R0 M* N
        }</P>
    1 d+ A1 W7 y5 T$ `2 b9 U<P>    //If the user wants to hold the thread, Sleep for given amount of time.! l# y  O4 e* \& b5 ]' k
        if ( m_dwServerThreadWait &gt; 0 )
    9 m7 F' \# P. z. p2 ^( ?    {
    - G. |/ b3 M5 s8 K        Sleep( m_dwServerThreadWait );; K. R+ _) Y4 o( E( n
        }( ]3 u, O3 ]5 y, C
       
    / E/ h2 ^3 X. z8 f$ X% V    // Retrieve thread data for this process.
    ' R1 t; T. G6 G" L+ Z    m_csThreadCountLock.Enter();</P>
    ( V4 ]1 a/ U9 |$ O; B9 L<P>    m_wActiveThreadCount--;</P>
    , u/ ^+ |, e2 h<P>    FLOAT fDiffTime = (DXUtil_Timer( TIMER_GETAPPTIME ) - fStartTime) - m_fAvgThreadTime;+ o: D  h# B, K( O
        m_fAvgThreadTime += fDiffTime/32;</P>
    2 x! }/ B1 o* \+ z<P>    //Get the Max time in the thread.
    * f6 h/ r* c5 @, F/ J/ y    if ( fDiffTime &gt; m_fMaxThreadTime ). }& e, o7 N  {
        {
      J: R, z! Q3 J/ L  ^+ E, x3 t        m_fMaxThreadTime = fDiffTime;  t* J8 u# U+ C1 G/ m' b
        }</P>6 B7 X" E/ C5 Y8 G
    <P>    m_csThreadCountLock.Leave();</P>( I: s% c- \0 ^3 H: Q4 s
    <P>    return S_OK;" ^) n! f0 \$ L' \% w
    }</P>
    + _. c" o. x0 \+ ~
    6 k  H1 E! c7 {/ ^( g) A( ^9 |; k<P>//-----------------------------------------------------------------------------
    % _  Z& b5 y! O+ \// Name: 5 E4 e% B( S% t3 c
    // Desc:
    4 t+ K2 d& l* z& _//-----------------------------------------------------------------------------
    . y  F5 @. N' _8 @( i$ B$ bBOOL CMazeServer::IsValidPackSize( DWORD dwSize )
    / S& s: _. V2 N1 t{! R7 a/ m$ {9 O! |+ ^
        BOOL fFoundSize = FALSE;
    % F! i- s$ S9 t    BYTE ubPackLocation = m_ClientNetConfig.ubClientPackIndex;
    0 ~0 Y% a4 C% A/ S, C. [9 L4 `    . ?$ h* i  |( n
        // Check through the array of valid pack sizes.- J4 d) V. }/ T* w8 v
        if(dwSize != m_ClientNetConfig.wClientPackSizeArray[ubPackLocation])
    9 p% X3 l6 t; G2 B' D    {
    - F! a6 v, i& x9 _1 d- L1 I        for( --ubPackLocation; ubPackLocation != m_ClientNetConfig.ubClientPackIndex; ubPackLocation--)
    % p4 v% M' [& D& R        {: v0 K1 S6 M  R2 q( Y, J5 X1 l/ P
                if(dwSize == m_ClientNetConfig.wClientPackSizeArray[ubPackLocation])( j2 x' K( R3 Y' u2 ~
                {: h! c$ Q$ @& r  R5 a
                    // Found valid size in the array.
    0 U1 o* e) {7 v- y. W  M                fFoundSize = TRUE;1 ]* h0 ]9 w- t! {4 A
                    break;8 k# D2 v: C/ O
                }
    - E, Y+ s, M$ e2 N# c$ T5 x2 Q# C            if(ubPackLocation &gt;= PACK_ARRAY_SIZE)  ubPackLocation = PACK_ARRAY_SIZE;  //Wrap the array.8 |' h6 U& L1 D! j
            }
    & |) H; p5 L8 h4 s' J$ L* `4 _    }% Q: r) _6 g, k9 t4 g2 A; P
        else
    3 Y' I4 u4 C6 o    {# U6 P% h6 Z1 {4 U9 I, o# L
            fFoundSize = TRUE;5 O! X; A, E' c( x2 [% [  G6 D
        }</P>2 ^9 ?: l0 H8 Q7 A
    <P>    return fFoundSize;8 N9 V' h9 `2 t4 ~# j
    }</P>$ c; z+ n6 A* D3 D3 E& x: Q
    <P>
    & ~: r* i, A! q//-----------------------------------------------------------------------------
    6 c7 |: Y/ g8 \; b  L$ {// Name: ) ~6 [. k; r& M( F( q7 ?: N
    // Desc: 4 Z$ }5 d: L& ~5 A* O; F9 g  w
    //-----------------------------------------------------------------------------, t' l( T# y  ]  r1 h
    void CMazeServer::OnSessionLost( DWORD dwReason )' S4 P. Q) L4 C& Y( e
    {
    % c  F4 {1 W3 c    ConsolePrintf( SLINE_LOG, TEXT("ERROR! Session was lost") );
    ' y3 q9 T+ F# O# _: _}</P>. ~" K* o9 W% _& L/ j- X( U$ a
    2 t# U8 _, C4 A) o$ m. G& o
    <P>' d8 |5 Z! Q1 {! A
    //-----------------------------------------------------------------------------
    ' l7 S8 z! [* y) x// Name:
    0 f$ |: d+ ^! e5 a// Desc: " ^/ T+ Y+ V, O/ e
    //-----------------------------------------------------------------------------9 A' u5 l' Q& v8 v
    PlayerData* CMazeServer::CreatePlayerData(), [6 w7 y% p' k/ G
    {
    . P: b0 E# Q1 }" V# Y5 l0 f0 C7 A    m_PlayerDataListLock.Enter();</P>
    ( K1 J; E8 L  s$ H$ u4 A<P>    // Grab first free player in the list
    7 w9 P6 F; L5 G5 C    PlayerData* pPlayerData = m_pFirstFreePlayerData;</P>
    ( J  H! D* n. X! H( r<P>    if( pPlayerData )" ?$ Y: s4 P  x1 ^5 P3 h
        {
    + ]( w$ O' G8 ?+ s% o5 y4 l0 d        LockPlayerData( pPlayerData );</P>9 C/ r+ b' e  }. _" n
    <P>        // Got one, so remove it from the free list* [7 O. }6 a& Z$ S/ a/ a2 M2 o
            if( pPlayerData-&gt;pPrevious )7 m! _6 Q4 a7 }2 c6 s8 u; B
                pPlayerData-&gt;pPrevious-&gt;pNext = pPlayerData-&gt;pNext;
    . T9 D# T& k4 X* m2 L7 G        if( pPlayerData-&gt;pNext )6 E7 c; F0 m9 U9 a6 g9 Q, v3 }
                pPlayerData-&gt;pNext-&gt;pPrevious = pPlayerData-&gt;pPrevious;2 c5 p5 A" D+ ~/ k9 U% }/ o7 [2 i
            m_pFirstFreePlayerData = pPlayerData-&gt;pNext;</P>
    - q( G1 o, `2 \( _4 |( z<P>        // Add it to the active list
    8 B$ t6 k" _( N        if( m_pFirstActivePlayerData )7 y6 F8 t9 T& `: D: T0 a& }3 v
                m_pFirstActivePlayerData-&gt;pPrevious = pPlayerData;
    / Q" \% R5 u3 S- M6 `$ w' W        pPlayerData-&gt;pNext = m_pFirstActivePlayerData;. K6 @6 ?+ r7 e3 o
            pPlayerData-&gt;pPrevious = NULL;* t. H# w& q- N
            m_pFirstActivePlayerData = pPlayerData;</P>: e( H, b. j' x/ \/ y  Z0 s
    <P>        // Update count of players
    8 W* t7 p5 Q9 x/ }) K0 m4 z& c        m_dwActivePlayerDataCount++;</P>' x* N0 {: ~% f' _" v
    <P>        // Generate the ID for this player
    8 {" z5 b( L  }5 s1 s  K        m_dwPlayerDataUniqueValue++;
    ) G% f& S& p# p2 W3 f; T" [! R        pPlayerData-&gt;dwID = (DWORD) ((pPlayerData-m_PlayerDatas)|(m_dwPlayerDataUniqueValue&lt;&lt;PLAYER_OBJECT_SLOT_BITS));</P>1 ?7 K- H7 e! X/ _) L
    <P>        pPlayerData-&gt;pNextInIDHashBucket = NULL;
    ! O, b2 m8 b, x+ u& o! @% \        pPlayerData-&gt;NetID = 0;
    # ~/ H6 q$ `- F- L; ^% a1 ~: v8 g        pPlayerData-&gt;dwNumNearbyPlayers = 0;</P>
    4 ~0 S4 g" J, Q$ D2 M! u5 o<P>        // Insert into the "off-map" cell
    % }; V/ ^7 U& P        pPlayerData-&gt;fPosX = pPlayerData-&gt;fPosY = -1;9 ?2 ~6 s: m( ^. S& T) o
            pPlayerData-&gt;wCellX = pPlayerData-&gt;wCellY = 0xffff;
    * V3 |) V% m6 d" D6 T        m_OffMapLock.Enter();$ }9 f& n) B. X+ Z0 c+ s
            pPlayerData-&gt;pNextInCell = m_OffMapCell.pFirstPlayerData;* S% b* J4 w4 k" D
            m_OffMapCell.pFirstPlayerData = pPlayerData;
    & g- h3 r7 W: `* h8 Q        m_OffMapLock.Leave();</P>
    4 F' k& p6 [# S% F<P>        // Mark as active, l. `: H8 i! S; t/ {! e
            pPlayerData-&gt;bActive = TRUE;</P>
    4 h9 r! ?' p( x+ O* K) ]<P>        UnlockPlayerData( pPlayerData );. f9 j1 |. m: f$ Y" F
        }</P>) H7 Z! J! `  C4 N$ Y$ t/ c5 T
    <P>    m_PlayerDataListLock.Leave();</P>
    - Z% m. g( Z% p- O0 m% I3 }<P>    return pPlayerData;7 y# O# _+ v4 M7 e1 q
    }</P>0 X9 w  y: g; R) C& I$ P6 L

    & T: E, J5 u, {, t- ]" s9 `; n<P>
    1 x" N0 t- a2 V, U  R2 t- {% }//-----------------------------------------------------------------------------
    ; \. x7 M( K9 v  w' k, v- s; f// Name: 6 s! B$ `; h# Y7 y1 b# K# g
    // Desc:
    . o5 R  z: ]9 t//-----------------------------------------------------------------------------5 b. j1 j7 }2 q" E7 R& c4 s
    void CMazeServer:estroyPlayerData( PlayerData* pPlayerData ), ~& Q, Z0 m6 T
    {
      A! [; D6 a$ v" L* W8 L8 D    m_PlayerDataListLock.Enter();7 T/ M0 u( k* V( L; o7 Q
        LockPlayerData( pPlayerData );</P>) M$ E8 W/ m! ]; a
    <P>    // Remove the player from its cell
    # _8 H; D4 U4 [$ R' v    RemovePlayerDataFromCell( pPlayerData );</P>) L6 I/ x7 i5 P$ j3 Z; u5 q  y# _% k
    <P>    // Mark as inactive
    ; X0 q) `4 v+ X% ]3 i$ o    pPlayerData-&gt;bActive = FALSE;</P>9 X0 p3 p# f8 m- s) y, t" j+ L
    <P>    // Remove player from active list
    # X$ n; J& o& g$ q0 H/ w% C    if( pPlayerData-&gt;pPrevious )2 X; n6 ]; \$ y7 v
            pPlayerData-&gt;pPrevious-&gt;pNext = pPlayerData-&gt;pNext;. j- m0 ^" u" B3 x
        if( pPlayerData-&gt;pNext ), |' H5 _# c& I8 X) |. t; D  U
            pPlayerData-&gt;pNext-&gt;pPrevious = pPlayerData-&gt;pPrevious;</P>
      ]# |! B# G; {<P>    if( m_pFirstActivePlayerData == pPlayerData )
    $ P5 L3 v' R/ t6 r) H) j9 h        m_pFirstActivePlayerData = pPlayerData-&gt;pNext;</P>
    ! ^5 s* Y( C0 {! `8 P% u6 y: u<P>    // Add it to the free list, n; l+ Y; b3 r! F* F- r
        if( m_pFirstFreePlayerData )* h6 B) ?4 o( Q% {
            m_pFirstFreePlayerData-&gt;pPrevious = pPlayerData;% z3 _1 t! N# L% f9 }: a  C
        pPlayerData-&gt;pNext = m_pFirstFreePlayerData;
    8 I' _+ ~- g6 ]$ E, q0 a    pPlayerData-&gt;pPrevious = NULL;# M0 u! f0 L0 J, w  c; K
        m_pFirstFreePlayerData = pPlayerData;</P>
    5 b- Q6 }4 C) n! `<P>    // Update count of players: q. {+ H! |9 _+ c' |6 a
        m_dwActivePlayerDataCount--;</P>
    7 k( Z, f% Z/ N" y9 R( ]6 y<P>    UnlockPlayerData( pPlayerData );4 M( g5 O- q1 U8 i5 i+ q0 j( B
        m_PlayerDataListLock.Leave();
    5 {# ^5 M1 h" X  |! c, f8 K* j}</P>5 S8 x0 j- V  U4 \& g% c

    4 k! E- t( W, d2 |" i<P>
    ) X; X; G( M+ d; j$ @3 H//-----------------------------------------------------------------------------4 y) e+ ^, r3 g6 X$ w* l% a
    // Name:
    , s2 q9 C% b0 ~, _0 e2 e// Desc: ! j7 S- p1 \. D! D$ ]
    //-----------------------------------------------------------------------------
    9 h* w3 u0 ^7 ivoid CMazeServer::RemovePlayerDataFromCell( PlayerData* pPlayerData )
    1 Z3 \7 B: I6 j! `* p{& D% ~9 u  i/ \$ }4 H% T; T
        // Lock the player& [3 T$ w" ^5 _( B2 E: Q
        LockPlayerData( pPlayerData );</P>
    0 b5 {7 `, e: C$ |. c<P>    // Lock the cell the player is in7 h7 a; m) x; ^- d5 m( }
        ServerCell* pCell;! Q8 |8 B, ?6 C( D3 R
        if( pPlayerData-&gt;wCellX == 0xffff )
    7 o+ k4 j( ]# I5 i3 l9 f$ R    {. g4 [$ ~4 M8 Z
            m_OffMapLock.Enter();
    & M' G3 Z  J% I1 \9 x8 ]        pCell = &amp;m_OffMapCell;; L' ~# c/ J( o2 r0 z- i
        }
    6 `) B! k$ g4 i    else
    : G! o, _% ]& ^8 k/ s    {5 \, g2 t7 s; w/ |, D
            LockCell( pPlayerData-&gt;wCellX, pPlayerData-&gt;wCellY );* ^7 C( w7 z" f0 o6 ]4 \! O) H
            pCell = &amp;m_Cells[pPlayerData-&gt;wCellY][pPlayerData-&gt;wCellX];
    3 b" k' I3 a# j9 U% Q) c9 ]    }</P>( O" s( Y% o7 K4 }+ l! ^' k# b% R
    <P>    // Remove it from the cell
    ) Q6 g) F; m- B# y4 }    PlayerData* pPt = pCell-&gt;pFirstPlayerData;* ^8 N6 q3 l. b4 Q* H: I8 h
        PlayerData* pPrev = NULL;3 ?  Y9 `) S+ S/ G# z' e, ~; e
        while ( pPt )
    4 i  B( Z, f' W6 o% f    {& @3 p, _2 n  b9 {; N  a
            if( pPt == pPlayerData )  @- r! _3 N. n3 g0 G( j2 F
            {
    . B2 i& Z8 [2 G0 _. M  M& X            if( pPrev )5 a, Y" b5 U; G1 n  c' N0 O! I
                    pPrev-&gt;pNextInCell = pPlayerData-&gt;pNextInCell;
    ! K/ C+ h0 B6 u$ o; [            else* F( F# Q& I5 u; t7 m
                    pCell-&gt;pFirstPlayerData = pPlayerData-&gt;pNextInCell;</P>2 x& A/ ~& y* J5 ~, G; ?$ y1 W
    <P>            pPlayerData-&gt;pNextInCell = NULL;
    8 O: G: T2 P. e# k+ z' V9 J            break;3 i$ ^6 d9 C7 v# M5 l3 X$ t# S5 G
            }7 E8 x+ n6 @/ j' \: v( |
            pPrev = pPt;( u5 ~' p  R9 c4 c% l: y  m+ G" s8 B
            pPt = pPt-&gt;pNextInCell;. Z5 y8 o- {  A
        }</P>" H: [" S9 j1 n" f2 m
    <P>    // Unlock the cell
      S+ ~  _2 m7 _( ]4 Y* X  k2 }    if( pPlayerData-&gt;wCellX == 0xffff )
    , S9 a7 e* y3 `$ U        m_OffMapLock.Leave();- R: p' F0 I' Q- I
        else
    ) Y" }9 Z8 N  J2 e8 D* [        UnlockCell( pPlayerData-&gt;wCellX, pPlayerData-&gt;wCellY );</P>
    ! }7 Y$ f0 o8 [$ ~4 `<P>    // Unlock the player
    - D: L, R- |! E8 e9 ^    UnlockPlayerData( pPlayerData );, N; O$ ?( R, n
    }</P>) o: G$ f1 i. _5 z5 S

    ; Q5 F0 c# W. V( C2 e( L<P>  v6 x) n. C2 u- P% v& Q! S0 g
    //-----------------------------------------------------------------------------( y" ~, S. z% Z
    // Name:
    ; d% R0 j' \+ l7 z! b* c// Desc:
    ) f) _" W/ A  W$ d8 Y. Y//-----------------------------------------------------------------------------
    * f& Y1 y: m' T) ]% Vvoid CMazeServer::UnsafeRemovePlayerDataFromCell( PlayerData* pPlayerData )1 M/ S6 h1 U2 z9 L
    {
      \! y# r2 \1 h  e    ServerCell* pCell = GetCell( pPlayerData );* @  ]: s; t, D! r+ I8 J0 S
        PlayerData* pPt  = pCell-&gt;pFirstPlayerData;$ P& L3 T8 B5 T' g
        PlayerData* pPrev = NULL;
    . C1 K4 o/ o4 ^6 f6 l    while ( pPt )  W" n, n8 v( \
        {
    % U/ G. @1 ]1 C# o        if( pPt == pPlayerData )* M5 [3 L  T+ r, s0 j, o" y
            {  Z" j' w+ L% S) g
                if( pPrev )
    6 I+ ?  ~0 k4 ^) F: h( e& Q                pPrev-&gt;pNextInCell = pPlayerData-&gt;pNextInCell;
    - d2 S0 l2 Z% e& B3 R6 N: H            else' k0 X4 w: S- b$ ?4 |  ~
                    pCell-&gt;pFirstPlayerData = pPlayerData-&gt;pNextInCell;- Y  c4 _* Q: N+ u
                pPlayerData-&gt;pNextInCell = NULL;; ~9 k$ K3 ^3 P
                break;
    # w4 q; c  N2 U& W: U& L  m/ _: j        }
    ; ?. u5 ?8 @4 a' ]# F! j        pPrev = pPt;+ P  b  k- c" @5 v$ i1 M5 S
            pPt = pPt-&gt;pNextInCell;
    . e% I& M+ j0 h; I, e& }/ E' I3 |9 Q, X    }; i* h- U1 z1 |1 L# e; i  a
    }</P>
    7 Q3 @- E4 O* a$ K. W3 x7 z' `7 W# L7 v8 J
    <P>& j+ ^! P/ W1 W' r7 T6 [
    //-----------------------------------------------------------------------------, m: [$ p! p/ L
    // Name:
    ; M% u3 h5 [9 y7 G- J// Desc: & }0 V7 ^2 k/ U. c' ]+ S1 n4 }; L  l
    //-----------------------------------------------------------------------------
    7 ?" T: a& V, C1 i' M: w; ovoid CMazeServer::UnsafeAddPlayerDataToCell( PlayerData* pPlayerData )
    , B! z, ]: Q, i: _{
    & R) c4 m9 ~4 o/ u) g    ServerCell* pCell   = GetCell( pPlayerData );7 h2 ~7 v3 [& ~3 U
        pPlayerData-&gt;pNextInCell = pCell-&gt;pFirstPlayerData;
    % _3 i* Z: Z: y& {& X    pCell-&gt;pFirstPlayerData = pPlayerData;+ |( Z6 u; c$ a, a
    }</P>  ~3 m, a/ ?- q6 Q7 m
    7 f& q( }) O7 Z# n( t
    <P>8 D  ~: S, S) ^2 Z) ~/ _' v* E
    //-----------------------------------------------------------------------------
    2 n8 H$ H: Y2 Z/ a. `% q! ]+ X4 t// Name: 4 q# F! k1 d# [# }- F
    // Desc: 0 s2 s( h% S  }  @3 `2 A
    //-----------------------------------------------------------------------------5 j* Y1 C8 ], a' _( j
    void CMazeServer::HandleClientPosPacket( DWORD dwFrom, ClientPosPacket* pClientPosPack )
    4 z" t) L+ e/ W8 ^- e% X( i{
    1 N6 O" b* ]: T4 R2 B1 r    // Grab player for this client and lock it+ N7 L, \. y4 \  \+ J7 ~5 C
        PlayerData* pFromPlayer = GetPlayerDataForID( dwFrom );
    9 D8 T) f5 o5 T2 m    if( pFromPlayer == NULL )
    5 Y, T& `+ m2 J2 s    {
    5 Y) \8 D3 q! J! @        if( m_dwLogLevel &gt; 1 )
    + ?$ J: N, g& C" L) c& l, X            ConsolePrintf( SLINE_LOG, TEXT("DPNID %0.8x: Could not find data structure for this player"), pFromPlayer-&gt;NetID );
    6 E+ C3 A) R- S" I! _2 S        return;" ?8 q2 I9 {; p% R' P- s/ ~8 |, N
        }</P>+ [. S& E( c" p! j( q
    <P>    LockPlayerData( pFromPlayer );</P>
    % [" \9 l9 P' ~( N% X<P>    if( FALSE == pFromPlayer-&gt;bAllow )
    6 V: [- h$ S8 C; o' \  U    {" J, Y/ ^2 L# o7 J
            if( m_dwLogLevel &gt; 0 )) Q6 N* P2 D  W7 P5 l
                ConsolePrintf( SLINE_LOG, TEXT("DPNID %0.8x: Got position packet from bad client.  Rejecting client"), pFromPlayer-&gt;NetID );</P>
    4 o- m' G8 `* j# t3 S; c+ S<P>        m_pNet-&gt;RejectClient( dwFrom, DISCONNNECT_REASON_CLIENT_OUT_OF_DATE );
    6 [: b! J' I: [$ Z5 w+ h/ m8 U- o        UnlockPlayerData( pFromPlayer );$ E7 o& a) Z) L, e/ x2 D* i
            return;- u) X; A( h! F+ \( g
        }</P>: U! ^* b' W2 r2 p  b0 R+ U) R
    <P>    // Compute the cell the player should be in now. u6 i' Y9 s0 t' r, g: F$ W
        DWORD newcellx = int(pClientPosPack-&gt;fX);
    4 i: T0 b* i' O# F1 f& C) _6 R    DWORD newcelly = int(pClientPosPack-&gt;fY);
    " r. V, }: N1 V3 W8 k% \9 d  ]    DWORD oldcellx = pFromPlayer-&gt;wCellX;: S$ q! s% n/ l5 @5 C
        DWORD oldcelly = pFromPlayer-&gt;wCellY;</P>! Q5 |8 g* [2 \! G
    <P>    // Have we moved cell?
    + T4 D/ _; V" H" E    if( newcellx != oldcellx || newcelly != oldcelly )
    6 ?3 {! |1 m& S* r: z! a4 V    {
    , ?, g! X1 U$ S  Q: _5 e        // Yes, so lock the pair of cells in question; k, S& G; Y: {
            LockCellPair( oldcellx, oldcelly, newcellx, newcelly );</P>1 D( R( i) ~8 a
    <P>        // Remove from old cell and add to new cell& W/ |! |3 E& E
            UnsafeRemovePlayerDataFromCell( pFromPlayer );% J9 n% {; D0 ^  V4 l
            pFromPlayer-&gt;wCellX = WORD(newcellx); pFromPlayer-&gt;wCellY = WORD(newcelly);
    1 D* p6 ]$ s! p4 W        UnsafeAddPlayerDataToCell( pFromPlayer );</P>1 I# Y. c1 k& k4 k+ C. u3 X- m
    <P>        // Unlock cells
    & S/ P4 S" ?# n" V: a+ O. {6 m        UnlockCellPair( oldcellx, oldcelly, newcellx, newcelly );
    ' u4 t/ b$ @% l  [9 f+ H, D, e& G    }</P>
    ; _' b% ]- o& p  q<P>    // Update player position# i$ B" d& J: V* S, A. q7 L- F3 b
        pFromPlayer-&gt;fPosX      = pClientPosPack-&gt;fX;& c6 Z1 ]3 _1 u
        pFromPlayer-&gt;fPosY      = pClientPosPack-&gt;fY;9 N  q% j2 u) q
        pFromPlayer-&gt;aCameraYaw = pClientPosPack-&gt;aCameraYaw;</P>
    ; t9 C5 a1 Y' I/ v<P>    // Allocate space to build the reply packet, and fill in header 8 ?4 M/ s* {) Y& U  X4 r1 `6 ]! c
        DWORD dwAllocSize;8 l" i3 w* e- e" D% V# Q8 x
        ServerAckPacket* pSvrAckPack = NULL;</P>2 m2 e! a& _* q! P4 ~
    <P>    // Begin by allocating a buffer sized according to
    5 ]/ ~  S+ Q  ^, R0 f    // the current number of nearby players + 4.  This will give 5 R2 M7 K: `% {, Y3 N* P
        // a little room for more players to come 'near' without resize
    8 A) s' L+ ~) |7 `    // the buffer.# b5 j% O$ g1 \0 K) y
        DWORD dwMaxPlayerStatePackets = pFromPlayer-&gt;dwNumNearbyPlayers + 4;</P>2 W: A# r4 l: v+ J9 I
    <P>    dwAllocSize = sizeof(ServerAckPacket) + dwMaxPlayerStatePackets*sizeof(PlayerStatePacket);0 ~* F' v0 |% u1 g0 M; H4 E$ a2 y
        pSvrAckPack = (ServerAckPacket*) realloc( pSvrAckPack, dwAllocSize );5 i2 M& k$ A4 T  m8 V
        if( NULL == pSvrAckPack )
    % j3 L2 @" K; ]  j+ S/ n+ |) e/ f    {  d- L& v; S0 F& U/ v; q
            // Out of mem.  Cleanup and return& e: i0 C* K4 m9 R/ J
            UnlockPlayerData( pFromPlayer );  W2 z$ N3 I0 Y# h8 z
            return;       7 O' n) j5 @3 s9 K+ Y( @
        }( t2 E8 E& x; Z0 l: P- Y0 K
        ZeroMemory( pSvrAckPack, dwAllocSize );</P>
    & o$ A6 q4 q/ O* P<P>    *pSvrAckPack = ServerAckPacket(m_dwPlayerCount);
    % C/ W! F3 V; w2 ~" L5 O4 X    pSvrAckPack-&gt;wPlayerStatePacketCount = 0;3 s; Q* N! Y0 u, Q( B2 E* v5 ]
        PlayerStatePacket* pChunk = (PlayerStatePacket*)(pSvrAckPack+1);</P>
    ( |! G& Z3 u2 L8 C2 g. g- y<P>    // Compute range of cells we're going to scan for players to send1 O" F5 g2 N2 H, Y/ V; T
        DWORD minx = (newcellx &gt; 7) ? (newcellx - 7) : 0;
    : B7 K# t# }( c2 ~2 W& P3 @    DWORD miny = (newcelly &gt; 7) ? (newcelly - 7) : 0;" ~) w6 J* X9 Q2 H: b: y8 ~
        DWORD maxx = (newcellx+7 &gt;= m_dwWidth) ? m_dwWidth-1 : newcellx+7;# ~4 ~9 ^9 J; C, H+ V
        DWORD maxy = (newcelly+7 &gt;= m_dwHeight) ? m_dwHeight-1 : newcelly+7;</P>
    - j8 t3 C1 B5 u* t+ o4 s' _<P>    // Lock that range of cells5 f& D! t3 x* U
        LockRange( minx, miny, maxx, maxy );</P>
    + N7 R/ u& U3 K% {" o& f; a<P>    // Scan through the cells, tagging player data onto the end of
    ; m" m5 {% J  U* v% F9 G    // our pSvrAckPacket until we run out of room* p* Z  H$ I( c7 V* b% W
        for( DWORD y = miny; y &lt;= maxy; y++ ): E2 C, _; l$ a* e  O& {5 O- ]
        {" m9 P! B' P7 S" V3 ~# V9 R5 ?+ p0 S
            for( DWORD x = minx; x &lt;= maxx; x++ )0 v  u( ]8 A! P/ Y3 S
            {
    ) n2 Z! N. Q1 Z            PlayerData* pCurPlayerData = m_Cells[y][x].pFirstPlayerData;8 y: x5 u% N0 g9 s6 z) Z, S; P6 |
                while ( pCurPlayerData )
    : {( F9 F  u4 D8 X  m            {
    " y0 S2 `6 m& q; W+ U                if( pCurPlayerData != pFromPlayer ). R0 ]; M9 l/ r
                    {* ~# `) Z2 r* b
                        if( pSvrAckPack-&gt;wPlayerStatePacketCount &gt;= dwMaxPlayerStatePackets )
    , G) o# x. A7 Z8 b% g, C/ ]1 y                    {
    3 y: \* b" p  Z2 u+ `. \% F                        // Make sure pChunk is where we think it is
    5 u) {$ U: H& M1 \                        assert( (BYTE*) pChunk == (BYTE*) ((BYTE*)pSvrAckPack + sizeof(ServerAckPacket) + pSvrAckPack-&gt;wPlayerStatePacketCount*sizeof(PlayerStatePacket)) );</P>  o9 _3 j9 u2 @, L2 F4 G! S  F
    <P>                        // There are more than just 4 new nearby players, so resize the
    3 F  I( ]1 Y1 N1 q                        // buffer pSvrAckPack to allow 16 more PlayerStatePacket's.
    + X; B+ {8 r- o# H                        dwMaxPlayerStatePackets += 16;
    , `/ G3 i% V- N9 l6 [; m' J& n                        dwAllocSize = sizeof(ServerAckPacket) + dwMaxPlayerStatePackets*sizeof(PlayerStatePacket);
    , w1 w) M- O( F8 j$ p6 {                        ServerAckPacket* pNewSvrAckPack = NULL;8 R0 k2 v  C, D' V' U' I8 w4 i: x
                            pNewSvrAckPack = (ServerAckPacket*) realloc( pSvrAckPack, dwAllocSize );
    4 ?7 }8 \. |, L                        if( NULL == pNewSvrAckPack )+ I6 R, T. J5 j8 Y
                            {
    2 B3 |6 |! \2 s# }1 M) P! `                            // Out of mem.  Cleanup and return
    ( |& k! O# w$ {. [                            free( pSvrAckPack );
    3 J4 a3 c  z$ c+ Y; k9 s6 f                            UnlockRange( minx, miny, maxx, maxy );
    & {! O; N* ?& L' N3 D2 d                            UnlockPlayerData( pFromPlayer );, `' w" ]7 S  }# ?$ S/ B
                                return;       , D2 I$ Z% q2 ^8 c8 N0 B8 a
                            }</P>, G2 m" s6 j4 M8 R; d9 E5 E
    <P>                        pSvrAckPack = pNewSvrAckPack;
      ?5 W/ m4 ?! X# o                        pChunk = (PlayerStatePacket*) ((BYTE*) ((BYTE*)pSvrAckPack + sizeof(ServerAckPacket) + pSvrAckPack-&gt;wPlayerStatePacketCount*sizeof(PlayerStatePacket) ) );</P>
    9 s0 c, x/ g* C<P>                        // Make sure pChunk is still where its supposed to be
    , b$ e& J, j. r3 {& K                        assert( (BYTE*) pChunk == (BYTE*) ((BYTE*)pSvrAckPack + sizeof(ServerAckPacket) + pSvrAckPack-&gt;wPlayerStatePacketCount*sizeof(PlayerStatePacket)) );
    9 O% L+ _0 }. G% ^1 r1 h                    }</P>
    & y- O# q3 \4 W$ M4 \9 \1 V<P>                    pChunk-&gt;dwID       = pCurPlayerData-&gt;dwID;; s5 K2 B! h6 a  Q
                        pChunk-&gt;fX         = pCurPlayerData-&gt;fPosX;
    6 y/ y! [! _/ W                    pChunk-&gt;fY         = pCurPlayerData-&gt;fPosY;
      p- X$ Q0 ^0 l$ O                    pChunk-&gt;aCameraYaw = pCurPlayerData-&gt;aCameraYaw;
      ~9 D$ i! h  j# M                    pChunk++;; I/ e2 `$ u/ O4 e8 Q9 z- N; d, \' g
                        pSvrAckPack-&gt;wPlayerStatePacketCount++;) W+ I, I  C7 @; T$ a! F5 ]
                    }
    ; c! S4 D- N5 H' g8 B                pCurPlayerData = pCurPlayerData-&gt;pNextInCell;5 T9 Q* ^0 C4 F0 K' v5 u9 `" f
                }
    ' y$ w/ k9 w( q9 V: l$ K        }
    ) l5 C6 e# i/ J( ]4 q; I7 W" u    }</P>* h6 I9 X* H  v6 F1 P
    <P>    // Update the dwNumNearbyPlayers for this player7 E3 M1 e" h% @, X  N
        pFromPlayer-&gt;dwNumNearbyPlayers = pSvrAckPack-&gt;wPlayerStatePacketCount;</P>+ a+ C6 H' u4 F* q
    <P>    // Unlock range of cells5 p' }. a8 c- M- g. F' h, h
        UnlockRange( minx, miny, maxx, maxy );</P>* d7 M; N6 B% u3 c
    <P>    if( m_dwLogLevel &gt; 2 )5 a( K4 ?% a1 C; j! t  c
        {/ ?: u( a4 n2 U$ m; ?
            ConsolePrintf( SLINE_LOG, TEXT("DPNID %0.8x: Position is (%0.2f,%0.2f)"), pFromPlayer-&gt;NetID, pFromPlayer-&gt;fPosX, pFromPlayer-&gt;fPosY );6 o6 C9 W4 i6 @
        }
    / K$ J: \- \! y+ {% i. r$ f: ?    else if( m_dwLogLevel == 2 )
    2 h2 @3 n! o7 E0 V2 [    {9 i' A# N3 b4 t. h
            FLOAT fTime = DXUtil_Timer( TIMER_GETAPPTIME );  G; ~1 r% z- F" [$ e2 m  a
            if( fTime - pFromPlayer-&gt;fLastDisplayTime &gt; 60.0f )
    $ Q# e$ Q7 s$ f5 P( X2 a9 v        {7 ]% G2 ~; x8 {+ ~& E7 P" o
                ConsolePrintf( SLINE_LOG, TEXT("DPNID %0.8x: Position is (%0.2f,%0.2f)"), pFromPlayer-&gt;NetID, pFromPlayer-&gt;fPosX, pFromPlayer-&gt;fPosY );- \% l7 H' A; t" L
                pFromPlayer-&gt;fLastDisplayTime = fTime;
    5 s2 m2 U9 E. a6 T! x7 \2 u& J        }
    0 q6 a9 v; r( L( ~3 l6 Q    }</P>  }1 }3 a3 B, t* z5 ^9 d) C
    <P>    // Unlock the playerdata% o, z# Z$ o+ n6 r/ m5 e8 R
        UnlockPlayerData( pFromPlayer );</P># l6 N9 {1 E: k9 U% A0 h$ J
    <P>    // Send acknowledgement back to client, including list of nearby players
    6 t- Y" M4 z6 w, h3 v    DWORD acksize = sizeof(ServerAckPacket) + (pSvrAckPack-&gt;wPlayerStatePacketCount * sizeof(PlayerStatePacket));( ^/ F# J: j) ]0 f

    1 X/ t& c$ `, w. W% U) L    // Pack the buffer with dummy data.
    % Q4 Z! g9 r, `6 Q" c    if(m_ClientNetConfig.wServerPackSizeArray[m_ClientNetConfig.ubServerPackIndex] &gt; 0)0 m% F5 L8 K5 Q- D
        {
    5 K. o" ~. k) l* s        DWORD   dwBufferSize = acksize + m_ClientNetConfig.wServerPackSizeArray[m_ClientNetConfig.ubServerPackIndex];
    ( E6 T0 j. Q0 z5 v        VOID*   pTempBuffer = 0;</P>
    / I* t5 V6 f1 l3 Z* N" ~$ g<P>        pTempBuffer = malloc(dwBufferSize);
    4 R  H. H1 _" Q  B9 h* O2 Y% k5 n        if( NULL == pTempBuffer )
    1 o6 P4 ?% e( X& N% Y+ L        {  [5 I/ t' a; \. r- W8 Y
                //Out of memory9 Y* V" t6 `7 I  |+ h) }( v( _
                DXTRACE_ERR_NOMSGBOX( TEXT("System out of Memory!"), E_OUTOFMEMORY );
    3 u9 L$ _) ?7 ?) p  O3 c            free( pSvrAckPack );
    ( n9 `: D4 Z1 x$ X+ K: c6 u            return;# j8 P. d/ M. |8 G
            }</P>+ F8 R$ d; H. f8 o8 J6 B3 y9 F
    <P>        FillMemory(pTempBuffer, dwBufferSize, 'Z');
    ) r  Y8 H" i; d7 O) Z' n        memcpy(pTempBuffer, pSvrAckPack, acksize);</P>
    5 h* U8 N& F% t# {" u9 ]# f<P>        SendPacket( dwFrom, pTempBuffer, dwBufferSize, FALSE, m_dwServerTimeout );
    . z4 _. `& b; Q* W6 S   
    % ]5 {/ f8 Z) D  w        free(pTempBuffer);
    5 y+ y2 L3 k6 X    }   4 X* y+ I% ^$ H9 r. m  W
        else
    * i* L: }) R# |    {% Q) f- ~) l. f3 }$ l4 J
            SendPacket( dwFrom, pSvrAckPack, acksize, FALSE, m_dwServerTimeout );
    $ m/ Q' Z4 [) H  ~    }</P>. x+ p; g( P; q, ~# I
    <P>    free( pSvrAckPack );</P>! ~1 A& _9 f7 c. P
    <P>}</P>9 g, s  x; C  d' }+ l( q- T6 l
      _; x* F3 Q1 l7 Z% x# J: f
    <P>3 O4 k% _3 j/ e! [: B' g8 K9 ^0 b
    //-----------------------------------------------------------------------------
    0 t8 b# ~0 m- ]2 w  p. K" m// Name: % ^% h' N; |1 m) K* J
    // Desc: ( D3 D( \- E, d0 R3 l+ ?) }- H
    //-----------------------------------------------------------------------------
    ! P% d  w- j( }& A6 G) U% ?void CMazeServer::HandleClientVersionPacket( DWORD dwFrom, ClientVersionPacket* pClientVersionPack )& O. y8 B6 N& f$ h& e
    {
    ( ~: A: W& j/ ~& K( g    // Grab playerdata for this client and lock it
    / G! h6 A- b- D4 L; x) }2 ?% p    PlayerData* pPlayerData = GetPlayerDataForID( dwFrom );- h2 F7 L; A4 S5 b1 g
        if( pPlayerData == NULL )" G/ o- @5 y  p) \6 O
            return;
    ' H3 `1 T! l$ D) _  _7 C    LockPlayerData( pPlayerData );</P>- a! V% _: r* A5 L2 m
    <P>    // Record the version number 9 r3 P1 D. `1 n! H5 [9 N$ k
        pPlayerData-&gt;dwVersion = pClientVersionPack-&gt;dwVersion;</P>
    ( t* S0 P8 t, H4 `3 [<P>    if( m_bLocalLoopback )
    ) x; K# Y5 j% p1 |        pPlayerData-&gt;bAllow = TRUE;3 Y) X) ?. _5 s9 ~7 t* y/ }) f
        else/ G- ?6 t* S; A" j* C$ i
            pPlayerData-&gt;bAllow = IsClientVersionSupported( pClientVersionPack-&gt;dwVersion );</P>
    ' M5 k7 G6 ~1 F- i: o" p  |<P>    if( m_dwLogLevel &gt; 0 )" O# }8 y7 Q2 H  U8 k
            ConsolePrintf( SLINE_LOG, TEXT("DPNID %0.8x: Client version=%d (%s)"), pPlayerData-&gt;NetID, pPlayerData-&gt;dwVersion, pPlayerData-&gt;bAllow ? TEXT("Accepted") : TEXT("Rejected") );</P>/ Z! x7 t  `- T7 i
    <P>    if( FALSE == pPlayerData-&gt;bAllow )! E0 D( n) a+ Z+ c3 }+ S" w* |
        {
    5 Q& C' c* Q' F& |( v        if( m_dwLogLevel &gt; 0 )
    0 h! u) Y. l6 s4 H4 z9 w            ConsolePrintf( SLINE_LOG, TEXT("DPNID %0.8x: Rejecting client"), pPlayerData-&gt;NetID );</P>' C+ E5 s) r" x% y6 l
    <P>        m_pNet-&gt;RejectClient( dwFrom, DISCONNNECT_REASON_CLIENT_OUT_OF_DATE );) W) `& q  [- t2 |
            UnlockPlayerData( pPlayerData );
    7 u3 N: t9 Q4 _" O        return;
    & W2 h: y; `: E, ]9 l" w    }</P>
    5 H  z3 h( r8 ?. @9 J5 D  i- x<P>    // Unlock the playerdata4 ]; \% e) L8 W4 M% {! ~( ^, x' q
        UnlockPlayerData( pPlayerData );</P>- M/ w# S( ?! a' ^: |
    <P>    // Send acknowledgement to client that the client was either accepted or rejected
    % Q1 r9 h6 l, o8 `# a    ServerAckVersionPacket packet( pPlayerData-&gt;bAllow, dwFrom );, Y' [+ s, d" }) D0 w5 x4 }0 i' d
        SendPacket( dwFrom, &amp;packet, sizeof(packet), TRUE, 0 );
    ) M9 T9 D. u/ l/ a$ d6 I2 o}</P>
    6 G3 ^  ?, K6 y9 d: F* _) d: z1 w' X5 C; Z
    <P>" f: ~. f4 y; q8 a& W
    //-----------------------------------------------------------------------------; C# \2 Q4 i4 G" l# y
    // Name:
    ' \& b' M% {% I# A, ^// Desc:
    $ t6 B0 N9 K1 G1 T! M//-----------------------------------------------------------------------------
    " V0 q9 c& ?8 t4 aBOOL CMazeServer::IsClientVersionSupported( DWORD dwClientVersion )4 T+ \* V/ v9 B! U
    {' ]% H: M2 r8 N9 b
        switch( dwClientVersion )% K: T8 S  v* y# k* w' a, T5 C
        {2 I' x) g, f) N/ U: W" i
            case 107: // only v107 is supported4 r, O& j% S" Q6 y
                return TRUE;
    ' T1 \+ s) C$ r, P        default:( J* ?, R6 |2 s, J  {! x4 P' x5 S# r
                return FALSE;  o: V$ W/ L" v/ a& t6 ^( F" _
        }
    1 x' t' s4 A- ^6 l5 K}</P>2 c* G# R- z( P, |

    + a. |! v* j5 }4 Q<P>" K1 l- d4 L+ t7 L6 W
    //-----------------------------------------------------------------------------
    - O( `5 |6 |8 q- m( X' e: ?// Name:   H2 U7 n0 }9 o" I9 t* P" c7 V
    // Desc:
    ! T$ d4 K6 Q1 u) n7 X//-----------------------------------------------------------------------------( R  r1 O0 p/ L4 y
    void CMazeServer::HandleUnknownPacket( DWORD dwFrom, ClientPacket* pClientPack, DWORD size )* Q& |+ U8 U  T( [( t. [
    {
    . d- D# a& o% F" [# I3 p0 b    if( m_dwLogLevel &gt; 1 )( [7 I$ C# D- U
            ConsolePrintf( SLINE_LOG, TEXT("ERROR! Unknown %d byte packet from player %0.8x"), size, dwFrom );</P>
    0 `$ G( v& Q; w/ [* Z<P>    m_pNet-&gt;RejectClient( dwFrom, DISCONNNECT_REASON_CLIENT_OUT_OF_DATE );
    & \4 D  c/ X$ J- h9 E. S}</P>
    - ^7 B: m9 i/ u! u2 K; E  E9 f7 q  k: S8 h- o) d
    <P>
    . ?. t+ h/ W6 ^, o) U' }2 u) ^//-----------------------------------------------------------------------------% @) G( W3 B8 y; L& P% R/ {
    // Name: 7 B, S7 J' e2 Z: o
    // Desc: % \: @" O* a3 b. z$ i6 C
    //-----------------------------------------------------------------------------
    ) G5 L: g, [2 N# QDWORD   CMazeServer::IDHash( DWORD id )0 h* W' F' B! C0 f, l; \  c
    {) P. w. Q7 A+ y* i- K
        DWORD   hash = ((id) + (id&gt;&gt;8) + (id&gt;&gt;16) + (id&gt;&gt;24)) &amp; (NUM_ID_HASH_BUCKETS-1);
    6 j! ~& H* }) n& c) e6 n3 h    return hash;8 ~. V' ]. V; |7 t
    }</P>+ T" M$ K! a% u8 h+ p: I

    3 b8 L3 R/ \6 C' B0 R6 U<P>& M) g- k4 P3 k: B; Y& }7 l# w6 |4 y
    //-----------------------------------------------------------------------------/ |1 T# d0 _  r' f( w2 f
    // Name:
    4 X' l4 V7 i' e; i// Desc: 8 n3 R/ T7 E- [5 G" k- \5 i6 x
    //-----------------------------------------------------------------------------; ~, `/ [2 ~8 Z& t9 A
    void CMazeServer::RemovePlayerDataID( PlayerData* pPlayerData )
    0 L* f. M7 `! l  G- _{7 {# W2 t: l! A8 ?/ `6 h
        // Hash the ID to a bucket number9 r5 K& g, ^* Q8 a- t8 d" }5 H
        DWORD   bucket = IDHash( pPlayerData-&gt;NetID );</P>" K" m- p- [2 _& ?$ @3 a; o- z
    <P>    // Lock that hash bucket
    - i" V8 }4 I% Z, c5 ?5 F2 u    const   DWORD   buckets_per_lock = NUM_ID_HASH_BUCKETS / NUM_ID_HASH_BUCKET_LOCKS;
    , M. \. g; o; p    m_IDHashBucketLocks[bucket/buckets_per_lock].Enter();</P>* C, s! y3 U3 y! v, y! E" x
    <P>    // Loop though players in bucket until we find the right one
    $ W- ?% q0 i" _4 z    PlayerData* pPt = m_pstIDHashBucket[bucket];
    * ^' D9 k0 S0 p$ D) z    PlayerData* pPrev = NULL;( R2 O4 m& k, W! k9 {2 L! }
        while( pPt )
    / Y% O7 X1 W) D: N* g    {
    6 j& k$ P4 [% t        if( pPt == pPlayerData )
    ) n0 d4 H9 C. z/ S' W. z            break;  }) ?: h6 q1 z( ~* H! _, p
            pPrev = pPt;( N# ~, [% c1 J0 [5 O. x9 }
            pPt = pPt-&gt;pNextInIDHashBucket;; r8 v# o. F. c2 W9 l- s' U
        }</P>
    1 i* G: V$ f" |% }7 x<P>    if( pPt )
    ! S9 E( F" s. ?& t' Y- j* B    {: J8 H4 Q: Y; N- n
            if( pPrev )
    / g, {) C! w: W' g! B+ ]! j* Q            pPrev-&gt;pNextInIDHashBucket = pPt-&gt;pNextInIDHashBucket;
    ' [* H& G+ P9 s' l        else
    ; W' O9 ~8 h* Q7 }' x7 ]1 u7 c9 Y            m_pstIDHashBucket[bucket] = pPt-&gt;pNextInIDHashBucket;
    3 w: K# A, [( ~! M! h        pPt-&gt;pNextInIDHashBucket = NULL;
      Q1 d, k) Q% D0 ]- K6 `/ R    }</P>& d0 Y+ X# |& ^; s4 Y; j
    <P>    // Unlock the hash bucket1 l3 c* |* [- [5 F
        m_IDHashBucketLocks[bucket/buckets_per_lock].Leave();
      }  v7 |3 n# ^1 x% ?& z9 S4 X}</P>
    & ^" l) o7 v: t. Z1 b$ r+ \. x7 z; C9 t' @3 k1 X
    <P>
    ' X+ o& x* y" F8 A7 ^//-----------------------------------------------------------------------------1 b. H( e" v6 {& u. J4 F4 V# F
    // Name: ' A' y5 O. Q. D' |
    // Desc:
    . j# O7 A( _! M$ y2 K/ N//-----------------------------------------------------------------------------: V. U; p, h. b. v; U# k
    void CMazeServer::SetPlayerDataForID( DWORD id, PlayerData* pPlayerData )
    7 s4 V& K! V* O9 u{
    9 T9 U! j7 L9 {2 [    // Make sure this player isn't added twice to the m_pstIDHashBucket[]7 F+ g& r: p; |& N8 h4 O0 U
        // otherwise there will be a circular reference" g! s- l( ~" k
        PlayerData* pSearch = GetPlayerDataForID( id );5 n7 F- e8 P8 @
        if( pSearch != NULL )( b6 J7 S, D4 C$ L6 `( y
            return;</P>6 K* _9 O- z2 N9 m6 _% k. \- U7 R
    <P>    // Hash the ID to a bucket number* l) ^6 I; _8 Q1 l
        DWORD   bucket = IDHash( id );</P>4 Q5 I* I$ _9 u) z( O
    <P>    // Lock that hash bucket
    9 K% a6 x) M& }/ V* ~1 W    const   DWORD   buckets_per_lock = NUM_ID_HASH_BUCKETS / NUM_ID_HASH_BUCKET_LOCKS;! F" h) F8 r6 X' ^+ h9 j/ r
        m_IDHashBucketLocks[bucket/buckets_per_lock].Enter();</P>
    5 n  p2 ]' m; K% \9 b! ]<P>    // Add player onto hash bucket chain
    / K; K8 E3 m7 x% f& {+ y" A, I4 C    pPlayerData-&gt;pNextInIDHashBucket = m_pstIDHashBucket[bucket];
    1 ?9 J3 z( O* o6 Z, b5 F3 f$ H- o    m_pstIDHashBucket[bucket] = pPlayerData;</P>' }  r6 f4 k9 w$ f
    <P>    // Store net id in player+ C0 }' _# v0 \: o( z- P" V
        pPlayerData-&gt;NetID = id;</P>7 {4 i5 O8 g& Q6 Y& `
    <P>    // Unlock the hash bucket
    6 O5 z4 i( E) S    m_IDHashBucketLocks[bucket/buckets_per_lock].Leave();  ~0 C* ^# m: m/ N
    }</P>8 q" A9 D* a/ p
    4 K& i7 v; P' ^, q. A+ G
    <P>" N, F: W, P; c/ L
    //-----------------------------------------------------------------------------
    2 `  S9 i+ O3 o( g- A// Name: 1 |: e/ G+ C1 M
    // Desc: & N' P/ a! a" W4 B
    //-----------------------------------------------------------------------------
    & c2 M- `; g+ k$ TPlayerData* CMazeServer::GetPlayerDataForID( DWORD id )  ]* }- c& H* @
    {& h+ c% L& V+ g4 t1 r0 y* i5 D
        // Hash the ID to a bucket number
    2 ?9 L2 b2 t* K6 S& j9 D# q    DWORD   bucket = IDHash( id );</P>
    2 w  V9 q$ P  p9 j  G<P>    // Lock that hash bucket
    ; H4 N9 ~9 F, r4 L$ ]/ A) [" d8 ?    const   DWORD   buckets_per_lock = NUM_ID_HASH_BUCKETS / NUM_ID_HASH_BUCKET_LOCKS;
    0 y: }2 h; I# ]    m_IDHashBucketLocks[bucket/buckets_per_lock].Enter();</P>
      d% i: O" w+ i" f8 D7 Y<P>    // Loop though players in bucket until we find the right one
    2 w7 R" f) l5 T4 R* S( ~1 [    PlayerData* pPlayerData = m_pstIDHashBucket[bucket];
    3 B% I. ?& G" m  G$ G2 ^- E1 j( y    while ( pPlayerData )
    9 s' t. {; ~* c. ?( G    {
    8 b0 e5 Y: G# R8 e7 j        if( pPlayerData-&gt;NetID == id )
    ! Q! w8 h1 Z/ K% @7 m) n1 f' n            break;
    1 X0 k1 m7 C& D/ a8 _2 o( k8 U# R        pPlayerData = pPlayerData-&gt;pNextInIDHashBucket;
    9 `1 `# `- p) t0 V    }</P>0 u- \, D- k5 H2 C# U+ `
    <P>    // Unlock the hash bucket- W$ w4 N+ Q  Y' p0 W
        m_IDHashBucketLocks[bucket/buckets_per_lock].Leave();</P>; {' x9 w" ]+ T/ o" Z
    <P>    // Return the player we found (will be NULL if we couldn't find it)
    # P# y" I- P5 S; L5 E    return pPlayerData;
    9 T' B% A' f+ O; Q7 p}</P>& y$ I+ I" Z/ ~3 d; D7 O* R
    1 G4 ]) _$ l: M
    <P>
    7 i( v' |# D; F5 I//-----------------------------------------------------------------------------$ o! H5 q5 Z0 z# X
    // Name: # F( Q% i) m* y1 }+ z: G. e' ~
    // Desc: calls DisplayConnectionInfo for each connection in a round-robin manner% b, E7 V. A( o1 c
    //-----------------------------------------------------------------------------. A* p: j% h! k1 A
    void CMazeServer:isplayNextConnectionInfo()
    * k  ~* G: h2 i1 Y0 k{
    5 X& {' N1 E; c    if( m_pNet )* Y% _+ k  a4 Q2 X2 z
        {7 o/ `1 K4 \, O) n
            // Find the player that was displayed the longest time ago, and display it.
    # C8 z* v0 o# L. t        FLOAT fCurTime = DXUtil_Timer( TIMER_GETAPPTIME );
    & `7 N& s! m$ u3 X* [        PlayerData* pOldestPlayerData = NULL;. d7 d  Y- W# w
            FLOAT fOldestTime = 0.0f;</P>
    , X# ]  a7 f# A0 X/ i<P>        m_PlayerDataListLock.Enter();</P>6 r& W! v  A! f$ \4 j0 N4 s
    <P>        PlayerData* pPlayerData = m_pFirstActivePlayerData;
    % l8 p& e$ s" a  C1 J% ?        while ( pPlayerData )- g2 R5 z: d; w: l# f  [' x6 u% |  A# Y
            {) @& h- {; }( O& V1 Y
                if( fCurTime - pPlayerData-&gt;fLastCITime &gt; fOldestTime )
    % C6 }- _; ?+ X9 E  W& J1 z            {
    ( y4 I5 C/ |+ t* g. P                fOldestTime  = fCurTime - pPlayerData-&gt;fLastCITime;% E9 g, ^9 ]. P
                    pOldestPlayerData = pPlayerData;% ^2 p) P  Z8 Y1 q0 b4 g! R
                }</P>
    ) s& _! U& U) m<P>            pPlayerData = pPlayerData-&gt;pNext;) K7 [! l0 f2 Z1 S' R+ C+ _
            }</P>& U* w* o2 V3 ~
    <P>        // Display the player with the oldest CI field, and update its CI field.
    & y6 Z- B, e/ Y6 ~6 v. w        if( pOldestPlayerData )0 l9 H' r8 s# B4 [. {9 P* H
            {
    6 }1 F  N+ k7 f- C* }            ConsolePrintf( SLINE_LOG, TEXT("Displaying connection info for next player") );
    + t2 T/ [! @$ @$ v            DisplayConnectionInfo( pOldestPlayerData-&gt;NetID );/ M0 h# a3 }& [8 B5 P& D6 f
                pOldestPlayerData-&gt;fLastCITime = fCurTime;
    ' t$ ~3 S4 T* `- k6 B        }
    4 `- ~1 u$ g& z        else
    1 t0 ], l- A: {9 n, G        {
    9 D. w: m  B9 c5 ?$ ?1 U! ^            ConsolePrintf( SLINE_LOG, TEXT("No players found") );0 W4 ]0 z9 c) a8 B/ p# M; [
            }</P>* Z. I4 V& q, Y: a4 p
    <P>        m_PlayerDataListLock.Leave();8 T- x/ {) X% o) F: T4 h6 a1 l8 l
        }% F. l2 G4 P9 Q4 e5 ^  Z
    }</P>8 Y! }6 c8 r) S( r. e

    . n3 `  b+ f# Y+ x; i6 Z<P>
    4 d: v" r. u' w! U& R; S+ b2 j! _+ D//-----------------------------------------------------------------------------. b# Q% b- v  |4 j3 S
    // Name:
    - {9 {: R7 K  ?8 L9 Y// Desc:
    8 ?( f$ G  t! z$ m. ~, v//-----------------------------------------------------------------------------
    ! L7 }+ N: r! S# @void CMazeServer:rintStats()
    , s7 K+ R" ]' a: J{
    . D1 t1 x  ]: N' s    ConsolePrintf( SLINE_LOG, TEXT("Thread count: Active=%d Avg=%.2f Max=%d"),
    , E. z' ?  O- Y                                    m_wActiveThreadCount, m_fAvgThreadCount, m_wMaxThreadCount );! G6 z- C6 M; z" w  {
        ConsolePrintf( SLINE_LOG, TEXT("Thread Time: Avg=%.4f Max=%.4f(s)")," U- {* m' }; Z' Z" ]
                                        m_fAvgThreadTime, m_fMaxThreadTime );6 f0 M4 q+ t6 j0 Q; p5 K
        ConsolePrintf( SLINE_LOG, TEXT("Players online (not including server player): %d"), m_dwPlayerCount );+ X: |5 G" s4 S1 o/ l1 \" I
        ConsolePrintf( SLINE_LOG, TEXT("Peak player count: %d"), m_dwPeakPlayerCount );
    9 d; L5 m- `! u# o}</P>
    * s) }0 W3 L; ^: X! ~" Q; H* M) A: h% d7 f. r& \2 S
    <P>
    9 o& s8 o4 f& [( p+ n$ |/ P//-----------------------------------------------------------------------------
      h* q0 Y3 H. F3 x9 W* M// Name:
    - c- B  c; j5 j0 }+ Y8 V// Desc:
    # j. `* g' T/ G5 `/ i//-----------------------------------------------------------------------------4 X; G) h: O  y
    void CMazeServer:isplayConnectionInfo( DWORD dwID )
    & V- ]4 c5 g* @) J, Z7 ~' V) s+ ?{7 t( e7 b3 C4 j, f) e
        TCHAR strInfo[5000];
    * S& E) F- u* j: L    TCHAR* strEndOfLine;6 c$ [1 ^- d8 V: k: z' Z9 ?
        TCHAR* strStartOfLine;</P>
    ( L) ]) L# H! M. S$ l<P>    // Query the IOutboudNet for info about the connection to this user6 ?7 L, v  S8 ^* m% G6 Q
        m_pNet-&gt;GetConnectionInfo( dwID, strInfo );</P>" W6 G  x- a8 Z+ U/ E4 B1 v
    <P>    ConsolePrintf( SLINE_LOG, TEXT("Displaying connection info for %0.8x"), dwID );
    5 f1 o7 h) p3 S; `    ConsolePrintf( SLINE_LOG, TEXT("(Key: G=Guaranteed NG=Non-Guaranteed B=Bytes P=Packets)") );</P>
      q1 o* Q$ Z# }, [<P>    // Display each line seperately* v6 Q) y; \  l1 q4 [8 _2 E
        strStartOfLine = strInfo;
    - j& {6 g/ Z2 K0 R- @8 r1 h    while( TRUE )
    3 [6 D0 B# k6 G7 M    {
    & u6 l2 q" `5 F0 o6 J        strEndOfLine = _tcschr( strStartOfLine, '\n' );- {8 `4 f6 q, a$ N3 Y9 v
            if( strEndOfLine == NULL )
    3 n; t" [0 V" B* ~) N            break;</P>
    : f) Q6 E! T! f( f1 [% ]<P>        *strEndOfLine = 0;
    ! t0 ~- M! t0 V8 G- Q        ConsolePrintf( SLINE_LOG, strStartOfLine );) m% b; I- q. n. N; y& {* p+ @
            strStartOfLine = strEndOfLine + 1;
    - K2 p$ V3 n+ k5 z0 p: d/ |( h. c    }, ?' _, v" d1 i' F- y- A- j! u
    }</P>  H0 ?0 z5 _& v) b
    8 V6 C( o. H3 v7 g
    <P>
    1 C' I+ m0 q: D/ Z& b" _) Y//-----------------------------------------------------------------------------
    / S! v/ N/ m& ]+ l6 F- C! j6 B// Name:
    & v; _6 B0 c0 L// Desc: 8 n( w( `1 y( n9 p6 v8 c
    //-----------------------------------------------------------------------------7 `5 [' I; J) ?
    HRESULT CMazeServer::SendPacket( DWORD to, void* pData, 1 w' F& D; l8 n9 \' [8 w
                                     DWORD size, BOOL reliable, DWORD dwTimeout )
    6 U1 c: [& I1 k* V. p9 \( |; k' m{
    & R: y9 k% n, B1 }8 I% q    // Chance of forcing any packet to be delivered reliably
    6 {& \4 G' ^, c    if( m_Rand.Get( 100 ) &lt; m_dwServerReliableRate )
    2 h: t% L2 q6 l0 D* d; ^$ [3 l        reliable = TRUE;</P>9 Q- t3 I. g, w( m0 r4 j) _
    <P>    return m_pNet-&gt;SendPacket( to, pData, size, reliable, dwTimeout );& G$ l2 f7 i9 U% @7 v/ a! B1 U
    }</P>- i/ K' x; T/ ?8 j# T6 K

    * _- J$ ?  h/ j( G. l: n' l/ B<P>
    2 \0 Z; e/ [7 t9 A* l7 y5 h//-----------------------------------------------------------------------------
    6 _4 l7 X; C6 O1 o5 w  J// Name: & X' \) l* w* a/ j9 g
    // Desc: ( l8 T: b1 c* D# y- U) Q5 Q) @1 ^
    //-----------------------------------------------------------------------------
    ' A2 t0 v& `8 E* |3 s* }6 u7 Z3 Wvoid CMazeServer::SendConfigPacketToAll( ServerConfigPacket* pPacket )) h; y7 c" y6 l
    {$ k+ |2 Q* K3 x4 c
        // If we're up and running, then send this new information to all clients. U# b6 N' Z+ j; c
        if( m_pNet )
    - r6 t' N  G, x) X1 b% i    {4 s! j( o' {; D1 {* _
            //Use the AllPlayers ID* h6 D8 A! K% G, X% S; N$ E  S( M
            SendPacket( DPNID_ALL_PLAYERS_GROUP, pPacket, sizeof(ServerConfigPacket), TRUE, 0 );
    . O7 r6 `( e" l) R    }/ U6 @5 b0 Q1 V1 S3 {* y% A7 j
    }</P>4 G( L- |  W  p0 |8 D$ V* m

    ! E/ O) E9 |3 W' Y<P>
    - \; ^9 e! |& U  n//-----------------------------------------------------------------------------! |2 U8 r. r9 P  a" G
    // Name: ; t6 Q4 i6 Y! s% _8 q4 P( i, ^
    // Desc: ; b/ u" A( D& f+ |9 O" r" ~2 }
    //-----------------------------------------------------------------------------2 }5 T7 l* c* t
    void CMazeServer::SetClientReliableRate( DWORD percent )
    3 S6 {# @3 @* p9 D{
    % ?# D; [+ \8 f. `    // Update client config, and build packet containing that data
    ! w% E0 p' Q6 v  e8 o6 F9 Q; Q2 @& C: V    m_ClientNetConfigLock.Enter();
    1 r- i7 r# x& p9 w8 K7 z0 a( e) u    m_ClientNetConfig.ubReliableRate = BYTE(percent);- p0 |& }% Z+ C8 ?$ t! O4 R
        ServerConfigPacket packet( m_ClientNetConfig );6 F  B7 C% Y4 p6 A7 a$ P
        m_ClientNetConfigLock.Leave();</P>
    & d1 `; N& k( V4 p<P>    SendConfigPacketToAll( &amp;packet );+ [" J! w+ t. [' z3 ]1 Q. g2 A: y
    }</P>( n6 Y) ~3 j- _) V/ }$ p

    ( \5 Y; [+ o8 W# s3 Q9 u8 v; J  U<P>! z6 J1 E# h/ I+ {7 y+ `3 a+ F  R2 j+ H
    //-----------------------------------------------------------------------------
    9 D5 [+ l1 g, _1 j" E1 m7 W4 e// Name:
    ( U. V9 _" }% d" W5 y// Desc:
    2 _  N. k  \" J$ ]. p//-----------------------------------------------------------------------------
      `/ Q) V% {: d0 n& E* \1 ?3 Bvoid CMazeServer::SetClientUpdateRate( DWORD rate )! a1 `$ ~" Z1 t0 u0 q! X
    {
    % n0 N' S. x/ s2 y! E5 q. r2 l    // Update client config, and build packet containing that data# U& m. s$ [1 j2 I( d* x+ t$ p
        m_ClientNetConfigLock.Enter();0 h; A% @+ b  R( ]5 R
        m_ClientNetConfig.wUpdateRate = WORD(rate);$ r3 {7 N6 e' U% }; a4 x
        ServerConfigPacket  packet( m_ClientNetConfig );
    + ~" G% Q7 H3 y& B$ k0 _+ f' p    m_ClientNetConfigLock.Leave();</P>
    4 x% l* ^2 n- p2 _2 p+ Q  Y<P>    SendConfigPacketToAll( &amp;packet );  w; Y/ q7 h8 G' W. U6 N
    }</P>
    2 x- z* o* y; q( m' t  z
      m# @. v2 Q9 Z, b; l) W! E& R<P>& o8 c' _6 k- S
    //-----------------------------------------------------------------------------
    0 ]/ `% C1 Z8 |; h1 [0 g// Name:
    ) [( z! Y+ a2 h: n9 Y* A* }// Desc: / _! a: k0 R) ^& z- N- P
    //-----------------------------------------------------------------------------
    9 G. M8 I/ ?) g: T0 X# @void CMazeServer::SetClientTimeout( DWORD timeout )4 n) y* o4 S) n7 m1 S
    {2 c, r- E. j2 d. g) j# n
        // Update client config, and build packet containing that data
    7 T9 y) l8 I8 Z/ G! v& X7 B* U    m_ClientNetConfigLock.Enter();
      d" e( G/ S( ?5 F    m_ClientNetConfig.wTimeout = WORD(timeout);2 E, ^& s+ ~! X8 B. x& O- ~
        ServerConfigPacket  packet( m_ClientNetConfig );
    - }. m1 k/ ^4 g7 V, J    m_ClientNetConfigLock.Leave();</P>
    3 f+ L! o8 d; {# n$ D<P>    SendConfigPacketToAll( &amp;packet );7 s: j, d3 n: z; s  ?  w6 t
    }</P>1 t& R! J- {% v6 y" @

    # y1 ]" P/ h- Q1 S. C( k<P>1 V6 k8 I/ i: {4 h' `  O6 @* ?7 s
    //-----------------------------------------------------------------------------
    % V: L1 ^9 J& r" E; D% E; a// Name:
    , `! T8 \0 J. J2 W1 B  C// Desc: 1 E+ @- Z- [+ `' B6 k; i
    //-----------------------------------------------------------------------------4 P  a8 x7 k( s, G0 O
    void CMazeServer::SetClientPackSize( DWORD size ). o+ _$ ?2 [0 G4 t0 H& v
    {
    % y% V/ m1 g$ _  d2 ]    // Update client config, and build packet containing that data3 ?  F& ]' a3 }! F4 T4 h
        m_ClientNetConfigLock.Enter();1 h: x" J5 s# i2 y+ p
       
    + q" b, j; _$ g1 k" L, `    m_ClientNetConfig.ubClientPackIndex++; //Increase index and verify location in array.
    3 b6 M6 }, q: V9 e' _6 v( N3 f    if(m_ClientNetConfig.ubClientPackIndex &gt;= PACK_ARRAY_SIZE)   
    $ e- h' ]" N: R/ J7 m        m_ClientNetConfig.ubClientPackIndex = 0;</P>
    $ B3 e+ g9 a  X1 ?3 p8 a% S- |7 b<P>    m_ClientNetConfig.wClientPackSizeArray[m_ClientNetConfig.ubClientPackIndex] = WORD(size);5 ?* J. i* X9 V$ N1 [: T, o
        ServerConfigPacket packet( m_ClientNetConfig );
    1 \: Y$ ]6 X2 [+ f# s) `$ S1 R    m_ClientNetConfigLock.Leave();</P>0 M+ A) t, _& @# Q
    <P>    SendConfigPacketToAll( &amp;packet );: w; L7 Y$ y$ v- }
    }</P>/ x6 _/ \7 A. n* {4 |4 e5 g
    " E% ~1 d- g: g1 K, \% g
    <P>$ E4 E7 {) t. ~# ~- u
    //-----------------------------------------------------------------------------
    $ ~% _" n9 \. n) l1 E// Name:
    - Q" k. C, @' d( Z" @! K3 N; E// Desc: 1 Z0 [8 c8 c) i( ^  G9 m+ L- }
    //-----------------------------------------------------------------------------
    & k+ R; `6 b! u$ z" M. i! f4 zvoid CMazeServer::SetServerPackSize( DWORD size )
    . B2 z: T$ d$ H  m0 P2 W{
    9 n# _; ~0 N: y4 b* Y6 x    // Update client config, and build packet containing that data
    ( e7 u; W5 D& i& k( I    m_ClientNetConfigLock.Enter();$ I* W2 i! ~. u* d
        6 i8 r+ g# L# G. R
        m_ClientNetConfig.ubServerPackIndex++; //Increase index and verify location in array.
    0 p' s1 M6 F2 a) o1 M# y    if(m_ClientNetConfig.ubServerPackIndex &gt;= PACK_ARRAY_SIZE)   $ y8 L8 E9 t8 V) b$ P
            m_ClientNetConfig.ubServerPackIndex = 0;</P>- @0 _4 j4 |# L$ h' p1 R
    <P>    m_ClientNetConfig.wServerPackSizeArray[m_ClientNetConfig.ubServerPackIndex] = WORD(size);/ r( H8 R" P0 {; [* s
        ServerConfigPacket packet( m_ClientNetConfig );1 u( R; L5 H8 l. K( O
        m_ClientNetConfigLock.Leave();</P>
    9 A8 Q1 |. w2 a) e, `' D* h<P>    SendConfigPacketToAll( &amp;packet );8 a; G& @  w; i1 O  w; ?
    }</P>
    # Q. Z- B. S/ B( R7 N' J<P>
    : l- }  I  ?! q' b//-----------------------------------------------------------------------------6 b" W$ d& t7 j$ h' D+ N
    // Name:
    # s" w( w5 M0 ^- q; E) }% K% D// Desc: ( Y4 ~8 r6 O# g
    //-----------------------------------------------------------------------------* B" ]3 i: E: A5 l' J; ?
    void CMazeServer::SetClientThreadWait( DWORD dwThreadWait )4 Z, T: [% t) Z# [
    {* t. {  a7 y) `% s* Y% @: O
        // Update client config, and build packet containing that data5 ~4 |, \) s: N- f1 I/ b% ?5 v
        m_ClientNetConfigLock.Enter();' h9 i5 p3 K) |- S5 q' |$ H
       
    + t# Y. X" n5 ?    m_ClientNetConfig.dwThreadWait = dwThreadWait;) X9 e- F5 m+ }" B* n* P
        ServerConfigPacket packet( m_ClientNetConfig );
    . y2 K0 S9 F. ]' G; B1 a( _$ f    m_ClientNetConfigLock.Leave();</P>
    ; S& M. R/ w5 n& [! ~: X) J<P>    SendConfigPacketToAll( &amp;packet );5 r1 t% r- b9 S$ d- P0 Z
    }</P></DIV>
    zan
    转播转播0 分享淘帖0 分享分享0 收藏收藏0 支持支持0 反对反对0 微信微信
    您需要登录后才可以回帖 登录 | 注册地址

    qq
    收缩
    • 电话咨询

    • 04714969085
    fastpost

    关于我们| 联系我们| 诚征英才| 对外合作| 产品服务| QQ

    手机版|Archiver| |繁體中文 手机客户端  

    蒙公网安备 15010502000194号

    Powered by Discuz! X2.5   © 2001-2013 数学建模网-数学中国 ( 蒙ICP备14002410号-3 蒙BBS备-0002号 )     论坛法律顾问:王兆丰

    GMT+8, 2026-8-23 05:59 , Processed in 0.446498 second(s), 51 queries .

    回顶部