mirror of
https://github.com/copyrighttxt/watrbx-game-engine.git
synced 2026-09-05 05:07:48 +00:00
GEEKING
This commit is contained in:
@@ -0,0 +1,616 @@
|
||||
//
|
||||
// PlaceLauncher.m
|
||||
// RobloxMobile
|
||||
//
|
||||
// Created by David York on 9/25/12.
|
||||
// Copyright (c) 2012 ROBLOX. All rights reserved.
|
||||
//
|
||||
|
||||
#include "PlaceLauncher.h"
|
||||
#include "util/Statistics.h"
|
||||
#include "RobloxView.h"
|
||||
#include "RobloxInfo.h"
|
||||
#include "JNIMain.h"
|
||||
#include "RobloxUtilities.h"
|
||||
|
||||
#include <iostream> // std::cout
|
||||
#include <fstream> // std::ifstream
|
||||
|
||||
#include "v8datamodel/DebugSettings.h"
|
||||
#include "v8datamodel/Workspace.h"
|
||||
#include "v8datamodel/GuiService.h"
|
||||
#include "v8datamodel/TeleportService.h"
|
||||
#include "v8datamodel/LoginService.h"
|
||||
#include "V8DataModel/ContentProvider.h"
|
||||
#include "v8datamodel/MeshContentProvider.h"
|
||||
#include "v8datamodel/TextureContentProvider.h"
|
||||
#include "v8datamodel/FastLogSettings.h"
|
||||
#include "V8DataModel/UserInputService.h"
|
||||
#include "script/ScriptContext.h"
|
||||
#include "util/Statistics.h"
|
||||
#include "util/standardout.h"
|
||||
#include "util/MemoryStats.h"
|
||||
#include "v8datamodel/Stats.h"
|
||||
|
||||
|
||||
#include "util/RobloxGoogleAnalytics.h"
|
||||
#include "util/Http.h"
|
||||
#include "LogManager.h"
|
||||
#include "rbx/Profiler.h"
|
||||
|
||||
#include <rapidjson/document.h>
|
||||
|
||||
DYNAMIC_LOGVARIABLE(PlaceLauncher, 0)
|
||||
DYNAMIC_LOGGROUP(NetworkTrace)
|
||||
LOGGROUP(PlayerShutdownLuaTimeoutSeconds)
|
||||
|
||||
|
||||
DYNAMIC_FASTINT(AndroidInfluxHundredthsPercentage)
|
||||
|
||||
using namespace RBX;
|
||||
using namespace RBX::JNI;
|
||||
|
||||
namespace
|
||||
{
|
||||
static const std::string kAndroidClientAppSettings = "AndroidAppSettings";
|
||||
static const std::string kAndroidClientSettingsAPIKey = "D6925E56-BFB9-4908-AAA2-A5B1EC4B2D79";
|
||||
static const std::string kStartGameURL = "%sGame/PlaceLauncher.ashx?request=%s&%s&isPartyLeader=false&gender=&isTeleport=false";
|
||||
static const std::string kStartGameStatusURL = "%sGame/PlaceLauncher.ashx?request=CheckGameJobStatus&jobId=%s";
|
||||
} // namespace
|
||||
|
||||
namespace RBX
|
||||
{
|
||||
namespace JNI
|
||||
{
|
||||
extern std::string platformUserAgent; // Comes from LogManager
|
||||
}
|
||||
}
|
||||
|
||||
PlaceLauncher::PlaceLauncher()
|
||||
{
|
||||
teleporter.reset(new Teleporter(RBX::FunctionMarshaller::GetWindow()));
|
||||
RBX::TeleportService::SetCallback(teleporter.get());
|
||||
};
|
||||
|
||||
PlaceLauncher& PlaceLauncher::getPlaceLauncher()
|
||||
{
|
||||
static PlaceLauncher placeLauncher;
|
||||
return placeLauncher;
|
||||
}
|
||||
|
||||
static std::string ReadStringValue(std::string &data, std::string name)
|
||||
{
|
||||
std::string result;
|
||||
int pos = data.find(name);
|
||||
if (pos != -1)
|
||||
{
|
||||
int start = pos + name.length() + 3;
|
||||
int end = data.find(",", start);
|
||||
result = data.substr(start, end - start - 1);
|
||||
}
|
||||
|
||||
pos = result.find("\\/"); // find first space
|
||||
while (pos != std::string::npos)
|
||||
{
|
||||
result.replace(pos, 2, "/");
|
||||
pos = result.find("\\/", pos + 1);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static RBX::ProtectedString fetchAndValidateScript(RBX::DataModel* dataModel, const std::string& urlScript)
|
||||
{
|
||||
RBX::Security::Impersonator impersonate(RBX::Security::COM);
|
||||
|
||||
std::ostringstream data;
|
||||
if (RBX::ContentProvider::isUrl(urlScript))
|
||||
{
|
||||
RBX::DataModel::LegacyLock lock(dataModel, RBX::DataModelJob::Write);
|
||||
std::auto_ptr<std::istream> stream(RBX::ServiceProvider::create<RBX::ContentProvider>(dataModel)->getContent(RBX::ContentId(urlScript.c_str())));
|
||||
boost::iostreams::copy(*stream, data);
|
||||
}
|
||||
else
|
||||
return RBX::ProtectedString();
|
||||
|
||||
RBX::ProtectedString verifiedSource;
|
||||
|
||||
try
|
||||
{
|
||||
verifiedSource = RBX::ProtectedString::fromTrustedSource(data.str());
|
||||
RBX::ContentProvider::verifyScriptSignature(verifiedSource, true);
|
||||
}
|
||||
catch(std::bad_alloc& e)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
catch(RBX::base_exception& e)
|
||||
{
|
||||
return RBX::ProtectedString();
|
||||
}
|
||||
|
||||
return verifiedSource;
|
||||
}
|
||||
|
||||
static void executeUrlJoinScript(boost::shared_ptr<RBX::Game> game, const std::string& urlScript)
|
||||
{
|
||||
RBXASSERT(urlScript.find("join.ashx"));
|
||||
|
||||
boost::shared_ptr<RBX::DataModel> dataModel = game->getDataModel();
|
||||
|
||||
RBX::ProtectedString verifiedSource = fetchAndValidateScript(dataModel.get(), urlScript);
|
||||
if (verifiedSource.empty())
|
||||
return;
|
||||
|
||||
RBX::DataModel::LegacyLock lock(dataModel, RBX::DataModelJob::Write);
|
||||
|
||||
if (dataModel->isClosed())
|
||||
return;
|
||||
|
||||
// new join script
|
||||
std::string dataString = verifiedSource.getSource();
|
||||
int firstNewLineIndex = dataString.find("\r\n");
|
||||
if (dataString[firstNewLineIndex+2] == '{')
|
||||
{
|
||||
RobloxUtilities::getRobloxUtilities().getGameTimer().reset();
|
||||
game->configurePlayer(RBX::Security::COM, dataString.substr(firstNewLineIndex+2));
|
||||
return;
|
||||
}
|
||||
|
||||
// old join script
|
||||
RBX::ScriptContext* context = dataModel->create<RBX::ScriptContext>();
|
||||
context->executeInNewThread(RBX::Security::COM, verifiedSource, "Start Script");
|
||||
}
|
||||
|
||||
static void joinGamePlaceId(StartGameParams sgp, shared_ptr<RBX::Game> game)
|
||||
{
|
||||
RobloxUtilities::getRobloxUtilities().getGameTimer().reset();
|
||||
try
|
||||
{
|
||||
int retrys = 5;
|
||||
|
||||
RBX::StandardOut::singleton()->printf(RBX::MESSAGE_INFO,"PlaceLauncher::joinGamePlaceId placeId = %i, userId = %d, accessCode = %s, gameId = %s, joinRequestType: %d\n", sgp.placeId, sgp.userId, sgp.accessCode.c_str(), sgp.gameId.c_str(), sgp.joinRequestType);
|
||||
|
||||
const char* base = GetBaseURL().c_str();
|
||||
std::string requestParamsString, requestType;
|
||||
std::string formattedParams;
|
||||
switch (sgp.joinRequestType)
|
||||
{
|
||||
case JOIN_GAME_REQUEST_PLACEID:
|
||||
requestParamsString = "placeId=%d";
|
||||
formattedParams = RBX::format(requestParamsString.c_str(), sgp.placeId);
|
||||
requestType = "RequestGame";
|
||||
break;
|
||||
case JOIN_GAME_REQUEST_USERID:
|
||||
requestParamsString = "userId=%d";
|
||||
formattedParams = RBX::format(requestParamsString.c_str(), sgp.userId);
|
||||
requestType = "RequestFollowUser";
|
||||
break;
|
||||
case JOIN_GAME_REQUEST_PRIVATE_SERVER:
|
||||
requestParamsString = "placeId=%d&accessCode=%s";
|
||||
formattedParams = RBX::format(requestParamsString.c_str(), sgp.placeId, sgp.accessCode.c_str());
|
||||
requestType = "RequestPrivateGame";
|
||||
break;
|
||||
case JOIN_GAME_REQUEST_GAME_INSTANCE:
|
||||
requestParamsString = "placeId=%d&gameId=%s";
|
||||
formattedParams = RBX::format(requestParamsString.c_str(), sgp.placeId, sgp.gameId.c_str());
|
||||
requestType = "RequestGameJob";
|
||||
break;
|
||||
}
|
||||
|
||||
std::string response;
|
||||
bool found = false;
|
||||
int status = -1;
|
||||
|
||||
std::string url = RBX::format(kStartGameURL.c_str(), base, requestType.c_str(), formattedParams.c_str());
|
||||
RBX::StandardOut::singleton()->printf(RBX::MESSAGE_INFO,"PlaceLauncher URL : %s\n", url.c_str());
|
||||
std::string jobId;
|
||||
while (retrys >= 0)
|
||||
{
|
||||
bool retryUsed = true;
|
||||
response = "";
|
||||
RBX::Http(url).get(response);
|
||||
|
||||
RBX::StandardOut::singleton()->printf(RBX::MESSAGE_INFO,"PlaceLauncher Response : %s\n", response.c_str());
|
||||
|
||||
rapidjson::Document doc;
|
||||
doc.Parse<rapidjson::kParseDefaultFlags>(response.c_str());
|
||||
|
||||
RBXASSERT(doc.HasMember("status"));
|
||||
status = doc["status"].GetInt();
|
||||
|
||||
// Place join status results
|
||||
// Waiting = 0,
|
||||
// Loading = 1,
|
||||
// Joining = 2,
|
||||
// Disabled = 3,
|
||||
// Error = 4,
|
||||
// GameEnded = 5,
|
||||
// GameFull = 6
|
||||
// UserLeft = 10
|
||||
// Restricted = 11
|
||||
|
||||
if (2 == status)
|
||||
{
|
||||
// not most efficient way to check status,
|
||||
// but we have web calls so strstr is not a big deal
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
else if (0 == status || 1 == status)
|
||||
{
|
||||
// 0 or 1 is not an error - it is a sign that we should wait
|
||||
retryUsed = false;
|
||||
RBXASSERT(doc.HasMember("jobId"));
|
||||
jobId = doc["jobId"].GetString();
|
||||
|
||||
// Check game status no matter what type of join we're attempting
|
||||
url = RBX::format(kStartGameStatusURL.c_str(), base, Http::urlEncode(jobId).c_str());
|
||||
}
|
||||
else
|
||||
break;
|
||||
|
||||
int sleepTime = 250*1000;
|
||||
|
||||
if (retryUsed)
|
||||
{
|
||||
--retrys;
|
||||
sleepTime = 999*1000;
|
||||
}
|
||||
|
||||
::usleep(sleepTime);
|
||||
}
|
||||
|
||||
if (found)
|
||||
{
|
||||
executeUrlJoinScript(game, ReadStringValue(response, "joinScriptUrl"));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (sgp.joinRequestType == JOIN_GAME_REQUEST_PLACEID)
|
||||
RBX::StandardOut::singleton()->printf(RBX::MESSAGE_ERROR, "PlaceLauncher: Cannot connect to place %d, return from GetPlaceLauncher.ashx = %s", sgp.placeId, response.c_str());
|
||||
else if (sgp.joinRequestType == JOIN_GAME_REQUEST_USERID)
|
||||
RBX::StandardOut::singleton()->printf(RBX::MESSAGE_ERROR, "PlaceLauncher: Cannot follow user %d, return from GetPlaceLauncher.ashx = %s", sgp.userId, response.c_str());
|
||||
else if (sgp.joinRequestType == JOIN_GAME_REQUEST_PRIVATE_SERVER)
|
||||
RBX::StandardOut::singleton()->printf(RBX::MESSAGE_ERROR, "PlaceLauncher: Cannot join private server, accessCode = %s, return from GetPlaceLauncher.ashx = %s", sgp.accessCode.c_str(), response.c_str());
|
||||
else if (sgp.joinRequestType)
|
||||
RBX::StandardOut::singleton()->printf(RBX::MESSAGE_ERROR, "PlaceLauncher: Cannot join game instance, gameId = %s, return from GetPlaceLauncher.ashx = %s", sgp.gameId.c_str(), response.c_str());
|
||||
|
||||
// Place join status results
|
||||
// Waiting = 0,
|
||||
// Loading = 1,
|
||||
// Joining = 2,
|
||||
// Disabled = 3,
|
||||
// Error = 4,
|
||||
// GameEnded = 5,
|
||||
// GameFull = 6
|
||||
// UserLeft = 10
|
||||
// Restricted = 11
|
||||
PlaceLauncher::handleStartGameFailure(status);
|
||||
}
|
||||
}
|
||||
catch (const RBX::base_exception& e)
|
||||
{
|
||||
if (sgp.joinRequestType == JOIN_GAME_REQUEST_PLACEID)
|
||||
RBX::StandardOut::singleton()->printf(RBX::MESSAGE_ERROR,"PlaceLauncher: Exception thrown: Can't join place %d, because %s\n", sgp.placeId, e.what());
|
||||
else if (sgp.joinRequestType == JOIN_GAME_REQUEST_USERID)
|
||||
RBX::StandardOut::singleton()->printf(RBX::MESSAGE_ERROR,"PlaceLauncher: Exception thrown: Can't follow user %d, because %s\n", sgp.userId, e.what());
|
||||
else if (sgp.joinRequestType == JOIN_GAME_REQUEST_PRIVATE_SERVER)
|
||||
RBX::StandardOut::singleton()->printf(RBX::MESSAGE_ERROR, "PlaceLauncher: Exception thrown: Cannot join private server, accessCode = %s, because %s", sgp.accessCode.c_str(), e.what());
|
||||
else if (sgp.joinRequestType)
|
||||
RBX::StandardOut::singleton()->printf(RBX::MESSAGE_ERROR, "PlaceLauncher: Exception thrown: Cannot join game instance, gameId = %s, because %s", sgp.gameId.c_str(), e.what());
|
||||
|
||||
//[[PlaceLauncher sharedInstance] handleStartGameFailure];
|
||||
}
|
||||
}
|
||||
|
||||
void PlaceLauncher::handleStartGameFailure(int status = 99)
|
||||
{
|
||||
// Place join status results
|
||||
// 0, 1, or 2 is handled in joinGamePlaceId above
|
||||
|
||||
// Disabled = 3,
|
||||
// Error = 4,
|
||||
// GameEnded = 5,
|
||||
// GameFull = 6
|
||||
// UserLeft = 10
|
||||
// Restricted = 11
|
||||
|
||||
std::string errorMsgName; // this is the name of the error message string in res/values/strings.xml
|
||||
std::string fastLogMsg; // only used for logging; not displayed to the user
|
||||
switch (status)
|
||||
{
|
||||
case 3:
|
||||
errorMsgName = "GameStartFailureDisabled";
|
||||
fastLogMsg = "PlaceLauncher failure - game was disabled.";
|
||||
break;
|
||||
case 4:
|
||||
errorMsgName = "GameStartFailureError";
|
||||
fastLogMsg = "PlaceLauncher failure - game failed to start.";
|
||||
break;
|
||||
case 5:
|
||||
errorMsgName = "GameStartFailureGameEnded";
|
||||
fastLogMsg = "PlaceLauncher failure - game has ended.";
|
||||
break;
|
||||
case 6:
|
||||
errorMsgName = "GameStartFailureGameFull";
|
||||
fastLogMsg = "PlaceLauncher failure - game is full.";
|
||||
break;
|
||||
case 10:
|
||||
errorMsgName = "GameStartFailureUserLeft";
|
||||
fastLogMsg = "PlaceLauncher failure - the user you were following has left the game.";
|
||||
break;
|
||||
case 11:
|
||||
errorMsgName = "GameStartFailureRestricted";
|
||||
fastLogMsg = "PlaceLauncher failure - game not available for this platform.";
|
||||
break;
|
||||
case 99:
|
||||
default:
|
||||
errorMsgName = "GameStartFailureUnknown";
|
||||
fastLogMsg = "PlaceLauncher failure - unknown game start failure.";
|
||||
break;
|
||||
}
|
||||
RBX::StandardOut::singleton()->printf(MESSAGE_INFO, "in handleGameStartFailure, msg is %s", errorMsgName.c_str());
|
||||
FASTLOG1(DFLog::PlaceLauncher, "%s", fastLogMsg.c_str());
|
||||
|
||||
JNI::exitGameWithError(errorMsgName); // from JNIMain
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool PlaceLauncher::prepareGame( const StartGameParams& sgp )
|
||||
{
|
||||
StandardOut::singleton()->printf(MESSAGE_INFO, "Asset Path in Place Launch: %s", RobloxInfo::getRobloxInfo().getAssetFolderPath().c_str());
|
||||
FASTLOG(DFLog::PlaceLauncher, "PlaceLauncher prepareGame - START");
|
||||
RBX::ContentProvider::setAssetFolder(RobloxInfo::getRobloxInfo().getAssetFolderPath().c_str());
|
||||
|
||||
Http::rbxUserAgent = platformUserAgent;
|
||||
RBX::Game::globalInit(false);
|
||||
RBX::TeleportService::SetBaseUrl(GetBaseURL().c_str());
|
||||
|
||||
/*
|
||||
if(needsOnline)
|
||||
{
|
||||
Reachability* reachability = [Reachability reachabilityForInternetConnection];
|
||||
NetworkStatus remoteStatus = [reachability currentReachabilityStatus];
|
||||
|
||||
if(remoteStatus == NotReachable)
|
||||
{
|
||||
RBX::StandardOut::singleton()->printf(RBX::MESSAGE_ERROR,"PlaceLauncher: No Network Connection available");
|
||||
[RobloxAlert RobloxAlertWithMessage:NSLocalizedString(@"ConnectionError", nil)];
|
||||
return false;
|
||||
}
|
||||
else if(remoteStatus == ReachableViaWWAN)
|
||||
{
|
||||
// if user preference is for wifi only, don't allow this
|
||||
NSUserDefaults *userDefaults =[NSUserDefaults standardUserDefaults];
|
||||
if([[userDefaults stringForKey:@"wifionly_preference"] boolValue])
|
||||
{
|
||||
[RobloxAlert RobloxAlertWithMessage:NSLocalizedString(@"WiFiOnlyError", nil)];
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
std::string ios = "i";
|
||||
ios += "o";
|
||||
ios += "s";
|
||||
ios = ios + "," + ios; // slight obfuscation
|
||||
|
||||
RBX::DataModel::hash = ios;
|
||||
|
||||
{
|
||||
RBX::Security::Impersonator impersonate(RBX::Security::RobloxGameScript_);
|
||||
RBX::GlobalBasicSettings::singleton()->loadState("");
|
||||
}
|
||||
|
||||
RBX::Profiler::onThreadCreate("Main");
|
||||
|
||||
RBX::TaskScheduler::singleton().setThreadCount(RBX::TaskSchedulerSettings::singleton().getThreadPoolConfig());
|
||||
|
||||
FASTLOG(DFLog::PlaceLauncher, "PlaceLauncher prepareGame - END");
|
||||
return true;
|
||||
}
|
||||
|
||||
void initClientSettings()
|
||||
{
|
||||
// This needs to be put in a manager and cached
|
||||
std::string clientSettingsData;
|
||||
std::string androidAppSettingsData;
|
||||
FetchClientSettingsData(CLIENT_APP_SETTINGS_STRING, CLIENT_SETTINGS_API_KEY, &clientSettingsData);
|
||||
FetchClientSettingsData(kAndroidClientAppSettings.c_str(), kAndroidClientSettingsAPIKey.c_str(), &androidAppSettingsData);
|
||||
RBX::ClientAppSettings settings = RBX::ClientAppSettings::singleton();
|
||||
LoadClientSettingsFromString(CLIENT_APP_SETTINGS_STRING, clientSettingsData, &RBX::ClientAppSettings::singleton());
|
||||
LoadClientSettingsFromString(kAndroidClientAppSettings.c_str(), androidAppSettingsData, &RBX::ClientAppSettings::singleton());
|
||||
|
||||
// Reset synchronized flags, they should be set by the server
|
||||
FLog::ResetSynchronizedVariablesState();
|
||||
}
|
||||
|
||||
static void initControlView(RobloxView* rbxView, bool isTouchDevice)
|
||||
{
|
||||
if(DataModel* dm = rbxView->getDataModel().get())
|
||||
{
|
||||
if(RBX::UserInputService* inputService = RBX::ServiceProvider::create<RBX::UserInputService>(dm))
|
||||
{
|
||||
inputService->setTouchEnabled(isTouchDevice);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PlaceLauncher::finishGameSetup( boost::shared_ptr<RBX::Game> game)
|
||||
{
|
||||
rbxView = RobloxView::create_view(currentGame, gameParams.view, gameParams.viewWidth, gameParams.viewHeight);
|
||||
rbxView->getDataModel()->submitTask(boost::bind(initControlView, rbxView, gameParams.isTouchDevice), RBX::DataModelJob::Write);
|
||||
}
|
||||
|
||||
|
||||
shared_ptr<RBX::Game> PlaceLauncher::setupGame( const StartGameParams& sgp )
|
||||
{
|
||||
FASTLOG(DFLog::PlaceLauncher, "PlaceLauncher setUpGame");
|
||||
if(isCurrentlyPlayingGame)
|
||||
return shared_ptr<RBX::Game>();
|
||||
|
||||
isCurrentlyPlayingGame = true;
|
||||
|
||||
initClientSettings();
|
||||
RobloxGoogleAnalytics::lotteryInit(
|
||||
ClientAppSettings::singleton().GetValueGoogleAnalyticsAccountPropertyIDPlayer(),
|
||||
ClientAppSettings::singleton().GetValueGoogleAnalyticsThreadPoolMaxScheduleSize(),
|
||||
ClientAppSettings::singleton().GetValueGoogleAnalyticsLoadPlayer());
|
||||
StandardOut::singleton()->printf(MESSAGE_INFO, "account = %s, schedule = %d",
|
||||
ClientAppSettings::singleton().GetValueGoogleAnalyticsAccountPropertyIDPlayer(),
|
||||
ClientAppSettings::singleton().GetValueGoogleAnalyticsThreadPoolMaxScheduleSize());
|
||||
|
||||
RBX::Http::SetUseStatistics(true);
|
||||
|
||||
if(prepareGame( sgp ))
|
||||
{
|
||||
FASTLOGS(DFLog::PlaceLauncher, "Game's base URL: %s", GetBaseURL().c_str());
|
||||
currentGame = shared_ptr<RBX::Game>( new RBX::SecurePlayerGame(NULL, GetBaseURL().c_str()) );
|
||||
|
||||
rbxView = RobloxView::create_view(currentGame, sgp.view, sgp.viewWidth, sgp.viewHeight);
|
||||
|
||||
rbxView->getDataModel()->submitTask(boost::bind(initControlView, rbxView, gameParams.isTouchDevice), RBX::DataModelJob::Write);
|
||||
|
||||
if (FLog::PlayerShutdownLuaTimeoutSeconds > 0)
|
||||
currentGame->getDataModel()->create<RBX::ScriptContext>();
|
||||
|
||||
return currentGame;
|
||||
}
|
||||
|
||||
return shared_ptr<RBX::Game>();
|
||||
}
|
||||
|
||||
|
||||
shared_ptr<RBX::Game> PlaceLauncher::setupPreloadedGame( const StartGameParams& sgp )
|
||||
{
|
||||
FASTLOG(DFLog::PlaceLauncher, "PlaceLauncher SetupPreloadedGame");
|
||||
return setupGame( sgp );
|
||||
}
|
||||
|
||||
bool PlaceLauncher::startGame( boost::function0 <void> scriptFunction , shared_ptr<RBX::Game> preloadedGame)
|
||||
{
|
||||
// Start the script thread!
|
||||
boost::thread(RBX::thread_wrapper(scriptFunction, "GameStartScript"));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool PlaceLauncher::startGame( const StartGameParams& sgp )
|
||||
{
|
||||
gameParams = sgp;
|
||||
FASTLOG(DFLog::PlaceLauncher, "PlaceLauncher StartGame");
|
||||
shared_ptr<RBX::Game> game = setupPreloadedGame( sgp );
|
||||
if( game != shared_ptr<RBX::Game>())
|
||||
{
|
||||
currentGame = game;
|
||||
return startGame(boost::bind(&joinGamePlaceId, sgp, game), game);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void PlaceLauncher::leaveGame ( bool userRequestedLeave)
|
||||
{
|
||||
RBX::Time::Interval gamePlayInterval = RobloxUtilities::getRobloxUtilities().getGameTimer().reset();
|
||||
RBX::Analytics::InfluxDb::Points points;
|
||||
points.addPoint("SessionReport" , "AndroidSuccess");
|
||||
points.addPoint("FreeMemoryKB" , RBX::MemoryStats::freeMemoryBytes());
|
||||
points.addPoint("UsedMemoryKB" , RBX::MemoryStats::usedMemoryBytes());
|
||||
points.addPoint("PlayTime" , gamePlayInterval.seconds());
|
||||
|
||||
points.report("Android-RobloxPlayer-SessionReport", DFInt::AndroidInfluxHundredthsPercentage);
|
||||
deleteRobloxView(true);
|
||||
}
|
||||
|
||||
|
||||
void PlaceLauncher::deleteRobloxView( bool resetCurrentGame )
|
||||
{
|
||||
if(resetCurrentGame)
|
||||
{
|
||||
// remove all shared ptr to games so it can properly be destroyed
|
||||
currentGame.reset();
|
||||
}
|
||||
|
||||
if( teleporter )
|
||||
{
|
||||
teleporter.reset();
|
||||
}
|
||||
|
||||
// do actual destruction of the Roblox View, only if it isn't NULL
|
||||
if (rbxView)
|
||||
{
|
||||
// Destroy the view synchronously
|
||||
// Take care to zero-out view pointer beforehand to support reentrancy
|
||||
RobloxView* view = rbxView;
|
||||
rbxView = NULL;
|
||||
delete view;
|
||||
}
|
||||
}
|
||||
|
||||
static void joinGameTeleport(std::string url, std::string ticket, std::string script, shared_ptr<RBX::Game> game)
|
||||
{
|
||||
try
|
||||
{
|
||||
// get authentication URL
|
||||
std::string compound = url;
|
||||
|
||||
if (!ticket.empty())
|
||||
{
|
||||
compound += "?suggest=";
|
||||
compound += ticket;
|
||||
}
|
||||
|
||||
// issue an authentication request
|
||||
std::string result;
|
||||
|
||||
try
|
||||
{
|
||||
RBX::Http http(compound.c_str());
|
||||
http.setAuthDomain(GetBaseURL().c_str());
|
||||
http.get(result);
|
||||
}
|
||||
catch (const RBX::base_exception& e)
|
||||
{
|
||||
}
|
||||
|
||||
// run game
|
||||
executeUrlJoinScript(game, script);
|
||||
|
||||
}
|
||||
catch (const RBX::base_exception& e)
|
||||
{
|
||||
RBX::StandardOut::singleton()->printf(RBX::MESSAGE_ERROR,"PlaceLauncher: Teleport failed: %s\n", e.what());
|
||||
}
|
||||
}
|
||||
|
||||
void PlaceLauncher::teleport( std::string ticket, std::string authUrl, std::string script)
|
||||
{
|
||||
if (!rbxView) return;
|
||||
|
||||
// first do an empty reset so serviceprovider oldProvider is called first
|
||||
currentGame.reset();
|
||||
currentGame.reset(new RBX::SecurePlayerGame(NULL, GetBaseURL().c_str()));
|
||||
|
||||
rbxView->replaceGame(currentGame);
|
||||
|
||||
rbxView->getDataModel()->submitTask(boost::bind(initControlView, rbxView, gameParams.isTouchDevice), RBX::DataModelJob::Write);
|
||||
|
||||
// Don't use submit task on data model for this thread, the script fetched in
|
||||
// the spawned thread does data model setup.
|
||||
// joinGameTeleport will take ownership of the game.
|
||||
boost::thread joinScriptThread(boost::bind(&joinGameTeleport, authUrl, ticket, script, currentGame));
|
||||
}
|
||||
|
||||
void PlaceLauncher::shutDownGraphics()
|
||||
{
|
||||
if (!rbxView) return;
|
||||
rbxView->shutDownGraphics(currentGame);
|
||||
}
|
||||
|
||||
void PlaceLauncher::startUpGraphics(void *wnd, unsigned int width, unsigned int height)
|
||||
{
|
||||
if (!rbxView) return;
|
||||
rbxView->startUpGraphics(currentGame, wnd, width, height);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user