1
0
forked from 0ad/0ad

Quite a lot of stack rooting related changes.

Changes GetProperty, SetProperty and HasProperty and a few other
functions to take handles. The conversions to CScriptVal or
CScriptValRooted at some places should be removed in the future. I've
done that to avoid an even larger patch.

Refs #2415
Refs #2462

This was SVN commit r15568.
This commit is contained in:
Yves 2014-07-26 22:33:16 +00:00
parent e818b08344
commit 28bdd8540f
25 changed files with 801 additions and 619 deletions

View File

@ -79,6 +79,9 @@ void* CMapGeneratorWorker::RunThread(void *data)
bool CMapGeneratorWorker::Run()
{
JSContext* cx = m_ScriptInterface->GetContext();
JSAutoRequest rq(cx);
m_ScriptInterface->SetCallbackData(static_cast<void*> (this));
// Replace RNG with a seeded deterministic function
@ -95,52 +98,44 @@ bool CMapGeneratorWorker::Run()
m_ScriptInterface->RegisterFunction<std::vector<std::string>, std::string, bool, CMapGeneratorWorker::FindTemplates>("FindTemplates");
m_ScriptInterface->RegisterFunction<std::vector<std::string>, std::string, bool, CMapGeneratorWorker::FindActorTemplates>("FindActorTemplates");
// TODO: This code is a bit ugly because we have to ensure that CScriptValRooted gets destroyed before the ScriptInterface.
// In the future we should work more with the standard JSAPI types for rooting on the stack, which should avoid such problems.
bool ret = true;
// Parse settings
JS::RootedValue settingsVal(cx, m_ScriptInterface->ParseJSON(m_Settings).get());
if (settingsVal.isUndefined())
{
// Parse settings
CScriptValRooted settingsVal = m_ScriptInterface->ParseJSON(m_Settings);
if (settingsVal.undefined())
{
LOGERROR(L"CMapGeneratorWorker::Run: Failed to parse settings");
ret = false;
}
else
{
// Init RNG seed
u32 seed;
if (!m_ScriptInterface->GetProperty(settingsVal.get(), "Seed", seed))
{ // No seed specified
LOGWARNING(L"CMapGeneratorWorker::Run: No seed value specified - using 0");
seed = 0;
}
LOGERROR(L"CMapGeneratorWorker::Run: Failed to parse settings");
return false;
}
m_MapGenRNG.seed(seed);
// Init RNG seed
u32 seed;
if (!m_ScriptInterface->GetProperty(settingsVal, "Seed", seed))
{ // No seed specified
LOGWARNING(L"CMapGeneratorWorker::Run: No seed value specified - using 0");
seed = 0;
}
// Copy settings to global variable
if (!m_ScriptInterface->SetProperty(m_ScriptInterface->GetGlobalObject(), "g_MapSettings", settingsVal))
{
LOGERROR(L"CMapGeneratorWorker::Run: Failed to define g_MapSettings");
ret = false;
}
else
{
// Load RMS
LOGMESSAGE(L"Loading RMS '%ls'", m_ScriptPath.string().c_str());
if (!m_ScriptInterface->LoadGlobalScriptFile(m_ScriptPath))
{
LOGERROR(L"CMapGeneratorWorker::Run: Failed to load RMS '%ls'", m_ScriptPath.string().c_str());
ret = false;
}
}
}
m_MapGenRNG.seed(seed);
// Copy settings to global variable
JS::RootedValue global(cx, m_ScriptInterface->GetGlobalObject());
if (!m_ScriptInterface->SetProperty(global, "g_MapSettings", settingsVal))
{
LOGERROR(L"CMapGeneratorWorker::Run: Failed to define g_MapSettings");
return false;
}
// Load RMS
LOGMESSAGE(L"Loading RMS '%ls'", m_ScriptPath.string().c_str());
if (!m_ScriptInterface->LoadGlobalScriptFile(m_ScriptPath))
{
LOGERROR(L"CMapGeneratorWorker::Run: Failed to load RMS '%ls'", m_ScriptPath.string().c_str());
return false;
}
// We must destroy the ScriptInterface in the same thread because the JSAPI requires that!
SAFE_DELETE(m_ScriptInterface);
return ret;
return true;
}
int CMapGeneratorWorker::GetProgress()

View File

@ -386,11 +386,14 @@ PSRETURN CMapSummaryReader::LoadMap(const VfsPath& pathname)
CScriptValRooted CMapSummaryReader::GetMapSettings(ScriptInterface& scriptInterface)
{
CScriptValRooted data;
scriptInterface.Eval("({})", data);
JSContext* cx = scriptInterface.GetContext();
JSAutoRequest rq(cx);
JS::RootedValue data(cx);
scriptInterface.Eval("({})", &data);
if (!m_ScriptSettings.empty())
scriptInterface.SetProperty(data.get(), "settings", scriptInterface.ParseJSON(m_ScriptSettings), false);
return data;
scriptInterface.SetProperty(data, "settings", scriptInterface.ParseJSON(m_ScriptSettings), false);
return CScriptValRooted(cx, data);
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@ -1311,6 +1314,8 @@ int CMapReader::GenerateMap()
int CMapReader::ParseTerrain()
{
TIMER(L"ParseTerrain");
JSContext* cx = pSimulation2->GetScriptInterface().GetContext();
JSAutoRequest rq(cx);
// parse terrain from map data
// an error here should stop the loading process
@ -1319,17 +1324,18 @@ int CMapReader::ParseTerrain()
{ LOGERROR(L"CMapReader::ParseTerrain() failed to get '%hs' property", #prop);\
throw PSERROR_Game_World_MapLoadFailed("Error parsing terrain data.\nCheck application log for details"); }
JS::RootedValue tmpMapData(cx, m_MapData.get()); // TODO: Check if this temporary root can be removed after SpiderMonkey 31 upgrade
u32 size;
GET_TERRAIN_PROPERTY(m_MapData.get(), size, size)
GET_TERRAIN_PROPERTY(tmpMapData, size, size)
m_PatchesPerSide = size / PATCH_SIZE;
// flat heightmap of u16 data
GET_TERRAIN_PROPERTY(m_MapData.get(), height, m_Heightmap)
GET_TERRAIN_PROPERTY(tmpMapData, height, m_Heightmap)
// load textures
std::vector<std::string> textureNames;
GET_TERRAIN_PROPERTY(m_MapData.get(), textureNames, textureNames)
GET_TERRAIN_PROPERTY(tmpMapData, textureNames, textureNames)
num_terrain_tex = textureNames.size();
while (cur_terrain_tex < num_terrain_tex)
@ -1344,14 +1350,14 @@ int CMapReader::ParseTerrain()
// build tile data
m_Tiles.resize(SQR(size));
CScriptValRooted tileData;
GET_TERRAIN_PROPERTY(m_MapData.get(), tileData, tileData)
JS::RootedValue tileData(cx);
GET_TERRAIN_PROPERTY(tmpMapData, tileData, &tileData)
// parse tile data object into flat arrays
std::vector<u16> tileIndex;
std::vector<u16> tilePriority;
GET_TERRAIN_PROPERTY(tileData.get(), index, tileIndex);
GET_TERRAIN_PROPERTY(tileData.get(), priority, tilePriority);
GET_TERRAIN_PROPERTY(tileData, index, tileIndex);
GET_TERRAIN_PROPERTY(tileData, priority, tilePriority);
ENSURE(SQR(size) == tileIndex.size() && SQR(size) == tilePriority.size());
@ -1385,11 +1391,15 @@ int CMapReader::ParseTerrain()
int CMapReader::ParseEntities()
{
TIMER(L"ParseEntities");
JSContext* cx = pSimulation2->GetScriptInterface().GetContext();
JSAutoRequest rq(cx);
JS::RootedValue tmpMapData(cx, m_MapData.get()); // TODO: Check if this temporary root can be removed after SpiderMonkey 31 upgrade
// parse entities from map data
std::vector<Entity> entities;
if (!pSimulation2->GetScriptInterface().GetProperty(m_MapData.get(), "entities", entities))
if (!pSimulation2->GetScriptInterface().GetProperty(tmpMapData, "entities", entities))
LOGWARNING(L"CMapReader::ParseEntities() failed to get 'entities' property");
CSimulation2& sim = *pSimulation2;
@ -1448,15 +1458,19 @@ int CMapReader::ParseEntities()
int CMapReader::ParseEnvironment()
{
// parse environment settings from map data
JSContext* cx = pSimulation2->GetScriptInterface().GetContext();
JSAutoRequest rq(cx);
JS::RootedValue tmpMapData(cx, m_MapData.get()); // TODO: Check if this temporary root can be removed after SpiderMonkey 31 upgrade
#define GET_ENVIRONMENT_PROPERTY(val, prop, out)\
if (!pSimulation2->GetScriptInterface().GetProperty(val, #prop, out))\
LOGWARNING(L"CMapReader::ParseEnvironment() failed to get '%hs' property", #prop);
CScriptValRooted envObj;
GET_ENVIRONMENT_PROPERTY(m_MapData.get(), Environment, envObj)
JS::RootedValue envObj(cx);
GET_ENVIRONMENT_PROPERTY(tmpMapData, Environment, &envObj)
if (envObj.undefined())
if (envObj.isUndefined())
{
LOGWARNING(L"CMapReader::ParseEnvironment(): Environment settings not found");
return 0;
@ -1467,35 +1481,35 @@ int CMapReader::ParseEnvironment()
pPostproc->SetPostEffect(L"default");
std::wstring skySet;
GET_ENVIRONMENT_PROPERTY(envObj.get(), SkySet, skySet)
GET_ENVIRONMENT_PROPERTY(envObj, SkySet, skySet)
if (pSkyMan)
pSkyMan->SetSkySet(skySet);
CColor sunColor;
GET_ENVIRONMENT_PROPERTY(envObj.get(), SunColour, sunColor)
GET_ENVIRONMENT_PROPERTY(envObj, SunColour, sunColor)
m_LightEnv.m_SunColor = RGBColor(sunColor.r, sunColor.g, sunColor.b);
GET_ENVIRONMENT_PROPERTY(envObj.get(), SunElevation, m_LightEnv.m_Elevation)
GET_ENVIRONMENT_PROPERTY(envObj.get(), SunRotation, m_LightEnv.m_Rotation)
GET_ENVIRONMENT_PROPERTY(envObj, SunElevation, m_LightEnv.m_Elevation)
GET_ENVIRONMENT_PROPERTY(envObj, SunRotation, m_LightEnv.m_Rotation)
CColor terrainAmbientColor;
GET_ENVIRONMENT_PROPERTY(envObj.get(), TerrainAmbientColour, terrainAmbientColor)
GET_ENVIRONMENT_PROPERTY(envObj, TerrainAmbientColour, terrainAmbientColor)
m_LightEnv.m_TerrainAmbientColor = RGBColor(terrainAmbientColor.r, terrainAmbientColor.g, terrainAmbientColor.b);
CColor unitsAmbientColor;
GET_ENVIRONMENT_PROPERTY(envObj.get(), UnitsAmbientColour, unitsAmbientColor)
GET_ENVIRONMENT_PROPERTY(envObj, UnitsAmbientColour, unitsAmbientColor)
m_LightEnv.m_UnitsAmbientColor = RGBColor(unitsAmbientColor.r, unitsAmbientColor.g, unitsAmbientColor.b);
// Water properties
CScriptValRooted waterObj;
GET_ENVIRONMENT_PROPERTY(envObj.get(), Water, waterObj)
JS::RootedValue waterObj(cx);
GET_ENVIRONMENT_PROPERTY(envObj, Water, &waterObj)
CScriptValRooted waterBodyObj;
GET_ENVIRONMENT_PROPERTY(waterObj.get(), WaterBody, waterBodyObj)
JS::RootedValue waterBodyObj(cx);
GET_ENVIRONMENT_PROPERTY(waterObj, WaterBody, &waterBodyObj)
// Water level - necessary
float waterHeight;
GET_ENVIRONMENT_PROPERTY(waterBodyObj.get(), Height, waterHeight)
GET_ENVIRONMENT_PROPERTY(waterBodyObj, Height, waterHeight)
CmpPtr<ICmpWaterManager> cmpWaterManager(*pSimulation2, SYSTEM_ENTITY);
ENSURE(cmpWaterManager);
@ -1504,39 +1518,39 @@ int CMapReader::ParseEnvironment()
// If we have graphics, get rest of settings
if (pWaterMan)
{
GET_ENVIRONMENT_PROPERTY(waterBodyObj.get(), Type, pWaterMan->m_WaterType)
GET_ENVIRONMENT_PROPERTY(waterBodyObj, Type, pWaterMan->m_WaterType)
if (pWaterMan->m_WaterType == L"default")
pWaterMan->m_WaterType = L"ocean";
GET_ENVIRONMENT_PROPERTY(waterBodyObj.get(), Colour, pWaterMan->m_WaterColor)
GET_ENVIRONMENT_PROPERTY(waterBodyObj.get(), Tint, pWaterMan->m_WaterTint)
GET_ENVIRONMENT_PROPERTY(waterBodyObj.get(), Waviness, pWaterMan->m_Waviness)
GET_ENVIRONMENT_PROPERTY(waterBodyObj.get(), Murkiness, pWaterMan->m_Murkiness)
GET_ENVIRONMENT_PROPERTY(waterBodyObj.get(), WindAngle, pWaterMan->m_WindAngle)
GET_ENVIRONMENT_PROPERTY(waterBodyObj, Colour, pWaterMan->m_WaterColor)
GET_ENVIRONMENT_PROPERTY(waterBodyObj, Tint, pWaterMan->m_WaterTint)
GET_ENVIRONMENT_PROPERTY(waterBodyObj, Waviness, pWaterMan->m_Waviness)
GET_ENVIRONMENT_PROPERTY(waterBodyObj, Murkiness, pWaterMan->m_Murkiness)
GET_ENVIRONMENT_PROPERTY(waterBodyObj, WindAngle, pWaterMan->m_WindAngle)
}
CScriptValRooted fogObject;
GET_ENVIRONMENT_PROPERTY(envObj.get(), Fog, fogObject);
JS::RootedValue fogObject(cx);
GET_ENVIRONMENT_PROPERTY(envObj, Fog, &fogObject);
GET_ENVIRONMENT_PROPERTY(fogObject.get(), FogFactor, m_LightEnv.m_FogFactor);
GET_ENVIRONMENT_PROPERTY(fogObject.get(), FogThickness, m_LightEnv.m_FogMax);
GET_ENVIRONMENT_PROPERTY(fogObject, FogFactor, m_LightEnv.m_FogFactor);
GET_ENVIRONMENT_PROPERTY(fogObject, FogThickness, m_LightEnv.m_FogMax);
CColor fogColor;
GET_ENVIRONMENT_PROPERTY(fogObject.get(), FogColor, fogColor);
GET_ENVIRONMENT_PROPERTY(fogObject, FogColor, fogColor);
m_LightEnv.m_FogColor = RGBColor(fogColor.r, fogColor.g, fogColor.b);
CScriptValRooted postprocObject;
GET_ENVIRONMENT_PROPERTY(envObj.get(), Postproc, postprocObject);
JS::RootedValue postprocObject(cx);
GET_ENVIRONMENT_PROPERTY(envObj, Postproc, &postprocObject);
std::wstring postProcEffect;
GET_ENVIRONMENT_PROPERTY(postprocObject.get(), PostprocEffect, postProcEffect);
GET_ENVIRONMENT_PROPERTY(postprocObject, PostprocEffect, postProcEffect);
if (pPostproc)
pPostproc->SetPostEffect(postProcEffect);
GET_ENVIRONMENT_PROPERTY(postprocObject.get(), Brightness, m_LightEnv.m_Brightness);
GET_ENVIRONMENT_PROPERTY(postprocObject.get(), Contrast, m_LightEnv.m_Contrast);
GET_ENVIRONMENT_PROPERTY(postprocObject.get(), Saturation, m_LightEnv.m_Saturation);
GET_ENVIRONMENT_PROPERTY(postprocObject.get(), Bloom, m_LightEnv.m_Bloom);
GET_ENVIRONMENT_PROPERTY(postprocObject, Brightness, m_LightEnv.m_Brightness);
GET_ENVIRONMENT_PROPERTY(postprocObject, Contrast, m_LightEnv.m_Contrast);
GET_ENVIRONMENT_PROPERTY(postprocObject, Saturation, m_LightEnv.m_Saturation);
GET_ENVIRONMENT_PROPERTY(postprocObject, Bloom, m_LightEnv.m_Bloom);
m_LightEnv.CalculateSunDirection();
@ -1547,6 +1561,8 @@ int CMapReader::ParseEnvironment()
int CMapReader::ParseCamera()
{
JSContext* cx = pSimulation2->GetScriptInterface().GetContext();
JSAutoRequest rq(cx);
// parse camera settings from map data
// defaults if we don't find player starting camera
float declination = DEGTORAD(30.f), rotation = DEGTORAD(-45.f);
@ -1556,17 +1572,18 @@ int CMapReader::ParseCamera()
if (!pSimulation2->GetScriptInterface().GetProperty(val, #prop, out))\
LOGWARNING(L"CMapReader::ParseCamera() failed to get '%hs' property", #prop);
CScriptValRooted cameraObj;
GET_CAMERA_PROPERTY(m_MapData.get(), Camera, cameraObj)
JS::RootedValue tmpMapData(cx, m_MapData.get()); // TODO: Check if this temporary root can be removed after SpiderMonkey 31 upgrade
JS::RootedValue cameraObj(cx);
GET_CAMERA_PROPERTY(tmpMapData, Camera, &cameraObj)
if (!cameraObj.undefined())
if (!cameraObj.isUndefined())
{ // If camera property exists, read values
CFixedVector3D pos;
GET_CAMERA_PROPERTY(cameraObj.get(), Position, pos)
GET_CAMERA_PROPERTY(cameraObj, Position, pos)
translation = pos;
GET_CAMERA_PROPERTY(cameraObj.get(), Rotation, rotation)
GET_CAMERA_PROPERTY(cameraObj.get(), Declination, declination)
GET_CAMERA_PROPERTY(cameraObj, Rotation, rotation)
GET_CAMERA_PROPERTY(cameraObj, Declination, declination)
}
#undef GET_CAMERA_PROPERTY

View File

@ -109,38 +109,41 @@ void CGUIManager::PopPageCB(shared_ptr<ScriptInterface::StructuredClone> args)
PopPage();
shared_ptr<ScriptInterface> scriptInterface = m_PageStack.back().gui->GetScriptInterface();
CScriptVal initDataVal;
JSContext* cx = scriptInterface->GetContext();
JS::RootedValue initDataVal(cx);
if (initDataClone)
initDataVal = scriptInterface->ReadStructuredClone(initDataClone);
initDataVal.set(scriptInterface->ReadStructuredClone(initDataClone));
else
{
LOGERROR(L"Called PopPageCB when initData (which should contain the callback function name) isn't set!");
return;
}
if (!scriptInterface->HasProperty(initDataVal.get(), "callback"))
if (!scriptInterface->HasProperty(initDataVal, "callback"))
{
LOGERROR(L"Called PopPageCB when the callback function name isn't set!");
return;
}
std::string callback;
if (!scriptInterface->GetProperty(initDataVal.get(), "callback", callback))
if (!scriptInterface->GetProperty(initDataVal, "callback", callback))
{
LOGERROR(L"Failed to get the callback property as a string from initData in PopPageCB!");
return;
}
if (!scriptInterface->HasProperty(scriptInterface->GetGlobalObject(), callback.c_str()))
JS::RootedValue global(cx, scriptInterface->GetGlobalObject());
if (!scriptInterface->HasProperty(global, callback.c_str()))
{
LOGERROR(L"The specified callback function %hs does not exist in the page %ls", callback.c_str(), m_PageStack.back().name.c_str());
return;
}
CScriptVal argVal;
JS::RootedValue argVal(cx);
if (args)
argVal = scriptInterface->ReadStructuredClone(args);
if (!scriptInterface->CallFunctionVoid(scriptInterface->GetGlobalObject(), callback.c_str(), argVal))
argVal.set(scriptInterface->ReadStructuredClone(args));
if (!scriptInterface->CallFunctionVoid(global, callback.c_str(), argVal))
{
LOGERROR(L"Failed to call the callback function %hs in the page %ls", callback.c_str(), m_PageStack.back().name.c_str());
return;
@ -149,17 +152,19 @@ void CGUIManager::PopPageCB(shared_ptr<ScriptInterface::StructuredClone> args)
void CGUIManager::DisplayMessageBox(int width, int height, const CStrW& title, const CStrW& message)
{
JSContext* cx = m_ScriptInterface->GetContext();
JSAutoRequest rq(cx);
// Set up scripted init data for the standard message box window
CScriptValRooted data;
m_ScriptInterface->Eval("({})", data);
m_ScriptInterface->SetProperty(data.get(), "width", width, false);
m_ScriptInterface->SetProperty(data.get(), "height", height, false);
m_ScriptInterface->SetProperty(data.get(), "mode", 2, false);
m_ScriptInterface->SetProperty(data.get(), "title", std::wstring(title), false);
m_ScriptInterface->SetProperty(data.get(), "message", std::wstring(message), false);
JS::RootedValue data(cx);
m_ScriptInterface->Eval("({})", &data);
m_ScriptInterface->SetProperty(data, "width", width, false);
m_ScriptInterface->SetProperty(data, "height", height, false);
m_ScriptInterface->SetProperty(data, "mode", 2, false);
m_ScriptInterface->SetProperty(data, "title", std::wstring(title), false);
m_ScriptInterface->SetProperty(data, "message", std::wstring(message), false);
// Display the message box
PushPage(L"page_msgbox.xml", m_ScriptInterface->WriteStructuredClone(data.get()));
PushPage(L"page_msgbox.xml", m_ScriptInterface->WriteStructuredClone(data));
}
void CGUIManager::LoadPage(SGUIPage& page)

View File

@ -471,16 +471,18 @@ void IGUIObject::ScriptEvent(const CStr& Action)
JSAutoRequest rq(cx);
// Set up the 'mouse' parameter
CScriptVal mouse;
m_pGUI->GetScriptInterface()->Eval("({})", mouse);
m_pGUI->GetScriptInterface()->SetProperty(mouse.get(), "x", m_pGUI->m_MousePos.x, false);
m_pGUI->GetScriptInterface()->SetProperty(mouse.get(), "y", m_pGUI->m_MousePos.y, false);
m_pGUI->GetScriptInterface()->SetProperty(mouse.get(), "buttons", m_pGUI->m_MouseButtons, false);
JS::RootedValue mouse(cx);
m_pGUI->GetScriptInterface()->Eval("({})", &mouse);
m_pGUI->GetScriptInterface()->SetProperty(mouse, "x", m_pGUI->m_MousePos.x, false);
m_pGUI->GetScriptInterface()->SetProperty(mouse, "y", m_pGUI->m_MousePos.y, false);
m_pGUI->GetScriptInterface()->SetProperty(mouse, "buttons", m_pGUI->m_MouseButtons, false);
jsval paramData[] = { mouse.get() };
jsval result;
bool ok = JS_CallFunctionValue(cx, GetJSObject(), (*it).second.get(), ARRAY_SIZE(paramData), paramData, &result);
JS::AutoValueVector paramData(cx);
paramData.append(mouse);
JS::RootedObject obj(cx, GetJSObject());
JS::RootedValue handlerVal(cx, (*it).second.get());
JS::RootedValue result(cx);
bool ok = JS_CallFunctionValue(cx, obj, handlerVal, paramData.length(), paramData.begin(), result.address());
if (!ok)
{
// We have no way to propagate the script exception, so just ignore it

View File

@ -246,14 +246,17 @@ float CMiniMap::GetAngle()
void CMiniMap::FireWorldClickEvent(int button, int clicks)
{
JSContext* cx = g_GUI->GetActiveGUI()->GetScriptInterface()->GetContext();
JSAutoRequest rq(cx);
float x, z;
GetMouseWorldCoordinates(x, z);
CScriptValRooted coords;
g_GUI->GetActiveGUI()->GetScriptInterface()->Eval("({})", coords);
g_GUI->GetActiveGUI()->GetScriptInterface()->SetProperty(coords.get(), "x", x, false);
g_GUI->GetActiveGUI()->GetScriptInterface()->SetProperty(coords.get(), "z", z, false);
ScriptEvent("worldclick", coords);
JS::RootedValue coords(cx);
g_GUI->GetActiveGUI()->GetScriptInterface()->Eval("({})", &coords);
g_GUI->GetActiveGUI()->GetScriptInterface()->SetProperty(coords, "x", x, false);
g_GUI->GetActiveGUI()->GetScriptInterface()->SetProperty(coords, "z", z, false);
ScriptEvent("worldclick", CScriptValRooted(cx, coords));
UNUSED2(button);
UNUSED2(clicks);

View File

@ -189,7 +189,6 @@ JSBool JSI_IGUIObject::getProperty(JSContext* cx, JS::HandleObject obj, JS::Hand
vp.setObject(*obj);
try
{
ScriptInterface* pScriptInterface = ScriptInterface::GetScriptInterfaceAndCBData(cx)->pScriptInterface;
#define P(x, y, z) pScriptInterface->SetProperty(vp, #z, area.x.y, false, true)
P(pixel, left, left);
P(pixel, top, top);
@ -626,6 +625,7 @@ void JSI_IGUIObject::init(ScriptInterface& scriptInterface)
JSBool JSI_IGUIObject::toString(JSContext* cx, uint argc, jsval* vp)
{
UNUSED2(argc);
JSAutoRequest rq(cx);
JS::CallReceiver rec = JS::CallReceiverFromVp(vp);
IGUIObject* e = (IGUIObject*)JS_GetInstancePrivate(cx, JS_THIS_OBJECT(cx, vp), &JSI_IGUIObject::JSI_class, NULL);
@ -642,6 +642,7 @@ JSBool JSI_IGUIObject::toString(JSContext* cx, uint argc, jsval* vp)
JSBool JSI_IGUIObject::focus(JSContext* cx, uint argc, jsval* vp)
{
UNUSED2(argc);
JSAutoRequest rq(cx);
JS::CallReceiver rec = JS::CallReceiverFromVp(vp);
IGUIObject* e = (IGUIObject*)JS_GetInstancePrivate(cx, JS_THIS_OBJECT(cx, vp), &JSI_IGUIObject::JSI_class, NULL);
@ -657,6 +658,7 @@ JSBool JSI_IGUIObject::focus(JSContext* cx, uint argc, jsval* vp)
JSBool JSI_IGUIObject::blur(JSContext* cx, uint argc, jsval* vp)
{
UNUSED2(argc);
JSAutoRequest rq(cx);
JS::CallReceiver rec = JS::CallReceiverFromVp(vp);
IGUIObject* e = (IGUIObject*)JS_GetInstancePrivate(cx, JS_THIS_OBJECT(cx, vp), &JSI_IGUIObject::JSI_class, NULL);
@ -672,6 +674,7 @@ JSBool JSI_IGUIObject::blur(JSContext* cx, uint argc, jsval* vp)
JSBool JSI_IGUIObject::getComputedSize(JSContext* cx, uint argc, jsval* vp)
{
UNUSED2(argc);
JSAutoRequest rq(cx);
JS::CallReceiver rec = JS::CallReceiverFromVp(vp);
IGUIObject* e = (IGUIObject*)JS_GetInstancePrivate(cx, JS_THIS_OBJECT(cx, vp), &JSI_IGUIObject::JSI_class, NULL);

View File

@ -219,8 +219,12 @@ void StartGame(ScriptInterface::CxPrivate* pCxPrivate, CScriptVal attribs, int p
g_Game->StartGame(gameAttribs, "");
}
CScriptVal StartSavedGame(ScriptInterface::CxPrivate* pCxPrivate, std::wstring name)
CScriptVal StartSavedGame(ScriptInterface::CxPrivate* UNUSED(pCxPrivate), std::wstring name)
{
CSimulation2* sim = g_Game->GetSimulation2();
JSContext* cx = sim->GetScriptInterface().GetContext();
JSAutoRequest rq(cx);
ENSURE(!g_NetServer);
ENSURE(!g_NetClient);
@ -229,28 +233,25 @@ CScriptVal StartSavedGame(ScriptInterface::CxPrivate* pCxPrivate, std::wstring n
// Load the saved game data from disk
CScriptValRooted metadata;
std::string savedState;
Status err = SavedGames::Load(name, *(pCxPrivate->pScriptInterface), metadata, savedState);
Status err = SavedGames::Load(name, sim->GetScriptInterface(), metadata, savedState);
if (err < 0)
return CScriptVal();
g_Game = new CGame();
// Convert from GUI script context to sim script context
CSimulation2* sim = g_Game->GetSimulation2();
CScriptValRooted gameMetadata (sim->GetScriptInterface().GetContext(),
sim->GetScriptInterface().CloneValueFromOtherContext(*(pCxPrivate->pScriptInterface), metadata.get()));
JS::RootedValue gameMetadata(cx, metadata.get());
CScriptValRooted gameInitAttributes;
sim->GetScriptInterface().GetProperty(gameMetadata.get(), "initAttributes", gameInitAttributes);
JS::RootedValue gameInitAttributes(cx);
sim->GetScriptInterface().GetProperty(gameMetadata, "initAttributes", &gameInitAttributes);
int playerID;
sim->GetScriptInterface().GetProperty(gameMetadata.get(), "player", playerID);
sim->GetScriptInterface().GetProperty(gameMetadata, "player", playerID);
// Start the game
g_Game->SetPlayerID(playerID);
g_Game->StartGame(gameInitAttributes, savedState);
g_Game->StartGame(CScriptValRooted(cx, gameInitAttributes), savedState);
return metadata.get();
return gameMetadata.get();
}
void SaveGame(ScriptInterface::CxPrivate* pCxPrivate, std::wstring filename, std::wstring description, CScriptVal GUIMetadata)

View File

@ -479,22 +479,25 @@ void XmppClient::handleOOB(const glooxwrapper::JID&, const glooxwrapper::OOB&)
*/
CScriptValRooted XmppClient::GUIGetPlayerList(ScriptInterface& scriptInterface)
{
CScriptValRooted playerList;
scriptInterface.Eval("([])", playerList);
JSContext* cx = scriptInterface.GetContext();
JSAutoRequest rq(cx);
JS::RootedValue playerList(cx);
scriptInterface.Eval("([])", &playerList);
// Convert the internal data structure to a Javascript object.
for (std::map<std::string, std::vector<std::string> >::const_iterator it = m_PlayerMap.begin(); it != m_PlayerMap.end(); ++it)
{
CScriptValRooted player;
scriptInterface.Eval("({})", player);
scriptInterface.SetProperty(player.get(), "name", wstring_from_utf8(it->first));
scriptInterface.SetProperty(player.get(), "presence", wstring_from_utf8(it->second[0]));
scriptInterface.SetProperty(player.get(), "rating", wstring_from_utf8(it->second[1]));
scriptInterface.SetProperty(player.get(), "role", wstring_from_utf8(it->second[2]));
scriptInterface.CallFunctionVoid(playerList.get(), "push", player);
JS::RootedValue player(cx);
scriptInterface.Eval("({})", &player);
scriptInterface.SetProperty(player, "name", wstring_from_utf8(it->first));
scriptInterface.SetProperty(player, "presence", wstring_from_utf8(it->second[0]));
scriptInterface.SetProperty(player, "rating", wstring_from_utf8(it->second[1]));
scriptInterface.SetProperty(player, "role", wstring_from_utf8(it->second[2]));
scriptInterface.CallFunctionVoid(playerList, "push", player);
}
return playerList;
return CScriptValRooted(cx, playerList);
}
/**
@ -504,22 +507,25 @@ CScriptValRooted XmppClient::GUIGetPlayerList(ScriptInterface& scriptInterface)
*/
CScriptValRooted XmppClient::GUIGetGameList(ScriptInterface& scriptInterface)
{
CScriptValRooted gameList;
scriptInterface.Eval("([])", gameList);
JSContext* cx = scriptInterface.GetContext();
JSAutoRequest rq(cx);
JS::RootedValue gameList(cx);
scriptInterface.Eval("([])", &gameList);
for(std::vector<const glooxwrapper::Tag*>::const_iterator it = m_GameList.begin(); it != m_GameList.end(); ++it)
{
CScriptValRooted game;
scriptInterface.Eval("({})", game);
JS::RootedValue game(cx);
scriptInterface.Eval("({})", &game);
const char* stats[] = { "name", "ip", "state", "nbp", "tnbp", "players", "mapName", "niceMapName", "mapSize", "mapType", "victoryCondition" };
short stats_length = 11;
for (short i = 0; i < stats_length; i++)
scriptInterface.SetProperty(game.get(), stats[i], wstring_from_utf8((*it)->findAttribute(stats[i]).to_string()));
scriptInterface.SetProperty(game, stats[i], wstring_from_utf8((*it)->findAttribute(stats[i]).to_string()));
scriptInterface.CallFunctionVoid(gameList.get(), "push", game);
scriptInterface.CallFunctionVoid(gameList, "push", game);
}
return gameList;
return CScriptValRooted(cx, gameList);;
}
/**
@ -529,22 +535,25 @@ CScriptValRooted XmppClient::GUIGetGameList(ScriptInterface& scriptInterface)
*/
CScriptValRooted XmppClient::GUIGetBoardList(ScriptInterface& scriptInterface)
{
CScriptValRooted boardList;
scriptInterface.Eval("([])", boardList);
JSContext* cx = scriptInterface.GetContext();
JSAutoRequest rq(cx);
JS::RootedValue boardList(cx);
scriptInterface.Eval("([])", &boardList);
for(std::vector<const glooxwrapper::Tag*>::const_iterator it = m_BoardList.begin(); it != m_BoardList.end(); ++it)
{
CScriptValRooted board;
scriptInterface.Eval("({})", board);
JS::RootedValue board(cx);
scriptInterface.Eval("({})", &board);
const char* attributes[] = { "name", "rank", "rating" };
short attributes_length = 3;
for (short i = 0; i < attributes_length; i++)
scriptInterface.SetProperty(board.get(), attributes[i], wstring_from_utf8((*it)->findAttribute(attributes[i]).to_string()));
scriptInterface.SetProperty(board, attributes[i], wstring_from_utf8((*it)->findAttribute(attributes[i]).to_string()));
scriptInterface.CallFunctionVoid(boardList.get(), "push", board);
scriptInterface.CallFunctionVoid(boardList, "push", board);
}
return boardList;
return CScriptValRooted(cx, boardList);
}
/*****************************************************
@ -560,23 +569,26 @@ CScriptValRooted XmppClient::GuiPollMessage(ScriptInterface& scriptInterface)
return CScriptValRooted();
GUIMessage message = m_GuiMessageQueue.front();
CScriptValRooted messageVal;
JSContext* cx = scriptInterface.GetContext();
JSAutoRequest rq(cx);
scriptInterface.Eval("({})", messageVal);
scriptInterface.SetProperty(messageVal.get(), "type", message.type);
JS::RootedValue messageVal(cx);
scriptInterface.Eval("({})", &messageVal);
scriptInterface.SetProperty(messageVal, "type", message.type);
if (!message.from.empty())
scriptInterface.SetProperty(messageVal.get(), "from", message.from);
scriptInterface.SetProperty(messageVal, "from", message.from);
if (!message.text.empty())
scriptInterface.SetProperty(messageVal.get(), "text", message.text);
scriptInterface.SetProperty(messageVal, "text", message.text);
if (!message.level.empty())
scriptInterface.SetProperty(messageVal.get(), "level", message.level);
scriptInterface.SetProperty(messageVal, "level", message.level);
if (!message.message.empty())
scriptInterface.SetProperty(messageVal.get(), "message", message.message);
scriptInterface.SetProperty(messageVal, "message", message.message);
if (!message.data.empty())
scriptInterface.SetProperty(messageVal.get(), "data", message.data);
scriptInterface.SetProperty(messageVal, "data", message.data);
m_GuiMessageQueue.pop_front();
return messageVal;
return CScriptValRooted(cx, messageVal);
}
/**

View File

@ -203,23 +203,26 @@ ScriptInterface& CNetClient::GetScriptInterface()
void CNetClient::PostPlayerAssignmentsToScript()
{
CScriptValRooted msg;
GetScriptInterface().Eval("({'type':'players', 'hosts':{}})", msg);
JSContext* cx = GetScriptInterface().GetContext();
JSAutoRequest rq(cx);
CScriptValRooted hosts;
GetScriptInterface().GetProperty(msg.get(), "hosts", hosts);
JS::RootedValue msg(cx);
GetScriptInterface().Eval("({'type':'players', 'hosts':{}})", &msg);
JS::RootedValue hosts(cx);
GetScriptInterface().GetProperty(msg, "hosts", &hosts);
for (PlayerAssignmentMap::iterator it = m_PlayerAssignments.begin(); it != m_PlayerAssignments.end(); ++it)
{
CScriptValRooted host;
GetScriptInterface().Eval("({})", host);
GetScriptInterface().SetProperty(host.get(), "name", std::wstring(it->second.m_Name), false);
GetScriptInterface().SetProperty(host.get(), "player", it->second.m_PlayerID, false);
GetScriptInterface().SetProperty(host.get(), "status", it->second.m_Status, false);
GetScriptInterface().SetProperty(hosts.get(), it->first.c_str(), host, false);
JS::RootedValue host(cx);
GetScriptInterface().Eval("({})", &host);
GetScriptInterface().SetProperty(host, "name", std::wstring(it->second.m_Name), false);
GetScriptInterface().SetProperty(host, "player", it->second.m_PlayerID, false);
GetScriptInterface().SetProperty(host, "status", it->second.m_Status, false);
GetScriptInterface().SetProperty(hosts, it->first.c_str(), host, false);
}
PushGuiMessage(msg);
PushGuiMessage(CScriptValRooted(cx, msg));
}
bool CNetClient::SendMessage(const CNetMessage* message)
@ -237,10 +240,13 @@ void CNetClient::HandleConnect()
void CNetClient::HandleDisconnect(u32 reason)
{
CScriptValRooted msg;
GetScriptInterface().Eval("({'type':'netstatus','status':'disconnected'})", msg);
GetScriptInterface().SetProperty(msg.get(), "reason", (int)reason, false);
PushGuiMessage(msg);
JSContext* cx = GetScriptInterface().GetContext();
JSAutoRequest rq(cx);
JS::RootedValue msg(cx);
GetScriptInterface().Eval("({'type':'netstatus','status':'disconnected'})", &msg);
GetScriptInterface().SetProperty(msg, "reason", (int)reason, false);
PushGuiMessage(CScriptValRooted(cx, msg));
SAFE_DELETE(m_Session);
@ -308,6 +314,9 @@ bool CNetClient::HandleMessage(CNetMessage* message)
void CNetClient::LoadFinished()
{
JSContext* cx = GetScriptInterface().GetContext();
JSAutoRequest rq(cx);
if (!m_JoinSyncBuffer.empty())
{
// We're rejoining a game, and just finished loading the initial map,
@ -329,16 +338,16 @@ void CNetClient::LoadFinished()
m_ClientTurnManager->ResetState(turn, turn);
CScriptValRooted msg;
GetScriptInterface().Eval("({'type':'netstatus','status':'join_syncing'})", msg);
PushGuiMessage(msg);
JS::RootedValue msg(cx);
GetScriptInterface().Eval("({'type':'netstatus','status':'join_syncing'})", &msg);
PushGuiMessage(CScriptValRooted(cx, msg));
}
else
{
// Connecting at the start of a game, so we'll wait for other players to finish loading
CScriptValRooted msg;
GetScriptInterface().Eval("({'type':'netstatus','status':'waiting_for_players'})", msg);
PushGuiMessage(msg);
JS::RootedValue msg(cx);
GetScriptInterface().Eval("({'type':'netstatus','status':'waiting_for_players'})", &msg);
PushGuiMessage(CScriptValRooted(cx, msg));
}
CLoadedGameMessage loaded;
@ -352,9 +361,12 @@ bool CNetClient::OnConnect(void* context, CFsmEvent* event)
CNetClient* client = (CNetClient*)context;
CScriptValRooted msg;
client->GetScriptInterface().Eval("({'type':'netstatus','status':'connected'})", msg);
client->PushGuiMessage(msg);
JSContext* cx = client->GetScriptInterface().GetContext();
JSAutoRequest rq(cx);
JS::RootedValue msg(cx);
client->GetScriptInterface().Eval("({'type':'netstatus','status':'connected'})", &msg);
client->PushGuiMessage(CScriptValRooted(cx, msg));
return true;
}
@ -395,6 +407,9 @@ bool CNetClient::OnAuthenticate(void* context, CFsmEvent* event)
CNetClient* client = (CNetClient*)context;
JSContext* cx = client->GetScriptInterface().GetContext();
JSAutoRequest rq(cx);
CAuthenticateResultMessage* message = (CAuthenticateResultMessage*)event->GetParamRef();
LOGMESSAGE(L"Net: Authentication result: host=%u, %ls", message->m_HostID, message->m_Message.c_str());
@ -403,10 +418,10 @@ bool CNetClient::OnAuthenticate(void* context, CFsmEvent* event)
client->m_HostID = message->m_HostID;
CScriptValRooted msg;
client->GetScriptInterface().Eval("({'type':'netstatus','status':'authenticated'})", msg);
client->GetScriptInterface().SetProperty(msg.get(), "rejoining", isRejoining);
client->PushGuiMessage(msg);
JS::RootedValue msg(cx);
client->GetScriptInterface().Eval("({'type':'netstatus','status':'authenticated'})", &msg);
client->GetScriptInterface().SetProperty(msg, "rejoining", isRejoining);
client->PushGuiMessage(CScriptValRooted(cx, msg));
return true;
}
@ -416,14 +431,16 @@ bool CNetClient::OnChat(void* context, CFsmEvent* event)
ENSURE(event->GetType() == (uint)NMT_CHAT);
CNetClient* client = (CNetClient*)context;
JSContext* cx = client->GetScriptInterface().GetContext();
JSAutoRequest rq(cx);
CChatMessage* message = (CChatMessage*)event->GetParamRef();
CScriptValRooted msg;
client->GetScriptInterface().Eval("({'type':'chat'})", msg);
client->GetScriptInterface().SetProperty(msg.get(), "guid", std::string(message->m_GUID), false);
client->GetScriptInterface().SetProperty(msg.get(), "text", std::wstring(message->m_Message), false);
client->PushGuiMessage(msg);
JS::RootedValue msg(cx);
client->GetScriptInterface().Eval("({'type':'chat'})", &msg);
client->GetScriptInterface().SetProperty(msg, "guid", std::string(message->m_GUID), false);
client->GetScriptInterface().SetProperty(msg, "text", std::wstring(message->m_Message), false);
client->PushGuiMessage(CScriptValRooted(cx, msg));
return true;
}
@ -433,14 +450,16 @@ bool CNetClient::OnReady(void* context, CFsmEvent* event)
ENSURE(event->GetType() == (uint)NMT_READY);
CNetClient* client = (CNetClient*)context;
JSContext* cx = client->GetScriptInterface().GetContext();
JSAutoRequest rq(cx);
CReadyMessage* message = (CReadyMessage*)event->GetParamRef();
CScriptValRooted msg;
client->GetScriptInterface().Eval("({'type':'ready'})", msg);
client->GetScriptInterface().SetProperty(msg.get(), "guid", std::string(message->m_GUID), false);
client->GetScriptInterface().SetProperty(msg.get(), "status", int (message->m_Status), false);
client->PushGuiMessage(msg);
JS::RootedValue msg(cx);
client->GetScriptInterface().Eval("({'type':'ready'})", &msg);
client->GetScriptInterface().SetProperty(msg, "guid", std::string(message->m_GUID), false);
client->GetScriptInterface().SetProperty(msg, "status", int (message->m_Status), false);
client->PushGuiMessage(CScriptValRooted(cx, msg));
return true;
}
@ -450,15 +469,17 @@ bool CNetClient::OnGameSetup(void* context, CFsmEvent* event)
ENSURE(event->GetType() == (uint)NMT_GAME_SETUP);
CNetClient* client = (CNetClient*)context;
JSContext* cx = client->GetScriptInterface().GetContext();
JSAutoRequest rq(cx);
CGameSetupMessage* message = (CGameSetupMessage*)event->GetParamRef();
client->m_GameAttributes = message->m_Data;
CScriptValRooted msg;
client->GetScriptInterface().Eval("({'type':'gamesetup'})", msg);
client->GetScriptInterface().SetProperty(msg.get(), "data", message->m_Data, false);
client->PushGuiMessage(msg);
JS::RootedValue msg(cx);
client->GetScriptInterface().Eval("({'type':'gamesetup'})", &msg);
client->GetScriptInterface().SetProperty(msg, "data", message->m_Data, false);
client->PushGuiMessage(CScriptValRooted(cx, msg));
return true;
}
@ -495,6 +516,8 @@ bool CNetClient::OnGameStart(void* context, CFsmEvent* event)
ENSURE(event->GetType() == (uint)NMT_GAME_START);
CNetClient* client = (CNetClient*)context;
JSContext* cx = client->GetScriptInterface().GetContext();
JSAutoRequest rq(cx);
// Find the player assigned to our GUID
int player = -1;
@ -507,9 +530,9 @@ bool CNetClient::OnGameStart(void* context, CFsmEvent* event)
client->m_Game->SetPlayerID(player);
client->m_Game->StartGame(client->m_GameAttributes, "");
CScriptValRooted msg;
client->GetScriptInterface().Eval("({'type':'start'})", msg);
client->PushGuiMessage(msg);
JS::RootedValue msg(cx);
client->GetScriptInterface().Eval("({'type':'start'})", &msg);
client->PushGuiMessage(CScriptValRooted(cx, msg));
return true;
}
@ -549,14 +572,16 @@ bool CNetClient::OnLoadedGame(void* context, CFsmEvent* event)
ENSURE(event->GetType() == (uint)NMT_LOADED_GAME);
CNetClient* client = (CNetClient*)context;
JSContext* cx = client->GetScriptInterface().GetContext();
JSAutoRequest rq(cx);
// All players have loaded the game - start running the turn manager
// so that the game begins
client->m_Game->SetTurnManager(client->m_ClientTurnManager);
CScriptValRooted msg;
client->GetScriptInterface().Eval("({'type':'netstatus','status':'active'})", msg);
client->PushGuiMessage(msg);
JS::RootedValue msg(cx);
client->GetScriptInterface().Eval("({'type':'netstatus','status':'active'})", &msg);
client->PushGuiMessage(CScriptValRooted(cx, msg));
return true;
}

View File

@ -593,6 +593,10 @@ void CConsole::UseHistoryFile(const VfsPath& filename, int max_history_lines)
void CConsole::ProcessBuffer(const wchar_t* szLine)
{
shared_ptr<ScriptInterface> pScriptInterface = g_GUI->GetActiveGUI()->GetScriptInterface();
JSContext* cx = pScriptInterface->GetContext();
JSAutoRequest rq(cx);
if (szLine == NULL) return;
if (wcslen(szLine) <= 0) return;
@ -604,10 +608,10 @@ void CConsole::ProcessBuffer(const wchar_t* szLine)
// Process it as JavaScript
CScriptVal rval;
g_GUI->GetActiveGUI()->GetScriptInterface()->Eval(szLine, rval);
if (!rval.undefined())
InsertMessageRaw(g_GUI->GetActiveGUI()->GetScriptInterface()->ToString(rval.get()));
JS::RootedValue rval(cx);
pScriptInterface->Eval(szLine, &rval);
if (!rval.isUndefined())
InsertMessageRaw(pScriptInterface->ToString(rval));
}
void CConsole::LoadHistory()

View File

@ -120,18 +120,22 @@ void CGame::SetTurnManager(CNetTurnManager* turnManager)
* Makes calls to initialize the game view, world, and simulation objects.
* Calls are made to facilitate progress reporting of the initialization.
**/
void CGame::RegisterInit(const CScriptValRooted& attribs, const std::string& savedState)
void CGame::RegisterInit(const JS::HandleValue attribs, const std::string& savedState)
{
JSContext* cx = m_Simulation2->GetScriptInterface().GetContext();
JSAutoRequest rq(cx);
m_InitialSavedState = savedState;
m_IsSavedGame = !savedState.empty();
m_Simulation2->SetInitAttributes(attribs);
CScriptValRooted tmpAttribs(cx, attribs);
m_Simulation2->SetInitAttributes(tmpAttribs);
std::string mapType;
m_Simulation2->GetScriptInterface().GetProperty(attribs.get(), "mapType", mapType);
m_Simulation2->GetScriptInterface().GetProperty(attribs, "mapType", mapType);
float speed;
if (m_Simulation2->GetScriptInterface().HasProperty(attribs.get(), "gameSpeed") && m_Simulation2->GetScriptInterface().GetProperty(attribs.get(), "gameSpeed", speed))
if (m_Simulation2->GetScriptInterface().HasProperty(attribs, "gameSpeed") && m_Simulation2->GetScriptInterface().GetProperty(attribs, "gameSpeed", speed))
SetSimRate(speed);
LDR_BeginRegistering();
@ -152,18 +156,18 @@ void CGame::RegisterInit(const CScriptValRooted& attribs, const std::string& sav
std::wstring scriptFile;
CScriptValRooted settings;
m_Simulation2->GetScriptInterface().GetProperty(attribs.get(), "script", scriptFile);
m_Simulation2->GetScriptInterface().GetProperty(attribs.get(), "settings", settings);
m_Simulation2->GetScriptInterface().GetProperty(attribs, "script", scriptFile);
m_Simulation2->GetScriptInterface().GetProperty(attribs, "settings", settings);
m_World->RegisterInitRMS(scriptFile, settings, m_PlayerID);
}
else
{
std::wstring mapFile;
m_Simulation2->GetScriptInterface().GetProperty(attribs.get(), "map", mapFile);
m_Simulation2->GetScriptInterface().GetProperty(attribs, "map", mapFile);
CScriptValRooted settings;
if (mapType == "skirmish")
m_Simulation2->GetScriptInterface().GetProperty(attribs.get(), "settings", settings);
m_Simulation2->GetScriptInterface().GetProperty(attribs, "settings", settings);
m_World->RegisterInit(mapFile, settings, m_PlayerID);
}
@ -203,6 +207,9 @@ int CGame::LoadInitialState()
**/
PSRETURN CGame::ReallyStartGame()
{
JSContext* cx = m_Simulation2->GetScriptInterface().GetContext();
JSAutoRequest rq(cx);
// Call the script function InitGame only for new games, not saved games
if (!m_IsSavedGame)
{
@ -216,9 +223,10 @@ PSRETURN CGame::ReallyStartGame()
m_Simulation2->ReplaceSkirmishGlobals();
m_Simulation2->FlushDestroyedEntities();
}
CScriptVal settings;
m_Simulation2->GetScriptInterface().GetProperty(m_Simulation2->GetInitAttributes().get(), "settings", settings);
m_Simulation2->InitGame(settings);
JS::RootedValue settings(cx);
JS::RootedValue tmpInitAttributes(cx, m_Simulation2->GetInitAttributes().get());
m_Simulation2->GetScriptInterface().GetProperty(tmpInitAttributes, "settings", &settings);
m_Simulation2->InitGame(CScriptVal(settings));
}
// We need to do an initial Interpolate call to set up all the models etc,
@ -234,10 +242,11 @@ PSRETURN CGame::ReallyStartGame()
Render();
// Call the reallyStartGame GUI function, but only if it exists
JS::RootedValue global(cx, g_GUI->GetActiveGUI()->GetGlobalObject());
if (g_GUI && g_GUI->HasPages())
{
if (g_GUI->GetActiveGUI()->GetScriptInterface()->HasProperty(g_GUI->GetActiveGUI()->GetGlobalObject(), "reallyStartGame"))
g_GUI->GetActiveGUI()->GetScriptInterface()->CallFunctionVoid(g_GUI->GetActiveGUI()->GetGlobalObject(), "reallyStartGame");
if (g_GUI->GetActiveGUI()->GetScriptInterface()->HasProperty(global, "reallyStartGame"))
g_GUI->GetActiveGUI()->GetScriptInterface()->CallFunctionVoid(global, "reallyStartGame");
}
if (g_NetClient)
@ -267,9 +276,13 @@ void CGame::SetPlayerID(int playerID)
m_TurnManager->SetPlayerID(m_PlayerID);
}
void CGame::StartGame(const CScriptValRooted& attribs, const std::string& savedState)
void CGame::StartGame(const CScriptValRooted& attribs1, const std::string& savedState)
{
m_ReplayLogger->StartGame(attribs);
JSContext* cx = m_Simulation2->GetScriptInterface().GetContext();
JSAutoRequest rq(cx);
JS::RootedValue attribs(cx, attribs1.get()); // TODO: Get Handle parameter directly with SpiderMonkey 31
m_ReplayLogger->StartGame(attribs1);
RegisterInit(attribs, savedState);
}

View File

@ -163,7 +163,7 @@ public:
{ return *m_ReplayLogger; }
private:
void RegisterInit(const CScriptValRooted& attribs, const std::string& savedState);
void RegisterInit(const JS::HandleValue attribs, const std::string& savedState);
IReplayLogger* m_ReplayLogger;
std::vector<CColor> m_PlayerColours;

View File

@ -1020,12 +1020,14 @@ void InitGraphics(const CmdLineArgs& args, int flags)
{
const bool setup_gui = ((flags & INIT_NO_GUI) == 0);
// We only want to display the splash screen at startup
CScriptValRooted data;
shared_ptr<ScriptInterface> scriptInterface = g_GUI->GetScriptInterface();
JSContext* cx = scriptInterface->GetContext();
JSAutoRequest rq(cx);
JS::RootedValue data(cx);
if (g_GUI)
{
shared_ptr<ScriptInterface> scriptInterface = g_GUI->GetScriptInterface();
scriptInterface->Eval("({})", data);
scriptInterface->SetProperty(data.get(), "isStartup", true);
scriptInterface->Eval("({})", &data);
scriptInterface->SetProperty(data, "isStartup", true);
}
InitPs(setup_gui, L"page_pregame.xml", g_GUI->GetScriptInterface().get(), data.get());
}
@ -1142,13 +1144,15 @@ bool Autostart(const CmdLineArgs& args)
g_Game = new CGame();
ScriptInterface& scriptInterface = g_Game->GetSimulation2()->GetScriptInterface();
JSContext* cx = scriptInterface.GetContext();
JSAutoRequest rq(cx);
CScriptValRooted attrs;
scriptInterface.Eval("({})", attrs);
CScriptVal settings;
scriptInterface.Eval("({})", settings);
CScriptVal playerData;
scriptInterface.Eval("([])", playerData);
JS::RootedValue attrs(cx);
scriptInterface.Eval("({})", &attrs);
JS::RootedValue settings(cx);
scriptInterface.Eval("({})", &settings);
JS::RootedValue playerData(cx);
scriptInterface.Eval("([])", &playerData);
// The directory in front of the actual map name indicates which type
// of map is being loaded. Drawback of this approach is the association
@ -1180,13 +1184,13 @@ bool Autostart(const CmdLineArgs& args)
// Random map definition will be loaded from JSON file, so we need to parse it
std::wstring scriptPath = L"maps/" + autoStartName.FromUTF8() + L".json";
CScriptValRooted scriptData = scriptInterface.ReadJSONFile(scriptPath);
if (!scriptData.undefined() && scriptInterface.GetProperty(scriptData.get(), "settings", settings))
JS::RootedValue scriptData(cx, scriptInterface.ReadJSONFile(scriptPath).get());
if (!scriptData.isUndefined() && scriptInterface.GetProperty(scriptData, "settings", &settings))
{
// JSON loaded ok - copy script name over to game attributes
std::wstring scriptFile;
scriptInterface.GetProperty(settings.get(), "Script", scriptFile);
scriptInterface.SetProperty(attrs.get(), "script", scriptFile); // RMS filename
scriptInterface.GetProperty(settings, "Script", scriptFile);
scriptInterface.SetProperty(attrs, "script", scriptFile); // RMS filename
}
else
{
@ -1203,8 +1207,8 @@ bool Autostart(const CmdLineArgs& args)
mapSize = size.ToUInt();
}
scriptInterface.SetProperty(settings.get(), "Seed", seed); // Random seed
scriptInterface.SetProperty(settings.get(), "Size", mapSize); // Random map size (in patches)
scriptInterface.SetProperty(settings, "Seed", seed); // Random seed
scriptInterface.SetProperty(settings, "Size", mapSize); // Random map size (in patches)
// Get optional number of players (default 2)
size_t numPlayers = 2;
@ -1217,13 +1221,13 @@ bool Autostart(const CmdLineArgs& args)
// Set up player data
for (size_t i = 0; i < numPlayers; ++i)
{
CScriptVal player;
scriptInterface.Eval("({})", player);
JS::RootedValue player(cx);
scriptInterface.Eval("({})", &player);
// We could load player_defaults.json here, but that would complicate the logic
// even more and autostart is only intended for developers anyway
scriptInterface.SetProperty(player.get(), "Civ", std::string("athen"));
scriptInterface.SetPropertyInt(playerData.get(), i, player);
scriptInterface.SetProperty(player, "Civ", std::string("athen"));
scriptInterface.SetPropertyInt(playerData, i, player);
}
mapType = "random";
}
@ -1255,7 +1259,7 @@ bool Autostart(const CmdLineArgs& args)
// ...and initialize the playerData array being edited by
// autostart-civ et.al. with the real map data, so sensible values
// are always present:
scriptInterface.GetProperty(settings.get(), "PlayerData", playerData);
scriptInterface.GetProperty(settings, "PlayerData", &playerData);
mapType = "skirmish";
}
if (mapType.empty())
@ -1263,10 +1267,10 @@ bool Autostart(const CmdLineArgs& args)
LOGERROR(L"Unrecognized map type '%ls' detected", mapType.c_str());
throw PSERROR_Game_World_MapLoadFailed("Unrecognized map type.\nConsult GameSetup.cpp for the currently supported types.");
}
scriptInterface.SetProperty(attrs.get(), "mapType", mapType);
scriptInterface.SetProperty(attrs.get(), "map", std::string("maps/" + autoStartName));
scriptInterface.SetProperty(attrs, "mapType", mapType);
scriptInterface.SetProperty(attrs, "map", std::string("maps/" + autoStartName));
scriptInterface.SetProperty(settings.get(), "mapType", mapType);
scriptInterface.SetProperty(settings, "mapType", mapType);
// Set player data for AIs
// attrs.settings = { PlayerData: [ { AI: ... }, ... ] }:
@ -1276,18 +1280,18 @@ bool Autostart(const CmdLineArgs& args)
for (size_t i = 0; i < aiArgs.size(); ++i)
{
// Instead of overwriting existing player data, modify the array
CScriptVal player;
if (!scriptInterface.GetPropertyInt(playerData.get(), i, player) || player.undefined())
JS::RootedValue player(cx);
if (!scriptInterface.GetPropertyInt(playerData, i, &player) || player.isUndefined())
{
scriptInterface.Eval("({})", player);
scriptInterface.Eval("({})", &player);
}
int playerID = aiArgs[i].BeforeFirst(":").ToInt();
CStr name = aiArgs[i].AfterFirst(":");
scriptInterface.SetProperty(player.get(), "AI", std::string(name));
scriptInterface.SetProperty(player.get(), "AIDiff", 2);
scriptInterface.SetPropertyInt(playerData.get(), playerID-1, player);
scriptInterface.SetProperty(player, "AI", std::string(name));
scriptInterface.SetProperty(player, "AIDiff", 2);
scriptInterface.SetPropertyInt(playerData, playerID-1, player);
}
}
// Set AI difficulty
@ -1297,17 +1301,17 @@ bool Autostart(const CmdLineArgs& args)
for (size_t i = 0; i < civArgs.size(); ++i)
{
// Instead of overwriting existing player data, modify the array
CScriptVal player;
if (!scriptInterface.GetPropertyInt(playerData.get(), i, player) || player.undefined())
JS::RootedValue player(cx);
if (!scriptInterface.GetPropertyInt(playerData, i, &player) || player.isUndefined())
{
scriptInterface.Eval("({})", player);
scriptInterface.Eval("({})", &player);
}
int playerID = civArgs[i].BeforeFirst(":").ToInt();
int difficulty = civArgs[i].AfterFirst(":").ToInt();
scriptInterface.SetProperty(player.get(), "AIDiff", difficulty);
scriptInterface.SetPropertyInt(playerData.get(), playerID-1, player);
scriptInterface.SetProperty(player, "AIDiff", difficulty);
scriptInterface.SetPropertyInt(playerData, playerID-1, player);
}
}
// Set player data for Civs
@ -1317,29 +1321,29 @@ bool Autostart(const CmdLineArgs& args)
for (size_t i = 0; i < civArgs.size(); ++i)
{
// Instead of overwriting existing player data, modify the array
CScriptVal player;
if (!scriptInterface.GetPropertyInt(playerData.get(), i, player) || player.undefined())
JS::RootedValue player(cx);
if (!scriptInterface.GetPropertyInt(playerData, i, &player) || player.isUndefined())
{
scriptInterface.Eval("({})", player);
scriptInterface.Eval("({})", &player);
}
int playerID = civArgs[i].BeforeFirst(":").ToInt();
CStr name = civArgs[i].AfterFirst(":");
scriptInterface.SetProperty(player.get(), "Civ", std::string(name));
scriptInterface.SetPropertyInt(playerData.get(), playerID-1, player);
scriptInterface.SetProperty(player, "Civ", std::string(name));
scriptInterface.SetPropertyInt(playerData, playerID-1, player);
}
}
// Add player data to map settings
scriptInterface.SetProperty(settings.get(), "PlayerData", playerData);
scriptInterface.SetProperty(settings, "PlayerData", playerData);
// Add map settings to game attributes
scriptInterface.SetProperty(attrs.get(), "settings", settings);
scriptInterface.SetProperty(attrs, "settings", settings);
CScriptVal mpInitData;
scriptInterface.Eval("({isNetworked:true, playerAssignments:{}})", mpInitData);
scriptInterface.SetProperty(mpInitData.get(), "attribs", attrs);
JS::RootedValue mpInitData(cx);
scriptInterface.Eval("({isNetworked:true, playerAssignments:{}})", &mpInitData);
scriptInterface.SetProperty(mpInitData, "attribs", attrs);
// Get optional playername
CStrW userName = L"anonymous";
@ -1388,7 +1392,7 @@ bool Autostart(const CmdLineArgs& args)
else
{
g_Game->SetPlayerID(1);
g_Game->StartGame(attrs, "");
g_Game->StartGame(CScriptValRooted(cx, attrs), "");
LDR_NonprogressiveLoad();
@ -1403,6 +1407,11 @@ bool Autostart(const CmdLineArgs& args)
void CancelLoad(const CStrW& message)
{
shared_ptr<ScriptInterface> pScriptInterface = g_GUI->GetActiveGUI()->GetScriptInterface();
JSContext* cx = pScriptInterface->GetContext();
JSAutoRequest rq(cx);
JS::RootedValue global(cx, pScriptInterface->GetGlobalObject());
// Cancel loader
LDR_Cancel();
@ -1410,8 +1419,8 @@ void CancelLoad(const CStrW& message)
// So all GUI pages that load games should include this script
if (g_GUI && g_GUI->HasPages())
{
if (g_GUI->GetActiveGUI()->GetScriptInterface()->HasProperty(g_GUI->GetActiveGUI()->GetGlobalObject(), "cancelOnError" ))
g_GUI->GetActiveGUI()->GetScriptInterface()->CallFunctionVoid(g_GUI->GetActiveGUI()->GetGlobalObject(), "cancelOnError", message);
if (pScriptInterface->HasProperty(global, "cancelOnError" ))
pScriptInterface->CallFunctionVoid(global, "cancelOnError", message);
}
}

View File

@ -66,50 +66,56 @@
#endif
static void ReportGLLimits(ScriptInterface& scriptInterface, CScriptValRooted settings);
static void ReportGLLimits(ScriptInterface& scriptInterface, JS::HandleValue settings);
#if ARCH_X86_X64
CScriptVal ConvertCaches(ScriptInterface& scriptInterface, x86_x64::IdxCache idxCache)
{
CScriptVal ret;
scriptInterface.Eval("[]", ret);
JSContext* cx = scriptInterface.GetContext();
JSAutoRequest rq(cx);
JS::RootedValue ret(cx);
scriptInterface.Eval("[]", &ret);
for (size_t idxLevel = 0; idxLevel < x86_x64::Cache::maxLevels; ++idxLevel)
{
const x86_x64::Cache* pcache = x86_x64::Caches(idxCache+idxLevel);
if (pcache->type == x86_x64::Cache::kNull || pcache->numEntries == 0)
continue;
CScriptVal cache;
scriptInterface.Eval("({})", cache);
scriptInterface.SetProperty(cache.get(), "type", (u32)pcache->type);
scriptInterface.SetProperty(cache.get(), "level", (u32)pcache->level);
scriptInterface.SetProperty(cache.get(), "associativity", (u32)pcache->associativity);
scriptInterface.SetProperty(cache.get(), "linesize", (u32)pcache->entrySize);
scriptInterface.SetProperty(cache.get(), "sharedby", (u32)pcache->sharedBy);
scriptInterface.SetProperty(cache.get(), "totalsize", (u32)pcache->TotalSize());
scriptInterface.SetPropertyInt(ret.get(), idxLevel, cache);
JS::RootedValue cache(cx);
scriptInterface.Eval("({})", &cache);
scriptInterface.SetProperty(cache, "type", (u32)pcache->type);
scriptInterface.SetProperty(cache, "level", (u32)pcache->level);
scriptInterface.SetProperty(cache, "associativity", (u32)pcache->associativity);
scriptInterface.SetProperty(cache, "linesize", (u32)pcache->entrySize);
scriptInterface.SetProperty(cache, "sharedby", (u32)pcache->sharedBy);
scriptInterface.SetProperty(cache, "totalsize", (u32)pcache->TotalSize());
scriptInterface.SetPropertyInt(ret, idxLevel, cache);
}
return ret;
return ret.get();
}
CScriptVal ConvertTLBs(ScriptInterface& scriptInterface)
{
CScriptVal ret;
scriptInterface.Eval("[]", ret);
JSContext* cx = scriptInterface.GetContext();
JSAutoRequest rq(cx);
JS::RootedValue ret(cx);
scriptInterface.Eval("[]", &ret);
for(size_t i = 0; ; i++)
{
const x86_x64::Cache* ptlb = x86_x64::Caches(x86_x64::TLB+i);
if (!ptlb)
break;
CScriptVal tlb;
scriptInterface.Eval("({})", tlb);
scriptInterface.SetProperty(tlb.get(), "type", (u32)ptlb->type);
scriptInterface.SetProperty(tlb.get(), "level", (u32)ptlb->level);
scriptInterface.SetProperty(tlb.get(), "associativity", (u32)ptlb->associativity);
scriptInterface.SetProperty(tlb.get(), "pagesize", (u32)ptlb->entrySize);
scriptInterface.SetProperty(tlb.get(), "entries", (u32)ptlb->numEntries);
scriptInterface.SetPropertyInt(ret.get(), i, tlb);
JS::RootedValue tlb(cx);
scriptInterface.Eval("({})", &tlb);
scriptInterface.SetProperty(tlb, "type", (u32)ptlb->type);
scriptInterface.SetProperty(tlb, "level", (u32)ptlb->level);
scriptInterface.SetProperty(tlb, "associativity", (u32)ptlb->associativity);
scriptInterface.SetProperty(tlb, "pagesize", (u32)ptlb->entrySize);
scriptInterface.SetProperty(tlb, "entries", (u32)ptlb->numEntries);
scriptInterface.SetPropertyInt(ret, i, tlb);
}
return ret;
return ret.get();
}
#endif
@ -180,6 +186,8 @@ void RunHardwareDetection()
TIMER(L"RunHardwareDetection");
ScriptInterface scriptInterface("Engine", "HWDetect", g_ScriptRuntime);
JSContext* cx = scriptInterface.GetContext();
JSAutoRequest rq(cx);
scriptInterface.RegisterFunction<void, bool, &SetDisableAudio>("SetDisableAudio");
scriptInterface.RegisterFunction<void, bool, &SetDisableS3TC>("SetDisableS3TC");
@ -206,58 +214,58 @@ void RunHardwareDetection()
// (We'll use this same data for the opt-in online reporting system, so it
// includes some fields that aren't directly useful for the hwdetect script)
CScriptValRooted settings;
scriptInterface.Eval("({})", settings);
JS::RootedValue settings(cx);
scriptInterface.Eval("({})", &settings);
scriptInterface.SetProperty(settings.get(), "os_unix", OS_UNIX);
scriptInterface.SetProperty(settings.get(), "os_bsd", OS_BSD);
scriptInterface.SetProperty(settings.get(), "os_linux", OS_LINUX);
scriptInterface.SetProperty(settings.get(), "os_android", OS_ANDROID);
scriptInterface.SetProperty(settings.get(), "os_macosx", OS_MACOSX);
scriptInterface.SetProperty(settings.get(), "os_win", OS_WIN);
scriptInterface.SetProperty(settings, "os_unix", OS_UNIX);
scriptInterface.SetProperty(settings, "os_bsd", OS_BSD);
scriptInterface.SetProperty(settings, "os_linux", OS_LINUX);
scriptInterface.SetProperty(settings, "os_android", OS_ANDROID);
scriptInterface.SetProperty(settings, "os_macosx", OS_MACOSX);
scriptInterface.SetProperty(settings, "os_win", OS_WIN);
scriptInterface.SetProperty(settings.get(), "arch_ia32", ARCH_IA32);
scriptInterface.SetProperty(settings.get(), "arch_amd64", ARCH_AMD64);
scriptInterface.SetProperty(settings.get(), "arch_arm", ARCH_ARM);
scriptInterface.SetProperty(settings, "arch_ia32", ARCH_IA32);
scriptInterface.SetProperty(settings, "arch_amd64", ARCH_AMD64);
scriptInterface.SetProperty(settings, "arch_arm", ARCH_ARM);
#ifdef NDEBUG
scriptInterface.SetProperty(settings.get(), "build_debug", 0);
scriptInterface.SetProperty(settings, "build_debug", 0);
#else
scriptInterface.SetProperty(settings.get(), "build_debug", 1);
scriptInterface.SetProperty(settings, "build_debug", 1);
#endif
scriptInterface.SetProperty(settings.get(), "build_opengles", CONFIG2_GLES);
scriptInterface.SetProperty(settings, "build_opengles", CONFIG2_GLES);
scriptInterface.SetProperty(settings.get(), "build_datetime", std::string(__DATE__ " " __TIME__));
scriptInterface.SetProperty(settings.get(), "build_revision", std::wstring(svn_revision));
scriptInterface.SetProperty(settings, "build_datetime", std::string(__DATE__ " " __TIME__));
scriptInterface.SetProperty(settings, "build_revision", std::wstring(svn_revision));
scriptInterface.SetProperty(settings.get(), "build_msc", (int)MSC_VERSION);
scriptInterface.SetProperty(settings.get(), "build_icc", (int)ICC_VERSION);
scriptInterface.SetProperty(settings.get(), "build_gcc", (int)GCC_VERSION);
scriptInterface.SetProperty(settings.get(), "build_clang", (int)CLANG_VERSION);
scriptInterface.SetProperty(settings, "build_msc", (int)MSC_VERSION);
scriptInterface.SetProperty(settings, "build_icc", (int)ICC_VERSION);
scriptInterface.SetProperty(settings, "build_gcc", (int)GCC_VERSION);
scriptInterface.SetProperty(settings, "build_clang", (int)CLANG_VERSION);
scriptInterface.SetProperty(settings.get(), "gfx_card", gfx::CardName());
scriptInterface.SetProperty(settings.get(), "gfx_drv_ver", gfx::DriverInfo());
scriptInterface.SetProperty(settings, "gfx_card", gfx::CardName());
scriptInterface.SetProperty(settings, "gfx_drv_ver", gfx::DriverInfo());
scriptInterface.SetProperty(settings.get(), "snd_card", std::wstring(snd_card));
scriptInterface.SetProperty(settings.get(), "snd_drv_ver", std::wstring(snd_drv_ver));
scriptInterface.SetProperty(settings, "snd_card", std::wstring(snd_card));
scriptInterface.SetProperty(settings, "snd_drv_ver", std::wstring(snd_drv_ver));
ReportGLLimits(scriptInterface, settings);
scriptInterface.SetProperty(settings.get(), "video_xres", g_VideoMode.GetXRes());
scriptInterface.SetProperty(settings.get(), "video_yres", g_VideoMode.GetYRes());
scriptInterface.SetProperty(settings.get(), "video_bpp", g_VideoMode.GetBPP());
scriptInterface.SetProperty(settings, "video_xres", g_VideoMode.GetXRes());
scriptInterface.SetProperty(settings, "video_yres", g_VideoMode.GetYRes());
scriptInterface.SetProperty(settings, "video_bpp", g_VideoMode.GetBPP());
scriptInterface.SetProperty(settings.get(), "video_desktop_xres", g_VideoMode.GetDesktopXRes());
scriptInterface.SetProperty(settings.get(), "video_desktop_yres", g_VideoMode.GetDesktopYRes());
scriptInterface.SetProperty(settings.get(), "video_desktop_bpp", g_VideoMode.GetDesktopBPP());
scriptInterface.SetProperty(settings.get(), "video_desktop_freq", g_VideoMode.GetDesktopFreq());
scriptInterface.SetProperty(settings, "video_desktop_xres", g_VideoMode.GetDesktopXRes());
scriptInterface.SetProperty(settings, "video_desktop_yres", g_VideoMode.GetDesktopYRes());
scriptInterface.SetProperty(settings, "video_desktop_bpp", g_VideoMode.GetDesktopBPP());
scriptInterface.SetProperty(settings, "video_desktop_freq", g_VideoMode.GetDesktopFreq());
struct utsname un;
uname(&un);
scriptInterface.SetProperty(settings.get(), "uname_sysname", std::string(un.sysname));
scriptInterface.SetProperty(settings.get(), "uname_release", std::string(un.release));
scriptInterface.SetProperty(settings.get(), "uname_version", std::string(un.version));
scriptInterface.SetProperty(settings.get(), "uname_machine", std::string(un.machine));
scriptInterface.SetProperty(settings, "uname_sysname", std::string(un.sysname));
scriptInterface.SetProperty(settings, "uname_release", std::string(un.release));
scriptInterface.SetProperty(settings, "uname_version", std::string(un.version));
scriptInterface.SetProperty(settings, "uname_machine", std::string(un.machine));
#if OS_LINUX
{
@ -265,61 +273,61 @@ void RunHardwareDetection()
if (ifs.good())
{
std::string str((std::istreambuf_iterator<char>(ifs)), std::istreambuf_iterator<char>());
scriptInterface.SetProperty(settings.get(), "linux_release", str);
scriptInterface.SetProperty(settings, "linux_release", str);
}
}
#endif
scriptInterface.SetProperty(settings.get(), "cpu_identifier", std::string(cpu_IdentifierString()));
scriptInterface.SetProperty(settings.get(), "cpu_frequency", os_cpu_ClockFrequency());
scriptInterface.SetProperty(settings.get(), "cpu_pagesize", (u32)os_cpu_PageSize());
scriptInterface.SetProperty(settings.get(), "cpu_largepagesize", (u32)os_cpu_LargePageSize());
scriptInterface.SetProperty(settings.get(), "cpu_numprocs", (u32)os_cpu_NumProcessors());
scriptInterface.SetProperty(settings, "cpu_identifier", std::string(cpu_IdentifierString()));
scriptInterface.SetProperty(settings, "cpu_frequency", os_cpu_ClockFrequency());
scriptInterface.SetProperty(settings, "cpu_pagesize", (u32)os_cpu_PageSize());
scriptInterface.SetProperty(settings, "cpu_largepagesize", (u32)os_cpu_LargePageSize());
scriptInterface.SetProperty(settings, "cpu_numprocs", (u32)os_cpu_NumProcessors());
#if ARCH_X86_X64
scriptInterface.SetProperty(settings.get(), "cpu_numpackages", (u32)topology::NumPackages());
scriptInterface.SetProperty(settings.get(), "cpu_coresperpackage", (u32)topology::CoresPerPackage());
scriptInterface.SetProperty(settings.get(), "cpu_logicalpercore", (u32)topology::LogicalPerCore());
scriptInterface.SetProperty(settings.get(), "cpu_numcaches", (u32)topology::NumCaches());
scriptInterface.SetProperty(settings, "cpu_numpackages", (u32)topology::NumPackages());
scriptInterface.SetProperty(settings, "cpu_coresperpackage", (u32)topology::CoresPerPackage());
scriptInterface.SetProperty(settings, "cpu_logicalpercore", (u32)topology::LogicalPerCore());
scriptInterface.SetProperty(settings, "cpu_numcaches", (u32)topology::NumCaches());
#endif
scriptInterface.SetProperty(settings.get(), "numa_numnodes", (u32)numa_NumNodes());
scriptInterface.SetProperty(settings.get(), "numa_factor", numa_Factor());
scriptInterface.SetProperty(settings.get(), "numa_interleaved", numa_IsMemoryInterleaved());
scriptInterface.SetProperty(settings, "numa_numnodes", (u32)numa_NumNodes());
scriptInterface.SetProperty(settings, "numa_factor", numa_Factor());
scriptInterface.SetProperty(settings, "numa_interleaved", numa_IsMemoryInterleaved());
scriptInterface.SetProperty(settings.get(), "ram_total", (u32)os_cpu_MemorySize());
scriptInterface.SetProperty(settings.get(), "ram_total_os", (u32)os_cpu_QueryMemorySize());
scriptInterface.SetProperty(settings.get(), "ram_free", (u32)os_cpu_MemoryAvailable());
scriptInterface.SetProperty(settings, "ram_total", (u32)os_cpu_MemorySize());
scriptInterface.SetProperty(settings, "ram_total_os", (u32)os_cpu_QueryMemorySize());
scriptInterface.SetProperty(settings, "ram_free", (u32)os_cpu_MemoryAvailable());
#if ARCH_X86_X64
scriptInterface.SetProperty(settings.get(), "x86_frequency", x86_x64::ClockFrequency());
scriptInterface.SetProperty(settings, "x86_frequency", x86_x64::ClockFrequency());
scriptInterface.SetProperty(settings.get(), "x86_vendor", (u32)x86_x64::Vendor());
scriptInterface.SetProperty(settings.get(), "x86_model", (u32)x86_x64::Model());
scriptInterface.SetProperty(settings.get(), "x86_family", (u32)x86_x64::Family());
scriptInterface.SetProperty(settings, "x86_vendor", (u32)x86_x64::Vendor());
scriptInterface.SetProperty(settings, "x86_model", (u32)x86_x64::Model());
scriptInterface.SetProperty(settings, "x86_family", (u32)x86_x64::Family());
u32 caps0, caps1, caps2, caps3;
x86_x64::GetCapBits(&caps0, &caps1, &caps2, &caps3);
scriptInterface.SetProperty(settings.get(), "x86_caps[0]", caps0);
scriptInterface.SetProperty(settings.get(), "x86_caps[1]", caps1);
scriptInterface.SetProperty(settings.get(), "x86_caps[2]", caps2);
scriptInterface.SetProperty(settings.get(), "x86_caps[3]", caps3);
scriptInterface.SetProperty(settings, "x86_caps[0]", caps0);
scriptInterface.SetProperty(settings, "x86_caps[1]", caps1);
scriptInterface.SetProperty(settings, "x86_caps[2]", caps2);
scriptInterface.SetProperty(settings, "x86_caps[3]", caps3);
scriptInterface.SetProperty(settings.get(), "x86_icaches", ConvertCaches(scriptInterface, x86_x64::L1I));
scriptInterface.SetProperty(settings.get(), "x86_dcaches", ConvertCaches(scriptInterface, x86_x64::L1D));
scriptInterface.SetProperty(settings.get(), "x86_tlbs", ConvertTLBs(scriptInterface));
scriptInterface.SetProperty(settings, "x86_icaches", ConvertCaches(scriptInterface, x86_x64::L1I));
scriptInterface.SetProperty(settings, "x86_dcaches", ConvertCaches(scriptInterface, x86_x64::L1D));
scriptInterface.SetProperty(settings, "x86_tlbs", ConvertTLBs(scriptInterface));
#endif
scriptInterface.SetProperty(settings.get(), "timer_resolution", timer_Resolution());
scriptInterface.SetProperty(settings, "timer_resolution", timer_Resolution());
// Send the same data to the reporting system
g_UserReporter.SubmitReport("hwdetect", 11, scriptInterface.StringifyJSON(settings.get(), false));
g_UserReporter.SubmitReport("hwdetect", 11, scriptInterface.StringifyJSON(settings, false));
// Run the detection script:
scriptInterface.CallFunctionVoid(scriptInterface.GetGlobalObject(), "RunHardwareDetection", settings);
}
static void ReportGLLimits(ScriptInterface& scriptInterface, CScriptValRooted settings)
static void ReportGLLimits(ScriptInterface& scriptInterface, JS::HandleValue settings)
{
const char* errstr = "(error)";
@ -327,20 +335,20 @@ static void ReportGLLimits(ScriptInterface& scriptInterface, CScriptValRooted se
GLint i = -1; \
glGetIntegerv(GL_##id, &i); \
if (ogl_SquelchError(GL_INVALID_ENUM)) \
scriptInterface.SetProperty(settings.get(), "GL_" #id, errstr); \
scriptInterface.SetProperty(settings, "GL_" #id, errstr); \
else \
scriptInterface.SetProperty(settings.get(), "GL_" #id, i); \
scriptInterface.SetProperty(settings, "GL_" #id, i); \
} while (false)
#define INTEGER2(id) do { \
GLint i[2] = { -1, -1 }; \
glGetIntegerv(GL_##id, i); \
if (ogl_SquelchError(GL_INVALID_ENUM)) { \
scriptInterface.SetProperty(settings.get(), "GL_" #id "[0]", errstr); \
scriptInterface.SetProperty(settings.get(), "GL_" #id "[1]", errstr); \
scriptInterface.SetProperty(settings, "GL_" #id "[0]", errstr); \
scriptInterface.SetProperty(settings, "GL_" #id "[1]", errstr); \
} else { \
scriptInterface.SetProperty(settings.get(), "GL_" #id "[0]", i[0]); \
scriptInterface.SetProperty(settings.get(), "GL_" #id "[1]", i[1]); \
scriptInterface.SetProperty(settings, "GL_" #id "[0]", i[0]); \
scriptInterface.SetProperty(settings, "GL_" #id "[1]", i[1]); \
} \
} while (false)
@ -348,20 +356,20 @@ static void ReportGLLimits(ScriptInterface& scriptInterface, CScriptValRooted se
GLfloat f = std::numeric_limits<GLfloat>::quiet_NaN(); \
glGetFloatv(GL_##id, &f); \
if (ogl_SquelchError(GL_INVALID_ENUM)) \
scriptInterface.SetProperty(settings.get(), "GL_" #id, errstr); \
scriptInterface.SetProperty(settings, "GL_" #id, errstr); \
else \
scriptInterface.SetProperty(settings.get(), "GL_" #id, f); \
scriptInterface.SetProperty(settings, "GL_" #id, f); \
} while (false)
#define FLOAT2(id) do { \
GLfloat f[2] = { std::numeric_limits<GLfloat>::quiet_NaN(), std::numeric_limits<GLfloat>::quiet_NaN() }; \
glGetFloatv(GL_##id, f); \
if (ogl_SquelchError(GL_INVALID_ENUM)) { \
scriptInterface.SetProperty(settings.get(), "GL_" #id "[0]", errstr); \
scriptInterface.SetProperty(settings.get(), "GL_" #id "[1]", errstr); \
scriptInterface.SetProperty(settings, "GL_" #id "[0]", errstr); \
scriptInterface.SetProperty(settings, "GL_" #id "[1]", errstr); \
} else { \
scriptInterface.SetProperty(settings.get(), "GL_" #id "[0]", f[0]); \
scriptInterface.SetProperty(settings.get(), "GL_" #id "[1]", f[1]); \
scriptInterface.SetProperty(settings, "GL_" #id "[0]", f[0]); \
scriptInterface.SetProperty(settings, "GL_" #id "[1]", f[1]); \
} \
} while (false)
@ -369,34 +377,34 @@ static void ReportGLLimits(ScriptInterface& scriptInterface, CScriptValRooted se
const char* c = (const char*)glGetString(GL_##id); \
if (!c) c = ""; \
if (ogl_SquelchError(GL_INVALID_ENUM)) c = errstr; \
scriptInterface.SetProperty(settings.get(), "GL_" #id, std::string(c)); \
scriptInterface.SetProperty(settings, "GL_" #id, std::string(c)); \
} while (false)
#define QUERY(target, pname) do { \
GLint i = -1; \
pglGetQueryivARB(GL_##target, GL_##pname, &i); \
if (ogl_SquelchError(GL_INVALID_ENUM)) \
scriptInterface.SetProperty(settings.get(), "GL_" #target ".GL_" #pname, errstr); \
scriptInterface.SetProperty(settings, "GL_" #target ".GL_" #pname, errstr); \
else \
scriptInterface.SetProperty(settings.get(), "GL_" #target ".GL_" #pname, i); \
scriptInterface.SetProperty(settings, "GL_" #target ".GL_" #pname, i); \
} while (false)
#define VERTEXPROGRAM(id) do { \
GLint i = -1; \
pglGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_##id, &i); \
if (ogl_SquelchError(GL_INVALID_ENUM)) \
scriptInterface.SetProperty(settings.get(), "GL_VERTEX_PROGRAM_ARB.GL_" #id, errstr); \
scriptInterface.SetProperty(settings, "GL_VERTEX_PROGRAM_ARB.GL_" #id, errstr); \
else \
scriptInterface.SetProperty(settings.get(), "GL_VERTEX_PROGRAM_ARB.GL_" #id, i); \
scriptInterface.SetProperty(settings, "GL_VERTEX_PROGRAM_ARB.GL_" #id, i); \
} while (false)
#define FRAGMENTPROGRAM(id) do { \
GLint i = -1; \
pglGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_##id, &i); \
if (ogl_SquelchError(GL_INVALID_ENUM)) \
scriptInterface.SetProperty(settings.get(), "GL_FRAGMENT_PROGRAM_ARB.GL_" #id, errstr); \
scriptInterface.SetProperty(settings, "GL_FRAGMENT_PROGRAM_ARB.GL_" #id, errstr); \
else \
scriptInterface.SetProperty(settings.get(), "GL_FRAGMENT_PROGRAM_ARB.GL_" #id, i); \
scriptInterface.SetProperty(settings, "GL_FRAGMENT_PROGRAM_ARB.GL_" #id, i); \
} while (false)
#define BOOL(id) INTEGER(id)
@ -670,30 +678,30 @@ static void ReportGLLimits(ScriptInterface& scriptInterface, CScriptValRooted se
#define GLXQCR_INTEGER(id) do { \
unsigned int i = UINT_MAX; \
if (pglXQueryCurrentRendererIntegerMESA(id, &i)) \
scriptInterface.SetProperty(settings.get(), #id, i); \
scriptInterface.SetProperty(settings, #id, i); \
} while (false)
#define GLXQCR_INTEGER2(id) do { \
unsigned int i[2] = { UINT_MAX, UINT_MAX }; \
if (pglXQueryCurrentRendererIntegerMESA(id, i)) { \
scriptInterface.SetProperty(settings.get(), #id "[0]", i[0]); \
scriptInterface.SetProperty(settings.get(), #id "[1]", i[1]); \
scriptInterface.SetProperty(settings, #id "[0]", i[0]); \
scriptInterface.SetProperty(settings, #id "[1]", i[1]); \
} \
} while (false)
#define GLXQCR_INTEGER3(id) do { \
unsigned int i[3] = { UINT_MAX, UINT_MAX, UINT_MAX }; \
if (pglXQueryCurrentRendererIntegerMESA(id, i)) { \
scriptInterface.SetProperty(settings.get(), #id "[0]", i[0]); \
scriptInterface.SetProperty(settings.get(), #id "[1]", i[1]); \
scriptInterface.SetProperty(settings.get(), #id "[2]", i[2]); \
scriptInterface.SetProperty(settings, #id "[0]", i[0]); \
scriptInterface.SetProperty(settings, #id "[1]", i[1]); \
scriptInterface.SetProperty(settings, #id "[2]", i[2]); \
} \
} while (false)
#define GLXQCR_STRING(id) do { \
const char* str = pglXQueryCurrentRendererStringMESA(id); \
if (str) \
scriptInterface.SetProperty(settings.get(), #id ".string", str); \
scriptInterface.SetProperty(settings, #id ".string", str); \
} while (false)
@ -706,7 +714,7 @@ static void ReportGLLimits(ScriptInterface& scriptInterface, CScriptValRooted se
const char* glxexts = glXQueryExtensionsString(dpy, scrnum);
scriptInterface.SetProperty(settings.get(), "glx_extensions", glxexts);
scriptInterface.SetProperty(settings, "glx_extensions", glxexts);
if (strstr(glxexts, "GLX_MESA_query_renderer") && pglXQueryCurrentRendererIntegerMESA && pglXQueryCurrentRendererStringMESA)
{

View File

@ -489,19 +489,23 @@ namespace
{
ScriptInterface& scriptInterface;
CScriptVal root;
DumpTable(ScriptInterface& scriptInterface, CScriptVal root) :
DumpTable(ScriptInterface& scriptInterface, JS::HandleValue root) :
scriptInterface(scriptInterface), root(root)
{
}
void operator() (AbstractProfileTable* table)
{
CScriptVal t;
scriptInterface.Eval(L"({})", t);
scriptInterface.SetProperty(t.get(), "cols", DumpCols(table));
scriptInterface.SetProperty(t.get(), "data", DumpRows(table));
JSContext* cx = scriptInterface.GetContext();
JSAutoRequest rq(cx);
scriptInterface.SetProperty(root.get(), table->GetTitle().c_str(), t);
JS::RootedValue t(cx);
scriptInterface.Eval(L"({})", &t);
scriptInterface.SetProperty(t, "cols", DumpCols(table));
scriptInterface.SetProperty(t, "data", DumpRows(table));
JS::RootedValue tmpRoot(cx, root.get()); // TODO: Check if this temporary root can be removed after SpiderMonkey 31 upgrade
scriptInterface.SetProperty(tmpRoot, table->GetTitle().c_str(), t);
}
std::vector<std::string> DumpCols(AbstractProfileTable* table)
@ -518,25 +522,28 @@ namespace
CScriptVal DumpRows(AbstractProfileTable* table)
{
CScriptVal data;
scriptInterface.Eval("({})", data);
JSContext* cx = scriptInterface.GetContext();
JSAutoRequest rq(cx);
JS::RootedValue data(cx);
scriptInterface.Eval("({})", &data);
const std::vector<ProfileColumn>& columns = table->GetColumns();
for (size_t r = 0; r < table->GetNumberRows(); ++r)
{
CScriptVal row;
scriptInterface.Eval("([])", row);
scriptInterface.SetProperty(data.get(), table->GetCellText(r, 0).c_str(), row);
JS::RootedValue row(cx);
scriptInterface.Eval("([])", &row);
scriptInterface.SetProperty(data, table->GetCellText(r, 0).c_str(), row);
if (table->GetChild(r))
scriptInterface.SetPropertyInt(row.get(), 0, DumpRows(table->GetChild(r)));
scriptInterface.SetPropertyInt(row, 0, DumpRows(table->GetChild(r)));
for (size_t c = 1; c < columns.size(); ++c)
scriptInterface.SetPropertyInt(row.get(), c, table->GetCellText(r, c));
scriptInterface.SetPropertyInt(row, c, table->GetCellText(r, c));
}
return data;
return data.get();
}
private:
@ -587,14 +594,17 @@ void CProfileViewer::SaveToFile()
CScriptVal CProfileViewer::SaveToJS(ScriptInterface& scriptInterface)
{
CScriptVal root;
scriptInterface.Eval("({})", root);
JSContext* cx = scriptInterface.GetContext();
JSAutoRequest rq(cx);
JS::RootedValue root(cx);
scriptInterface.Eval("({})", &root);
std::vector<AbstractProfileTable*> tables = m->rootTables;
sort(tables.begin(), tables.end(), SortByName);
for_each(tables.begin(), tables.end(), DumpTable(scriptInterface, root));
return root;
return root.get();
}
void CProfileViewer::ShowTable(const CStr& table)

View File

@ -80,32 +80,32 @@ Status SavedGames::Save(const std::wstring& name, const std::wstring& descriptio
if (!simulation.SerializeState(simStateStream))
WARN_RETURN(ERR::FAIL);
CScriptValRooted metadata;
simulation.GetScriptInterface().Eval("({})", metadata);
simulation.GetScriptInterface().SetProperty(metadata.get(), "version_major", SAVED_GAME_VERSION_MAJOR);
simulation.GetScriptInterface().SetProperty(metadata.get(), "version_minor", SAVED_GAME_VERSION_MINOR);
simulation.GetScriptInterface().SetProperty(metadata.get(), "mods", g_modsLoaded);
simulation.GetScriptInterface().SetProperty(metadata.get(), "time", (double)now);
simulation.GetScriptInterface().SetProperty(metadata.get(), "player", playerID);
simulation.GetScriptInterface().SetProperty(metadata.get(), "initAttributes", simulation.GetInitAttributes());
JS::RootedValue metadata(cx);
simulation.GetScriptInterface().Eval("({})", &metadata);
simulation.GetScriptInterface().SetProperty(metadata, "version_major", SAVED_GAME_VERSION_MAJOR);
simulation.GetScriptInterface().SetProperty(metadata, "version_minor", SAVED_GAME_VERSION_MINOR);
simulation.GetScriptInterface().SetProperty(metadata, "mods", g_modsLoaded);
simulation.GetScriptInterface().SetProperty(metadata, "time", (double)now);
simulation.GetScriptInterface().SetProperty(metadata, "player", playerID);
simulation.GetScriptInterface().SetProperty(metadata, "initAttributes", simulation.GetInitAttributes());
JS::RootedValue guiMetadata(cx, simulation.GetScriptInterface().ReadStructuredClone(guiMetadataClone));
// get some camera data
CScriptVal cameraMetadata;
simulation.GetScriptInterface().Eval("({})", cameraMetadata);
simulation.GetScriptInterface().SetProperty(cameraMetadata.get(), "PosX", g_Game->GetView()->GetCameraPosX());
simulation.GetScriptInterface().SetProperty(cameraMetadata.get(), "PosY", g_Game->GetView()->GetCameraPosY());
simulation.GetScriptInterface().SetProperty(cameraMetadata.get(), "PosZ", g_Game->GetView()->GetCameraPosZ());
simulation.GetScriptInterface().SetProperty(cameraMetadata.get(), "RotX", g_Game->GetView()->GetCameraRotX());
simulation.GetScriptInterface().SetProperty(cameraMetadata.get(), "RotY", g_Game->GetView()->GetCameraRotY());
simulation.GetScriptInterface().SetProperty(cameraMetadata.get(), "Zoom", g_Game->GetView()->GetCameraZoom());
JS::RootedValue cameraMetadata(cx);
simulation.GetScriptInterface().Eval("({})", &cameraMetadata);
simulation.GetScriptInterface().SetProperty(cameraMetadata, "PosX", g_Game->GetView()->GetCameraPosX());
simulation.GetScriptInterface().SetProperty(cameraMetadata, "PosY", g_Game->GetView()->GetCameraPosY());
simulation.GetScriptInterface().SetProperty(cameraMetadata, "PosZ", g_Game->GetView()->GetCameraPosZ());
simulation.GetScriptInterface().SetProperty(cameraMetadata, "RotX", g_Game->GetView()->GetCameraRotX());
simulation.GetScriptInterface().SetProperty(cameraMetadata, "RotY", g_Game->GetView()->GetCameraRotY());
simulation.GetScriptInterface().SetProperty(cameraMetadata, "Zoom", g_Game->GetView()->GetCameraZoom());
simulation.GetScriptInterface().SetProperty(guiMetadata, "camera", cameraMetadata);
simulation.GetScriptInterface().SetProperty(metadata.get(), "gui", guiMetadata);
simulation.GetScriptInterface().SetProperty(metadata, "gui", guiMetadata);
simulation.GetScriptInterface().SetProperty(metadata.get(), "description", description);
simulation.GetScriptInterface().SetProperty(metadata, "description", description);
std::string metadataString = simulation.GetScriptInterface().StringifyJSON(metadata.get(), true);
std::string metadataString = simulation.GetScriptInterface().StringifyJSON(metadata, true);
// Write the saved game as zip file containing the various components
PIArchiveWriter archiveWriter = CreateArchiveWriter_Zip(tempSaveFileRealPath, false);
@ -194,6 +194,8 @@ Status SavedGames::Load(const std::wstring& name, ScriptInterface& scriptInterfa
std::vector<CScriptValRooted> SavedGames::GetSavedGames(ScriptInterface& scriptInterface)
{
TIMER(L"GetSavedGames");
JSContext* cx = scriptInterface.GetContext();
JSAutoRequest rq(cx);
std::vector<CScriptValRooted> games;
@ -221,8 +223,9 @@ std::vector<CScriptValRooted> SavedGames::GetSavedGames(ScriptInterface& scriptI
continue; // skip this file
}
CScriptValRooted metadata;
CGameLoader loader(scriptInterface, &metadata, NULL);
JS::RootedValue metadata(cx);
CScriptValRooted tmpMetada(cx, metadata);
CGameLoader loader(scriptInterface, &tmpMetada, NULL);
err = archiveReader->ReadEntries(CGameLoader::ReadEntryCallback, (uintptr_t)&loader);
if (err < 0)
{
@ -230,11 +233,11 @@ std::vector<CScriptValRooted> SavedGames::GetSavedGames(ScriptInterface& scriptI
continue; // skip this file
}
CScriptValRooted game;
scriptInterface.Eval("({})", game);
scriptInterface.SetProperty(game.get(), "id", pathnames[i].Basename());
scriptInterface.SetProperty(game.get(), "metadata", metadata);
games.push_back(game);
JS::RootedValue game(cx);
scriptInterface.Eval("({})", &game);
scriptInterface.SetProperty(game, "id", pathnames[i].Basename());
scriptInterface.SetProperty(game, "metadata", metadata);
games.push_back(CScriptValRooted(cx, game));
}
return games;
@ -264,11 +267,14 @@ bool SavedGames::DeleteSavedGame(const std::wstring& name)
CScriptValRooted SavedGames::GetEngineInfo(ScriptInterface& scriptInterface)
{
CScriptValRooted metainfo;
scriptInterface.Eval("({})", metainfo);
scriptInterface.SetProperty(metainfo.get(), "version_major", SAVED_GAME_VERSION_MAJOR);
scriptInterface.SetProperty(metainfo.get(), "version_minor", SAVED_GAME_VERSION_MINOR);
scriptInterface.SetProperty(metainfo.get(), "mods" , g_modsLoaded);
return metainfo;
JSContext* cx = scriptInterface.GetContext();
JSAutoRequest rq(cx);
JS::RootedValue metainfo(cx);
scriptInterface.Eval("({})", &metainfo);
scriptInterface.SetProperty(metainfo, "version_major", SAVED_GAME_VERSION_MAJOR);
scriptInterface.SetProperty(metainfo, "version_minor", SAVED_GAME_VERSION_MINOR);
scriptInterface.SetProperty(metainfo, "mods" , g_modsLoaded);
return CScriptValRooted(cx, metainfo);
}

View File

@ -193,6 +193,8 @@ static Status AddActorToTemplates(const VfsPath& pathname, const CFileInfo& UNUS
std::vector<std::string> CTemplateLoader::FindPlaceableTemplates(const std::string& path, bool includeSubdirectories, ETemplatesType templatesType, ScriptInterface& scriptInterface)
{
JSContext* cx = scriptInterface.GetContext();
JSAutoRequest rq(cx);
std::vector<std::string> templates;
Status ok;
@ -201,16 +203,16 @@ std::vector<std::string> CTemplateLoader::FindPlaceableTemplates(const std::stri
if (templatesType == SIMULATION_TEMPLATES || templatesType == ALL_TEMPLATES)
{
CScriptValRooted placeablesFilter = scriptInterface.ReadJSONFile("simulation/data/placeablesFilter.json");
JS::RootedValue placeablesFilter(cx, scriptInterface.ReadJSONFile("simulation/data/placeablesFilter.json").get());
std::vector<CScriptValRooted> folders;
if (scriptInterface.GetProperty(placeablesFilter.get(), "templates", folders))
if (scriptInterface.GetProperty(placeablesFilter, "templates", folders))
{
templatePath = VfsPath(TEMPLATE_ROOT) / path;
//I have every object inside, just run for each
for (std::vector<CScriptValRooted>::iterator iterator = folders.begin(); iterator != folders.end();++iterator)
{
jsval val = (*iterator).get();
JS::RootedValue val(cx, (*iterator).get());
std::string directoryPath;
std::wstring fileFilter;
scriptInterface.GetProperty(val, "directory", directoryPath);

View File

@ -1021,7 +1021,7 @@ bool ScriptInterface::SetGlobal_(const char* name, jsval value, bool replace)
return ok;
}
bool ScriptInterface::SetProperty_(jsval obj, const char* name, jsval value, bool constant, bool enumerate)
bool ScriptInterface::SetProperty_(JS::HandleValue obj, const char* name, JS::HandleValue value, bool constant, bool enumerate)
{
JSAutoRequest rq(m->m_cx);
uint attrs = 0;
@ -1039,7 +1039,7 @@ bool ScriptInterface::SetProperty_(jsval obj, const char* name, jsval value, boo
return true;
}
bool ScriptInterface::SetProperty_(jsval obj, const wchar_t* name, jsval value, bool constant, bool enumerate)
bool ScriptInterface::SetProperty_(JS::HandleValue obj, const wchar_t* name, JS::HandleValue value, bool constant, bool enumerate)
{
JSAutoRequest rq(m->m_cx);
uint attrs = 0;
@ -1058,7 +1058,7 @@ bool ScriptInterface::SetProperty_(jsval obj, const wchar_t* name, jsval value,
return true;
}
bool ScriptInterface::SetPropertyInt_(jsval obj, int name, jsval value, bool constant, bool enumerate)
bool ScriptInterface::SetPropertyInt_(JS::HandleValue obj, int name, JS::HandleValue value, bool constant, bool enumerate)
{
JSAutoRequest rq(m->m_cx);
uint attrs = 0;
@ -1076,7 +1076,7 @@ bool ScriptInterface::SetPropertyInt_(jsval obj, int name, jsval value, bool con
return true;
}
bool ScriptInterface::GetProperty_(jsval obj, const char* name, JS::MutableHandleValue out)
bool ScriptInterface::GetProperty_(JS::HandleValue obj, const char* name, JS::MutableHandleValue out)
{
JSAutoRequest rq(m->m_cx);
if (!obj.isObject())
@ -1088,7 +1088,7 @@ bool ScriptInterface::GetProperty_(jsval obj, const char* name, JS::MutableHandl
return true;
}
bool ScriptInterface::GetPropertyInt_(jsval obj, int name, JS::MutableHandleValue out)
bool ScriptInterface::GetPropertyInt_(JS::HandleValue obj, int name, JS::MutableHandleValue out)
{
JSAutoRequest rq(m->m_cx);
if (!obj.isObject())
@ -1100,7 +1100,7 @@ bool ScriptInterface::GetPropertyInt_(jsval obj, int name, JS::MutableHandleValu
return true;
}
bool ScriptInterface::HasProperty(jsval obj, const char* name)
bool ScriptInterface::HasProperty(JS::HandleValue obj, const char* name)
{
// TODO: proper errorhandling
JSAutoRequest rq(m->m_cx);

View File

@ -190,27 +190,27 @@ public:
* Optionally makes it {ReadOnly, DontDelete, DontEnum}.
*/
template<typename T>
bool SetProperty(jsval obj, const char* name, const T& value, bool constant = false, bool enumerate = true);
bool SetProperty(JS::HandleValue obj, const char* name, const T& value, bool constant = false, bool enumerate = true);
/**
* Set the named property on the given object.
* Optionally makes it {ReadOnly, DontDelete, DontEnum}.
*/
template<typename T>
bool SetProperty(jsval obj, const wchar_t* name, const T& value, bool constant = false, bool enumerate = true);
bool SetProperty(JS::HandleValue obj, const wchar_t* name, const T& value, bool constant = false, bool enumerate = true);
/**
* Set the integer-named property on the given object.
* Optionally makes it {ReadOnly, DontDelete, DontEnum}.
*/
template<typename T>
bool SetPropertyInt(jsval obj, int name, const T& value, bool constant = false, bool enumerate = true);
bool SetPropertyInt(JS::HandleValue obj, int name, const T& value, bool constant = false, bool enumerate = true);
/**
* Get the named property on the given object.
*/
template<typename T>
bool GetProperty(jsval obj, const char* name, T& out);
bool GetProperty(JS::HandleValue obj, const char* name, T& out);
/**
* Get the named property of the given object.
@ -220,7 +220,7 @@ public:
* |out| using the & operator.
*/
template<typename T>
bool GetProperty(jsval obj, const char* name, JS::Rooted<T>* out);
bool GetProperty(JS::HandleValue obj, const char* name, JS::Rooted<T>* out);
/**
* Get the named property of the given object.
@ -228,21 +228,23 @@ public:
* to GetProperty as |out| parameter directly (usually when you get it as a function parameter).
*/
template<typename T>
bool GetProperty(jsval obj, const char* name, JS::MutableHandle<T> out);
bool GetProperty(JS::HandleValue obj, const char* name, JS::MutableHandle<T> out);
/**
* Get the integer-named property on the given object.
*/
template<typename T>
bool GetPropertyInt(jsval obj, int name, T& out);
bool GetPropertyInt(JS::HandleValue obj, int name, T& out);
/**
* Get the integer-named property on the given object.
* This version is for taking JS::MutableHandle<T> out parameters. Check the comment for GetProperty for
* background information
* This overload takes JS::Rooted<T>* and converts it to JS::MutableHandle<T> in the function body because implicit
* conversion is not supported for templates.
* It's used in the case where a JS::Rooted<T> gets created inside the same function and then passed to GetPropertyInt as
* |out| using the & operator.
*/
template<typename T>
bool GetPropertyInt(jsval obj, int name, JS::Rooted<T>* out);
bool GetPropertyInt(JS::HandleValue obj, int name, JS::Rooted<T>* out);
/**
* Get the named property of the given object.
@ -250,12 +252,12 @@ public:
* to GetPropertyInt as |out| parameter directly (usually when you get it as a function parameter).
*/
template<typename T>
bool GetPropertyInt(jsval obj, int name, JS::MutableHandle<T> out);
bool GetPropertyInt(JS::HandleValue obj, int name, JS::MutableHandle<T> out);
/**
* Check the named property has been defined on the given object.
*/
bool HasProperty(jsval obj, const char* name);
bool HasProperty(JS::HandleValue obj, const char* name);
bool EnumeratePropertyNamesWithPrefix(JS::HandleValue objVal, const char* prefix, std::vector<std::string>& out);
@ -410,11 +412,11 @@ private:
bool Eval_(const char* code, JS::MutableHandleValue ret);
bool Eval_(const wchar_t* code, JS::MutableHandleValue ret);
bool SetGlobal_(const char* name, jsval value, bool replace);
bool SetProperty_(jsval obj, const char* name, jsval value, bool readonly, bool enumerate);
bool SetProperty_(jsval obj, const wchar_t* name, jsval value, bool readonly, bool enumerate);
bool SetPropertyInt_(jsval obj, int name, jsval value, bool readonly, bool enumerate);
bool GetProperty_(jsval obj, const char* name, JS::MutableHandleValue out);
bool GetPropertyInt_(jsval obj, int name, JS::MutableHandleValue value);
bool SetProperty_(JS::HandleValue obj, const char* name, JS::HandleValue value, bool readonly, bool enumerate);
bool SetProperty_(JS::HandleValue obj, const wchar_t* name, JS::HandleValue value, bool readonly, bool enumerate);
bool SetPropertyInt_(JS::HandleValue obj, int name, JS::HandleValue value, bool readonly, bool enumerate);
bool GetProperty_(JS::HandleValue obj, const char* name, JS::MutableHandleValue out);
bool GetPropertyInt_(JS::HandleValue obj, int name, JS::MutableHandleValue value);
static bool IsExceptionPending(JSContext* cx);
static JSClass* GetClass(JSObject* obj);
static void* GetPrivate(JSObject* obj);
@ -529,7 +531,7 @@ bool ScriptInterface::SetGlobal(const char* name, const T& value, bool replace)
}
template<typename T>
bool ScriptInterface::SetProperty(jsval obj, const char* name, const T& value, bool readonly, bool enumerate)
bool ScriptInterface::SetProperty(JS::HandleValue obj, const char* name, const T& value, bool readonly, bool enumerate)
{
JSAutoRequest rq(GetContext());
JS::RootedValue val(GetContext());
@ -538,7 +540,7 @@ bool ScriptInterface::SetProperty(jsval obj, const char* name, const T& value, b
}
template<typename T>
bool ScriptInterface::SetProperty(jsval obj, const wchar_t* name, const T& value, bool readonly, bool enumerate)
bool ScriptInterface::SetProperty(JS::HandleValue obj, const wchar_t* name, const T& value, bool readonly, bool enumerate)
{
JSAutoRequest rq(GetContext());
JS::RootedValue val(GetContext());
@ -547,7 +549,7 @@ bool ScriptInterface::SetProperty(jsval obj, const wchar_t* name, const T& value
}
template<typename T>
bool ScriptInterface::SetPropertyInt(jsval obj, int name, const T& value, bool readonly, bool enumerate)
bool ScriptInterface::SetPropertyInt(JS::HandleValue obj, int name, const T& value, bool readonly, bool enumerate)
{
JSAutoRequest rq(GetContext());
JS::RootedValue val(GetContext());
@ -556,7 +558,7 @@ bool ScriptInterface::SetPropertyInt(jsval obj, int name, const T& value, bool r
}
template<typename T>
bool ScriptInterface::GetProperty(jsval obj, const char* name, T& out)
bool ScriptInterface::GetProperty(JS::HandleValue obj, const char* name, T& out)
{
JSContext* cx = GetContext();
JSAutoRequest rq(cx);
@ -567,7 +569,7 @@ bool ScriptInterface::GetProperty(jsval obj, const char* name, T& out)
}
template<typename T>
bool ScriptInterface::GetProperty(jsval obj, const char* name, JS::Rooted<T>* out)
bool ScriptInterface::GetProperty(JS::HandleValue obj, const char* name, JS::Rooted<T>* out)
{
JS::MutableHandle<T> handleOut(out);
if (! GetProperty_(obj, name, handleOut))
@ -576,7 +578,7 @@ bool ScriptInterface::GetProperty(jsval obj, const char* name, JS::Rooted<T>* ou
}
template<typename T>
bool ScriptInterface::GetProperty(jsval obj, const char* name, JS::MutableHandle<T> out)
bool ScriptInterface::GetProperty(JS::HandleValue obj, const char* name, JS::MutableHandle<T> out)
{
if (! GetProperty_(obj, name, out))
return false;
@ -584,7 +586,7 @@ bool ScriptInterface::GetProperty(jsval obj, const char* name, JS::MutableHandle
}
template<typename T>
bool ScriptInterface::GetPropertyInt(jsval obj, int name, T& out)
bool ScriptInterface::GetPropertyInt(JS::HandleValue obj, int name, T& out)
{
JSAutoRequest rq(GetContext());
JS::RootedValue val(GetContext());
@ -594,7 +596,7 @@ bool ScriptInterface::GetPropertyInt(jsval obj, int name, T& out)
}
template<typename T>
bool ScriptInterface::GetPropertyInt(jsval obj, int name, JS::Rooted<T>* out)
bool ScriptInterface::GetPropertyInt(JS::HandleValue obj, int name, JS::Rooted<T>* out)
{
JS::MutableHandle<T> handleOut(out);
if (! GetPropertyInt_(obj, name, handleOut))
@ -603,7 +605,7 @@ bool ScriptInterface::GetPropertyInt(jsval obj, int name, JS::Rooted<T>* out)
}
template<typename T>
bool ScriptInterface::GetPropertyInt(jsval obj, int name, JS::MutableHandle<T> out)
bool ScriptInterface::GetPropertyInt(JS::HandleValue obj, int name, JS::MutableHandle<T> out)
{
if (! GetPropertyInt_(obj, name, out))
return false;

View File

@ -367,22 +367,31 @@ void CSimulation2Impl::Update(int turnLength, const std::vector<SimulationComman
LDR_BeginRegistering();
CMapReader* mapReader = new CMapReader; // automatically deletes itself
// TODO: this duplicates CWorld::RegisterInit and could probably be cleaned up a bit
std::string mapType;
m_ComponentManager.GetScriptInterface().GetProperty(m_InitAttributes.get(), "mapType", mapType);
if (mapType == "random")
// These braces limit the scope of rq and cx (mainly because we're working with different contexts here).
// TODO: Check after the upgrade to SpiderMonkey ESR31 if m_InitAtrributes can be made a PersistentRooted<T>
// and check if we even need a request in this case.
{
// TODO: support random map scripts
debug_warn(L"Serialization test mode only supports scenarios");
}
else
{
std::wstring mapFile;
m_ComponentManager.GetScriptInterface().GetProperty(m_InitAttributes.get(), "map", mapFile);
// TODO: this duplicates CWorld::RegisterInit and could probably be cleaned up a bit
JSContext* cx = m_ComponentManager.GetScriptInterface().GetContext();
JSAutoRequest rq(cx);
VfsPath mapfilename = VfsPath(mapFile).ChangeExtension(L".pmp");
mapReader->LoadMap(mapfilename, CScriptValRooted(), &secondaryTerrain, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, &secondaryContext, INVALID_PLAYER, true); // throws exception on failure
std::string mapType;
JS::RootedValue tmpInitAttributes(cx, m_InitAttributes.get()); // TODO: Check if this temporary root can be removed after SpiderMonkey 31 upgrade
m_ComponentManager.GetScriptInterface().GetProperty(tmpInitAttributes, "mapType", mapType);
if (mapType == "random")
{
// TODO: support random map scripts
debug_warn(L"Serialization test mode only supports scenarios");
}
else
{
std::wstring mapFile;
m_ComponentManager.GetScriptInterface().GetProperty(tmpInitAttributes, "map", mapFile);
VfsPath mapfilename = VfsPath(mapFile).ChangeExtension(L".pmp");
mapReader->LoadMap(mapfilename, CScriptValRooted(), &secondaryTerrain, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, &secondaryContext, INVALID_PLAYER, true); // throws exception on failure
}
}
LDR_EndRegistering();
ENSURE(LDR_NonprogressiveLoad() == INFO::OK);
@ -730,7 +739,7 @@ void CSimulation2::LoadMapSettings()
JS::RootedValue tmpMapSettings(cx, m->m_MapSettings.get()); // TODO: Check if this temporary root can be removed after SpiderMonkey 31 upgrade
// Initialize here instead of in Update()
GetScriptInterface().CallFunctionVoid(GetScriptInterface().GetGlobalObject(), "LoadMapSettings", m->m_MapSettings);
GetScriptInterface().CallFunctionVoid(GetScriptInterface().GetGlobalObject(), "LoadMapSettings", tmpMapSettings);
if (!m->m_StartupScript.empty())
GetScriptInterface().LoadScript(L"map startup script", m->m_StartupScript);
@ -891,12 +900,14 @@ std::string CSimulation2::ReadJSON(VfsPath path)
std::string CSimulation2::GetAIData()
{
ScriptInterface& scriptInterface = GetScriptInterface();
JSContext* cx = scriptInterface.GetContext();
JSAutoRequest rq(cx);
std::vector<CScriptValRooted> aiData = ICmpAIManager::GetAIs(scriptInterface);
// Build single JSON string with array of AI data
CScriptValRooted ais;
if (!scriptInterface.Eval("({})", ais) || !scriptInterface.SetProperty(ais.get(), "AIData", aiData))
JS::RootedValue ais(cx);
if (!scriptInterface.Eval("({})", &ais) || !scriptInterface.SetProperty(ais, "AIData", aiData))
return std::string();
return scriptInterface.StringifyJSON(ais.get());
return scriptInterface.StringifyJSON(ais);
}

View File

@ -96,9 +96,12 @@ private:
if (!m_Worker.LoadScripts(m_AIName))
return false;
JSContext* cx = m_ScriptInterface->GetContext();
JSAutoRequest rq(cx);
OsPath path = L"simulation/ai/" + m_AIName + L"/data.json";
CScriptValRooted metadata = m_Worker.LoadMetadata(path);
if (metadata.uninitialised())
JS::RootedValue metadata(cx, m_Worker.LoadMetadata(path).get());
if (metadata.isUndefined())
{
LOGERROR(L"Failed to create AI player: can't find %ls", path.string().c_str());
return false;
@ -109,50 +112,51 @@ private:
// TODO: All AIs should use modules. Remove the condition if this requirement is met.
std::string moduleName;
std::string constructor;
CScriptVal objectWithConstructor; // object that should contain the constructor function
JS::RootedValue objectWithConstructor(cx); // object that should contain the constructor function
JS::RootedValue global(cx, m_ScriptInterface->GetGlobalObject());
CScriptVal ctor;
if (!m_ScriptInterface->HasProperty(metadata.get(), "moduleName"))
if (!m_ScriptInterface->HasProperty(metadata, "moduleName"))
{
objectWithConstructor = m_ScriptInterface->GetGlobalObject();
objectWithConstructor.set(m_ScriptInterface->GetGlobalObject());
}
else
{
m_ScriptInterface->GetProperty(metadata.get(), "moduleName", moduleName);
if(!m_ScriptInterface->GetProperty(m_ScriptInterface->GetGlobalObject(), moduleName.c_str(), objectWithConstructor) || objectWithConstructor.undefined())
m_ScriptInterface->GetProperty(metadata, "moduleName", moduleName);
if(!m_ScriptInterface->GetProperty(global, moduleName.c_str(), &objectWithConstructor) || objectWithConstructor.isUndefined())
{
LOGERROR(L"Failed to create AI player: %ls: can't find the module that should contain the constructor: '%hs'", path.string().c_str(), moduleName.c_str());
return false;
}
}
if (!m_ScriptInterface->GetProperty(metadata.get(), "constructor", constructor))
if (!m_ScriptInterface->GetProperty(metadata, "constructor", constructor))
{
LOGERROR(L"Failed to create AI player: %ls: missing 'constructor'", path.string().c_str());
return false;
}
// Get the constructor function from the loaded scripts
if (!m_ScriptInterface->GetProperty(objectWithConstructor.get(), constructor.c_str(), ctor)
if (!m_ScriptInterface->GetProperty(objectWithConstructor, constructor.c_str(), ctor)
|| ctor.undefined())
{
LOGERROR(L"Failed to create AI player: %ls: can't find constructor '%hs'", path.string().c_str(), constructor.c_str());
return false;
}
m_ScriptInterface->GetProperty(metadata.get(), "useShared", m_UseSharedComponent);
m_ScriptInterface->GetProperty(metadata, "useShared", m_UseSharedComponent);
CScriptVal obj;
if (callConstructor)
{
// Set up the data to pass as the constructor argument
CScriptVal settings;
m_ScriptInterface->Eval(L"({})", settings);
m_ScriptInterface->SetProperty(settings.get(), "player", m_Player, false);
m_ScriptInterface->SetProperty(settings.get(), "difficulty", m_Difficulty, false);
JS::RootedValue settings(cx);
m_ScriptInterface->Eval(L"({})", &settings);
m_ScriptInterface->SetProperty(settings, "player", m_Player, false);
m_ScriptInterface->SetProperty(settings, "difficulty", m_Difficulty, false);
ENSURE(m_Worker.m_HasLoadedEntityTemplates);
m_ScriptInterface->SetProperty(settings.get(), "templates", m_Worker.m_EntityTemplates, false);
m_ScriptInterface->SetProperty(settings, "templates", m_Worker.m_EntityTemplates, false);
JS::AutoValueVector argv(m_ScriptInterface->GetContext());
JS::AutoValueVector argv(cx);
argv.append(settings.get());
obj = m_ScriptInterface->CallConstructor(ctor.get(), argv.length(), argv.handleAt(0));
}
@ -170,23 +174,23 @@ private:
return false;
}
m_Obj = CScriptValRooted(m_ScriptInterface->GetContext(), obj);
m_Obj = CScriptValRooted(cx, obj);
return true;
}
void Run(CScriptVal state, int playerID)
void Run(JS::HandleValue state, int playerID)
{
m_Commands.clear();
m_ScriptInterface->CallFunctionVoid(m_Obj.get(), "HandleMessage", state, playerID);
}
// overloaded with a sharedAI part.
// javascript can handle both natively on the same function.
void Run(CScriptVal state, int playerID, CScriptValRooted SharedAI)
void Run(JS::HandleValue state, int playerID, CScriptValRooted SharedAI)
{
m_Commands.clear();
m_ScriptInterface->CallFunctionVoid(m_Obj.get(), "HandleMessage", state, playerID, SharedAI);
}
void InitAI(CScriptVal state, CScriptValRooted SharedAI)
void InitAI(JS::HandleValue state, CScriptValRooted SharedAI)
{
m_Commands.clear();
m_ScriptInterface->CallFunctionVoid(m_Obj.get(), "Init", state, m_Player, SharedAI);
@ -370,53 +374,54 @@ public:
// Constructor name is SharedScript, it's in the module API3
// TODO: Hardcoding this is bad, we need a smarter way.
CScriptVal AIModule;
CScriptVal ctor;
if (!m_ScriptInterface->GetProperty(m_ScriptInterface->GetGlobalObject(), "API3", AIModule) || AIModule.undefined())
JS::RootedValue AIModule(cx);
JS::RootedValue global(cx, m_ScriptInterface->GetGlobalObject());
JS::RootedValue ctor(cx);
if (!m_ScriptInterface->GetProperty(global, "API3", &AIModule) || AIModule.isUndefined())
{
LOGERROR(L"Failed to create shared AI component: %ls: can't find module '%hs'", path.string().c_str(), "API3");
return false;
}
if (!m_ScriptInterface->GetProperty(AIModule.get(), "SharedScript", ctor)
|| ctor.undefined())
if (!m_ScriptInterface->GetProperty(AIModule, "SharedScript", &ctor)
|| ctor.isUndefined())
{
LOGERROR(L"Failed to create shared AI component: %ls: can't find constructor '%hs'", path.string().c_str(), "SharedScript");
return false;
}
// Set up the data to pass as the constructor argument
CScriptVal settings;
m_ScriptInterface->Eval(L"({})", settings);
CScriptVal playersID;
m_ScriptInterface->Eval(L"({})", playersID);
JS::RootedValue settings(cx);
m_ScriptInterface->Eval(L"({})", &settings);
JS::RootedValue playersID(cx);
m_ScriptInterface->Eval(L"({})", &playersID);
for (size_t i = 0; i < m_Players.size(); ++i)
{
JS::RootedValue val(cx);
m_ScriptInterface->ToJSVal(cx, &val, m_Players[i]->m_Player);
m_ScriptInterface->SetPropertyInt(playersID.get(), i, CScriptVal(val), true);
m_ScriptInterface->SetPropertyInt(playersID, i, val, true);
}
m_ScriptInterface->SetProperty(settings.get(), "players", playersID);
m_ScriptInterface->SetProperty(settings, "players", playersID);
ENSURE(m_HasLoadedEntityTemplates);
m_ScriptInterface->SetProperty(settings.get(), "templates", m_EntityTemplates, false);
m_ScriptInterface->SetProperty(settings, "templates", m_EntityTemplates, false);
if (hasTechs)
{
m_ScriptInterface->SetProperty(settings.get(), "techTemplates", m_TechTemplates, false);
m_ScriptInterface->SetProperty(settings, "techTemplates", m_TechTemplates, false);
}
else
{
// won't get the tech templates directly.
CScriptVal fakeTech;
m_ScriptInterface->Eval("({})", fakeTech);
m_ScriptInterface->SetProperty(settings.get(), "techTemplates", fakeTech, false);
JS::RootedValue fakeTech(cx);
m_ScriptInterface->Eval("({})", &fakeTech);
m_ScriptInterface->SetProperty(settings, "techTemplates", fakeTech, false);
}
JS::AutoValueVector argv(cx);
argv.append(settings.get());
m_SharedAIObj = CScriptValRooted(cx, m_ScriptInterface->CallConstructor(ctor.get(), argv.length(), argv.handleAt(0)));
argv.append(settings);
m_SharedAIObj = CScriptValRooted(cx, m_ScriptInterface->CallConstructor(ctor, argv.length(), argv.handleAt(0)));
if (m_SharedAIObj.undefined())
@ -448,25 +453,29 @@ public:
// this will be run last by InitGame.Js, passing the full game representation.
// For now it will run for the shared Component.
// This is NOT run during deserialization.
CScriptVal state = m_ScriptInterface->ReadStructuredClone(gameState);
JSContext* cx = m_ScriptInterface->GetContext();
JSAutoRequest rq(cx);
JS::RootedValue tmpVal(cx);
JS::RootedValue state(cx, m_ScriptInterface->ReadStructuredClone(gameState));
JS::RootedValue tmpVal(cx); // TODO: Check if this temporary root can be removed after SpiderMonkey 31 upgrade
ScriptInterface::ToJSVal(cx, &tmpVal, passabilityMap);
m_PassabilityMapVal = CScriptValRooted(cx, tmpVal.get());
ScriptInterface::ToJSVal(cx, &tmpVal, territoryMap);
m_TerritoryMapVal = CScriptValRooted(cx, tmpVal);
if (m_HasSharedComponent)
{
m_ScriptInterface->SetProperty(state.get(), "passabilityMap", m_PassabilityMapVal, true);
m_ScriptInterface->SetProperty(state.get(), "territoryMap", m_TerritoryMapVal, true);
m_ScriptInterface->SetProperty(state, "passabilityMap", m_PassabilityMapVal, true);
m_ScriptInterface->SetProperty(state, "territoryMap", m_TerritoryMapVal, true);
m_ScriptInterface->CallFunctionVoid(m_SharedAIObj.get(), "init", state);
for (size_t i = 0; i < m_Players.size(); ++i)
{
if (m_HasSharedComponent && m_Players[i]->m_UseSharedComponent)
m_Players[i]->InitAI(state,m_SharedAIObj);
m_Players[i]->InitAI(state, m_SharedAIObj);
}
}
@ -484,7 +493,7 @@ public:
if (passabilityMap.m_DirtyID != m_PassabilityMap.m_DirtyID)
{
m_PassabilityMap = passabilityMap;
JS::RootedValue tmpVal(cx);
JS::RootedValue tmpVal(cx); // TODO: Check if this temporary root can be removed after SpiderMonkey 31 upgrade
ScriptInterface::ToJSVal(cx, &tmpVal, m_PassabilityMap);
m_PassabilityMapVal = CScriptValRooted(cx, tmpVal);
}
@ -529,18 +538,23 @@ public:
void LoadEntityTemplates(const std::vector<std::pair<std::string, const CParamNode*> >& templates)
{
JSContext* cx = m_ScriptInterface->GetContext();
JSAutoRequest rq(cx);
m_HasLoadedEntityTemplates = true;
m_ScriptInterface->Eval("({})", m_EntityTemplates);
JS::RootedValue tmpEntityTemplates(cx); // TODO: Check if this temporary root can be removed after SpiderMonkey 31 upgrade
m_ScriptInterface->Eval("({})", &tmpEntityTemplates);
for (size_t i = 0; i < templates.size(); ++i)
{
jsval val = templates[i].second->ToJSVal(m_ScriptInterface->GetContext(), false);
m_ScriptInterface->SetProperty(m_EntityTemplates.get(), templates[i].first.c_str(), CScriptVal(val), true);
JS::RootedValue val(cx, templates[i].second->ToJSVal(cx, false));
m_ScriptInterface->SetProperty(tmpEntityTemplates, templates[i].first.c_str(), val, true);
}
// Since the template data is shared between AI players, freeze it
// to stop any of them changing it and confusing the other players
m_EntityTemplates = CScriptValRooted(cx, tmpEntityTemplates);
m_ScriptInterface->FreezeObject(m_EntityTemplates.get(), true);
}
@ -565,6 +579,9 @@ public:
void SerializeState(ISerializer& serializer)
{
JSContext* cx = m_ScriptInterface->GetContext();
JSAutoRequest rq(cx);
std::stringstream rngStream;
rngStream << m_RNG;
serializer.StringASCII("rng", rngStream.str(), 0, 32);
@ -594,23 +611,27 @@ public:
serializer.ScriptVal("command", val);
}
bool hasCustomSerialize = m_ScriptInterface->HasProperty(m_Players[i]->m_Obj.get(), "Serialize");
JS::RootedValue tmpPlayerObj(cx, m_Players[i]->m_Obj.get()); // TODO: Check if this temporary root can be removed after SpiderMonkey 31 upgrade
bool hasCustomSerialize = m_ScriptInterface->HasProperty(tmpPlayerObj, "Serialize");
if (hasCustomSerialize)
{
CScriptVal scriptData;
if (!m_ScriptInterface->CallFunction(m_Players[i]->m_Obj.get(), "Serialize", scriptData))
JS::RootedValue scriptData(cx);
if (!m_ScriptInterface->CallFunction(tmpPlayerObj, "Serialize", &scriptData))
LOGERROR(L"AI script Serialize call failed");
serializer.ScriptVal("data", scriptData);
}
else
{
serializer.ScriptVal("data", m_Players[i]->m_Obj.get());
serializer.ScriptVal("data", tmpPlayerObj);
}
}
}
void Deserialize(std::istream& stream)
{
JSContext* cx = m_ScriptInterface->GetContext();
JSAutoRequest rq(cx);
ENSURE(m_CommandsComputed); // deserializing while we're still actively computing would be bad
CStdDeserializer deserializer(*m_ScriptInterface, stream);
@ -666,24 +687,25 @@ public:
// prototypes could be stored in their ScriptInterface
deserializer.SetSerializablePrototypes(m_DeserializablePrototypes);
bool hasCustomDeserialize = m_ScriptInterface->HasProperty(m_Players.back()->m_Obj.get(), "Deserialize");
JS::RootedValue tmpPlayerObj(cx, m_Players.back()->m_Obj.get()); // TODO: Check if this temporary root can be removed after SpiderMonkey 31 upgrade
bool hasCustomDeserialize = m_ScriptInterface->HasProperty(tmpPlayerObj, "Deserialize");
if (hasCustomDeserialize)
{
CScriptVal scriptData;
deserializer.ScriptVal("data", scriptData);
if (m_Players[i]->m_UseSharedComponent)
{
if (!m_ScriptInterface->CallFunctionVoid(m_Players.back()->m_Obj.get(), "Deserialize", scriptData, m_SharedAIObj))
if (!m_ScriptInterface->CallFunctionVoid(tmpPlayerObj, "Deserialize", scriptData, m_SharedAIObj))
LOGERROR(L"AI script Deserialize call failed");
}
else if (!m_ScriptInterface->CallFunctionVoid(m_Players.back()->m_Obj.get(), "Deserialize", scriptData))
else if (!m_ScriptInterface->CallFunctionVoid(tmpPlayerObj, "Deserialize", scriptData))
{
LOGERROR(L"AI script deserialize() call failed");
}
}
else
{
deserializer.ScriptVal("data", m_Players.back()->m_Obj);
deserializer.ScriptVal("data", tmpPlayerObj.get());
}
}
}
@ -719,12 +741,14 @@ private:
void PerformComputation()
{
// Deserialize the game state, to pass to the AI's HandleMessage
CScriptVal state;
JSContext* cx = m_ScriptInterface->GetContext();
JSAutoRequest rq(cx);
JS::RootedValue state(cx);
{
PROFILE3("AI compute read state");
state = m_ScriptInterface->ReadStructuredClone(m_GameState);
m_ScriptInterface->SetProperty(state.get(), "passabilityMap", m_PassabilityMapVal, true);
m_ScriptInterface->SetProperty(state.get(), "territoryMap", m_TerritoryMapVal, true);
state.set(m_ScriptInterface->ReadStructuredClone(m_GameState));
m_ScriptInterface->SetProperty(state, "passabilityMap", m_PassabilityMapVal, true);
m_ScriptInterface->SetProperty(state, "territoryMap", m_TerritoryMapVal, true);
}
// It would be nice to do
@ -887,13 +911,15 @@ public:
virtual void RunGamestateInit()
{
ScriptInterface& scriptInterface = GetSimContext().GetScriptInterface();
JSContext* cx = scriptInterface.GetContext();
JSAutoRequest rq(cx);
CmpPtr<ICmpAIInterface> cmpAIInterface(GetSystemEntity());
ENSURE(cmpAIInterface);
// Get the game state from AIInterface
// We flush events from the initialization so we get a clean state now.
CScriptVal state = cmpAIInterface->GetFullRepresentation(true);
JS::RootedValue state(cx, cmpAIInterface->GetFullRepresentation(true).get());
// Get the passability data
Grid<u16> dummyGrid;
@ -924,6 +950,8 @@ public:
ForceLoadEntityTemplates();
ScriptInterface& scriptInterface = GetSimContext().GetScriptInterface();
JSContext* cx = scriptInterface.GetContext();
JSAutoRequest rq(cx);
if (m_Worker.getPlayerSize() == 0)
return;
@ -932,11 +960,11 @@ public:
ENSURE(cmpAIInterface);
// Get the game state from AIInterface
CScriptVal state;
JS::RootedValue state(cx);
if (m_JustDeserialized)
state = cmpAIInterface->GetFullRepresentation(true);
state.set(cmpAIInterface->GetFullRepresentation(true).get());
else
state = cmpAIInterface->GetRepresentation();
state.set(cmpAIInterface->GetRepresentation().get());
// Get the passability data
Grid<u16> dummyGrid;
@ -959,7 +987,7 @@ public:
LoadPathfinderClasses(state);
m_Worker.StartComputation(scriptInterface.WriteStructuredClone(state.get()), *passabilityMap, *territoryMap, territoryMapDirty);
m_Worker.StartComputation(scriptInterface.WriteStructuredClone(state), *passabilityMap, *territoryMap, territoryMapDirty);
m_JustDeserialized = false;
}
@ -1032,22 +1060,24 @@ private:
}
}
void LoadPathfinderClasses(CScriptVal state)
void LoadPathfinderClasses(JS::HandleValue state)
{
CmpPtr<ICmpPathfinder> cmpPathfinder(GetSystemEntity());
if (!cmpPathfinder)
return;
ScriptInterface& scriptInterface = GetSimContext().GetScriptInterface();
JSContext* cx = scriptInterface.GetContext();
JSAutoRequest rq(cx);
CScriptVal classesVal;
scriptInterface.Eval("({ pathfinderObstruction: 1, foundationObstruction: 2 })", classesVal);
JS::RootedValue classesVal(cx);
scriptInterface.Eval("({ pathfinderObstruction: 1, foundationObstruction: 2 })", &classesVal);
std::map<std::string, ICmpPathfinder::pass_class_t> classes = cmpPathfinder->GetPassabilityClasses();
for (std::map<std::string, ICmpPathfinder::pass_class_t>::iterator it = classes.begin(); it != classes.end(); ++it)
scriptInterface.SetProperty(classesVal.get(), it->first.c_str(), it->second, true);
scriptInterface.SetProperty(classesVal, it->first.c_str(), it->second, true);
scriptInterface.SetProperty(state.get(), "passabilityClasses", classesVal, true);
scriptInterface.SetProperty(state, "passabilityClasses", classesVal, true);
}
CAIWorker m_Worker;

View File

@ -50,6 +50,8 @@ public:
static Status Callback(const VfsPath& pathname, const CFileInfo& UNUSED(fileInfo), const uintptr_t cbData)
{
GetAIsHelper* self = (GetAIsHelper*)cbData;
JSContext* cx = self->m_ScriptInterface.GetContext();
JSAutoRequest rq(cx);
// Extract the 3rd component of the path (i.e. the directory after simulation/ai/)
fs::wpath components = pathname.string();
@ -57,11 +59,11 @@ public:
std::advance(it, 2);
std::wstring dirname = GetWstringFromWpath(*it);
CScriptValRooted ai;
self->m_ScriptInterface.Eval("({})", ai);
self->m_ScriptInterface.SetProperty(ai.get(), "id", dirname, true);
self->m_ScriptInterface.SetProperty(ai.get(), "data", self->m_ScriptInterface.ReadJSONFile(pathname), true);
self->m_AIs.push_back(ai);
JS::RootedValue ai(cx);
self->m_ScriptInterface.Eval("({})", &ai);
self->m_ScriptInterface.SetProperty(ai, "id", dirname, true);
self->m_ScriptInterface.SetProperty(ai, "data", self->m_ScriptInterface.ReadJSONFile(pathname), true);
self->m_AIs.push_back(CScriptValRooted(cx, ai));
return INFO::OK;
}

View File

@ -26,28 +26,40 @@ CComponentTypeScript::CComponentTypeScript(ScriptInterface& scriptInterface, jsv
m_ScriptInterface(scriptInterface), m_Instance(CScriptValRooted(scriptInterface.GetContext(), instance))
{
// Cache the property detection for efficiency
m_HasCustomSerialize = m_ScriptInterface.HasProperty(m_Instance.get(), "Serialize");
m_HasCustomDeserialize = m_ScriptInterface.HasProperty(m_Instance.get(), "Deserialize");
JSContext* cx = m_ScriptInterface.GetContext();
JSAutoRequest rq(cx);
JS::RootedValue tmpInstance(cx, m_Instance.get()); // TODO: Check if this temporary root can be removed after SpiderMonkey 31 upgrade
m_HasCustomSerialize = m_ScriptInterface.HasProperty(tmpInstance, "Serialize");
m_HasCustomDeserialize = m_ScriptInterface.HasProperty(tmpInstance, "Deserialize");
m_HasNullSerialize = false;
if (m_HasCustomSerialize)
{
CScriptVal val;
if (m_ScriptInterface.GetProperty(m_Instance.get(), "Serialize", val) && JSVAL_IS_NULL(val.get()))
JS::RootedValue val(cx);
if (m_ScriptInterface.GetProperty(tmpInstance, "Serialize", &val) && val.isNull())
m_HasNullSerialize = true;
}
}
void CComponentTypeScript::Init(const CParamNode& paramNode, entity_id_t ent)
{
m_ScriptInterface.SetProperty(m_Instance.get(), "entity", (int)ent, true, false);
m_ScriptInterface.SetProperty(m_Instance.get(), "template", paramNode, true, false);
m_ScriptInterface.CallFunctionVoid(m_Instance.get(), "Init");
JSContext* cx = m_ScriptInterface.GetContext();
JSAutoRequest rq(cx);
JS::RootedValue tmpInstance(cx, m_Instance.get()); // TODO: Check if this temporary root can be removed after SpiderMonkey 31 upgrade
m_ScriptInterface.SetProperty(tmpInstance, "entity", (int)ent, true, false);
m_ScriptInterface.SetProperty(tmpInstance, "template", paramNode, true, false);
m_ScriptInterface.CallFunctionVoid(tmpInstance, "Init");
}
void CComponentTypeScript::Deinit()
{
m_ScriptInterface.CallFunctionVoid(m_Instance.get(), "Deinit");
JSContext* cx = m_ScriptInterface.GetContext();
JSAutoRequest rq(cx);
JS::RootedValue tmpInstance(cx, m_Instance.get()); // TODO: Check if this temporary root can be removed after SpiderMonkey 31 upgrade
m_ScriptInterface.CallFunctionVoid(tmpInstance, "Deinit");
}
void CComponentTypeScript::HandleMessage(const CMessage& msg, bool global)
@ -83,17 +95,21 @@ void CComponentTypeScript::Serialize(ISerializer& serialize)
void CComponentTypeScript::Deserialize(const CParamNode& paramNode, IDeserializer& deserialize, entity_id_t ent)
{
JSContext* cx = m_ScriptInterface.GetContext();
JSAutoRequest rq(cx);
JS::RootedValue tmpInstance(cx, m_Instance.get()); // TODO: Check if this temporary root can be removed after SpiderMonkey 31 upgrade
// Support a custom "Deserialize" function, to which we pass the deserialized data
// instead of automatically adding the deserialized properties onto the object
if (m_HasCustomDeserialize)
{
CScriptVal val;
JS::RootedValue val(cx);
// If Serialize = null, we'll still call Deserialize but with undefined argument
if (!m_HasNullSerialize)
deserialize.ScriptVal("object", val);
deserialize.ScriptVal("object", val.get());
if (!m_ScriptInterface.CallFunctionVoid(m_Instance.get(), "Deserialize", val))
if (!m_ScriptInterface.CallFunctionVoid(tmpInstance, "Deserialize", val))
LOGERROR(L"Script Deserialize call failed");
}
else
@ -106,6 +122,6 @@ void CComponentTypeScript::Deserialize(const CParamNode& paramNode, IDeserialize
}
}
m_ScriptInterface.SetProperty(m_Instance.get(), "entity", (int)ent, true, false);
m_ScriptInterface.SetProperty(m_Instance.get(), "template", paramNode, true, false);
m_ScriptInterface.SetProperty(tmpInstance, "entity", (int)ent, true, false);
m_ScriptInterface.SetProperty(tmpInstance, "template", paramNode, true, false);
}

View File

@ -147,12 +147,14 @@ bool CComponentManager::LoadScript(const VfsPath& filename, bool hotload)
return ok;
}
void CComponentManager::Script_RegisterComponentType_Common(ScriptInterface::CxPrivate* pCxPrivate, int iid, std::string cname, CScriptVal ctor, bool reRegister, bool systemComponent)
void CComponentManager::Script_RegisterComponentType_Common(ScriptInterface::CxPrivate* pCxPrivate, int iid, std::string cname, CScriptVal ctor1, bool reRegister, bool systemComponent)
{
CComponentManager* componentManager = static_cast<CComponentManager*> (pCxPrivate->pCBData);
JSContext* cx = componentManager->m_ScriptInterface.GetContext();
JSAutoRequest rq(cx);
JS::RootedValue ctor(cx, ctor1.get()); // TODO: Get Handle parameter directly with SpiderMonkey 31
// Find the C++ component that wraps the interface
int cidWrapper = componentManager->GetScriptWrapper(iid);
if (cidWrapper == CID__Invalid)
@ -231,11 +233,11 @@ void CComponentManager::Script_RegisterComponentType_Common(ScriptInterface::CxP
std::string schema = "<empty/>";
{
CScriptValRooted prototype;
if (componentManager->m_ScriptInterface.GetProperty(ctor.get(), "prototype", prototype) &&
componentManager->m_ScriptInterface.HasProperty(prototype.get(), "Schema"))
JS::RootedValue prototype(cx);
if (componentManager->m_ScriptInterface.GetProperty(ctor, "prototype", &prototype) &&
componentManager->m_ScriptInterface.HasProperty(prototype, "Schema"))
{
componentManager->m_ScriptInterface.GetProperty(prototype.get(), "Schema", schema);
componentManager->m_ScriptInterface.GetProperty(prototype, "Schema", schema);
}
}
@ -256,7 +258,7 @@ void CComponentManager::Script_RegisterComponentType_Common(ScriptInterface::CxP
// Find all the ctor prototype's On* methods, and subscribe to the appropriate messages:
JS::RootedValue protoVal(cx);
if (!componentManager->m_ScriptInterface.GetProperty(ctor.get(), "prototype", &protoVal))
if (!componentManager->m_ScriptInterface.GetProperty(ctor, "prototype", &protoVal))
return; // error
std::vector<std::string> methods;

View File

@ -88,18 +88,20 @@ QUERYHANDLER(GenerateMap)
// Random map
ScriptInterface& scriptInterface = g_Game->GetSimulation2()->GetScriptInterface();
JSContext* cx = scriptInterface.GetContext();
JSAutoRequest rq(cx);
CScriptValRooted settings = scriptInterface.ParseJSON(*msg->settings);
JS::RootedValue settings(cx, scriptInterface.ParseJSON(*msg->settings).get());
CScriptValRooted attrs;
scriptInterface.Eval("({})", attrs);
scriptInterface.SetProperty(attrs.get(), "mapType", std::string("random"));
scriptInterface.SetProperty(attrs.get(), "script", std::wstring(*msg->filename));
scriptInterface.SetProperty(attrs.get(), "settings", settings, false);
JS::RootedValue attrs(cx);
scriptInterface.Eval("({})", &attrs);
scriptInterface.SetProperty(attrs, "mapType", std::string("random"));
scriptInterface.SetProperty(attrs, "script", std::wstring(*msg->filename));
scriptInterface.SetProperty(attrs, "settings", settings, false);
try
{
StartGame(attrs);
StartGame(CScriptValRooted(cx, attrs));
msg->status = 0;
}
@ -113,11 +115,11 @@ QUERYHANDLER(GenerateMap)
InitGame();
ScriptInterface& si = g_Game->GetSimulation2()->GetScriptInterface();
CScriptValRooted atts;
si.Eval("({})", atts);
si.SetProperty(atts.get(), "mapType", std::string("scenario"));
si.SetProperty(atts.get(), "map", std::wstring(L"maps/scenarios/_default"));
StartGame(atts);
JS::RootedValue atts(cx);
si.Eval("({})", &atts);
si.SetProperty(atts, "mapType", std::string("scenario"));
si.SetProperty(atts, "map", std::wstring(L"maps/scenarios/_default"));
StartGame(CScriptValRooted(cx, atts));
msg->status = -1;
}
@ -125,20 +127,22 @@ QUERYHANDLER(GenerateMap)
MESSAGEHANDLER(LoadMap)
{
ScriptInterface& scriptInterface = g_Game->GetSimulation2()->GetScriptInterface();
JSContext* cx = scriptInterface.GetContext();
JSAutoRequest rq(cx);
InitGame();
// Scenario
CStrW map = *msg->filename;
CStrW mapBase = map.BeforeLast(L".pmp"); // strip the file extension, if any
ScriptInterface& scriptInterface = g_Game->GetSimulation2()->GetScriptInterface();
JS::RootedValue attrs(cx);
scriptInterface.Eval("({})", &attrs);
scriptInterface.SetProperty(attrs, "mapType", std::string("scenario"));
scriptInterface.SetProperty(attrs, "map", std::wstring(mapBase));
CScriptValRooted attrs;
scriptInterface.Eval("({})", attrs);
scriptInterface.SetProperty(attrs.get(), "mapType", std::string("scenario"));
scriptInterface.SetProperty(attrs.get(), "map", std::wstring(mapBase));
StartGame(attrs);
StartGame(CScriptValRooted(cx, attrs));
}
MESSAGEHANDLER(ImportHeightmap)