home *** CD-ROM | disk | FTP | other *** search
- //----------------------------------------------------------------------------
- // File: mazecient.cpp
- //
- // Desc: see main.cpp
- //
- // Copyright (c) 1999-2001 Microsoft Corp. All rights reserved.
- //-----------------------------------------------------------------------------
- #define STRICT
- #define D3D_OVERLOADS
- #include <windows.h>
- #include <d3dx.h>
- #include <stdio.h>
- #include <math.h>
- #include <dplay8.h>
- #include <dpaddr.h>
- #include <dxerr8.h>
- #include "DXUtil.h"
- #include "SyncObjects.h"
- #include "IMazeGraphics.h"
- #include "DummyConnector.h"
- #include "MazeApp.h"
- #include "MazeClient.h"
- #include "Packets.h"
- #include "DXUtil.h"
-
-
-
-
- //-----------------------------------------------------------------------------
- // Name:
- // Desc:
- //-----------------------------------------------------------------------------
- #define NORTH_ANGLE 0x8000
- #define EAST_ANGLE 0xc000
- #define SOUTH_ANGLE 0x0000
- #define WEST_ANGLE 0x4000
-
-
-
-
- //-----------------------------------------------------------------------------
- // Name:
- // Desc:
- //-----------------------------------------------------------------------------
- CMazeClient::CMazeClient()
- {
- ZeroMemory( m_pctCells, sizeof(m_pctCells) );
- m_hReady = CreateEvent( NULL, TRUE, FALSE, NULL );
- m_hGotFirstConfig = CreateEvent( NULL, TRUE, FALSE, NULL );
- m_pNet = NULL;
- m_bAutopilot = FALSE;
- m_bEngageAutopilot = TRUE;
- m_dwNumNearbyPlayers = 0;
-
- m_NetConfig.ubReliableRate = 0;
- m_NetConfig.wUpdateRate = 150;
- m_NetConfig.wTimeout = 150;
- m_NetConfig.dwMazeWidth = 0;
- m_NetConfig.dwMazeHeight = 0;
-
- m_NetConfig.dwThreadWait = 0;
-
- m_NetConfig.ubClientPackIndex = 0;
- m_NetConfig.ubServerPackIndex = 0;
- for(WORD x = 0; x < PACK_ARRAY_SIZE; x++)
- {
- m_NetConfig.wClientPackSizeArray[x] = 0;
- m_NetConfig.wServerPackSizeArray[x] = 0;
- }
-
- }
-
-
-
-
- //-----------------------------------------------------------------------------
- // Name:
- // Desc:
- //-----------------------------------------------------------------------------
- CMazeClient::~CMazeClient()
- {
- CloseHandle( m_hGotFirstConfig );
- CloseHandle( m_hReady );
- }
-
-
-
-
- //-----------------------------------------------------------------------------
- // Name:
- // Desc:
- //-----------------------------------------------------------------------------
- HRESULT CMazeClient::Init( CMazeApp* pMazeApp, IMazeGraphics* pMazeGraphics )
- {
- m_pMazeApp = pMazeApp;
- m_pMazeGraphics = pMazeGraphics;
- m_aCameraYaw = 0;
- m_fLastOutboundTime = DXUtil_Timer( TIMER_GETAPPTIME );
- m_bHaveInputFocus = TRUE;
-
- Reset();
-
- return S_OK;
- }
-
-
-
-
- //-----------------------------------------------------------------------------
- // Name:
- // Desc:
- //-----------------------------------------------------------------------------
- HRESULT CMazeClient::Reset()
- {
- m_dwNumPlayers = 0;
- m_bAutopilot = FALSE;
-
- SetFirstConfig( FALSE );
- SetMazeReady( FALSE );
-
- ZeroMemory( m_pctCells, sizeof(m_pctCells) );
-
- PlayerObject* pPlayerObject = m_PlayerObjects;
- for( DWORD i = 0; i < MAX_PLAYER_OBJECTS; i++, pPlayerObject++ )
- {
- pPlayerObject->dwID = 0;
- pPlayerObject->wCellX = pPlayerObject->wCellY = 0xffff;
- pPlayerObject->pNext = NULL;
- }
-
- return S_OK;
- }
-
-
-
-
-
- //-----------------------------------------------------------------------------
- // Name:
- // Desc:
- //-----------------------------------------------------------------------------
- void CMazeClient::Shutdown()
- {
- // Destroy the maze
-
- Reset();
- m_Maze.Empty();
- }
-
-
-
-
- //-----------------------------------------------------------------------------
- // Name:
- // Desc:
- //-----------------------------------------------------------------------------
- void CMazeClient::Update( FLOAT fElapsed )
- {
- // Don't do anyPlayerObject until we get a server config packet
- if( !IsMazeReady() )
- return;
-
- if( m_bAutopilot )
- DoAutopilot( fElapsed );
- else
- DoManualPilot( fElapsed );
-
- // See if it's time to send a packet to the server with our updated coordinates
- FLOAT fCurTime = DXUtil_Timer( TIMER_GETAPPTIME );
- if( (fCurTime - m_fLastOutboundTime)*1000.0f > m_NetConfig.wUpdateRate )
- {
-
- ClientPosPacket packet( m_vCameraPos.x, m_vCameraPos.z, m_aCameraYaw );
-
- // Pack the buffer with dummy data for testing.
- if(m_NetConfig.wClientPackSizeArray[m_NetConfig.ubClientPackIndex] > 0)
- {
- WORD wBufferSize = sizeof(packet) + m_NetConfig.wClientPackSizeArray[m_NetConfig.ubClientPackIndex];
- VOID* pTempBuffer = 0;
-
- pTempBuffer = malloc(wBufferSize);
- if( NULL == pTempBuffer )
- {
- //Out of memory, just bail
- DXTRACE_ERR_NOMSGBOX( TEXT("System out of Memory!"), E_OUTOFMEMORY );
- return;
- }
-
-
- FillMemory(pTempBuffer, wBufferSize, 'Z');
- memcpy(pTempBuffer, &packet, sizeof(packet));
-
- SendPacket( (ClientPacket*)pTempBuffer, wBufferSize, FALSE, m_NetConfig.wTimeout );
-
- free(pTempBuffer);
- }
- else
- {
- SendPacket( &packet, sizeof(packet), FALSE, m_NetConfig.wTimeout );
- }
-
- m_fLastOutboundTime = fCurTime;
-
- }
- }
-
-
-
-
- //-----------------------------------------------------------------------------
- // Name:
- // Desc:
- //-----------------------------------------------------------------------------
- void CMazeClient::DoManualPilot( FLOAT fElapsed )
- {
- // Check if we have the input focus
- if( !m_bHaveInputFocus )
- return;
-
- // Do rotations
- if( GetAsyncKeyState( VK_LEFT ) & 0x8000 )
- m_aCameraYaw += (DWORD) ((fElapsed*1000.0f) * 40.0f);
- if( GetAsyncKeyState( VK_RIGHT ) & 0x8000 )
- m_aCameraYaw -= (DWORD) ((fElapsed*1000.0f) * 40.0f);
-
- float e = fElapsed*1000.0f;
-
- // Compute new position based key input
- D3DXVECTOR3 pos = m_vCameraPos;
- if( GetAsyncKeyState( VK_UP ) & 0x8000 )
- {
- pos.x -= Sin(m_aCameraYaw) * 0.002f * e;
- pos.z += Cos(m_aCameraYaw) * 0.002f * e;
- }
-
- if( GetAsyncKeyState( VK_DOWN ) & 0x8000 )
- {
- pos.x += Sin(m_aCameraYaw) * 0.002f * e;
- pos.z -= Cos(m_aCameraYaw) * 0.002f * e;
- }
-
- // Ensure that we have stayed within the maze boundaries
- if( pos.x < 0 ) pos.x = 0.1f;
- if( pos.x >= m_Maze.GetWidth() ) pos.x = m_Maze.GetWidth() - 0.1f;
- if( pos.z < 0 ) pos.z = 0.1f;
- if( pos.z >= m_Maze.GetHeight() ) pos.z = m_Maze.GetHeight() - 0.1f;
-
- m_vCameraPos = pos;
- }
-
-
-
-
- //-----------------------------------------------------------------------------
- // Name:
- // Desc:
- //-----------------------------------------------------------------------------
- void CMazeClient::DoAutopilot( FLOAT fElapsed )
- {
- // While there is still time to use up...
- while( fElapsed )
- {
- // See if we need to turn
- if( m_aAutopilotTargetAngle != m_aCameraYaw )
- {
- SHORT diff = SHORT((m_aAutopilotTargetAngle - m_aCameraYaw)&TRIG_ANGLE_MASK);
- FLOAT fNeeded = abs(diff)/40.0f;
- if( fNeeded/1000.0f <= fElapsed )
- {
- m_aCameraYaw = m_aAutopilotTargetAngle;
- fElapsed -= fNeeded/1000.0f;
- }
- else
- {
- if( diff < 0 )
- m_aCameraYaw -= (DWORD) ((fElapsed*1000.0f) * 40.0f);
- else
- m_aCameraYaw += (DWORD) ((fElapsed*1000.0f) * 40.0f);
- fElapsed = 0;
- }
- }
- else
- {
- // Ensure vAutopilotTarget is inside the maze boundry
- if( m_vAutopilotTarget.x < 0 ||
- m_vAutopilotTarget.x >= m_Maze.GetWidth() ||
- m_vAutopilotTarget.z < 0 ||
- m_vAutopilotTarget.z >= m_Maze.GetHeight() )
- {
- ZeroMemory( m_AutopilotVisited, sizeof(m_AutopilotVisited) );
- m_AutopilotStack.Empty();
- PickAutopilotTarget();
- return;
- }
-
- // Facing right way, so now compute distance to target
- D3DXVECTOR3 diff = m_vAutopilotTarget - m_vCameraPos;
-
- float fRange = float(sqrt((diff.x*diff.x)+(diff.z*diff.z)));
-
- // Are we there yet?
- if( fRange > 0 )
- {
- // No, so compute how long we'd need
- FLOAT fNeeded = fRange / 0.002f;
-
- //Ensure we never leave the boundary of the Maze.
- D3DXVECTOR3 pos = m_vCameraPos;
-
- // Do we have enough time this frame?
- if( fNeeded/1000.0f <= fElapsed )
- {
-
- // Yes, so just snap us there
- pos.x = m_vAutopilotTarget.x;
- pos.z = m_vAutopilotTarget.z;
-
- fElapsed -= fNeeded/1000.0f;
- }
- else
- {
- // No, so move us as far as we can
- pos.x -= Sin(m_aCameraYaw) * 0.002f * fElapsed*1000.0f;
- pos.z += Cos(m_aCameraYaw) * 0.002f * fElapsed*1000.0f;
-
- fElapsed = 0;
- }
-
- // Ensure that we have stayed within the maze boundaries
- if( pos.x < 0 ) pos.x = 0.1f;
- if( pos.x >= m_Maze.GetWidth() ) pos.x = m_Maze.GetWidth() - 0.1f;
- if( pos.z < 0 ) pos.z = 0.1f;
- if( pos.z >= m_Maze.GetHeight() ) pos.z = m_Maze.GetHeight() - 0.1f;
-
- // Assign our new values back to our globals.
- m_vCameraPos = pos;
-
- }
- else
- {
- // Reached target, so pick another
- PickAutopilotTarget();
- }
- }
- }
- }
-
-
-
-
- //-----------------------------------------------------------------------------
- // Name:
- // Desc:
- //-----------------------------------------------------------------------------
- void CMazeClient::EngageAutopilot( BOOL bEngage )
- {
- m_bEngageAutopilot = bEngage;
-
- if( !IsMazeReady() )
- return;
-
- BOOL bPrevious = m_bAutopilot;
- m_bAutopilot = bEngage;
-
- // If we weren't on autopilot before and are are autopilot now then need to init autopilot
- if( m_bAutopilot && !bPrevious )
- {
- // First of all, snap us to the centre of the current cell
- int cellx = int(m_vCameraPos.x);
- int cellz = int(m_vCameraPos.z);
- m_vCameraPos.x = cellx + 0.5f;
- m_vCameraPos.z = cellz + 0.5f;
-
- // Ensure we're within the maze boundaries
- if( cellx < 0 ) m_vCameraPos.x = 0.5f;
- if( cellx >= int(m_Maze.GetWidth()) ) m_vCameraPos.x = m_Maze.GetWidth() - 0.5f;
- if( cellz < 0 ) m_vCameraPos.z = 0.5f;
- if( cellz >= int(m_Maze.GetHeight()) ) m_vCameraPos.z = m_Maze.GetHeight() - 0.5f;
-
- // Clear the visited array and stack
- ZeroMemory( m_AutopilotVisited, sizeof(m_AutopilotVisited) );
- m_AutopilotStack.Empty();
-
- // Pick the next target cell
- PickAutopilotTarget();
- }
- }
-
-
-
-
- //-----------------------------------------------------------------------------
- // Name:
- // Desc:
- //-----------------------------------------------------------------------------
- void CMazeClient::PickAutopilotTarget()
- {
- // Get current cell and mark as visited
- DWORD currentx = DWORD(m_vCameraPos.x);
- DWORD currentz = DWORD(m_vCameraPos.z);
- m_AutopilotVisited[currentz][currentx] = 1;
-
- // Figure out which directions are allowed. We're allowed to go in any direction
- // where there isn't a wall in the way and that takes us to a cell we've visited before.
- BYTE cell = m_Maze.GetCell(currentx,currentz);
- ANGLE alloweddirs[5];
- DWORD dwAllowed = 0;
-
- if( !(cell & MAZE_WALL_NORTH) && !m_AutopilotVisited[currentz-1][currentx] )
- alloweddirs[dwAllowed++] = NORTH_ANGLE;
- if( !(cell & MAZE_WALL_WEST) && !m_AutopilotVisited[currentz][currentx-1] )
- alloweddirs[dwAllowed++] = WEST_ANGLE;
- if( !(cell & MAZE_WALL_EAST) && !m_AutopilotVisited[currentz][currentx+1] )
- alloweddirs[dwAllowed++] = EAST_ANGLE;
- if( !(cell & MAZE_WALL_SOUTH) && !m_AutopilotVisited[currentz+1][currentx] )
- alloweddirs[dwAllowed++] = SOUTH_ANGLE;
- /*
- printf( "Walls: ") );
- if( (cell & MAZE_WALL_NORTH) )
- printf( "N ") );
- if( (cell & MAZE_WALL_WEST) )
- printf( "W ") );
- if( (cell & MAZE_WALL_EAST) )
- printf( "E ") );
- if( (cell & MAZE_WALL_SOUTH) )
- printf( "S ") );
- printf( "\n") );
- */
-
- // Is there anywhere to go?
- if( dwAllowed == 0 )
- {
- // Nope. Can we backtrack?
- if( m_AutopilotStack.GetCount() > 0 )
- {
- // Yes, so pop cell off the stack
- AutopilotCell cell(m_AutopilotStack.Pop());
- m_vAutopilotTarget.x = float(cell.x) + 0.5f;
- m_vAutopilotTarget.z = float(cell.y) + 0.5f;
-
- if( cell.x < currentx )
- m_aAutopilotTargetAngle = WEST_ANGLE;
- else if( cell.x > currentx )
- m_aAutopilotTargetAngle = EAST_ANGLE;
- else if( cell.y > currentz )
- m_aAutopilotTargetAngle = SOUTH_ANGLE;
- else
- m_aAutopilotTargetAngle = NORTH_ANGLE;
- }
- else
- {
- // No, so we have explored entire maze and must start again
- ZeroMemory( m_AutopilotVisited, sizeof(m_AutopilotVisited) );
- m_AutopilotStack.Empty();
- PickAutopilotTarget();
- }
- }
- else
- {
- // See if we can continue in current direction
- BOOL bPossible = FALSE;
- for( DWORD i = 0; i < dwAllowed; i++ )
- {
- if( alloweddirs[i] == m_aCameraYaw )
- {
- bPossible = TRUE;
- break;
- }
- }
-
- // If it's allowed to go forward, then have 1 in 2 chance of doing that anyway, otherwise pick randomly from
- // available alternatives
- if( bPossible && (rand() & 0x1000) )
- m_aAutopilotTargetAngle = m_aCameraYaw;
- else
- m_aAutopilotTargetAngle = alloweddirs[ (rand() % (dwAllowed<<3) ) >>3 ];
-
- m_vAutopilotTarget.z = float(currentz) + 0.5f;
- m_vAutopilotTarget.x = float(currentx) + 0.5f;
-
- switch( m_aAutopilotTargetAngle )
- {
- case SOUTH_ANGLE:
- m_vAutopilotTarget.z += 1.0f;
- break;
-
- case WEST_ANGLE:
- m_vAutopilotTarget.x -= 1.0f;
- break;
-
- case EAST_ANGLE:
- m_vAutopilotTarget.x += 1.0f;
- break;
-
- case NORTH_ANGLE:
- m_vAutopilotTarget.z -= 1.0f;
- break;
- }
-
- // Push current cell onto stack
- m_AutopilotStack.Push( AutopilotCell(BYTE(currentx),BYTE(currentz)) );
- }
- }
-
-
-
-
- //-----------------------------------------------------------------------------
- // Name:
- // Desc:
- //-----------------------------------------------------------------------------
- HRESULT CMazeClient::OnPacket( DWORD dwFrom, void* dwData, DWORD dwSize )
- {
- HRESULT hr = DPN_OK;
-
- BOOL fFoundSize = FALSE;
- DWORD dwReqSize = 0;
- DWORD dwSRand = 0;
-
- ServerPacket* pPacket = (ServerPacket*)dwData;
- switch( pPacket->wType )
- {
- case PACKETTYPE_SERVER_CONFIG:
- {
- if( dwSize != sizeof(ServerConfigPacket) )
- {
- m_pMazeApp->SetDisconnectNow( TRUE );
- m_pMazeApp->SetOutOfDateClient( TRUE );
- m_pMazeApp->ConsolePrintf( LINE_LOG, TEXT("Disconnected because MazeClient is out of date.") );
- m_pMazeApp->ConsolePrintf( LINE_LOG, TEXT("Please get updated version") );
- m_pMazeApp->ConsolePrintf( LINE_LOG, TEXT("from http://msdn.microsoft.com/directx/") );
- break;
- }
-
- m_NetConfig = ((ServerConfigPacket*)pPacket)->Config;
-
- m_pMazeApp->ConsolePrintf( LINE_LOG, TEXT("Got MazeServer config settings") );
- m_pMazeApp->ConsolePrintf( LINE_LOG, TEXT("Maze Size=(%d,%d) ReliableRate=%d%%"),
- m_NetConfig.dwMazeWidth, m_NetConfig.dwMazeHeight,
- DWORD(m_NetConfig.ubReliableRate) );
- m_pMazeApp->ConsolePrintf( LINE_LOG, TEXT("UpdateRate=%dms Timeout=%d"),
- m_NetConfig.wUpdateRate, m_NetConfig.wTimeout );
- m_pMazeApp->ConsolePrintf( LINE_LOG, TEXT("ThreadWait=%dms"),
- m_NetConfig.dwThreadWait );
- m_pMazeApp->ConsolePrintf( LINE_LOG, TEXT("ClientPackSize=%d ServerPackSize=%d (bytes)"),
- m_NetConfig.wClientPackSizeArray[m_NetConfig.ubClientPackIndex],
- m_NetConfig.wServerPackSizeArray[m_NetConfig.ubServerPackIndex]);
-
- // See if we have gotten our fist config. If not, send version info.
- if(! GotFirstConfig()) //If first time in maze.
- {
- // The client expects the server to send a ServerConfigPacket packet first,
- // then the client sends a ClientVersionPacket, and then the server sends a
- // ServerAckVersionPacket packet and the game begins
- ClientVersionPacket packet( MAZE_CLIENT_VERSION );
- SendPacket( &packet, sizeof(packet), TRUE, 0 );
-
- SetFirstConfig( TRUE );
- }
-
- break;
- }
-
- case PACKETTYPE_SERVER_ACKVERSION:
- {
- if( dwSize != sizeof(ServerAckVersionPacket) )
- {
- m_pMazeApp->SetDisconnectNow( TRUE );
- m_pMazeApp->SetOutOfDateClient( TRUE );
- m_pMazeApp->ConsolePrintf( LINE_LOG, TEXT("Disconnected because MazeClient is out of date.") );
- m_pMazeApp->ConsolePrintf( LINE_LOG, TEXT("Please get updated version") );
- m_pMazeApp->ConsolePrintf( LINE_LOG, TEXT("from http://msdn.microsoft.com/directx/") );
- break;
- }
-
- ServerAckVersionPacket* pAckVersionPacket = (ServerAckVersionPacket*)pPacket;
-
- // Record the dpnid that the server uses for to talk to us.
- // This is just done so that we can record this number in the
- // logs to help match server side logs with client side logs.
- m_dwLocalClientID = pAckVersionPacket->dwClientID;
-
- m_pMazeApp->ConsolePrintf( LINE_LOG, TEXT("Server assigned ID: 0x%0.8x"), m_dwLocalClientID );
- m_pMazeApp->ConsolePrintf( LINE_LOG, TEXT("Server accepted client version") );
-
-
- hr = m_Maze.Init( m_NetConfig.dwMazeWidth,
- m_NetConfig.dwMazeHeight, DEFAULT_SEED );
- if( FAILED(hr) )
- DXTRACE_ERR( TEXT("Init"), hr );
-
- //Seed the random number generator.
- dwSRand = (DWORD) (DXUtil_Timer( TIMER_GETABSOLUTETIME ) * (DWORD)GetCurrentThreadId() );
- srand( dwSRand );
-
- // Set random start location
- m_vCameraPos = D3DXVECTOR3( rand() % m_Maze.GetWidth() + 0.5f, 0.5,
- rand() % m_Maze.GetHeight() + 0.5f );
-
- SetMazeReady( TRUE );
- EngageAutopilot( TRUE );
- break;
- }
-
- case PACKETTYPE_SERVER_ACKPOS:
-
- //Make sure we at least have a ServerAckPacket.
- if( dwSize < sizeof(ServerAckPacket) )
- {
- fFoundSize = FALSE;
- }
- else
- {
- //Size of our required packet. Does not include custom pack data.
- dwReqSize = (sizeof(ServerAckPacket) +
- (sizeof(PlayerStatePacket) *
- ((ServerAckPacket*)pPacket)->wPlayerStatePacketCount));
-
- //Check to see if we have a valid packet size.
- if (dwSize < dwReqSize)
- fFoundSize = FALSE;
- else if ( !IsValidPackSize( dwSize - dwReqSize ))
- fFoundSize = FALSE;
- else
- fFoundSize = TRUE;
- }
-
- //If we did not find a correct packet size. Exit.
- if( !fFoundSize )
- {
- m_pMazeApp->SetDisconnectNow( TRUE );
- m_pMazeApp->SetOutOfDateClient( TRUE );
- m_pMazeApp->ConsolePrintf( LINE_LOG, TEXT("Disconnected because MazeClient is out of date.") );
- m_pMazeApp->ConsolePrintf( LINE_LOG, TEXT("Please get updated version") );
- m_pMazeApp->ConsolePrintf( LINE_LOG, TEXT("from http://msdn.microsoft.com/directx/") );
- break;
- }
-
- //Found correct packet size. Update clients.
- SetPlayerStats( ((ServerAckPacket*)pPacket)->wPlayerCount,
- ((ServerAckPacket*)pPacket)->wPlayerStatePacketCount );
-
- if( ((ServerAckPacket*)pPacket)->wPlayerStatePacketCount )
- HandlePlayerObjectsInAckPacket( (ServerAckPacket*)pPacket );
- break;
-
- default:
- m_pMazeApp->ConsolePrintf( LINE_LOG, TEXT("Received unknown %d byte packet from server"), dwSize );
- break;
- };
-
-
- //If the server has given us a custom wait time, Let's sleep for that amount of time.
- if( m_NetConfig.dwThreadWait > 0 )
- {
- Sleep( m_NetConfig.dwThreadWait );
- }
-
-
- return S_OK;
- }
-
-
-
-
- //-----------------------------------------------------------------------------
- // Name:
- // Desc:
- //-----------------------------------------------------------------------------
- BOOL CMazeClient::IsValidPackSize( DWORD dwSize )
- {
- BOOL fFoundSize = FALSE;
- BYTE ubPackLocation = m_NetConfig.ubServerPackIndex;
-
- // Look for valid Client pack size in PackArray.
- // If found, return TRUE, otherwise FALSE.
- if(dwSize != m_NetConfig.wServerPackSizeArray[ubPackLocation])
- {
- for( --ubPackLocation; ubPackLocation != m_NetConfig.ubServerPackIndex; ubPackLocation--)
- {
- if(dwSize == m_NetConfig.wServerPackSizeArray[ubPackLocation])
- {
- fFoundSize = TRUE;
- break;
- }
-
- if(ubPackLocation >= PACK_ARRAY_SIZE) ubPackLocation = PACK_ARRAY_SIZE; //Wrap the array.
- }
- }
- else
- {
- fFoundSize = TRUE;
- }
-
- return fFoundSize;
-
- }
-
- //-----------------------------------------------------------------------------
- // Name:
- // Desc:
- //-----------------------------------------------------------------------------
- void CMazeClient::OnSessionLost( DWORD dwReason )
- {
- }
-
-
-
- //-----------------------------------------------------------------------------
- // Name:
- // Desc:
- //-----------------------------------------------------------------------------
- void CMazeClient::SendPacket( ClientPacket* pPacket, DWORD dwSize,
- BOOL bGuaranteed, DWORD dwTimeout )
- {
- if( m_NetConfig.ubReliableRate > m_NetRandom.Get( 100 ) )
- bGuaranteed = TRUE;
-
- m_pNet->SendPacket( pPacket, dwSize, bGuaranteed, dwTimeout );
- };
-
-
-
-
- //-----------------------------------------------------------------------------
- // Name:
- // Desc:
- //-----------------------------------------------------------------------------
- DWORD CMazeClient::GetRoundTripLatencyMS()
- {
- return m_pNet->GetRoundTripLatencyMS();
- }
-
-
-
-
- //-----------------------------------------------------------------------------
- // Name:
- // Desc:
- //-----------------------------------------------------------------------------
- DWORD CMazeClient::GetThroughputBPS()
- {
- return m_pNet->GetThroughputBPS();
- }
-
-
-
- //-----------------------------------------------------------------------------
- // Name:
- // Desc:
- //-----------------------------------------------------------------------------
- void CMazeClient::HandlePlayerObjectsInAckPacket( ServerAckPacket* pPacket )
- {
- PlayerStatePacket* pClientInfo = (PlayerStatePacket*)(pPacket+1);
-
- if( !IsMazeReady() )
- return;
-
- // Lock the world database
- LockWorld();
-
- // Loop though the PlayerObject chunks
- for( DWORD count = pPacket->wPlayerStatePacketCount; count; count--, pClientInfo++ )
- {
- // Get the PlayerObject we think this is
- PlayerObject* pPlayerObject = &m_PlayerObjects[pClientInfo->dwID & PLAYER_OBJECT_SLOT_MASK];
-
- // Does the ID match the one we have?
- if( pPlayerObject->dwID != pClientInfo->dwID )
- {
- // No, so the PlayerObject we have needs to be deleted (server reused the same slot
- // number, so old PlayerObject must be toast)
- RemovePlayerObjectFromCells( pPlayerObject );
-
- // Set the ID to the new ID
- pPlayerObject->dwID = pClientInfo->dwID;
- pPlayerObject->wCellX = WORD(pClientInfo->fX);
- pPlayerObject->wCellY = WORD(pClientInfo->fY);
-
- // Insert into the appropriate cell list
- AddPlayerObjectToCells( pPlayerObject );
- }
- else
- {
- // Yes, compute the new cell coordinates
- DWORD newcellx = DWORD(pClientInfo->fX);
- DWORD newcelly = DWORD(pClientInfo->fY);
-
- // Are they the same as the ones we already have?
- if( newcellx != pPlayerObject->wCellX || newcelly != pPlayerObject->wCellY )
- {
- // No, so need to remove from old cell and add to new one
- RemovePlayerObjectFromCells( pPlayerObject );
- pPlayerObject->wCellX = WORD(newcellx);
- pPlayerObject->wCellY = WORD(newcelly);
- AddPlayerObjectToCells( pPlayerObject );
- }
- }
-
- // Update timestamp and position
- pPlayerObject->vPos.x = pClientInfo->fX;
- pPlayerObject->vPos.y = 0.5f;
- pPlayerObject->vPos.z = pClientInfo->fY;
- pPlayerObject->aCameraYaw = pClientInfo->aCameraYaw;
- pPlayerObject->fLastValidTime = DXUtil_Timer( TIMER_GETAPPTIME );
- }
-
- // Unlock world database
- UnlockWorld();
- }
-
-
-
-
- //-----------------------------------------------------------------------------
- // Name:
- // Desc:
- //-----------------------------------------------------------------------------
- void CMazeClient::AddPlayerObjectToCells( PlayerObject* pPlayerObject )
- {
- if( pPlayerObject->wCellX == 0xffff )
- return;
-
- if( FALSE == IsPlayerObjectInCell( pPlayerObject->wCellX, pPlayerObject->wCellY, pPlayerObject ) )
- {
- PlayerObject** ppCell = &m_pctCells[pPlayerObject->wCellY][pPlayerObject->wCellX];
- pPlayerObject->pNext = *ppCell;
- *ppCell = pPlayerObject;
- }
- }
-
-
-
-
- //-----------------------------------------------------------------------------
- // Name:
- // Desc:
- //-----------------------------------------------------------------------------
- void CMazeClient::RemovePlayerObjectFromCells( PlayerObject* pPlayerObject )
- {
- if( pPlayerObject->wCellX == 0xffff )
- return;
-
- PlayerObject** ppCell = &m_pctCells[pPlayerObject->wCellY][pPlayerObject->wCellX];
- PlayerObject* pCur = *ppCell;
- PlayerObject* pPrev = NULL;
- while( pCur )
- {
- if( pCur == pPlayerObject )
- {
- pCur = pPlayerObject->pNext;
-
- // Found pPlayerObject, so remove pPlayerObject from the m_pctCells linked list
- if( pPrev )
- pPrev->pNext = pPlayerObject->pNext;
- else
- *ppCell = pPlayerObject->pNext;
- pPlayerObject->pNext = NULL;
-
- // Update pPlayerObject so that it is marked as removed
- pPlayerObject->wCellX = pPlayerObject->wCellY = 0xffff;
-
- // Continue searching, and remove any other instances of
- // pPlayerObject from list (there shouldn't be, however)
- }
- else
- {
- pPrev = pCur;
- pCur = pCur->pNext;
- }
- }
- }
-
-
-
-
- //-----------------------------------------------------------------------------
- // Name:
- // Desc:
- //-----------------------------------------------------------------------------
- PlayerObject* CMazeClient::GetFirstPlayerObjectInCell( DWORD x, DWORD z )
- {
- if( !IsMazeReady() )
- return NULL;
-
- FLOAT fCurTime = DXUtil_Timer( TIMER_GETAPPTIME );
-
- // Remove any PlayerObjects which are out of date (since they're probably not really in this
- // cell any more, but the server has just stopped telling us about them)
- PlayerObject** ppCell = &m_pctCells[z][x];
- PlayerObject* pCur = m_pctCells[z][x];
- PlayerObject* pPrev = NULL;
- PlayerObject* pPlayerObject = NULL;
- while( pCur )
- {
- // Too old?
- if( (fCurTime - pCur->fLastValidTime) > 5.0f )
- {
- pPlayerObject = pCur;
- pCur = pCur->pNext;
-
- // pPlayerObject is too old, so remove pPlayerObject from the m_pctCells linked list
- if( pPrev )
- pPrev->pNext = pPlayerObject->pNext;
- else
- *ppCell = pPlayerObject->pNext;
- pPlayerObject->pNext = NULL;
-
- // Update pPlayerObject so that it is marked as removed
- pPlayerObject->wCellX = pPlayerObject->wCellY = 0xffff;
-
- // Continue searching, and remove any other old instances from list
- }
- else
- {
- pPrev = pCur;
- pCur = pCur->pNext;
- }
- }
-
- // Now return first remaining PlayerObject in the cell (if any)
- return m_pctCells[z][x];
- }
-
-
-
-
- //-----------------------------------------------------------------------------
- // Name:
- // Desc:
- //-----------------------------------------------------------------------------
- BOOL CMazeClient::IsPlayerObjectInCell( DWORD wCellX, DWORD wCellY, PlayerObject* pPlayerObject )
- {
- PlayerObject* pPlayerObjectTmp = m_pctCells[wCellY][wCellX];
- while( pPlayerObjectTmp )
- {
- if( pPlayerObjectTmp == pPlayerObject )
- return TRUE;
-
- pPlayerObjectTmp = pPlayerObjectTmp->pNext;
- }
-
- return FALSE;
- }
-
-