Page MenuHomeWildfire Games

Entities panel error out on hero death
Needs ReviewPublic

Authored by bb on Mar 17 2018, 2:12 AM.
This revision needs review, but there are no reviewers specified.

Details

Reviewers
None
Trac Tickets
#5504
Summary

Noticed by Feldfeld nani and myself in an svn match on jebel barkal the entPanelbuttons placement can error out. This happens we there are 20 or more panelEnts (13 relics and 8 heroes in this case) and one of the heroes is killed and afterwards a new hero is created (we were in observer mode, players didn't notice). The placement code tries to reuse old slots but the heroes are always displayed before the relics so it when the new hero is trained all buttons are filled, but we want to add a new icon, but we can't find a free index, thus finding a nonexisting gui index errors out.

Fixing it by only trying to keep actually displayed buttons on the same index.

Test Plan

Use this replay to see the bug solved:

Diff Detail

Repository
rP 0 A.D. Public Repository
Branch
/ps/trunk
Lint
Lint OK
Unit
No Unit Test Coverage
Build Status
Buildable 8441
Build 13788: Vulcan BuildJenkins
Build 13787: arc lint + arc unit

Event Timeline

bb created this revision.Mar 17 2018, 2:12 AM
Vulcan added a subscriber: Vulcan.Mar 17 2018, 4:23 AM

Successful build - Chance fights ever on the side of the prudent.

Linter detected issues:
Executing section Default...
Executing section Source...
Executing section JS...
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 6 tabs but found 5.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/gui/session/session.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/gui/session/session.js
| 412| 412| 				// Players see colors depending on diplomacy
| 413| 413| 				g_DisplayedPlayerColors[i] =
| 414| 414| 					g_ViewedPlayer == i ? getDiplomacyColor("self") :
| 415|    |-					g_Players[g_ViewedPlayer].isAlly[i] ? getDiplomacyColor("ally") :
|    | 415|+						g_Players[g_ViewedPlayer].isAlly[i] ? getDiplomacyColor("ally") :
| 416| 416| 					g_Players[g_ViewedPlayer].isNeutral[i] ? getDiplomacyColor("neutral") :
| 417| 417| 					getDiplomacyColor("enemy");
| 418| 418| 
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 7 tabs but found 5.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/gui/session/session.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/gui/session/session.js
| 413| 413| 				g_DisplayedPlayerColors[i] =
| 414| 414| 					g_ViewedPlayer == i ? getDiplomacyColor("self") :
| 415| 415| 					g_Players[g_ViewedPlayer].isAlly[i] ? getDiplomacyColor("ally") :
| 416|    |-					g_Players[g_ViewedPlayer].isNeutral[i] ? getDiplomacyColor("neutral") :
|    | 416|+							g_Players[g_ViewedPlayer].isNeutral[i] ? getDiplomacyColor("neutral") :
| 417| 417| 					getDiplomacyColor("enemy");
| 418| 418| 
| 419| 419| 		g_DisplayedPlayerColors[0] = g_Players[0].color;
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 8 tabs but found 5.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/gui/session/session.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/gui/session/session.js
| 414| 414| 					g_ViewedPlayer == i ? getDiplomacyColor("self") :
| 415| 415| 					g_Players[g_ViewedPlayer].isAlly[i] ? getDiplomacyColor("ally") :
| 416| 416| 					g_Players[g_ViewedPlayer].isNeutral[i] ? getDiplomacyColor("neutral") :
| 417|    |-					getDiplomacyColor("enemy");
|    | 417|+								getDiplomacyColor("enemy");
| 418| 418| 
| 419| 419| 		g_DisplayedPlayerColors[0] = g_Players[0].color;
| 420| 420| 	}
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 4 tabs but found 3.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/gui/session/session.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/gui/session/session.js
| 659| 659| 					"civ": setStringTags(g_CivData[g_Players[g_ViewedPlayer].civ].Name, { "font": "sans-bold-stroke-14" }),
| 660| 660| 					"hotkey_civinfo": colorizeHotkey("%(hotkey)s", "civinfo"),
| 661| 661| 					"hotkey_structree": colorizeHotkey("%(hotkey)s", "structree")
| 662|    |-			});
|    | 662|+				});
| 663| 663| 	}
| 664| 664| 
| 665| 665| 	Engine.GetGUIObjectByName("optionFollowPlayer").hidden = !g_IsObserver ||
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 3 tabs but found 2.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/gui/session/session.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/gui/session/session.js
|1254|1254| 
|1255|1255| 	let orderHotkeyTooltip = Object.keys(viewablePlayerStates).length <= 1 ? "" :
|1256|1256| 		"\n" + sprintf(translate("%(order)s: %(hotkey)s to change order."), {
|1257|    |-		"hotkey": setStringTags("\\[Click]", g_HotkeyTags),
|    |1257|+			"hotkey": setStringTags("\\[Click]", g_HotkeyTags),
|1258|1258| 		"order": tooltipSort == 0 ? translate("Unordered") : tooltipSort == 1 ? translate("Descending") : translate("Ascending")
|1259|1259| 	});
|1260|1260| 
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 3 tabs but found 2.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/gui/session/session.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/gui/session/session.js
|1255|1255| 	let orderHotkeyTooltip = Object.keys(viewablePlayerStates).length <= 1 ? "" :
|1256|1256| 		"\n" + sprintf(translate("%(order)s: %(hotkey)s to change order."), {
|1257|1257| 		"hotkey": setStringTags("\\[Click]", g_HotkeyTags),
|1258|    |-		"order": tooltipSort == 0 ? translate("Unordered") : tooltipSort == 1 ? translate("Descending") : translate("Ascending")
|    |1258|+			"order": tooltipSort == 0 ? translate("Unordered") : tooltipSort == 1 ? translate("Descending") : translate("Ascending")
|1259|1259| 	});
|1260|1260| 
|1261|1261| 	let resCodes = g_ResourceData.GetCodes();
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 2 tabs but found 1.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/gui/session/session.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/gui/session/session.js
|1256|1256| 		"\n" + sprintf(translate("%(order)s: %(hotkey)s to change order."), {
|1257|1257| 		"hotkey": setStringTags("\\[Click]", g_HotkeyTags),
|1258|1258| 		"order": tooltipSort == 0 ? translate("Unordered") : tooltipSort == 1 ? translate("Descending") : translate("Ascending")
|1259|    |-	});
|    |1259|+		});
|1260|1260| 
|1261|1261| 	let resCodes = g_ResourceData.GetCodes();
|1262|1262| 	for (let r = 0; r < resCodes.length; ++r)
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 1 tab but found 3.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/gui/session/session.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/gui/session/session.js
|1754|1754| 	for (let rct of resourcesCounterTypes)
|1755|1755| 		for (let rt of resourcesTypes)
|1756|1756| 			reportObject[rt + rct.substr(9)] = playerStatistics[rct][rt];
|1757|    |-			// eg. rt = food rct.substr = Gathered rct = resourcesGathered
|    |1757|+	// eg. rt = food rct.substr = Gathered rct = resourcesGathered
|1758|1758| 
|1759|1759| 	reportObject.vegetarianFoodGathered = playerStatistics.resourcesGathered.vegetarianFood;
|1760|1760| 	for (let type of unitsClasses)

binaries/data/mods/public/gui/session/session.js
|1078| »   let·getPanelEntNameTooltip·=·panelEntState·=>·"[font=\"sans-bold-16\"]"·+·template.name.specific·+·"[/font]";
|    | [NORMAL] ESLintBear (no-shadow):
|    | 'panelEntState' is already declared in the upper scope.

binaries/data/mods/public/gui/session/session.js
|1157| »   »   button.onpress·=·(function(i)·{·return·function()·{·performGroup((Engine.HotkeyIsPressed("selection.add")·?·"add"·:·"select"),·i);·};·})(i);
|    | [NORMAL] ESLintBear (no-shadow):
|    | 'i' is already declared in the upper scope.

binaries/data/mods/public/gui/session/session.js
|1158| »   »   button.ondoublepress·=·(function(i)·{·return·function()·{·performGroup("snap",·i);·};·})(i);
|    | [NORMAL] ESLintBear (no-shadow):
|    | 'i' is already declared in the upper scope.

binaries/data/mods/public/gui/session/session.js
|1159| »   »   button.onpressright·=·(function(i)·{·return·function()·{·performGroup("breakUp",·i);·};·})(i);
|    | [NORMAL] ESLintBear (no-shadow):
|    | 'i' is already declared in the upper scope.

Link to build: https://jenkins.wildfiregames.com/job/differential/262/display/redirect

elexis added a subscriber: elexis.Mar 18 2018, 1:04 PM

(There's also the problem that the civ icon is overlapped by the many panel entities, see rP18361.)
Error exists in a22 already, we only had it now because Hannibal insisted on using the relic-gaia exploit. So might not be a super-priority, but it should still be fixed of course.

About the patch, wouldn't it be easier to only extend the global if there is enough space rather than adding a helper variable and reducing the size of the global if its too big?

bb updated this revision to Diff 6203.Mar 18 2018, 1:57 PM
Owners added a subscriber: Restricted Owners Package.Mar 18 2018, 1:57 PM
bb added a comment.Mar 18 2018, 1:57 PM
In D1397#57350, @elexis wrote:

Error exists in a22 already, we only had it now because Hannibal insisted on using the relic-gaia exploit. So might not be a super-priority, but it should still be fixed of course.

a22 => yes, only gaia-relic exploit => nope: start a normal relic match with 13 relics and 8 players, give everyone a hero, kill a hero and respawn a hero => errors for the observers (notice this is what is done in the replay)

About the patch, wouldn't it be easier to only extend the global if there is enough space rather than adding a helper variable and reducing the size of the global if its too big?

Ah yes, was thinking the sim way were it only would be updated onOwnershipChanged, but we actually do it onTick

Successful build - Chance fights ever on the side of the prudent.

Linter detected issues:
Executing section Default...
Executing section Source...
Executing section JS...
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 6 tabs but found 5.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/gui/session/session.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/gui/session/session.js
| 412| 412| 				// Players see colors depending on diplomacy
| 413| 413| 				g_DisplayedPlayerColors[i] =
| 414| 414| 					g_ViewedPlayer == i ? getDiplomacyColor("self") :
| 415|    |-					g_Players[g_ViewedPlayer].isAlly[i] ? getDiplomacyColor("ally") :
|    | 415|+						g_Players[g_ViewedPlayer].isAlly[i] ? getDiplomacyColor("ally") :
| 416| 416| 					g_Players[g_ViewedPlayer].isNeutral[i] ? getDiplomacyColor("neutral") :
| 417| 417| 					getDiplomacyColor("enemy");
| 418| 418| 
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 7 tabs but found 5.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/gui/session/session.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/gui/session/session.js
| 413| 413| 				g_DisplayedPlayerColors[i] =
| 414| 414| 					g_ViewedPlayer == i ? getDiplomacyColor("self") :
| 415| 415| 					g_Players[g_ViewedPlayer].isAlly[i] ? getDiplomacyColor("ally") :
| 416|    |-					g_Players[g_ViewedPlayer].isNeutral[i] ? getDiplomacyColor("neutral") :
|    | 416|+							g_Players[g_ViewedPlayer].isNeutral[i] ? getDiplomacyColor("neutral") :
| 417| 417| 					getDiplomacyColor("enemy");
| 418| 418| 
| 419| 419| 		g_DisplayedPlayerColors[0] = g_Players[0].color;
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 8 tabs but found 5.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/gui/session/session.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/gui/session/session.js
| 414| 414| 					g_ViewedPlayer == i ? getDiplomacyColor("self") :
| 415| 415| 					g_Players[g_ViewedPlayer].isAlly[i] ? getDiplomacyColor("ally") :
| 416| 416| 					g_Players[g_ViewedPlayer].isNeutral[i] ? getDiplomacyColor("neutral") :
| 417|    |-					getDiplomacyColor("enemy");
|    | 417|+								getDiplomacyColor("enemy");
| 418| 418| 
| 419| 419| 		g_DisplayedPlayerColors[0] = g_Players[0].color;
| 420| 420| 	}
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 4 tabs but found 3.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/gui/session/session.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/gui/session/session.js
| 659| 659| 					"civ": setStringTags(g_CivData[g_Players[g_ViewedPlayer].civ].Name, { "font": "sans-bold-stroke-14" }),
| 660| 660| 					"hotkey_civinfo": colorizeHotkey("%(hotkey)s", "civinfo"),
| 661| 661| 					"hotkey_structree": colorizeHotkey("%(hotkey)s", "structree")
| 662|    |-			});
|    | 662|+				});
| 663| 663| 	}
| 664| 664| 
| 665| 665| 	Engine.GetGUIObjectByName("optionFollowPlayer").hidden = !g_IsObserver ||
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 3 tabs but found 2.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/gui/session/session.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/gui/session/session.js
|1252|1252| 
|1253|1253| 	let orderHotkeyTooltip = Object.keys(viewablePlayerStates).length <= 1 ? "" :
|1254|1254| 		"\n" + sprintf(translate("%(order)s: %(hotkey)s to change order."), {
|1255|    |-		"hotkey": setStringTags("\\[Click]", g_HotkeyTags),
|    |1255|+			"hotkey": setStringTags("\\[Click]", g_HotkeyTags),
|1256|1256| 		"order": tooltipSort == 0 ? translate("Unordered") : tooltipSort == 1 ? translate("Descending") : translate("Ascending")
|1257|1257| 	});
|1258|1258| 
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 3 tabs but found 2.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/gui/session/session.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/gui/session/session.js
|1253|1253| 	let orderHotkeyTooltip = Object.keys(viewablePlayerStates).length <= 1 ? "" :
|1254|1254| 		"\n" + sprintf(translate("%(order)s: %(hotkey)s to change order."), {
|1255|1255| 		"hotkey": setStringTags("\\[Click]", g_HotkeyTags),
|1256|    |-		"order": tooltipSort == 0 ? translate("Unordered") : tooltipSort == 1 ? translate("Descending") : translate("Ascending")
|    |1256|+			"order": tooltipSort == 0 ? translate("Unordered") : tooltipSort == 1 ? translate("Descending") : translate("Ascending")
|1257|1257| 	});
|1258|1258| 
|1259|1259| 	let resCodes = g_ResourceData.GetCodes();
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 2 tabs but found 1.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/gui/session/session.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/gui/session/session.js
|1254|1254| 		"\n" + sprintf(translate("%(order)s: %(hotkey)s to change order."), {
|1255|1255| 		"hotkey": setStringTags("\\[Click]", g_HotkeyTags),
|1256|1256| 		"order": tooltipSort == 0 ? translate("Unordered") : tooltipSort == 1 ? translate("Descending") : translate("Ascending")
|1257|    |-	});
|    |1257|+		});
|1258|1258| 
|1259|1259| 	let resCodes = g_ResourceData.GetCodes();
|1260|1260| 	for (let r = 0; r < resCodes.length; ++r)
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 1 tab but found 3.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/gui/session/session.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/gui/session/session.js
|1752|1752| 	for (let rct of resourcesCounterTypes)
|1753|1753| 		for (let rt of resourcesTypes)
|1754|1754| 			reportObject[rt + rct.substr(9)] = playerStatistics[rct][rt];
|1755|    |-			// eg. rt = food rct.substr = Gathered rct = resourcesGathered
|    |1755|+	// eg. rt = food rct.substr = Gathered rct = resourcesGathered
|1756|1756| 
|1757|1757| 	reportObject.vegetarianFoodGathered = playerStatistics.resourcesGathered.vegetarianFood;
|1758|1758| 	for (let type of unitsClasses)

binaries/data/mods/public/gui/session/session.js
|1080| »   let·getPanelEntNameTooltip·=·panelEntState·=>·"[font=\"sans-bold-16\"]"·+·template.name.specific·+·"[/font]";
|    | [NORMAL] ESLintBear (no-shadow):
|    | 'panelEntState' is already declared in the upper scope.

binaries/data/mods/public/gui/session/session.js
|1155| »   »   button.onpress·=·(function(i)·{·return·function()·{·performGroup((Engine.HotkeyIsPressed("selection.add")·?·"add"·:·"select"),·i);·};·})(i);
|    | [NORMAL] ESLintBear (no-shadow):
|    | 'i' is already declared in the upper scope.

binaries/data/mods/public/gui/session/session.js
|1156| »   »   button.ondoublepress·=·(function(i)·{·return·function()·{·performGroup("snap",·i);·};·})(i);
|    | [NORMAL] ESLintBear (no-shadow):
|    | 'i' is already declared in the upper scope.

binaries/data/mods/public/gui/session/session.js
|1157| »   »   button.onpressright·=·(function(i)·{·return·function()·{·performGroup("breakUp",·i);·};·})(i);
|    | [NORMAL] ESLintBear (no-shadow):
|    | 'i' is already declared in the upper scope.

Link to build: https://jenkins.wildfiregames.com/job/differential/269/display/redirect

bb updated the Trac tickets for this revision.Jul 18 2019, 12:21 PM
bb updated this revision to Diff 8976.Jul 18 2019, 12:56 PM
bb edited the test plan for this revision. (Show Details)

slice>splice

A replay for current svn:

Successful build - Chance fights ever on the side of the prudent.

Linter detected issues:
Executing section Source...
Executing section JS...
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 6 tabs but found 5.
|----|    | /zpool0/trunk/binaries/data/mods/public/gui/session/session.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/gui/session/session.js
| 392| 392| 				// Players see colors depending on diplomacy
| 393| 393| 				g_DisplayedPlayerColors[i] =
| 394| 394| 					g_ViewedPlayer == i ? getDiplomacyColor("self") :
| 395|    |-					g_Players[g_ViewedPlayer].isAlly[i] ? getDiplomacyColor("ally") :
|    | 395|+						g_Players[g_ViewedPlayer].isAlly[i] ? getDiplomacyColor("ally") :
| 396| 396| 					g_Players[g_ViewedPlayer].isNeutral[i] ? getDiplomacyColor("neutral") :
| 397| 397| 					getDiplomacyColor("enemy");
| 398| 398| 
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 7 tabs but found 5.
|----|    | /zpool0/trunk/binaries/data/mods/public/gui/session/session.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/gui/session/session.js
| 393| 393| 				g_DisplayedPlayerColors[i] =
| 394| 394| 					g_ViewedPlayer == i ? getDiplomacyColor("self") :
| 395| 395| 					g_Players[g_ViewedPlayer].isAlly[i] ? getDiplomacyColor("ally") :
| 396|    |-					g_Players[g_ViewedPlayer].isNeutral[i] ? getDiplomacyColor("neutral") :
|    | 396|+							g_Players[g_ViewedPlayer].isNeutral[i] ? getDiplomacyColor("neutral") :
| 397| 397| 					getDiplomacyColor("enemy");
| 398| 398| 
| 399| 399| 		g_DisplayedPlayerColors[0] = g_Players[0].color;
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 8 tabs but found 5.
|----|    | /zpool0/trunk/binaries/data/mods/public/gui/session/session.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/gui/session/session.js
| 394| 394| 					g_ViewedPlayer == i ? getDiplomacyColor("self") :
| 395| 395| 					g_Players[g_ViewedPlayer].isAlly[i] ? getDiplomacyColor("ally") :
| 396| 396| 					g_Players[g_ViewedPlayer].isNeutral[i] ? getDiplomacyColor("neutral") :
| 397|    |-					getDiplomacyColor("enemy");
|    | 397|+								getDiplomacyColor("enemy");
| 398| 398| 
| 399| 399| 		g_DisplayedPlayerColors[0] = g_Players[0].color;
| 400| 400| 	}
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 4 tabs but found 3.
|----|    | /zpool0/trunk/binaries/data/mods/public/gui/session/session.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/gui/session/session.js
| 644| 644| 					"civ": setStringTags(g_CivData[g_Players[g_ViewedPlayer].civ].Name, { "font": "sans-bold-stroke-14" }),
| 645| 645| 					"hotkey_civinfo": colorizeHotkey("%(hotkey)s", "civinfo"),
| 646| 646| 					"hotkey_structree": colorizeHotkey("%(hotkey)s", "structree")
| 647|    |-			});
|    | 647|+				});
| 648| 648| 	}
| 649| 649| 
| 650| 650| 	// Following gaia can be interesting on scripted maps
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 3 tabs but found 2.
|----|    | /zpool0/trunk/binaries/data/mods/public/gui/session/session.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/gui/session/session.js
|1196|1196| 
|1197|1197| 	let orderHotkeyTooltip = Object.keys(viewablePlayerStates).length <= 1 ? "" :
|1198|1198| 		"\n" + sprintf(translate("%(order)s: %(hotkey)s to change order."), {
|1199|    |-		"hotkey": setStringTags("\\[Click]", g_HotkeyTags),
|    |1199|+			"hotkey": setStringTags("\\[Click]", g_HotkeyTags),
|1200|1200| 		"order": tooltipSort == 0 ? translate("Unordered") : tooltipSort == 1 ? translate("Descending") : translate("Ascending")
|1201|1201| 	});
|1202|1202| 
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 3 tabs but found 2.
|----|    | /zpool0/trunk/binaries/data/mods/public/gui/session/session.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/gui/session/session.js
|1197|1197| 	let orderHotkeyTooltip = Object.keys(viewablePlayerStates).length <= 1 ? "" :
|1198|1198| 		"\n" + sprintf(translate("%(order)s: %(hotkey)s to change order."), {
|1199|1199| 		"hotkey": setStringTags("\\[Click]", g_HotkeyTags),
|1200|    |-		"order": tooltipSort == 0 ? translate("Unordered") : tooltipSort == 1 ? translate("Descending") : translate("Ascending")
|    |1200|+			"order": tooltipSort == 0 ? translate("Unordered") : tooltipSort == 1 ? translate("Descending") : translate("Ascending")
|1201|1201| 	});
|1202|1202| 
|1203|1203| 	let resCodes = g_ResourceData.GetCodes();
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 2 tabs but found 1.
|----|    | /zpool0/trunk/binaries/data/mods/public/gui/session/session.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/gui/session/session.js
|1198|1198| 		"\n" + sprintf(translate("%(order)s: %(hotkey)s to change order."), {
|1199|1199| 		"hotkey": setStringTags("\\[Click]", g_HotkeyTags),
|1200|1200| 		"order": tooltipSort == 0 ? translate("Unordered") : tooltipSort == 1 ? translate("Descending") : translate("Ascending")
|1201|    |-	});
|    |1201|+		});
|1202|1202| 
|1203|1203| 	let resCodes = g_ResourceData.GetCodes();
|1204|1204| 	for (let r = 0; r < resCodes.length; ++r)

binaries/data/mods/public/gui/session/session.js
|1057| »   let·getPanelEntNameTooltip·=·panelEntState·=>·"[font=\"sans-bold-16\"]"·+·template.name.specific·+·"[/font]";
|    | [NORMAL] ESLintBear (no-shadow):
|    | 'panelEntState' is already declared in the upper scope.

binaries/data/mods/public/gui/session/session.js
|1132| »   »   button.onpress·=·(function(i)·{·return·function()·{·performGroup((Engine.HotkeyIsPressed("selection.add")·?·"add"·:·"select"),·i);·};·})(i);
|    | [NORMAL] ESLintBear (no-shadow):
|    | 'i' is already declared in the upper scope.

binaries/data/mods/public/gui/session/session.js
|1133| »   »   button.ondoublepress·=·(function(i)·{·return·function()·{·performGroup("snap",·i);·};·})(i);
|    | [NORMAL] ESLintBear (no-shadow):
|    | 'i' is already declared in the upper scope.

binaries/data/mods/public/gui/session/session.js
|1134| »   »   button.onpressright·=·(function(i)·{·return·function()·{·performGroup("breakUp",·i);·};·})(i);
|    | [NORMAL] ESLintBear (no-shadow):
|    | 'i' is already declared in the upper scope.
Executing section cli...

Link to build: https://jenkins.wildfiregames.com/job/docker-differential/123/display/redirect