2014-01-13 12:44:33 +01:00
|
|
|
/////////////////////////////////////////////////////////////////////
|
|
|
|
// Created by [Dennis Andersen] [2013]
|
|
|
|
/////////////////////////////////////////////////////////////////////
|
2014-01-28 09:00:02 +01:00
|
|
|
#include "..\GameSession.h"
|
|
|
|
#include "..\GameClient.h"
|
2014-02-18 11:34:24 +01:00
|
|
|
#include "..\GameLobby.h"
|
2014-01-14 09:25:22 +01:00
|
|
|
#include <Protocols.h>
|
2014-01-13 12:44:33 +01:00
|
|
|
#include <PostBox\PostBox.h>
|
|
|
|
#include <GameLogicStates.h>
|
|
|
|
|
2014-01-29 10:18:01 +01:00
|
|
|
#define NOMINMAX
|
2014-01-13 12:44:33 +01:00
|
|
|
#include <Windows.h>
|
2014-02-04 16:07:10 +01:00
|
|
|
#include <Queue.h>
|
2014-02-15 09:29:54 +01:00
|
|
|
#include <future>
|
2014-01-13 12:44:33 +01:00
|
|
|
|
2014-02-09 16:42:26 +01:00
|
|
|
#define DELTA_TIME_20 0.05f
|
|
|
|
#define DELTA_TIME_24 0.04166666666666666666666666666667f
|
|
|
|
#define DELTA_TIME_30 0.03333333333333333333333333333333f
|
|
|
|
#define DELTA_TIME_60 0.01666666666666666666666666666667f
|
|
|
|
#define DELTA_TIME_120 0.00833333333333333333333333333333f
|
|
|
|
|
2014-01-13 12:44:33 +01:00
|
|
|
|
|
|
|
using namespace Utility::DynamicMemory;
|
|
|
|
using namespace Oyster;
|
|
|
|
using namespace Oyster::Network;
|
|
|
|
using namespace Oyster::Thread;
|
|
|
|
using namespace GameLogic;
|
2014-02-18 08:55:38 +01:00
|
|
|
using namespace DanBias;
|
2014-01-13 12:44:33 +01:00
|
|
|
|
2014-02-18 08:55:38 +01:00
|
|
|
GameSession* GameSession::gameSession = nullptr;
|
2014-01-30 00:19:00 +01:00
|
|
|
|
2014-02-18 08:55:38 +01:00
|
|
|
GameSession::GameSession()
|
|
|
|
:gameInstance(GameAPI::Instance())
|
|
|
|
{
|
|
|
|
this->owner = 0;
|
|
|
|
this->isCreated = false;
|
|
|
|
this->isRunning = false;
|
|
|
|
this->gameSession = this;
|
2014-02-21 15:02:42 +01:00
|
|
|
this->logicFrameTime = DELTA_TIME_60;
|
|
|
|
this->networkFrameTime = DELTA_TIME_60;
|
2014-02-18 08:55:38 +01:00
|
|
|
this->networkTimer.reset();
|
|
|
|
this->logicTimer.reset();
|
|
|
|
|
|
|
|
memset(&this->description, 0, sizeof(GameDescription));
|
|
|
|
}
|
|
|
|
|
|
|
|
GameSession::~GameSession()
|
|
|
|
{
|
|
|
|
this->worker.Terminate();
|
|
|
|
this->clients.Clear();
|
|
|
|
this->gameInstance;
|
|
|
|
this->owner = 0;
|
|
|
|
this->isCreated = false;
|
|
|
|
this->isRunning = false;
|
|
|
|
}
|
|
|
|
|
2014-02-18 13:12:08 +01:00
|
|
|
bool GameSession::Create(GameDescription& desc, bool forceStart)
|
2014-02-18 08:55:38 +01:00
|
|
|
{
|
|
|
|
this->description = desc;
|
|
|
|
/* Do some error checking */
|
2014-02-18 13:12:08 +01:00
|
|
|
if(!forceStart && desc.clients.Size() == 0) return false;
|
|
|
|
if(!desc.owner) return false;
|
|
|
|
if(this->isCreated) return false;
|
2014-02-18 08:55:38 +01:00
|
|
|
|
|
|
|
/* standard initialization of some data */
|
2014-02-18 11:34:24 +01:00
|
|
|
this->gClients.Resize((unsigned int)desc.maxClients);
|
|
|
|
for (unsigned int i = 0; i < desc.clients.Size(); i++)
|
2014-01-13 12:44:33 +01:00
|
|
|
{
|
2014-02-18 11:34:24 +01:00
|
|
|
if(desc.clients[i])
|
|
|
|
{
|
|
|
|
this->clientCount++;
|
|
|
|
this->gClients[i] = desc.clients[i];
|
|
|
|
this->gClients[i]->SetOwner(this);
|
|
|
|
}
|
2014-01-13 12:44:33 +01:00
|
|
|
}
|
2014-02-18 08:55:38 +01:00
|
|
|
this->owner = desc.owner;
|
2014-01-13 12:44:33 +01:00
|
|
|
|
2014-02-18 08:55:38 +01:00
|
|
|
/* Initiate the game instance */
|
|
|
|
if(!this->gameInstance.Initiate())
|
2014-01-13 12:44:33 +01:00
|
|
|
{
|
2014-02-18 08:55:38 +01:00
|
|
|
printf("Failed to initiate the game instance\n");
|
2014-01-13 12:44:33 +01:00
|
|
|
}
|
|
|
|
|
2014-02-18 08:55:38 +01:00
|
|
|
/* Create the players in the game instance */
|
|
|
|
GameLogic::IPlayerData* p = 0;
|
2014-02-18 11:34:24 +01:00
|
|
|
for (unsigned int i = 0; i < this->gClients.Size(); i++)
|
2014-01-13 12:44:33 +01:00
|
|
|
{
|
2014-02-18 11:34:24 +01:00
|
|
|
if(this->gClients[i])
|
2014-01-20 15:47:52 +01:00
|
|
|
{
|
2014-02-18 08:55:38 +01:00
|
|
|
if( (p = this->gameInstance.CreatePlayer()) )
|
2014-01-20 15:47:52 +01:00
|
|
|
{
|
2014-02-18 11:34:24 +01:00
|
|
|
this->gClients[i]->SetPlayer(p);
|
2014-02-18 08:55:38 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
printf("Failed to create player (%i)\n", i);
|
2014-01-20 15:47:52 +01:00
|
|
|
}
|
2014-01-13 12:44:33 +01:00
|
|
|
}
|
2014-02-18 08:55:38 +01:00
|
|
|
}
|
2014-01-13 12:44:33 +01:00
|
|
|
|
2014-02-18 08:55:38 +01:00
|
|
|
/* Create the game level */
|
2014-02-18 21:50:51 +01:00
|
|
|
if(!(this->levelData = this->gameInstance.CreateLevel(this->description.mapName.c_str())))
|
2014-02-18 08:55:38 +01:00
|
|
|
{
|
|
|
|
printf("Level not created!");
|
|
|
|
return false;
|
|
|
|
}
|
2014-01-13 12:44:33 +01:00
|
|
|
|
2014-02-18 08:55:38 +01:00
|
|
|
/* Set some game instance data options */
|
|
|
|
this->gameInstance.SetSubscription(GameSession::ObjectMove);
|
|
|
|
this->gameInstance.SetSubscription(GameSession::ObjectDisabled);
|
|
|
|
this->gameInstance.SetFPS(60);
|
2014-02-04 16:07:10 +01:00
|
|
|
|
2014-02-18 08:55:38 +01:00
|
|
|
this->description.clients.Clear();
|
2014-01-20 15:47:52 +01:00
|
|
|
|
2014-02-18 08:55:38 +01:00
|
|
|
this->isCreated = true;
|
2014-02-09 16:42:26 +01:00
|
|
|
|
2014-02-18 08:55:38 +01:00
|
|
|
/* Create the worker thread */
|
|
|
|
if(this->worker.Create(this, false) != OYSTER_THREAD_ERROR_SUCCESS)
|
|
|
|
return false;
|
2014-02-09 16:42:26 +01:00
|
|
|
|
2014-02-18 08:55:38 +01:00
|
|
|
return this->isCreated;
|
|
|
|
}
|
2014-01-13 12:44:33 +01:00
|
|
|
|
2014-02-18 08:55:38 +01:00
|
|
|
void GameSession::Run()
|
|
|
|
{
|
|
|
|
if(this->isRunning) return;
|
2014-01-13 12:44:33 +01:00
|
|
|
|
2014-02-18 13:12:08 +01:00
|
|
|
this->worker.Start();
|
|
|
|
this->worker.SetPriority(OYSTER_THREAD_PRIORITY_1);
|
|
|
|
this->isRunning = true;
|
|
|
|
|
2014-02-18 08:55:38 +01:00
|
|
|
}
|
2014-01-13 12:44:33 +01:00
|
|
|
|
2014-02-18 08:55:38 +01:00
|
|
|
void GameSession::ThreadEntry( )
|
|
|
|
{
|
|
|
|
//List with clients that we are waiting on..
|
2014-02-18 11:34:24 +01:00
|
|
|
DynamicArray<gClient> readyList;// = this->clients;
|
2014-01-13 12:44:33 +01:00
|
|
|
|
2014-02-18 08:55:38 +01:00
|
|
|
//First we need to clean invalid clients, if any, and tell them to start loading game data
|
2014-02-18 11:34:24 +01:00
|
|
|
for (unsigned int i = 0; i < this->gClients.Size(); i++)
|
2014-02-18 08:55:38 +01:00
|
|
|
{
|
2014-02-18 11:34:24 +01:00
|
|
|
if(this->gClients[i])
|
2014-02-04 16:07:10 +01:00
|
|
|
{
|
2014-02-18 11:34:24 +01:00
|
|
|
readyList.Push(this->gClients[i]);
|
|
|
|
Protocol_LobbyCreateGame p((char)1, (char)0, Utility::String::WStringToString(this->description.mapName, std::string()));
|
2014-02-18 08:55:38 +01:00
|
|
|
readyList[readyList.Size() - 1]->GetClient()->Send(p);
|
2014-02-04 16:07:10 +01:00
|
|
|
}
|
2014-02-18 08:55:38 +01:00
|
|
|
}
|
2014-02-04 16:07:10 +01:00
|
|
|
|
2014-02-18 08:55:38 +01:00
|
|
|
unsigned int readyCounter = readyList.Size();
|
2014-02-09 16:42:26 +01:00
|
|
|
|
2014-02-18 08:55:38 +01:00
|
|
|
//Sync with clients
|
|
|
|
while (readyCounter != 0)
|
|
|
|
{
|
|
|
|
this->ProcessClients();
|
|
|
|
for (unsigned int i = 0; i < readyList.Size(); i++)
|
2014-02-04 16:07:10 +01:00
|
|
|
{
|
2014-02-18 08:55:38 +01:00
|
|
|
if(readyList[i] && readyList[i]->IsReady())
|
2014-02-04 16:07:10 +01:00
|
|
|
{
|
2014-02-18 08:55:38 +01:00
|
|
|
//Need to send information about other players, to all players
|
2014-02-18 11:34:24 +01:00
|
|
|
for (unsigned int k = 0; k < this->gClients.Size(); k++)
|
2014-02-04 16:07:10 +01:00
|
|
|
{
|
2014-02-18 11:34:24 +01:00
|
|
|
if((this->gClients[k] && readyList[i]) && readyList[i]->GetClient()->GetID() != this->gClients[k]->GetClient()->GetID())
|
2014-02-04 16:07:10 +01:00
|
|
|
{
|
2014-02-18 11:34:24 +01:00
|
|
|
IPlayerData* pl = this->gClients[k]->GetPlayer();
|
2014-02-18 08:55:38 +01:00
|
|
|
Protocol_ObjectCreatePlayer p( pl->GetPosition(), pl->GetRotation(), pl->GetScale(),
|
2014-02-18 11:34:24 +01:00
|
|
|
pl->GetID(), true, this->gClients[k]->GetPlayer()->GetTeamID(),
|
2014-02-19 11:02:44 +01:00
|
|
|
Utility::String::WStringToString(this->gClients[k]->GetAlias(), std::string()),
|
|
|
|
Utility::String::WStringToString(this->gClients[k]->GetCharacter(), std::string()));
|
2014-02-18 08:55:38 +01:00
|
|
|
readyList[i]->GetClient()->Send(p);
|
2014-02-04 16:07:10 +01:00
|
|
|
}
|
|
|
|
}
|
2014-02-18 08:55:38 +01:00
|
|
|
|
|
|
|
readyCounter-- ;
|
|
|
|
readyList[i] = 0;
|
2014-02-04 16:07:10 +01:00
|
|
|
}
|
|
|
|
}
|
2014-02-18 08:55:38 +01:00
|
|
|
Sleep(5); //TODO: This might not be needed here.
|
|
|
|
}
|
2014-02-09 16:42:26 +01:00
|
|
|
|
2014-02-18 08:55:38 +01:00
|
|
|
//Sync with clients before starting countdown
|
2014-02-18 11:34:24 +01:00
|
|
|
for (unsigned int i = 0; i < this->gClients.Size(); i++)
|
2014-02-18 08:55:38 +01:00
|
|
|
{
|
2014-02-18 11:34:24 +01:00
|
|
|
if(this->gClients[i])
|
2014-02-09 16:42:26 +01:00
|
|
|
{
|
2014-02-18 11:34:24 +01:00
|
|
|
this->gClients[i]->GetClient()->Send(GameLogic::Protocol_LobbyStartGame(5.0f));
|
2014-02-09 16:42:26 +01:00
|
|
|
}
|
2014-02-04 16:07:10 +01:00
|
|
|
}
|
2014-02-18 08:55:38 +01:00
|
|
|
}
|
2014-01-13 12:44:33 +01:00
|
|
|
|
2014-02-18 11:34:24 +01:00
|
|
|
bool GameSession::Join(gClient gameClient)
|
2014-02-18 08:55:38 +01:00
|
|
|
{
|
|
|
|
if(!this->isCreated) return false;
|
2014-02-18 11:34:24 +01:00
|
|
|
if(this->GetClientCount() == this->gClients.Capacity()) return false;
|
2014-01-13 12:44:33 +01:00
|
|
|
|
2014-02-18 11:34:24 +01:00
|
|
|
gameClient->SetOwner(this);
|
2014-02-09 16:42:26 +01:00
|
|
|
|
2014-02-18 08:55:38 +01:00
|
|
|
IPlayerData* playerData = this->gameInstance.CreatePlayer();
|
|
|
|
if(!playerData) return false;
|
2014-02-09 16:42:26 +01:00
|
|
|
|
2014-02-18 11:34:24 +01:00
|
|
|
gameClient->SetPlayer(playerData);
|
2014-02-18 08:55:38 +01:00
|
|
|
NetworkClient* nwClient = gameClient->GetClient();
|
2014-02-15 09:29:54 +01:00
|
|
|
|
2014-02-18 08:55:38 +01:00
|
|
|
// Send the player data only
|
|
|
|
{
|
|
|
|
Protocol_ObjectCreatePlayer oc( playerData->GetPosition(), playerData->GetRotation(), playerData->GetScale(),
|
|
|
|
playerData->GetID(), true, playerData->GetTeamID(),
|
2014-02-19 11:02:44 +01:00
|
|
|
Utility::String::WStringToString(gameClient->GetAlias(), std::string()),
|
|
|
|
Utility::String::WStringToString(gameClient->GetCharacter(), std::string()));
|
2014-02-18 08:55:38 +01:00
|
|
|
nwClient->Send(oc);
|
|
|
|
}
|
2014-02-15 09:29:54 +01:00
|
|
|
|
2014-02-18 08:55:38 +01:00
|
|
|
// Send information about other clients
|
|
|
|
{
|
2014-02-18 11:34:24 +01:00
|
|
|
for (unsigned int i = 0; i < this->gClients.Size(); i++)
|
2014-02-15 09:29:54 +01:00
|
|
|
{
|
2014-02-20 16:52:36 +01:00
|
|
|
if(this->gClients[i] && !this->gClients[i]->IsInvalid())
|
2014-02-15 09:29:54 +01:00
|
|
|
{
|
2014-02-18 11:34:24 +01:00
|
|
|
IPlayerData* temp = this->gClients[i]->GetPlayer();
|
2014-02-20 16:54:24 +01:00
|
|
|
Protocol_ObjectCreatePlayer p1( temp->GetPosition(), temp->GetRotation(), temp->GetScale(),
|
2014-02-18 08:55:38 +01:00
|
|
|
temp->GetID(), false, temp->GetTeamID(),
|
2014-02-19 11:02:44 +01:00
|
|
|
Utility::String::WStringToString(this->gClients[i]->GetAlias(), std::string()),
|
|
|
|
Utility::String::WStringToString(this->gClients[i]->GetCharacter(), std::string()));
|
2014-02-20 16:54:24 +01:00
|
|
|
nwClient->Send(p1);
|
|
|
|
|
|
|
|
temp = playerData;
|
|
|
|
Protocol_ObjectCreatePlayer p2( temp->GetPosition(), temp->GetRotation(), temp->GetScale(),
|
|
|
|
temp->GetID(), false, temp->GetTeamID(),
|
|
|
|
Utility::String::WStringToString(gameClient->GetAlias(), std::string()),
|
|
|
|
Utility::String::WStringToString(gameClient->GetCharacter(), std::string()));
|
|
|
|
this->gClients[i]->GetClient()->Send(p2);
|
2014-02-15 09:29:54 +01:00
|
|
|
}
|
|
|
|
}
|
2014-02-18 08:55:38 +01:00
|
|
|
}
|
2014-02-15 09:29:54 +01:00
|
|
|
|
2014-02-18 08:55:38 +01:00
|
|
|
//TODO: Need to be able to get the current gameplay data from the logic, to sync it with the client
|
|
|
|
{
|
2014-02-18 11:56:36 +01:00
|
|
|
DynamicArray<IObjectData*> objects;
|
|
|
|
this->levelData->GetAllDynamicObjects(objects);
|
|
|
|
for (unsigned int i = 0; i < objects.Size(); i++)
|
|
|
|
{
|
|
|
|
//Protocol_ObjectPosition p(movedObject->GetPosition(), id);
|
|
|
|
Protocol_ObjectPositionRotation p(objects[i]->GetPosition(), objects[i]->GetRotation(), objects[i]->GetID());
|
2014-02-21 10:54:30 +01:00
|
|
|
nwClient->Send(p.GetProtocol());
|
2014-02-18 11:56:36 +01:00
|
|
|
}
|
2014-02-18 08:55:38 +01:00
|
|
|
}
|
2014-02-15 09:29:54 +01:00
|
|
|
|
2014-02-18 08:55:38 +01:00
|
|
|
// Insert the new client to the update list
|
2014-02-18 11:34:24 +01:00
|
|
|
bool added = false;
|
2014-02-18 08:55:38 +01:00
|
|
|
{
|
2014-02-18 11:34:24 +01:00
|
|
|
for (unsigned int i = 0; !added && i < this->gClients.Size(); i++)
|
2014-01-13 12:44:33 +01:00
|
|
|
{
|
2014-02-18 11:34:24 +01:00
|
|
|
if(!this->gClients[i])
|
2014-01-13 12:44:33 +01:00
|
|
|
{
|
2014-02-18 11:34:24 +01:00
|
|
|
this->gClients[i] = gameClient;
|
|
|
|
// Send the start signal
|
|
|
|
{
|
|
|
|
nwClient->Send(GameLogic::Protocol_LobbyStartGame(0));
|
|
|
|
}
|
2014-02-18 08:55:38 +01:00
|
|
|
added = true;
|
2014-02-18 11:34:24 +01:00
|
|
|
this->clientCount++;
|
2014-01-13 12:44:33 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-02-18 16:38:08 +01:00
|
|
|
gameClient->SetState(GameClient::ClientState_Ready);
|
|
|
|
|
2014-02-18 11:34:24 +01:00
|
|
|
return added;
|
2014-02-18 08:55:38 +01:00
|
|
|
}
|
|
|
|
|
2014-02-18 11:34:24 +01:00
|
|
|
//DynamicArray<gClient> GameSession::CloseSession( bool dissconnectClients )
|
|
|
|
//{
|
|
|
|
// this->worker.Terminate();
|
|
|
|
// //TODO: Send clients to lobby
|
|
|
|
//
|
|
|
|
// //for (unsigned int i = 0; i < this->gClients.Size(); i++)
|
|
|
|
// //{
|
|
|
|
// // if(this->gClients[i])
|
|
|
|
// // {
|
|
|
|
// // ((GameLobby*)this->owner)-> this->gClients[i]
|
|
|
|
// // }
|
|
|
|
// //}
|
|
|
|
//
|
|
|
|
// this->gClients.Clear();
|
|
|
|
//}
|
2014-02-04 16:07:10 +01:00
|
|
|
|
2014-01-13 12:44:33 +01:00
|
|
|
|