Index: binaries/data/mods/public/gui/aiconfig/aiconfig.js
===================================================================
--- binaries/data/mods/public/gui/aiconfig/aiconfig.js (revision 18188)
+++ binaries/data/mods/public/gui/aiconfig/aiconfig.js (working copy)
@@ -16,20 +16,20 @@
let aiSelection = Engine.GetGUIObjectByName("aiSelection");
aiSelection.list = g_AIDescriptions.map(ai => ai.data.name);
aiSelection.selected = g_AIDescriptions.findIndex(ai => ai.id == settings.id);
- aiSelection.hidden = !settings.isController;
+ aiSelection.hidden = !settings.canBeChanged;
let aiSelectionText = Engine.GetGUIObjectByName("aiSelectionText");
aiSelectionText.caption = aiSelection.list[aiSelection.selected];
- aiSelectionText.hidden = settings.isController;
+ aiSelectionText.hidden = settings.canBeChanged;
let aiDiff = Engine.GetGUIObjectByName("aiDifficulty");
aiDiff.list = prepareForDropdown(g_Settings.AIDifficulties).Title;
aiDiff.selected = settings.difficulty;
- aiDiff.hidden = !settings.isController;
+ aiDiff.hidden = !settings.canBeChanged;
let aiDiffText = Engine.GetGUIObjectByName("aiDifficultyText");
aiDiffText.caption = aiDiff.list[aiDiff.selected];
- aiDiffText.hidden = settings.isController;
+ aiDiffText.hidden = settings.canBeChanged;
}
function selectAI(idx)
Index: binaries/data/mods/public/gui/common/settings.js
===================================================================
--- binaries/data/mods/public/gui/common/settings.js (revision 18188)
+++ binaries/data/mods/public/gui/common/settings.js (working copy)
@@ -37,6 +37,7 @@
"MapTypes": loadMapTypes(),
"MapSizes": loadSettingValuesFile("map_sizes.json"),
"PlayerDefaults": loadPlayerDefaults(),
+ "GuestSettings": loadSettingValuesFile("guest_settings.json"),
"PopulationCapacities": loadPopulationCapacities(),
"StartingResources": loadSettingValuesFile("starting_resources.json"),
"VictoryConditions": loadVictoryConditions()
Index: binaries/data/mods/public/gui/gamesetup/gamesetup.js
===================================================================
--- binaries/data/mods/public/gui/gamesetup/gamesetup.js (revision 18188)
+++ binaries/data/mods/public/gui/gamesetup/gamesetup.js (working copy)
@@ -5,6 +5,7 @@
const g_GameSpeeds = prepareForDropdown(g_Settings && g_Settings.GameSpeeds.filter(speed => !speed.ReplayOnly));
const g_MapSizes = prepareForDropdown(g_Settings && g_Settings.MapSizes);
const g_MapTypes = prepareForDropdown(g_Settings && g_Settings.MapTypes);
+const g_GuestSettings = prepareForDropdown(g_Settings && g_Settings.GuestSettings);
const g_PopulationCapacities = prepareForDropdown(g_Settings && g_Settings.PopulationCapacities);
const g_StartingResources = prepareForDropdown(g_Settings && g_Settings.StartingResources);
const g_VictoryConditions = prepareForDropdown(g_Settings && g_Settings.VictoryConditions);
@@ -146,7 +147,7 @@
*/
const g_RandomCiv = '[color="' + g_ColorRandom + '"]' + translateWithContext("civilization", "Random") + '[/color]';
-// Is this is a networked game, or offline
+// Is this a networked game, or offline
var g_IsNetworked;
// Is this user in control of game settings (i.e. is a network server, or offline player)
@@ -260,19 +261,8 @@
g_GameAttributes.settings.CheatsEnabled = !g_IsNetworked;
g_GameAttributes.settings.RatingEnabled = Engine.IsRankedGame() || undefined;
- initMapNameList();
- initNumberOfPlayers();
- initGameSpeed();
- initPopulationCaps();
- initStartingResources();
- initCeasefire();
- initWonderDurations();
- initVictoryConditions();
- initMapSizes();
- initRadioButtons();
+ initDropdowns();
}
- else
- hideControls();
initMultiplayerSettings();
initPlayerAssignments();
@@ -291,6 +281,21 @@
}
}
+function initDropdowns()
+{
+ initMapNameList();
+ initNumberOfPlayers();
+ initGameSpeed();
+ initGuestSettings();
+ initPopulationCaps();
+ initStartingResources();
+ initCeasefire();
+ initWonderDurations();
+ initVictoryConditions();
+ initMapSizes();
+ initRadioButtons();
+}
+
function initMapTypes()
{
let mapTypes = Engine.GetGUIObjectByName("mapType");
@@ -331,6 +336,7 @@
"optionPopulationCap",
"optionStartingResources",
"optionCeasefire",
+ "optionGuestSettings",
"optionRevealMap",
"optionExploreMap",
"optionDisableTreasures",
@@ -380,8 +386,8 @@
function initGameSpeed()
{
let gameSpeed = Engine.GetGUIObjectByName("gameSpeed");
- gameSpeed.hidden = false;
- Engine.GetGUIObjectByName("gameSpeedText").hidden = true;
+ gameSpeed.hidden = !canPlayerChange("gameSpeed");
+ Engine.GetGUIObjectByName("gameSpeedText").hidden = canPlayerChange("gameSpeed");
gameSpeed.list = g_GameSpeeds.Title;
gameSpeed.list_data = g_GameSpeeds.Speed;
gameSpeed.onSelectionChange = function() {
@@ -435,6 +441,21 @@
};
}
+function initGuestSettings()
+{
+ let guestSettings = Engine.GetGUIObjectByName("guestSettings");
+ guestSettings.list = g_GuestSettings.Title;
+ guestSettings.list_data = g_GuestSettings.Data;
+ if (guestSettings.selected == -1)
+ guestSettings.selected = g_GuestSettings.Default;
+ guestSettings.onSelectionChange = function() {
+ if (this.selected != -1)
+ g_GameAttributes.GuestSettings = g_GuestSettings.Data[this.selected];
+
+ updateGameAttributes();
+ };
+}
+
function initVictoryConditions()
{
let victoryConditions = Engine.GetGUIObjectByName("victoryCondition");
@@ -515,7 +536,7 @@
function hideControls()
{
for (let ctrl of ["mapType", "mapFilter", "mapSelection", "victoryCondition", "gameSpeed", "numPlayers"])
- hideControl(ctrl, ctrl + "Text");
+ hideControl(ctrl, ctrl + "Text", canPlayerChange(ctrl));
// TODO: Shouldn't players be able to choose their own assignment?
for (let i = 0; i < g_MaxPlayers; ++i)
@@ -555,6 +576,32 @@
}
/**
+ * Returns if the player is allowed to change this setting
+ */
+function canPlayerChange(setting)
+{
+ if (g_GameAttributes.mapType == "scenario" &&
+ ["victoryCondition", "wonderDuration", "populationCap",
+ "startingResources", "ceasefire", "revealMap", "exploreMap",
+ "disableTreasures", "lockTeams", "playerCiv", "playerTeam", "playerColor"].indexOf(setting) >= 0)
+ return false;
+
+ if (g_GameAttributes.mapType != "random" && setting == "numPlayers")
+ return false;
+
+ if (g_IsController)
+ return true;
+
+ if (setting == "guestSettings")
+ return false;
+
+ if (g_GuestSettings.Data.indexOf(setting) == -1)
+ return g_GameAttributes.GuestSettings == "all";
+
+ return g_GuestSettings.Data.indexOf(g_GameAttributes.GuestSettings) >= g_GuestSettings.Data.indexOf(setting);
+}
+
+/**
* Hide and set some elements depending on whether we play single- or multiplayer.
*/
function initMultiplayerSettings()
@@ -561,6 +608,7 @@
{
Engine.GetGUIObjectByName("chatPanel").hidden = !g_IsNetworked;
Engine.GetGUIObjectByName("optionCheats").hidden = !g_IsNetworked;
+ Engine.GetGUIObjectByName("optionGuestSettings").hidden = !g_IsNetworked;
Engine.GetGUIObjectByName("optionRating").hidden = !Engine.HasXmppClient();
Engine.GetGUIObjectByName("enableCheats").enabled = !Engine.IsRankedGame();
@@ -677,7 +725,7 @@
}
/**
- * Called whenever the host changed any setting.
+ * Called whenever someone changed any setting.
* @param {Object} message
*/
function handleGamesetupMessage(message)
@@ -694,7 +742,6 @@
}
Engine.SetRankedGame(!!g_GameAttributes.settings.RatingEnabled);
-
updateGUIObjects();
}
@@ -995,7 +1042,7 @@
initGUIObjects();
++g_LoadingState;
}
- else if (g_LoadingState == 2)
+ else if (g_LoadingState == 2 || g_LoadingState == 3)
{
while (true)
{
@@ -1006,7 +1053,15 @@
log("Net message: " + uneval(message));
if (g_NetMessageTypes[message.type])
+ {
g_NetMessageTypes[message.type](message);
+ if (g_LoadingState == 2 && message.type == "gamesetup")
+ {
+ ++g_LoadingState;
+ initDropdowns();
+ hideControls();
+ }
+ }
else
error("Unrecognised net message type " + message.type);
}
@@ -1022,9 +1077,8 @@
function selectNumPlayers(num)
{
// Avoid recursion
- if (g_IsInGuiUpdate || !g_IsController || g_GameAttributes.mapType != "random")
+ if (g_IsInGuiUpdate || !canPlayerChange("numPlayers") || g_GameAttributes.mapType != "random")
return;
-
// Unassign players from nonexistent slots
if (g_IsNetworked)
{
@@ -1086,7 +1140,7 @@
function selectMapType(type)
{
// Avoid recursion
- if (g_IsInGuiUpdate || !g_IsController)
+ if (g_IsInGuiUpdate)
return;
if (!g_MapPath[type])
@@ -1116,7 +1170,7 @@
function selectMapFilter(id)
{
// Avoid recursion
- if (g_IsInGuiUpdate || !g_IsController)
+ if (g_IsInGuiUpdate)
return;
g_GameAttributes.mapFilter = id;
@@ -1130,7 +1184,7 @@
function selectMap(name)
{
// Avoid recursion
- if (g_IsInGuiUpdate || !g_IsController || !name)
+ if (g_IsInGuiUpdate || !name)
return;
// Reset some map specific properties which are not necessarily redefined on each map
@@ -1262,7 +1316,7 @@
if (g_IsNetworked)
{
- Engine.SetNetworkGameAttributes(g_GameAttributes);
+ Engine.NetworkChangeSettings(g_GameAttributes);
Engine.StartNetworkGame();
}
else
@@ -1301,6 +1355,7 @@
let mapFilterIdx = g_MapFilters.findIndex(mapFilter => mapFilter.id == (g_GameAttributes.mapFilter || "default"));
let mapTypeIdx = g_GameAttributes.mapType !== undefined ? g_MapTypes.Name.indexOf(g_GameAttributes.mapType) : g_MapTypes.Default;
let gameSpeedIdx = g_GameAttributes.gameSpeed !== undefined ? g_GameSpeeds.Speed.indexOf(g_GameAttributes.gameSpeed) : g_GameSpeeds.Default;
+ let guestSettingsIdx = g_GameAttributes.GuestSettings !== undefined ? g_GuestSettings.Data.indexOf(g_GameAttributes.GuestSettings) : g_GuestSettings.Default;
// These dropdowns might set the default (as they ignore g_IsInGuiUpdate)
let mapSizeIdx = mapSettings.Size !== undefined ? g_MapSizes.Tiles.indexOf(mapSettings.Size) : g_MapSizes.Default;
@@ -1311,37 +1366,35 @@
let ceasefireIdx = mapSettings.Ceasefire !== undefined ? g_Ceasefire.Duration.indexOf(mapSettings.Ceasefire) : g_Ceasefire.Default;
let numPlayers = mapSettings.PlayerData ? mapSettings.PlayerData.length : g_MaxPlayers;
- if (g_IsController)
- {
- Engine.GetGUIObjectByName("mapType").selected = mapTypeIdx;
- Engine.GetGUIObjectByName("mapFilter").selected = mapFilterIdx;
- Engine.GetGUIObjectByName("mapSelection").selected = Engine.GetGUIObjectByName("mapSelection").list_data.indexOf(mapName);
- Engine.GetGUIObjectByName("mapSize").selected = mapSizeIdx;
- Engine.GetGUIObjectByName("numPlayers").selected = numPlayers - 1;
- Engine.GetGUIObjectByName("victoryCondition").selected = victoryIdx;
- Engine.GetGUIObjectByName("wonderDuration").selected = wonderDurationIdx;
- Engine.GetGUIObjectByName("populationCap").selected = popIdx;
- Engine.GetGUIObjectByName("gameSpeed").selected = gameSpeedIdx;
- Engine.GetGUIObjectByName("ceasefire").selected = ceasefireIdx;
- Engine.GetGUIObjectByName("startingResources").selected = startingResIdx;
- }
- else
- {
- Engine.GetGUIObjectByName("mapTypeText").caption = g_MapTypes.Title[mapTypeIdx];
- Engine.GetGUIObjectByName("mapFilterText").caption = g_MapFilters[mapFilterIdx].name;
- Engine.GetGUIObjectByName("mapSelectionText").caption = mapName == "random" ? g_RandomMap : translate(getMapDisplayName(mapName));
- initMapNameList();
- }
+ Engine.GetGUIObjectByName("mapType").selected = mapTypeIdx;
+ Engine.GetGUIObjectByName("mapFilter").selected = mapFilterIdx;
+ Engine.GetGUIObjectByName("mapSelection").selected = Engine.GetGUIObjectByName("mapSelection").list_data.indexOf(mapName);
+ Engine.GetGUIObjectByName("mapSize").selected = mapSizeIdx;
+ Engine.GetGUIObjectByName("numPlayers").selected = numPlayers - 1;
+ Engine.GetGUIObjectByName("victoryCondition").selected = victoryIdx;
+ Engine.GetGUIObjectByName("wonderDuration").selected = wonderDurationIdx;
+ Engine.GetGUIObjectByName("populationCap").selected = popIdx;
+ Engine.GetGUIObjectByName("gameSpeed").selected = gameSpeedIdx;
+ Engine.GetGUIObjectByName("ceasefire").selected = ceasefireIdx;
+ Engine.GetGUIObjectByName("startingResources").selected = startingResIdx;
+ Engine.GetGUIObjectByName("guestSettings").selected = guestSettingsIdx;
+
+ initMapNameList();
+
// Can be visible to both host and clients
Engine.GetGUIObjectByName("mapSizeText").caption = g_GameAttributes.mapType == "random" ? g_MapSizes.LongName[mapSizeIdx] : translate("Default");
Engine.GetGUIObjectByName("numPlayersText").caption = numPlayers;
Engine.GetGUIObjectByName("victoryConditionText").caption = g_VictoryConditions.Title[victoryIdx];
Engine.GetGUIObjectByName("wonderDurationText").caption = g_WonderDurations.Title[wonderDurationIdx];
+ Engine.GetGUIObjectByName("guestSettingsText").caption = g_GuestSettings.Title[guestSettingsIdx];
Engine.GetGUIObjectByName("populationCapText").caption = g_PopulationCapacities.Title[popIdx];
Engine.GetGUIObjectByName("startingResourcesText").caption = g_StartingResources.Title[startingResIdx];
Engine.GetGUIObjectByName("ceasefireText").caption = g_Ceasefire.Title[ceasefireIdx];
Engine.GetGUIObjectByName("gameSpeedText").caption = g_GameSpeeds.Title[gameSpeedIdx];
+ Engine.GetGUIObjectByName("mapTypeText").caption = g_MapTypes.Title[mapTypeIdx];
+ Engine.GetGUIObjectByName("mapFilterText").caption = g_MapFilters[mapFilterIdx].name;
+ Engine.GetGUIObjectByName("mapSelectionText").caption = mapName == "random" ? g_RandomMap : translate(getMapDisplayName(mapName));
setGUIBoolean("enableCheats", "enableCheatsText", !!mapSettings.CheatsEnabled);
setGUIBoolean("disableTreasures", "disableTreasuresText", !!mapSettings.DisableTreasures);
@@ -1364,15 +1417,16 @@
Engine.GetGUIObjectByName("mapSizeDesc").hidden = !isRandom;
Engine.GetGUIObjectByName("mapSize").hidden = !isRandom || !g_IsController;
Engine.GetGUIObjectByName("mapSizeText").hidden = !isRandom || g_IsController;
- hideControl("numPlayers", "numPlayersText", isRandom && g_IsController);
- let notScenario = g_GameAttributes.mapType != "scenario" && g_IsController ;
-
for (let ctrl of ["victoryCondition", "wonderDuration", "populationCap",
"startingResources", "ceasefire", "revealMap",
- "exploreMap", "disableTreasures", "lockTeams"])
- hideControl(ctrl, ctrl + "Text", notScenario);
+ "exploreMap", "disableTreasures", "lockTeams",
+ "gameSpeed", "guestSettings", "enableCheats",
+ "mapSelection", "numPlayers", "mapType", "mapFilter"])
+ hideControl(ctrl, ctrl + "Text", canPlayerChange(ctrl));
+ let notScenario = g_GameAttributes.mapType != "scenario" && g_IsController ;
+
setMapDescription();
for (let i = 0; i < g_MaxPlayers; ++i)
@@ -1408,17 +1462,17 @@
pCiv.selected = civ ? pCiv.list_data.indexOf(civ) : 0;
pTeam.selected = team !== undefined && team >= 0 ? team+1 : 0;
- hideControl("playerAssignment["+i+"]", "playerAssignmentText["+i+"]", g_IsController);
- hideControl("playerCiv["+i+"]", "playerCivText["+i+"]", notScenario);
- hideControl("playerTeam["+i+"]", "playerTeamText["+i+"]", notScenario);
+ hideControl("playerAssignment["+i+"]", "playerAssignmentText["+i+"]", canPlayerChange("playerAssignment"));
+ hideControl("playerCiv["+i+"]", "playerCivText["+i+"]", canPlayerChange("playerCiv"));
+ hideControl("playerTeam["+i+"]", "playerTeamText["+i+"]", canPlayerChange("playerTeam"));
// Allow host to chose player colors on non-scenario maps
let pColorPicker = Engine.GetGUIObjectByName("playerColorPicker["+i+"]");
let pColorPickerHeading = Engine.GetGUIObjectByName("playerColorHeading");
- let canChangeColors = g_IsController && g_GameAttributes.mapType != "scenario";
- pColorPicker.hidden = !canChangeColors;
- pColorPickerHeading.hidden = !canChangeColors;
- if (canChangeColors)
+ //let canChangeColors = g_IsController && g_GameAttributes.mapType != "scenario";
+ pColorPicker.hidden = !canPlayerChange("playerColor");
+ pColorPickerHeading.hidden = !canPlayerChange("playerColor");
+ if (canPlayerChange("playerColor"))
pColorPicker.selected = g_PlayerColors.findIndex(col => sameColor(col, color));
}
@@ -1485,12 +1539,12 @@
*/
function updateGameAttributes()
{
- if (g_IsInGuiUpdate || !g_IsController)
+ if (g_IsInGuiUpdate)
return;
if (g_IsNetworked)
{
- Engine.SetNetworkGameAttributes(g_GameAttributes);
+ Engine.NetworkChangeSettings(g_GameAttributes);
if (g_LoadingState >= 2)
sendRegisterGameStanza();
}
@@ -1504,7 +1558,7 @@
Engine.PushGuiPage("page_aiconfig.xml", {
"callback": "AIConfigCallback",
- "isController": g_IsController,
+ "canBeChanged": canPlayerChange("playerConfig"),
"playerSlot": playerSlot,
"id": g_GameAttributes.settings.PlayerData[playerSlot].AI,
"difficulty": g_GameAttributes.settings.PlayerData[playerSlot].AIDiff
@@ -1518,7 +1572,7 @@
{
g_LastViewedAIPlayer = -1;
- if (!ai.save || !g_IsController)
+ if (!ai.save)
return;
g_GameAttributes.settings.PlayerData[ai.playerSlot].AI = ai.id;
@@ -1525,7 +1579,7 @@
g_GameAttributes.settings.PlayerData[ai.playerSlot].AIDiff = ai.difficulty;
if (g_IsNetworked)
- Engine.SetNetworkGameAttributes(g_GameAttributes);
+ Engine.NetworkChangeSettings(g_GameAttributes);
else
updatePlayerList();
}
@@ -1621,7 +1675,7 @@
{
g_GameAttributes.settings.PlayerData[playerSlot].AI = "";
if (g_IsNetworked)
- Engine.SetNetworkGameAttributes(g_GameAttributes);
+ Engine.NetworkChangeSettings(g_GameAttributes);
}
let assignBox = Engine.GetGUIObjectByName("playerAssignment["+i+"]");
@@ -1632,37 +1686,36 @@
assignBox.selected = selection;
assignBoxText.caption = hostNameList[selection];
- if (g_IsController)
- assignBox.onselectionchange = function() {
- if (g_IsInGuiUpdate)
- return;
+ assignBox.onselectionchange = function() {
+ if (g_IsInGuiUpdate)
+ return;
- let guid = hostGuidList[this.selected];
- if (!guid)
- {
- if (g_IsNetworked)
- // Unassign any host from this player slot
- Engine.AssignNetworkPlayer(playerID, "");
- // Remove AI from this player slot
- g_GameAttributes.settings.PlayerData[playerSlot].AI = "";
- }
- else if (guid.substr(0, 3) == "ai:")
- {
- if (g_IsNetworked)
- // Unassign any host from this player slot
- Engine.AssignNetworkPlayer(playerID, "");
- // Set the AI for this player slot
- g_GameAttributes.settings.PlayerData[playerSlot].AI = guid.substr(3);
- }
- else
- swapPlayers(guid, playerSlot);
+ let guid = hostGuidList[this.selected];
+ if (!guid)
+ {
+ if (g_IsNetworked)
+ // Unassign any host from this player slot
+ Engine.AssignNetworkPlayer(playerID, "");
+ // Remove AI from this player slot
+ g_GameAttributes.settings.PlayerData[playerSlot].AI = "";
+ }
+ else if (guid.substr(0, 3) == "ai:")
+ {
+ if (g_IsNetworked)
+ // Unassign any host from this player slot
+ Engine.AssignNetworkPlayer(playerID, "");
+ // Set the AI for this player slot
+ g_GameAttributes.settings.PlayerData[playerSlot].AI = guid.substr(3);
+ }
+ else
+ swapPlayers(guid, playerSlot);
- if (g_IsNetworked)
- Engine.SetNetworkGameAttributes(g_GameAttributes);
- else
- updatePlayerList();
- updateReadyUI();
- };
+ if (g_IsNetworked)
+ Engine.NetworkChangeSettings(g_GameAttributes);
+ else
+ updatePlayerList();
+ updateReadyUI();
+ };
}
g_IsInGuiUpdate = false;
Index: binaries/data/mods/public/gui/gamesetup/gamesetup.xml
===================================================================
--- binaries/data/mods/public/gui/gamesetup/gamesetup.xml (revision 18188)
+++ binaries/data/mods/public/gui/gamesetup/gamesetup.xml (working copy)
@@ -80,7 +80,7 @@
-
+
-
+
+
+
Revealed Map:
Index: binaries/data/mods/public/simulation/data/settings/guest_settings.json
===================================================================
--- binaries/data/mods/public/simulation/data/settings/guest_settings.json (nonexistent)
+++ binaries/data/mods/public/simulation/data/settings/guest_settings.json (working copy)
@@ -0,0 +1,28 @@
+{
+ "TranslatedKeys": ["Title"],
+ "TranslationContext": "players can change",
+ "Data":
+ [
+ {
+ "Title": "None",
+ "Data": "none"
+ },
+ {
+ "Title": "Color",
+ "Data": "playerColor",
+ "Default": true
+ },
+ {
+ "Title": "Color & Civilization",
+ "Data": "playerCiv"
+ },
+ {
+ "Title": "Color, Civilization & Team",
+ "Data": "playerTeam"
+ },
+ {
+ "Title": "All",
+ "Data": "all"
+ }
+ ]
+}
Index: source/gui/scripting/ScriptFunctions.cpp
===================================================================
--- source/gui/scripting/ScriptFunctions.cpp (revision 18188)
+++ source/gui/scripting/ScriptFunctions.cpp (working copy)
@@ -344,6 +344,18 @@
g_NetServer->UpdateGameAttributes(&attribs, *(pCxPrivate->pScriptInterface));
}
+void NetworkChangeSettings(ScriptInterface::CxPrivate* pCxPrivate, JS::HandleValue attribs1)
+{
+ ENSURE(g_NetClient);
+ //TODO: This is a workaround because we need to pass a MutableHandle to a JSAPI functions somewhere
+ // (with no obvious reason).
+ JSContext* cx = pCxPrivate->pScriptInterface->GetContext();
+ JSAutoRequest rq(cx);
+ JS::RootedValue attribs(cx, attribs1);
+
+ g_NetClient->SendChangeSettingsMessage(&attribs, *(pCxPrivate->pScriptInterface));
+}
+
void StartNetworkHost(ScriptInterface::CxPrivate* pCxPrivate, const std::wstring& playerName)
{
ENSURE(!g_NetClient);
@@ -427,9 +439,9 @@
void AssignNetworkPlayer(ScriptInterface::CxPrivate* UNUSED(pCxPrivate), int playerID, const std::string& guid)
{
- ENSURE(g_NetServer);
+ ENSURE(g_NetClient);
- g_NetServer->AssignPlayer(playerID, guid);
+ g_NetClient->SendAssignPlayerMessage(playerID, guid);
}
void SetNetworkPlayerStatus(ScriptInterface::CxPrivate* UNUSED(pCxPrivate), const std::string& guid, int ready)
@@ -1049,6 +1061,7 @@
scriptInterface.RegisterFunction("KickPlayer");
scriptInterface.RegisterFunction("PollNetworkClient");
scriptInterface.RegisterFunction("SetNetworkGameAttributes");
+ scriptInterface.RegisterFunction("NetworkChangeSettings");
scriptInterface.RegisterFunction("AssignNetworkPlayer");
scriptInterface.RegisterFunction("SetNetworkPlayerStatus");
scriptInterface.RegisterFunction("ClearAllPlayerReady");
Index: source/network/NetClient.cpp
===================================================================
--- source/network/NetClient.cpp (revision 18188)
+++ source/network/NetClient.cpp (working copy)
@@ -321,6 +321,24 @@
SetCurrState(NCS_UNCONNECTED);
}
+void CNetClient::SendChangeSettingsMessage(JS::MutableHandleValue attrs, ScriptInterface& scriptInterface)
+{
+ // Pass the attributes as JSON, since that's the easiest safe
+ // cross-thread way of passing script data
+ std::string attrsJSON = scriptInterface.StringifyJSON(attrs, false);
+ CChangeSettingsMessage changeSetting;
+ changeSetting.m_Settings = attrsJSON;
+ SendMessage(&changeSetting);
+}
+
+void CNetClient::SendAssignPlayerMessage(const int playerID, const std::string guid)
+{
+ CAssignPlayerMessage assignPlayer;
+ assignPlayer.m_PlayerID = playerID;
+ assignPlayer.m_GUIDToAssign = guid;
+ SendMessage(&assignPlayer);
+}
+
void CNetClient::SendChatMessage(const std::wstring& text)
{
CChatMessage chat;
Index: source/network/NetClient.h
===================================================================
--- source/network/NetClient.h (revision 18188)
+++ source/network/NetClient.h (working copy)
@@ -187,6 +187,10 @@
*/
void LoadFinished();
+ void SendChangeSettingsMessage(JS::MutableHandleValue attrs, ScriptInterface& scriptInterface);
+
+ void SendAssignPlayerMessage(const int playerID, const std::string guid);
+
void SendChatMessage(const std::wstring& text);
void SendReadyMessage(const int status);
Index: source/network/NetMessage.cpp
===================================================================
--- source/network/NetMessage.cpp (revision 18188)
+++ source/network/NetMessage.cpp (working copy)
@@ -199,6 +199,13 @@
pNewMessage = new CSimulationMessage(scriptInterface);
break;
+ case NMT_CHANGE_SETTINGS:
+ pNewMessage = new CChangeSettingsMessage;
+ break;
+ case NMT_ASSIGN_PLAYER:
+ pNewMessage = new CAssignPlayerMessage;
+ break;
+
default:
LOGERROR("CNetMessageFactory::CreateMessage(): Unknown message type '%d' received", header.GetType());
break;
Index: source/network/NetMessages.h
===================================================================
--- source/network/NetMessages.h (revision 18188)
+++ source/network/NetMessages.h (working copy)
@@ -45,7 +45,7 @@
NMT_SERVER_HANDSHAKE_RESPONSE,
NMT_AUTHENTICATE, // Authentication stage
NMT_AUTHENTICATE_RESULT,
- NMT_CHAT, // Common chat message
+ NMT_CHAT, // Common chat message
NMT_READY,
NMT_GAME_SETUP,
NMT_PLAYER_ASSIGNMENT,
@@ -66,9 +66,11 @@
NMT_LOADED_GAME,
NMT_GAME_START,
NMT_END_COMMAND_BATCH,
- NMT_SYNC_CHECK, // OOS-detection hash checking
- NMT_SYNC_ERROR, // OOS-detection error
+ NMT_SYNC_CHECK, // OOS-detection hash checking
+ NMT_SYNC_ERROR, // OOS-detection error
NMT_SIMULATION_COMMAND,
+ NMT_CHANGE_SETTINGS, // User changes a setting in gamesetup
+ NMT_ASSIGN_PLAYER,
NMT_LAST // Last message in the list
};
@@ -109,7 +111,7 @@
END_NMT_CLASS()
START_NMT_CLASS_(Authenticate, NMT_AUTHENTICATE)
- NMT_FIELD(CStr8, m_GUID)
+ NMT_FIELD(CStr, m_GUID)
NMT_FIELD(CStrW, m_Name)
NMT_FIELD(CStrW, m_Password)
NMT_FIELD_INT(m_IsLocalClient, u8, 1)
@@ -122,18 +124,18 @@
END_NMT_CLASS()
START_NMT_CLASS_(Chat, NMT_CHAT)
- NMT_FIELD(CStr8, m_GUID) // ignored when client->server, valid when server->client
+ NMT_FIELD(CStr, m_GUID) // ignored when client->server, valid when server->client
NMT_FIELD(CStrW, m_Message)
END_NMT_CLASS()
START_NMT_CLASS_(Ready, NMT_READY)
- NMT_FIELD(CStr8, m_GUID)
+ NMT_FIELD(CStr, m_GUID)
NMT_FIELD_INT(m_Status, u8, 1)
END_NMT_CLASS()
START_NMT_CLASS_(PlayerAssignment, NMT_PLAYER_ASSIGNMENT)
NMT_START_ARRAY(m_Hosts)
- NMT_FIELD(CStr8, m_GUID)
+ NMT_FIELD(CStr, m_GUID)
NMT_FIELD(CStrW, m_Name)
NMT_FIELD_INT(m_PlayerID, i8, 1)
NMT_FIELD_INT(m_Status, u8, 1)
@@ -151,7 +153,7 @@
START_NMT_CLASS_(FileTransferData, NMT_FILE_TRANSFER_DATA)
NMT_FIELD_INT(m_RequestID, u32, 4)
- NMT_FIELD(CStr8, m_Data)
+ NMT_FIELD(CStr, m_Data)
END_NMT_CLASS()
START_NMT_CLASS_(FileTransferAck, NMT_FILE_TRANSFER_ACK)
@@ -163,7 +165,7 @@
END_NMT_CLASS()
START_NMT_CLASS_(Rejoined, NMT_REJOINED)
- NMT_FIELD(CStr8, m_GUID)
+ NMT_FIELD(CStr, m_GUID)
END_NMT_CLASS()
START_NMT_CLASS_(Kicked, NMT_KICKED)
@@ -172,13 +174,13 @@
END_NMT_CLASS()
START_NMT_CLASS_(ClientTimeout, NMT_CLIENT_TIMEOUT)
- NMT_FIELD(CStr8, m_GUID)
+ NMT_FIELD(CStr, m_GUID)
NMT_FIELD_INT(m_LastReceivedTime, u32, 4)
END_NMT_CLASS()
START_NMT_CLASS_(ClientPerformance, NMT_CLIENT_PERFORMANCE)
NMT_START_ARRAY(m_Clients)
- NMT_FIELD(CStr8, m_GUID)
+ NMT_FIELD(CStr, m_GUID)
NMT_FIELD_INT(m_MeanRTT, u32, 4)
NMT_END_ARRAY()
END_NMT_CLASS()
@@ -208,6 +210,16 @@
NMT_END_ARRAY()
END_NMT_CLASS()
+START_NMT_CLASS_(ChangeSettings, NMT_CHANGE_SETTINGS)
+ NMT_FIELD(CStr, m_GUID)
+ NMT_FIELD(CStr, m_Settings)
+END_NMT_CLASS()
+
+START_NMT_CLASS_(AssignPlayer, NMT_ASSIGN_PLAYER)
+ NMT_FIELD_INT(m_PlayerID, i8, 1)
+ NMT_FIELD(CStr, m_GUIDToAssign)
+END_NMT_CLASS()
+
END_NMTS()
#else
Index: source/network/NetServer.cpp
===================================================================
--- source/network/NetServer.cpp (revision 18188)
+++ source/network/NetServer.cpp (working copy)
@@ -649,6 +649,8 @@
session->AddTransition(NSS_PREGAME, (uint)NMT_CONNECTION_LOST, NSS_UNCONNECTED, (void*)&OnDisconnect, context);
session->AddTransition(NSS_PREGAME, (uint)NMT_CHAT, NSS_PREGAME, (void*)&OnChat, context);
session->AddTransition(NSS_PREGAME, (uint)NMT_READY, NSS_PREGAME, (void*)&OnReady, context);
+ session->AddTransition(NSS_PREGAME, (uint)NMT_CHANGE_SETTINGS, NSS_PREGAME, (void*)&OnChangeSettings, context);
+ session->AddTransition(NSS_PREGAME, (uint)NMT_ASSIGN_PLAYER, NSS_PREGAME, (void*)&OnAssignPlayer, context);
session->AddTransition(NSS_PREGAME, (uint)NMT_LOADED_GAME, NSS_INGAME, (void*)&OnLoadedGame, context);
session->AddTransition(NSS_JOIN_SYNCING, (uint)NMT_CONNECTION_LOST, NSS_UNCONNECTED, (void*)&OnDisconnect, context);
@@ -1106,6 +1108,28 @@
return true;
}
+bool CNetServerWorker::OnChangeSettings(void* context, CFsmEvent* event)
+{
+ ENSURE(event->GetType() == (uint)NMT_CHANGE_SETTINGS);
+ CNetServerSession* session = (CNetServerSession*)context;
+ CNetServerWorker& server = session->GetServer();
+
+ CChangeSettingsMessage* message = (CChangeSettingsMessage*)event->GetParamRef();
+ server.m_GameAttributesQueue.push_back(message->m_Settings);
+ return true;
+}
+
+bool CNetServerWorker::OnAssignPlayer(void* context, CFsmEvent* event)
+{
+ ENSURE(event->GetType() == (uint)NMT_ASSIGN_PLAYER);
+ CNetServerSession* session = (CNetServerSession*)context;
+ CNetServerWorker& server = session->GetServer();
+
+ CAssignPlayerMessage* message = (CAssignPlayerMessage*)event->GetParamRef();
+ server.m_AssignPlayerQueue.emplace_back(message->m_PlayerID, message->m_GUIDToAssign);
+ return true;
+}
+
bool CNetServerWorker::OnLoadedGame(void* context, CFsmEvent* event)
{
ENSURE(event->GetType() == (uint)NMT_LOADED_GAME);
Index: source/network/NetServer.h
===================================================================
--- source/network/NetServer.h (revision 18188)
+++ source/network/NetServer.h (working copy)
@@ -270,6 +270,8 @@
static bool OnInGame(void* context, CFsmEvent* event);
static bool OnChat(void* context, CFsmEvent* event);
static bool OnReady(void* context, CFsmEvent* event);
+ static bool OnChangeSettings(void* context, CFsmEvent* event);
+ static bool OnAssignPlayer(void* context, CFsmEvent* event);
static bool OnLoadedGame(void* context, CFsmEvent* event);
static bool OnJoinSyncingLoadedGame(void* context, CFsmEvent* event);
static bool OnRejoined(void* context, CFsmEvent* event);