Index: ps/trunk/binaries/data/mods/public/simulation/components/GuiInterface.js =================================================================== --- ps/trunk/binaries/data/mods/public/simulation/components/GuiInterface.js +++ ps/trunk/binaries/data/mods/public/simulation/components/GuiInterface.js @@ -5,9 +5,9 @@ GuiInterface.prototype.Serialize = function() { - // This component isn't network-synchronised for the biggest part - // So most of the attributes shouldn't be serialized - // Return an object with a small selection of deterministic data + // This component isn't network-synchronized for the biggest part, + // so most of the attributes shouldn't be serialized. + // Return an object with a small selection of deterministic data. return { "timeNotifications": this.timeNotifications, "timeNotificationID": this.timeNotificationID @@ -63,7 +63,7 @@ let cmpPlayer = QueryPlayerIDInterface(i); let cmpPlayerEntityLimits = QueryPlayerIDInterface(i, IID_EntityLimits); - // Work out what phase we are in + // Work out which phase we are in. let phase = ""; let cmpTechnologyManager = QueryPlayerIDInterface(i, IID_TechnologyManager); if (cmpTechnologyManager) @@ -76,7 +76,6 @@ phase = "village"; } - // store player ally/neutral/enemy data as arrays let allies = []; let mutualAllies = []; let neutrals = []; @@ -136,11 +135,9 @@ if (cmpTerrain) ret.mapSize = cmpTerrain.GetMapSize(); - // Add timeElapsed let cmpTimer = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer); ret.timeElapsed = cmpTimer.GetTime(); - // Add ceasefire info let cmpCeasefireManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_CeasefireManager); if (cmpCeasefireManager) { @@ -148,17 +145,14 @@ ret.ceasefireTimeRemaining = ret.ceasefireActive ? cmpCeasefireManager.GetCeasefireStartedTime() + cmpCeasefireManager.GetCeasefireTime() - ret.timeElapsed : 0; } - // Add cinema path info let cmpCinemaManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_CinemaManager); if (cmpCinemaManager) ret.cinemaPlaying = cmpCinemaManager.IsPlaying(); - // Add the game type and allied victory let cmpEndGameManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_EndGameManager); ret.victoryConditions = cmpEndGameManager.GetVictoryConditions(); ret.alliedVictory = cmpEndGameManager.GetAlliedVictory(); - // Add basic statistics to each player for (let i = 0; i < numPlayers; ++i) { let cmpPlayerStatisticsTracker = QueryPlayerIDInterface(i, IID_StatisticsTracker); @@ -177,10 +171,8 @@ */ GuiInterface.prototype.GetExtendedSimulationState = function() { - // Get basic simulation info let ret = this.GetSimulationState(); - // Add statistics to each player let numPlayers = Engine.QueryInterface(SYSTEM_ENTITY, IID_PlayerManager).GetNumPlayers(); for (let i = 0; i < numPlayers; ++i) { @@ -236,13 +228,13 @@ }; /** - * Get common entity info, often used in the gui + * Get common entity info, often used in the gui. */ GuiInterface.prototype.GetEntityState = function(player, ent) { let cmpTemplateManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_TemplateManager); - // All units must have a template; if not then it's a nonexistent entity id + // All units must have a template; if not then it's a nonexistent entity id. let template = cmpTemplateManager.GetCurrentTemplateName(ent); if (!template) return null; @@ -266,7 +258,7 @@ "selectionGroupName": cmpIdentity.GetSelectionGroupName(), "canDelete": !cmpIdentity.IsUndeletable(), "hasSomeFormation": cmpIdentity.HasSomeFormation(), - "formations": cmpIdentity.GetFormationsList(), + "formations": cmpIdentity.GetFormationsList() }; let cmpPosition = Engine.QueryInterface(ent, IID_Position); @@ -297,17 +289,17 @@ if (cmpMarket) ret.market = { "land": cmpMarket.HasType("land"), - "naval": cmpMarket.HasType("naval"), + "naval": cmpMarket.HasType("naval") }; let cmpPack = Engine.QueryInterface(ent, IID_Pack); if (cmpPack) ret.pack = { "packed": cmpPack.IsPacked(), - "progress": cmpPack.GetProgress(), + "progress": cmpPack.GetProgress() }; - var cmpUpgrade = Engine.QueryInterface(ent, IID_Upgrade); + let cmpUpgrade = Engine.QueryInterface(ent, IID_Upgrade); if (cmpUpgrade) ret.upgrade = { "upgrades": cmpUpgrade.GetUpgrades(), @@ -378,13 +370,13 @@ "isGuarding": cmpUnitAI.IsGuardOf(), "canPatrol": cmpUnitAI.CanPatrol(), "selectableStances": cmpUnitAI.GetSelectableStances(), - "isIdle": cmpUnitAI.IsIdle(), + "isIdle": cmpUnitAI.IsIdle() }; let cmpGuard = Engine.QueryInterface(ent, IID_Guard); if (cmpGuard) ret.guard = { - "entities": cmpGuard.GetEntities(), + "entities": cmpGuard.GetEntities() }; let cmpResourceGatherer = Engine.QueryInterface(ent, IID_ResourceGatherer); @@ -397,7 +389,7 @@ let cmpGate = Engine.QueryInterface(ent, IID_Gate); if (cmpGate) ret.gate = { - "locked": cmpGate.IsLocked(), + "locked": cmpGate.IsLocked() }; let cmpAlertRaiser = Engine.QueryInterface(ent, IID_AlertRaiser); @@ -434,7 +426,7 @@ if (type != "Ranged") { - // not a ranged attack, set some defaults + // Not a ranged attack, set some defaults. ret.attack[type].elevationBonus = 0; ret.attack[type].elevationAdaptedRange = ret.attack.maxRange; continue; @@ -442,21 +434,13 @@ ret.attack[type].elevationBonus = range.elevationBonus; - if (cmpUnitAI && cmpPosition && cmpPosition.IsInWorld()) - { - // For units, take the range in front of it, no spread. So angle = 0 - ret.attack[type].elevationAdaptedRange = cmpRangeManager.GetElevationAdaptedRange(cmpPosition.GetPosition(), cmpPosition.GetRotation(), range.max, range.elevationBonus, 0); - } - else if(cmpPosition && cmpPosition.IsInWorld()) - { - // For buildings, take the average elevation around it. So angle = 2*pi - ret.attack[type].elevationAdaptedRange = cmpRangeManager.GetElevationAdaptedRange(cmpPosition.GetPosition(), cmpPosition.GetRotation(), range.max, range.elevationBonus, 2*Math.PI); - } + if (cmpPosition && cmpPosition.IsInWorld()) + // For units, take the range in front of it, no spread, so angle = 0, + // else, take the average elevation around it: angle = 2 * pi. + ret.attack[type].elevationAdaptedRange = cmpRangeManager.GetElevationAdaptedRange(cmpPosition.GetPosition(), cmpPosition.GetRotation(), range.max, range.elevationBonus, cmpUnitAI ? 0 : 2 * Math.PI); else - { - // not in world, set a default? + // Not in world, set a default? ret.attack[type].elevationAdaptedRange = ret.attack.maxRange; - } } } @@ -514,7 +498,7 @@ "range": cmpHeal.GetRange().max, "rate": cmpHeal.GetRate(), "unhealableClasses": cmpHeal.GetUnhealableClasses(), - "healableClasses": cmpHeal.GetHealableClasses(), + "healableClasses": cmpHeal.GetHealableClasses() }; let cmpLoot = Engine.QueryInterface(ent, IID_Loot); @@ -561,7 +545,7 @@ let elevationBonus = cmd.elevationBonus || 0; let range = cmd.range; - return cmpRangeManager.GetElevationAdaptedRange(pos, rot, range, elevationBonus, 2*Math.PI); + return cmpRangeManager.GetElevationAdaptedRange(pos, rot, range, elevationBonus, 2 * Math.PI); }; GuiInterface.prototype.GetTemplateData = function(player, data) @@ -593,26 +577,28 @@ return true; let cmpTechnologyManager = QueryPlayerIDInterface(data.player !== undefined ? data.player : player, IID_TechnologyManager); - if (!cmpTechnologyManager) return false; return cmpTechnologyManager.IsTechnologyResearched(data.tech); }; -// Checks whether the requirements for this technology have been met +/** + * Checks whether the requirements for this technology have been met. + */ GuiInterface.prototype.CheckTechnologyRequirements = function(player, data) { let cmpTechnologyManager = QueryPlayerIDInterface(data.player !== undefined ? data.player : player, IID_TechnologyManager); - if (!cmpTechnologyManager) return false; return cmpTechnologyManager.CanResearch(data.tech); }; -// Returns technologies that are being actively researched, along with -// which entity is researching them and how far along the research is. +/** + * Returns technologies that are being actively researched, along with + * which entity is researching them and how far along the research is. + */ GuiInterface.prototype.GetStartedResearch = function(player) { let cmpTechnologyManager = QueryPlayerIDInterface(player, IID_TechnologyManager); @@ -638,24 +624,29 @@ return ret; }; -// Returns the battle state of the player. +/** + * Returns the battle state of the player. + */ GuiInterface.prototype.GetBattleState = function(player) { let cmpBattleDetection = QueryPlayerIDInterface(player, IID_BattleDetection); - if (!cmpBattleDetection) return false; return cmpBattleDetection.GetState(); }; -// Returns a list of ongoing attacks against the player. +/** + * Returns a list of ongoing attacks against the player. + */ GuiInterface.prototype.GetIncomingAttacks = function(player) { return QueryPlayerIDInterface(player, IID_AttackDetection).GetIncomingAttacks(); }; -// Used to show a red square over GUI elements you can't yet afford. +/** + * Used to show a red square over GUI elements you can't yet afford. + */ GuiInterface.prototype.GetNeededResources = function(player, data) { return QueryPlayerIDInterface(data.player !== undefined ? data.player : player).GetNeededResources(data.cost); @@ -692,7 +683,7 @@ notification.endTime = duration + cmpTimer.GetTime(); notification.id = ++this.timeNotificationID; - // Let all players and observers receive the notification by default + // Let all players and observers receive the notification by default. if (!notification.players) { notification.players = Engine.QueryInterface(SYSTEM_ENTITY, IID_PlayerManager).GetAllPlayers(); @@ -715,7 +706,7 @@ GuiInterface.prototype.GetTimeNotifications = function(player) { let time = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer).GetTime(); - // filter on players and time, since the delete timer might be executed with a delay + // Filter on players and time, since the delete timer might be executed with a delay. return this.timeNotifications.filter(n => n.players.indexOf(player) != -1 && n.endTime > time); }; @@ -826,7 +817,7 @@ updateEntityColor(data.showAllStatusBars && (i == player || player == -1) ? [IID_Minimap, IID_RangeOverlayRenderer, IID_RallyPointRenderer, IID_StatusBars] : [IID_Minimap, IID_RangeOverlayRenderer, IID_RallyPointRenderer], - cmpRangeManager.GetEntitiesByPlayer(i)); + cmpRangeManager.GetEntitiesByPlayer(i)); } updateEntityColor([IID_Selectable, IID_StatusBars], data.selected); Engine.QueryInterface(SYSTEM_ENTITY, IID_TerritoryManager).UpdateColors(); @@ -834,7 +825,8 @@ GuiInterface.prototype.SetSelectionHighlight = function(player, cmd) { - let playerColors = {}; // cache of owner -> color map + // Cache of owner -> color map + let playerColors = {}; for (let ent of cmd.entities) { @@ -842,7 +834,7 @@ if (!cmpSelectable) continue; - // Find the entity's owner's color: + // Find the entity's owner's color. let owner = INVALID_PLAYER; let cmpOwnership = Engine.QueryInterface(ent, IID_Ownership); if (cmpOwnership) @@ -946,7 +938,7 @@ { let cmpPlayer = QueryPlayerIDInterface(player); - // If there are some rally points already displayed, first hide them + // If there are some rally points already displayed, first hide them. for (let ent of this.entsRallyPointsDisplayed) { let cmpRallyPointRenderer = Engine.QueryInterface(ent, IID_RallyPointRenderer); @@ -956,50 +948,53 @@ this.entsRallyPointsDisplayed = []; - // Show the rally points for the passed entities + // Show the rally points for the passed entities. for (let ent of cmd.entities) { let cmpRallyPointRenderer = Engine.QueryInterface(ent, IID_RallyPointRenderer); if (!cmpRallyPointRenderer) continue; - // entity must have a rally point component to display a rally point marker - // (regardless of whether cmd specifies a custom location) + // Entity must have a rally point component to display a rally point marker + // (regardless of whether cmd specifies a custom location). let cmpRallyPoint = Engine.QueryInterface(ent, IID_RallyPoint); if (!cmpRallyPoint) continue; - // Verify the owner + // Verify the owner. let cmpOwnership = Engine.QueryInterface(ent, IID_Ownership); if (!(cmpPlayer && cmpPlayer.CanControlAllUnits())) if (!cmpOwnership || cmpOwnership.GetOwner() != player) continue; // If the command was passed an explicit position, use that and - // override the real rally point position; otherwise use the real position + // override the real rally point position; otherwise use the real position. let pos; if (cmd.x && cmd.z) pos = cmd; else - pos = cmpRallyPoint.GetPositions()[0]; // may return undefined if no rally point is set + // May return undefined if no rally point is set. + pos = cmpRallyPoint.GetPositions()[0]; if (pos) { - // Only update the position if we changed it (cmd.queued is set) + // Only update the position if we changed it (cmd.queued is set). + // Note that Add-/SetPosition take a CFixedVector2D which has X/Y components, not X/Z. if ("queued" in cmd) + { if (cmd.queued == true) - cmpRallyPointRenderer.AddPosition({ 'x': pos.x, 'y': pos.z }); // AddPosition takes a CFixedVector2D which has X/Y components, not X/Z + cmpRallyPointRenderer.AddPosition(new Vector2D(pos.x, pos.z)); else - cmpRallyPointRenderer.SetPosition({ 'x': pos.x, 'y': pos.z }); // SetPosition takes a CFixedVector2D which has X/Y components, not X/Z - - // rebuild the renderer when not set (when reading saved game or in case of building update) + cmpRallyPointRenderer.SetPosition(new Vector2D(pos.x, pos.z)); + } else if (!cmpRallyPointRenderer.IsSet()) + // Rebuild the renderer when not set (when reading saved game or in case of building update). for (let posi of cmpRallyPoint.GetPositions()) - cmpRallyPointRenderer.AddPosition({ 'x': posi.x, 'y': posi.z }); + cmpRallyPointRenderer.AddPosition(new Vector2D(posi.x, posi.z)); cmpRallyPointRenderer.SetDisplayed(true); - // remember which entities have their rally points displayed so we can hide them again + // Remember which entities have their rally points displayed so we can hide them again. this.entsRallyPointsDisplayed.push(ent); } } @@ -1038,17 +1033,14 @@ "message": "", "parameters": {}, "translateMessage": false, - "translateParameters": [], + "translateParameters": [] }; - // See if we're changing template if (!this.placementEntity || this.placementEntity[0] != cmd.template) { - // Destroy the old preview if there was one if (this.placementEntity) Engine.DestroyEntity(this.placementEntity[1]); - // Load the new template if (cmd.template == "") this.placementEntity = undefined; else @@ -1059,7 +1051,6 @@ { let ent = this.placementEntity[1]; - // Move the preview into the right location let pos = Engine.QueryInterface(ent, IID_Position); if (pos) { @@ -1070,7 +1061,6 @@ let cmpOwnership = Engine.QueryInterface(ent, IID_Ownership); cmpOwnership.SetOwner(player); - // Check whether building placement is valid let cmpBuildRestrictions = Engine.QueryInterface(ent, IID_BuildRestrictions); if (!cmpBuildRestrictions) error("cmpBuildRestrictions not defined"); @@ -1081,7 +1071,7 @@ if (cmpRangeOverlayManager) cmpRangeOverlayManager.SetEnabled(true, this.enabledVisualRangeOverlayTypes); - // Set it to a red shade if this is an invalid location + // Set it to a red shade if this is an invalid location. let cmpVisual = Engine.QueryInterface(ent, IID_Visual); if (cmpVisual) { @@ -1163,29 +1153,33 @@ { let wallSet = cmd.wallSet; + // Did the start position snap to anything? + // If we snapped, was it to an entity? If yes, hold that entity's ID. let start = { "pos": cmd.start, "angle": 0, - "snapped": false, // did the start position snap to anything? - "snappedEnt": INVALID_ENTITY, // if we snapped, was it to an entity? if yes, holds that entity's ID + "snapped": false, + "snappedEnt": INVALID_ENTITY }; + // Did the end position snap to anything? + // If we snapped, was it to an entity? If yes, hold that entity's ID. let end = { "pos": cmd.end, "angle": 0, - "snapped": false, // did the start position snap to anything? - "snappedEnt": INVALID_ENTITY, // if we snapped, was it to an entity? if yes, holds that entity's ID + "snapped": false, + "snappedEnt": INVALID_ENTITY }; // -------------------------------------------------------------------------------- - // do some entity cache management and check for snapping + // Do some entity cache management and check for snapping. if (!this.placementWallEntities) this.placementWallEntities = {}; if (!wallSet) { - // we're clearing the preview, clear the entity cache and bail + // We're clearing the preview, clear the entity cache and bail. for (let tpl in this.placementWallEntities) { for (let ent of this.placementWallEntities[tpl].entities) @@ -1193,13 +1187,12 @@ this.placementWallEntities[tpl].numUsed = 0; this.placementWallEntities[tpl].entities = []; - // keep template data around + // Keep template data around. } return false; } - // Move all existing cached entities outside of the world and reset their use count for (let tpl in this.placementWallEntities) { for (let ent of this.placementWallEntities[tpl].entities) @@ -1212,7 +1205,7 @@ this.placementWallEntities[tpl].numUsed = 0; } - // Create cache entries for templates we haven't seen before + // Create cache entries for templates we haven't seen before. for (let type in wallSet.templates) { if (type == "curves") @@ -1227,7 +1220,6 @@ "templateData": this.GetTemplateData(player, { "templateName": tpl }), }; - // ensure that the loaded template data contains a wallPiece component if (!this.placementWallEntities[tpl].templateData.wallPiece) { error("[SetWallPlacementPreview] No WallPiece component found for wall set template '" + tpl + "'"); @@ -1236,7 +1228,7 @@ } } - // prevent division by zero errors further on if the start and end positions are the same + // Prevent division by zero errors further on if the start and end positions are the same. if (end.pos && (start.pos.x === end.pos.x && start.pos.z === end.pos.z)) end.pos = undefined; @@ -1245,7 +1237,8 @@ // data to determine whether it snapped to an entity (if any), and to which one (see GetFoundationSnapData). if (cmd.snapEntities) { - let snapRadius = this.placementWallEntities[wallSet.templates.tower].templateData.wallPiece.length * 0.5; // determined through trial and error + // Value of 0.5 was determined through trial and error. + let snapRadius = this.placementWallEntities[wallSet.templates.tower].templateData.wallPiece.length * 0.5; let startSnapData = this.GetFoundationSnapData(player, { "x": start.pos.x, "z": start.pos.z, @@ -1288,22 +1281,23 @@ } } - // clear the single-building preview entity (we'll be rolling our own) + // Clear the single-building preview entity (we'll be rolling our own). this.SetBuildingPlacementPreview(player, { "template": "" }); // -------------------------------------------------------------------------------- - // calculate wall placement and position preview entities + // Calculate wall placement and position preview entities. let result = { "pieces": [], - "cost": { "population": 0, "populationBonus": 0, "time": 0 }, + "cost": { "population": 0, "populationBonus": 0, "time": 0 } }; for (let res of Resources.GetCodes()) result.cost[res] = 0; let previewEntities = []; if (end.pos) - previewEntities = GetWallPlacement(this.placementWallEntities, wallSet, start, end); // see helpers/Walls.js + // See helpers/Walls.js. + previewEntities = GetWallPlacement(this.placementWallEntities, wallSet, start, end); // For wall placement, we may (and usually do) need to have wall pieces overlap each other more than would // otherwise be allowed by their obstruction shapes. However, during this preview phase, this is not so much of @@ -1326,10 +1320,10 @@ if (start.snappedEnt && start.snappedEnt != INVALID_ENTITY) { let startEntObstruction = Engine.QueryInterface(start.snappedEnt, IID_Obstruction); - if (previewEntities.length > 0 && startEntObstruction) + if (previewEntities.length && startEntObstruction) previewEntities[0].controlGroups = [startEntObstruction.GetControlGroup()]; - // if we're snapping to merely a foundation, add an extra preview tower and also set it to the same control group + // If we're snapping to merely a foundation, add an extra preview tower and also set it to the same control group. let startEntState = this.GetEntityState(player, start.snappedEnt); if (startEntState.foundation) { @@ -1340,7 +1334,7 @@ "pos": start.pos, "angle": cmpPosition.GetRotation().y, "controlGroups": [startEntObstruction ? startEntObstruction.GetControlGroup() : undefined], - "excludeFromResult": true, // preview only, must not appear in the result + "excludeFromResult": true // Preview only, must not appear in the result. }); } } @@ -1364,13 +1358,13 @@ previewEntities.unshift({ "template": wallSet.templates.tower, "pos": start.pos, - "angle": previewEntities.length > 0 ? previewEntities[0].angle : this.placementWallLastAngle + "angle": previewEntities.length ? previewEntities[0].angle : this.placementWallLastAngle }); } if (end.pos) { - // Analogous to the starting side case above + // Analogous to the starting side case above. if (end.snappedEnt && end.snappedEnt != INVALID_ENTITY) { let endEntObstruction = Engine.QueryInterface(end.snappedEnt, IID_Obstruction); @@ -1382,11 +1376,11 @@ // '.controlGroup' property. Note that this array can only ever have 0, 1 or 2 elements (checked at a later time). if (previewEntities.length > 0 && endEntObstruction) { - previewEntities[previewEntities.length-1].controlGroups = previewEntities[previewEntities.length-1].controlGroups || []; - previewEntities[previewEntities.length-1].controlGroups.push(endEntObstruction.GetControlGroup()); + previewEntities[previewEntities.length - 1].controlGroups = previewEntities[previewEntities.length - 1].controlGroups || []; + previewEntities[previewEntities.length - 1].controlGroups.push(endEntObstruction.GetControlGroup()); } - // if we're snapping to a foundation, add an extra preview tower and also set it to the same control group + // If we're snapping to a foundation, add an extra preview tower and also set it to the same control group. let endEntState = this.GetEntityState(player, end.snappedEnt); if (endEntState.foundation) { @@ -1405,7 +1399,7 @@ previewEntities.push({ "template": wallSet.templates.tower, "pos": end.pos, - "angle": previewEntities.length > 0 ? previewEntities[previewEntities.length-1].angle : this.placementWallLastAngle + "angle": previewEntities.length ? previewEntities[previewEntities.length - 1].angle : this.placementWallLastAngle }); } @@ -1428,7 +1422,8 @@ // but cannot validly be, constructed). See method-level documentation for more details. let allPiecesValid = true; - let numRequiredPieces = 0; // number of entities that are required to build the entire wall, regardless of validity + // Number of entities that are required to build the entire wall, regardless of validity. + let numRequiredPieces = 0; for (let i = 0; i < previewEntities.length; ++i) { @@ -1441,12 +1436,10 @@ if (entPool.numUsed >= entPool.entities.length) { - // allocate new entity ent = Engine.AddLocalEntity("preview|" + tpl); entPool.entities.push(ent); } else - // reuse an existing one ent = entPool.entities[entPool.numUsed]; if (!ent) @@ -1455,25 +1448,25 @@ continue; } - // move piece to right location - // TODO: consider reusing SetBuildingPlacementReview for this, enhanced to be able to deal with multiple entities + // Move piece to right location. + // TODO: Consider reusing SetBuildingPlacementReview for this, enhanced to be able to deal with multiple entities. let cmpPosition = Engine.QueryInterface(ent, IID_Position); if (cmpPosition) { cmpPosition.JumpTo(entInfo.pos.x, entInfo.pos.z); cmpPosition.SetYRotation(entInfo.angle); - // if this piece is a tower, then it should have a Y position that is at least as high as its surrounding pieces + // If this piece is a tower, then it should have a Y position that is at least as high as its surrounding pieces. if (tpl === wallSet.templates.tower) { let terrainGroundPrev = null; let terrainGroundNext = null; if (i > 0) - terrainGroundPrev = cmpTerrain.GetGroundLevel(previewEntities[i-1].pos.x, previewEntities[i-1].pos.z); + terrainGroundPrev = cmpTerrain.GetGroundLevel(previewEntities[i - 1].pos.x, previewEntities[i - 1].pos.z); if (i < previewEntities.length - 1) - terrainGroundNext = cmpTerrain.GetGroundLevel(previewEntities[i+1].pos.x, previewEntities[i+1].pos.z); + terrainGroundNext = cmpTerrain.GetGroundLevel(previewEntities[i + 1].pos.x, previewEntities[i + 1].pos.z); if (terrainGroundPrev != null || terrainGroundNext != null) { @@ -1519,14 +1512,13 @@ cmpObstruction.SetControlGroup(primaryControlGroup); cmpObstruction.SetControlGroup2(secondaryControlGroup); - // check whether this wall piece can be validly positioned here let validPlacement = false; let cmpOwnership = Engine.QueryInterface(ent, IID_Ownership); cmpOwnership.SetOwner(player); - // Check whether it's in a visible or fogged region - // TODO: should definitely reuse SetBuildingPlacementPreview, this is just straight up copy/pasta + // Check whether it's in a visible or fogged region. + // TODO: Should definitely reuse SetBuildingPlacementPreview, this is just straight up copy/pasta. let visible = cmpRangeManager.GetLosVisibility(ent, player) != "hidden"; if (visible) { @@ -1537,7 +1529,7 @@ continue; } - // TODO: Handle results of CheckPlacement + // TODO: Handle results of CheckPlacement. validPlacement = cmpBuildRestrictions && cmpBuildRestrictions.CheckPlacement().success; // If a wall piece has two control groups, it's likely a segment that spans @@ -1570,9 +1562,9 @@ }); this.placementWallLastAngle = entInfo.angle; - // grab the cost of this wall piece and add it up (note; preview entities don't have their Cost components + // Grab the cost of this wall piece and add it up (note; preview entities don't have their Cost components // copied over, so we need to fetch it from the template instead). - // TODO: we should really use a Cost object or at least some utility functions for this, this is mindless + // TODO: We should really use a Cost object or at least some utility functions for this, this is mindless // boilerplate that's probably duplicated in tons of places. for (let res of Resources.GetCodes().concat(["population", "populationBonus", "time"])) result.cost[res] += tplData.cost[res]; @@ -1637,8 +1629,8 @@ if (data.snapEntities && data.snapRadius && data.snapRadius > 0) { - // see if {data.x, data.z} is inside the snap radius of any of the snap entities; and if so, to which it is closest - // (TODO: break unlikely ties by choosing the lowest entity ID) + // See if {data.x, data.z} is inside the snap radius of any of the snap entities; and if so, to which it is closest. + // (TODO: Break unlikely ties by choosing the lowest entity ID.) let minDist2 = -1; let minDistEntitySnapData = null; @@ -1659,10 +1651,10 @@ { minDist2 = dist2; minDistEntitySnapData = { - "x": pos.x, - "z": pos.z, - "angle": cmpPosition.GetRotation().y, - "ent": ent + "x": pos.x, + "z": pos.z, + "angle": cmpPosition.GetRotation().y, + "ent": ent }; } } @@ -1725,8 +1717,8 @@ // If the entity is in the 'current' (first, 0) bucket on a resumed search, it must be after the "previous" unit, if any. // By adding to the 'end', there is no pause if the series of units loops. - var bucket = filtered.bucket; - if(bucket == 0 && data.prevUnit && entity <= data.prevUnit) + let bucket = filtered.bucket; + if (bucket == 0 && data.prevUnit && entity <= data.prevUnit) bucket = data.idleClasses.length; if (!idleUnits[bucket]) @@ -1777,7 +1769,7 @@ return { "idle": false }; let cmpIdentity = Engine.QueryInterface(unit, IID_Identity); - if(!cmpIdentity) + if (!cmpIdentity) return { "idle": false }; let bucket = idleClasses.findIndex(elem => MatchesClassList(cmpIdentity.GetClassesList(), elem)); @@ -1814,28 +1806,20 @@ result.gain = cmpEntityTrader.GetGoods().amount; } else if (data.target === secondMarket) - { result = { "type": "is second", "gain": cmpEntityTrader.GetGoods().amount, }; - } else if (!firstMarket) - { result = { "type": "set first" }; - } else if (!secondMarket) - { result = { "type": "set second", "gain": cmpEntityTrader.CalculateGain(firstMarket, data.target), }; - } else - { - // Else both markets are not null and target is different from them result = { "type": "set first" }; - } + return result; }; @@ -1941,11 +1925,13 @@ this.renamedEntities.push(msg); }; -// List the GuiInterface functions that can be safely called by GUI scripts. -// (GUI scripts are non-deterministic and untrusted, so these functions must be -// appropriately careful. They are called with a first argument "player", which is -// trusted and indicates the player associated with the current client; no data should -// be returned unless this player is meant to be able to see it.) +/** + * List the GuiInterface functions that can be safely called by GUI scripts. + * (GUI scripts are non-deterministic and untrusted, so these functions must be + * appropriately careful. They are called with a first argument "player", which is + * trusted and indicates the player associated with the current client; no data should + * be returned unless this player is meant to be able to see it.) + */ let exposedFunctions = { "GetSimulationState": 1, @@ -2013,7 +1999,7 @@ if (exposedFunctions[name]) return this[name](player, args); - throw new Error("Invalid GuiInterface Call name \""+name+"\""); + throw new Error("Invalid GuiInterface Call name \"" + name + "\""); }; Engine.RegisterSystemComponentType(IID_GuiInterface, "GuiInterface", GuiInterface); Index: ps/trunk/binaries/data/mods/public/simulation/components/tests/test_GuiInterface.js =================================================================== --- ps/trunk/binaries/data/mods/public/simulation/components/tests/test_GuiInterface.js +++ ps/trunk/binaries/data/mods/public/simulation/components/tests/test_GuiInterface.js @@ -49,7 +49,7 @@ "GetResource": resource => ({ "aiAnalysisInfluenceGroup": resource == "food" ? "ignore" : - resource == "wood" ? "abundant" : "sparse" + resource == "wood" ? "abundant" : "sparse" }) }; @@ -57,71 +57,71 @@ AddMock(SYSTEM_ENTITY, IID_Barter, { - GetPrices: function() { + "GetPrices": function() { return { "buy": { "food": 150 }, "sell": { "food": 25 } }; }, - PlayerHasMarket: function () { return false; } + "PlayerHasMarket": function() { return false; } }); AddMock(SYSTEM_ENTITY, IID_EndGameManager, { - GetVictoryConditions: () => ["conquest", "wonder"], - GetAlliedVictory: function() { return false; } + "GetVictoryConditions": () => ["conquest", "wonder"], + "GetAlliedVictory": function() { return false; } }); AddMock(SYSTEM_ENTITY, IID_PlayerManager, { - GetNumPlayers: function() { return 2; }, - GetPlayerByID: function(id) { TS_ASSERT(id === 0 || id === 1); return 100+id; } + "GetNumPlayers": function() { return 2; }, + "GetPlayerByID": function(id) { TS_ASSERT(id === 0 || id === 1); return 100 + id; } }); AddMock(SYSTEM_ENTITY, IID_RangeManager, { - GetLosVisibility: function(ent, player) { return "visible"; }, - GetLosCircular: function() { return false; } + "GetLosVisibility": function(ent, player) { return "visible"; }, + "GetLosCircular": function() { return false; } }); AddMock(SYSTEM_ENTITY, IID_TemplateManager, { - GetCurrentTemplateName: function(ent) { return "example"; }, - GetTemplate: function(name) { return ""; } + "GetCurrentTemplateName": function(ent) { return "example"; }, + "GetTemplate": function(name) { return ""; } }); AddMock(SYSTEM_ENTITY, IID_Timer, { - GetTime: function() { return 0; }, - SetTimeout: function(ent, iid, funcname, time, data) { return 0; } + "GetTime": function() { return 0; }, + "SetTimeout": function(ent, iid, funcname, time, data) { return 0; } }); AddMock(100, IID_Player, { - GetName: function() { return "Player 1"; }, - GetCiv: function() { return "gaia"; }, - GetColor: function() { return { r: 1, g: 1, b: 1, a: 1}; }, - CanControlAllUnits: function() { return false; }, - GetPopulationCount: function() { return 10; }, - GetPopulationLimit: function() { return 20; }, - GetMaxPopulation: function() { return 200; }, - GetResourceCounts: function() { return { food: 100 }; }, - GetPanelEntities: function() { return []; }, - IsTrainingBlocked: function() { return false; }, - GetState: function() { return "active"; }, - GetTeam: function() { return -1; }, - GetLockTeams: function() { return false; }, - GetCheatsEnabled: function() { return false; }, - GetDiplomacy: function() { return [-1, 1]; }, - IsAlly: function() { return false; }, - IsMutualAlly: function() { return false; }, - IsNeutral: function() { return false; }, - IsEnemy: function() { return true; }, - GetDisabledTemplates: function() { return {}; }, - GetDisabledTechnologies: function() { return {}; }, - GetSpyCostMultiplier: function() { return 1; }, - HasSharedDropsites: function() { return false; }, - HasSharedLos: function() { return false; } + "GetName": function() { return "Player 1"; }, + "GetCiv": function() { return "gaia"; }, + "GetColor": function() { return { "r": 1, "g": 1, "b": 1, "a": 1 }; }, + "CanControlAllUnits": function() { return false; }, + "GetPopulationCount": function() { return 10; }, + "GetPopulationLimit": function() { return 20; }, + "GetMaxPopulation": function() { return 200; }, + "GetResourceCounts": function() { return { "food": 100 }; }, + "GetPanelEntities": function() { return []; }, + "IsTrainingBlocked": function() { return false; }, + "GetState": function() { return "active"; }, + "GetTeam": function() { return -1; }, + "GetLockTeams": function() { return false; }, + "GetCheatsEnabled": function() { return false; }, + "GetDiplomacy": function() { return [-1, 1]; }, + "IsAlly": function() { return false; }, + "IsMutualAlly": function() { return false; }, + "IsNeutral": function() { return false; }, + "IsEnemy": function() { return true; }, + "GetDisabledTemplates": function() { return {}; }, + "GetDisabledTechnologies": function() { return {}; }, + "GetSpyCostMultiplier": function() { return 1; }, + "HasSharedDropsites": function() { return false; }, + "HasSharedLos": function() { return false; } }); AddMock(100, IID_EntityLimits, { - GetLimits: function() { return {"Foo": 10}; }, - GetCounts: function() { return {"Foo": 5}; }, - GetLimitChangers: function() {return {"Foo": {}}; } + "GetLimits": function() { return { "Foo": 10 }; }, + "GetCounts": function() { return { "Foo": 5 }; }, + "GetLimitChangers": function() {return { "Foo": {} }; } }); AddMock(100, IID_TechnologyManager, { @@ -134,7 +134,7 @@ }); AddMock(100, IID_StatisticsTracker, { - GetBasicStatistics: function() { + "GetBasicStatistics": function() { return { "resourcesGathered": { "food": 100, @@ -146,7 +146,7 @@ "percentMapExplored": 10 }; }, - GetSequences: function() { + "GetSequences": function() { return { "unitsTrained": [0, 10], "unitsLost": [0, 42], @@ -171,42 +171,42 @@ "teamPeakPercentOfMapControlled": [0, 10] }; }, - IncreaseTrainedUnitsCounter: function() { return 1; }, - IncreaseConstructedBuildingsCounter: function() { return 1; }, - IncreaseBuiltCivCentresCounter: function() { return 1; } + "IncreaseTrainedUnitsCounter": function() { return 1; }, + "IncreaseConstructedBuildingsCounter": function() { return 1; }, + "IncreaseBuiltCivCentresCounter": function() { return 1; } }); AddMock(101, IID_Player, { - GetName: function() { return "Player 2"; }, - GetCiv: function() { return "mace"; }, - GetColor: function() { return { r: 1, g: 0, b: 0, a: 1}; }, - CanControlAllUnits: function() { return true; }, - GetPopulationCount: function() { return 40; }, - GetPopulationLimit: function() { return 30; }, - GetMaxPopulation: function() { return 300; }, - GetResourceCounts: function() { return { food: 200 }; }, - GetPanelEntities: function() { return []; }, - IsTrainingBlocked: function() { return false; }, - GetState: function() { return "active"; }, - GetTeam: function() { return -1; }, - GetLockTeams: function() {return false; }, - GetCheatsEnabled: function() { return false; }, - GetDiplomacy: function() { return [-1, 1]; }, - IsAlly: function() { return true; }, - IsMutualAlly: function() {return false; }, - IsNeutral: function() { return false; }, - IsEnemy: function() { return false; }, - GetDisabledTemplates: function() { return {}; }, - GetDisabledTechnologies: function() { return {}; }, - GetSpyCostMultiplier: function() { return 1; }, - HasSharedDropsites: function() { return false; }, - HasSharedLos: function() { return false; } + "GetName": function() { return "Player 2"; }, + "GetCiv": function() { return "mace"; }, + "GetColor": function() { return { "r": 1, "g": 0, "b": 0, "a": 1 }; }, + "CanControlAllUnits": function() { return true; }, + "GetPopulationCount": function() { return 40; }, + "GetPopulationLimit": function() { return 30; }, + "GetMaxPopulation": function() { return 300; }, + "GetResourceCounts": function() { return { "food": 200 }; }, + "GetPanelEntities": function() { return []; }, + "IsTrainingBlocked": function() { return false; }, + "GetState": function() { return "active"; }, + "GetTeam": function() { return -1; }, + "GetLockTeams": function() {return false; }, + "GetCheatsEnabled": function() { return false; }, + "GetDiplomacy": function() { return [-1, 1]; }, + "IsAlly": function() { return true; }, + "IsMutualAlly": function() {return false; }, + "IsNeutral": function() { return false; }, + "IsEnemy": function() { return false; }, + "GetDisabledTemplates": function() { return {}; }, + "GetDisabledTechnologies": function() { return {}; }, + "GetSpyCostMultiplier": function() { return 1; }, + "HasSharedDropsites": function() { return false; }, + "HasSharedLos": function() { return false; } }); AddMock(101, IID_EntityLimits, { - GetLimits: function() { return {"Bar": 20}; }, - GetCounts: function() { return {"Bar": 0}; }, - GetLimitChangers: function() {return {"Bar": {}}; } + "GetLimits": function() { return { "Bar": 20 }; }, + "GetCounts": function() { return { "Bar": 0 }; }, + "GetLimitChangers": function() {return { "Bar": {} }; } }); AddMock(101, IID_TechnologyManager, { @@ -219,7 +219,7 @@ }); AddMock(101, IID_StatisticsTracker, { - GetBasicStatistics: function() { + "GetBasicStatistics": function() { return { "resourcesGathered": { "food": 100, @@ -231,7 +231,7 @@ "percentMapExplored": 10 }; }, - GetSequences: function() { + "GetSequences": function() { return { "unitsTrained": [0, 10], "unitsLost": [0, 9], @@ -256,119 +256,119 @@ "teamPeakPercentOfMapControlled": [0, 10] }; }, - IncreaseTrainedUnitsCounter: function() { return 1; }, - IncreaseConstructedBuildingsCounter: function() { return 1; }, - IncreaseBuiltCivCentresCounter: function() { return 1; } + "IncreaseTrainedUnitsCounter": function() { return 1; }, + "IncreaseConstructedBuildingsCounter": function() { return 1; }, + "IncreaseBuiltCivCentresCounter": function() { return 1; } }); // Note: property order matters when using TS_ASSERT_UNEVAL_EQUALS, // because uneval preserves property order. So make sure this object // matches the ordering in GuiInterface. TS_ASSERT_UNEVAL_EQUALS(cmp.GetSimulationState(), { - players: [ + "players": [ { - name: "Player 1", - civ: "gaia", - color: { r:1, g:1, b:1, a:1 }, - controlsAll: false, - popCount: 10, - popLimit: 20, - popMax: 200, - panelEntities: [], - resourceCounts: { food: 100 }, - trainingBlocked: false, - state: "active", - team: -1, - teamsLocked: false, - cheatsEnabled: false, - disabledTemplates: {}, - disabledTechnologies: {}, - hasSharedDropsites: false, - hasSharedLos: false, - spyCostMultiplier: 1, - phase: "village", - isAlly: [false, false], - isMutualAlly: [false, false], - isNeutral: [false, false], - isEnemy: [true, true], - entityLimits: {"Foo": 10}, - entityCounts: {"Foo": 5}, - entityLimitChangers: {"Foo": {}}, - researchQueued: new Map(), - researchStarted: new Set(), - researchedTechs: new Set(), - classCounts: {}, - typeCountsByClass: {}, - canBarter: false, - barterPrices: { + "name": "Player 1", + "civ": "gaia", + "color": { "r": 1, "g": 1, "b": 1, "a": 1 }, + "controlsAll": false, + "popCount": 10, + "popLimit": 20, + "popMax": 200, + "panelEntities": [], + "resourceCounts": { "food": 100 }, + "trainingBlocked": false, + "state": "active", + "team": -1, + "teamsLocked": false, + "cheatsEnabled": false, + "disabledTemplates": {}, + "disabledTechnologies": {}, + "hasSharedDropsites": false, + "hasSharedLos": false, + "spyCostMultiplier": 1, + "phase": "village", + "isAlly": [false, false], + "isMutualAlly": [false, false], + "isNeutral": [false, false], + "isEnemy": [true, true], + "entityLimits": { "Foo": 10 }, + "entityCounts": { "Foo": 5 }, + "entityLimitChangers": { "Foo": {} }, + "researchQueued": new Map(), + "researchStarted": new Set(), + "researchedTechs": new Set(), + "classCounts": {}, + "typeCountsByClass": {}, + "canBarter": false, + "barterPrices": { "buy": { "food": 150 }, "sell": { "food": 25 } }, - statistics: { - resourcesGathered: { - food: 100, - wood: 0, - metal: 0, - stone: 0, - vegetarianFood: 0 + "statistics": { + "resourcesGathered": { + "food": 100, + "wood": 0, + "metal": 0, + "stone": 0, + "vegetarianFood": 0 }, - percentMapExplored: 10 + "percentMapExplored": 10 } }, { - name: "Player 2", - civ: "mace", - color: { r:1, g:0, b:0, a:1 }, - controlsAll: true, - popCount: 40, - popLimit: 30, - popMax: 300, - panelEntities: [], - resourceCounts: { food: 200 }, - trainingBlocked: false, - state: "active", - team: -1, - teamsLocked: false, - cheatsEnabled: false, - disabledTemplates: {}, - disabledTechnologies: {}, - hasSharedDropsites: false, - hasSharedLos: false, - spyCostMultiplier: 1, - phase: "village", - isAlly: [true, true], - isMutualAlly: [false, false], - isNeutral: [false, false], - isEnemy: [false, false], - entityLimits: {"Bar": 20}, - entityCounts: {"Bar": 0}, - entityLimitChangers: {"Bar": {}}, - researchQueued: new Map(), - researchStarted: new Set(), - researchedTechs: new Set(), - classCounts: {}, - typeCountsByClass: {}, - canBarter: false, - barterPrices: { + "name": "Player 2", + "civ": "mace", + "color": { "r": 1, "g": 0, "b": 0, "a": 1 }, + "controlsAll": true, + "popCount": 40, + "popLimit": 30, + "popMax": 300, + "panelEntities": [], + "resourceCounts": { "food": 200 }, + "trainingBlocked": false, + "state": "active", + "team": -1, + "teamsLocked": false, + "cheatsEnabled": false, + "disabledTemplates": {}, + "disabledTechnologies": {}, + "hasSharedDropsites": false, + "hasSharedLos": false, + "spyCostMultiplier": 1, + "phase": "village", + "isAlly": [true, true], + "isMutualAlly": [false, false], + "isNeutral": [false, false], + "isEnemy": [false, false], + "entityLimits": { "Bar": 20 }, + "entityCounts": { "Bar": 0 }, + "entityLimitChangers": { "Bar": {} }, + "researchQueued": new Map(), + "researchStarted": new Set(), + "researchedTechs": new Set(), + "classCounts": {}, + "typeCountsByClass": {}, + "canBarter": false, + "barterPrices": { "buy": { "food": 150 }, "sell": { "food": 25 } }, - statistics: { - resourcesGathered: { - food: 100, - wood: 0, - metal: 0, - stone: 0, - vegetarianFood: 0 + "statistics": { + "resourcesGathered": { + "food": 100, + "wood": 0, + "metal": 0, + "stone": 0, + "vegetarianFood": 0 }, - percentMapExplored: 10 + "percentMapExplored": 10 } } ], - circularMap: false, - timeElapsed: 0, + "circularMap": false, + "timeElapsed": 0, "victoryConditions": ["conquest", "wonder"], - alliedVictory: false + "alliedVictory": false }); TS_ASSERT_UNEVAL_EQUALS(cmp.GetExtendedSimulationState(), { @@ -376,7 +376,7 @@ { "name": "Player 1", "civ": "gaia", - "color": { "r":1, "g":1, "b":1, "a":1 }, + "color": { "r": 1, "g": 1, "b": 1, "a": 1 }, "controlsAll": false, "popCount": 10, "popLimit": 20, @@ -398,9 +398,9 @@ "isMutualAlly": [false, false], "isNeutral": [false, false], "isEnemy": [true, true], - "entityLimits": {"Foo": 10}, - "entityCounts": {"Foo": 5}, - "entityLimitChangers": {"Foo": {}}, + "entityLimits": { "Foo": 10 }, + "entityCounts": { "Foo": 5 }, + "entityLimitChangers": { "Foo": {} }, "researchQueued": new Map(), "researchStarted": new Set(), "researchedTechs": new Set(), @@ -448,7 +448,7 @@ { "name": "Player 2", "civ": "mace", - "color": { "r":1, "g":0, "b":0, "a":1 }, + "color": { "r": 1, "g": 0, "b": 0, "a": 1 }, "controlsAll": true, "popCount": 40, "popLimit": 30, @@ -470,9 +470,9 @@ "isMutualAlly": [false, false], "isNeutral": [false, false], "isEnemy": [false, false], - "entityLimits": {"Bar": 20}, - "entityCounts": {"Bar": 0}, - "entityLimitChangers": {"Bar": {}}, + "entityLimits": { "Bar": 20 }, + "entityCounts": { "Bar": 0 }, + "entityLimitChangers": { "Bar": {} }, "researchQueued": new Map(), "researchStarted": new Set(), "researchedTechs": new Set(), @@ -526,35 +526,35 @@ AddMock(10, IID_Builder, { - GetEntitiesList: function() { + "GetEntitiesList": function() { return ["test1", "test2"]; }, }); AddMock(10, IID_Health, { - GetHitpoints: function() { return 50; }, - GetMaxHitpoints: function() { return 60; }, - IsRepairable: function() { return false; }, - IsUnhealable: function() { return false; } + "GetHitpoints": function() { return 50; }, + "GetMaxHitpoints": function() { return 60; }, + "IsRepairable": function() { return false; }, + "IsUnhealable": function() { return false; } }); AddMock(10, IID_Identity, { - GetClassesList: function() { return ["class1", "class2"]; }, - GetVisibleClassesList: function() { return ["class3", "class4"]; }, - GetRank: function() { return "foo"; }, - GetSelectionGroupName: function() { return "Selection Group Name"; }, - HasClass: function() { return true; }, - IsUndeletable: function() { return false; }, - HasSomeFormation: function() { return false; }, - GetFormationsList: function() { return []; }, + "GetClassesList": function() { return ["class1", "class2"]; }, + "GetVisibleClassesList": function() { return ["class3", "class4"]; }, + "GetRank": function() { return "foo"; }, + "GetSelectionGroupName": function() { return "Selection Group Name"; }, + "HasClass": function() { return true; }, + "IsUndeletable": function() { return false; }, + "HasSomeFormation": function() { return false; }, + "GetFormationsList": function() { return []; }, }); AddMock(10, IID_Position, { - GetTurretParent: function() {return INVALID_ENTITY;}, - GetPosition: function() { - return {x:1, y:2, z:3}; + "GetTurretParent": function() { return INVALID_ENTITY; }, + "GetPosition": function() { + return { "x": 1, "y": 2, "z": 3 }; }, - IsInWorld: function() { + "IsInWorld": function() { return true; } }); @@ -580,7 +580,7 @@ "hasSomeFormation": false, "formations": [], }, - "position": {x:1, y:2, z:3}, + "position": { "x": 1, "y": 2, "z": 3 }, "hitpoints": 50, "maxHitpoints": 60, "needsRepair": false, @@ -588,7 +588,7 @@ "builder": true, "canGarrison": false, "visibility": "visible", - "isBarterMarket":true, + "isBarterMarket": true, "resourceTrickle": { "interval": 1250, "rates": { "food": 2, "wood": 3, "stone": 5, "metal": 9 }