Page MenuHomeWildfire Games

Read-only Gate selection panel issue
ClosedPublic

Authored by temple on Nov 1 2017, 11:39 PM.

Details

Summary

Selecting a locked gate and an unlocked gate at the same time gives this error:

ERROR: JavaScript error: gui/session/selection_panels.js line 451
TypeError: property "locked" is non-configurable and can't be deleted

Test Plan

Patch fixes it.

Diff Detail

Repository
rP 0 A.D. Public Repository
Lint
Automatic diff as part of commit; lint not applicable.
Unit
Automatic diff as part of commit; unit tests not applicable.

Event Timeline

temple created this revision.Nov 1 2017, 11:39 PM
elexis added a subscriber: elexis.

Nice find. If you ever see such read-only errors, you can assign me. #4257

The unintentional entity state modification you discovered was introduced by rP15375.
The issue never surfaced (until rP20100) because only this one place reads from that entity state property.

How about displayLocked = state.gate.locked to avoid the clone? (primitives are copied instead of referenced)
(Not a huge performance gain, but doing something odd and then undoing something odd seems odd to the reader when it could just set a bool)

If so, GATE_ACTIONS seems worth to delete, especially when looking how the only place that uses it, uses it. (If we want such a thing, it should contain filenames)
Those two hidden = setts could be unified.

binaries/data/mods/public/gui/session/selection_panels.js
451 ↗(On Diff #4066)

So this intended to delete the locked property of gates, but changed the entity state, because it set a reference of the`gates[i].gate` object to the entity state gate.

elexis retitled this revision from Clone state.gate to Read-only Gate selection panel issue.Nov 2 2017, 12:38 AM
elexis awarded a token.
temple updated this revision to Diff 4072.Nov 2 2017, 5:21 AM

data.neededResources, does that mean in some mods it costs resources every time you open or close a gate?

elexis added inline comments.Nov 4 2017, 9:27 PM
binaries/data/mods/public/gui/session/selection_panels.js
434 ↗(On Diff #4072)

(Possibly if (!state.gate)\n continue;)

462 ↗(On Diff #4072)

Isn't x == !y equal to x != y here?

464 ↗(On Diff #4072)

I don't see anything filling out neededResources, in which case this part of the line would be misleading and should be removed (If someone wants to create a campaign where unlocking some specific gate costs resources, it needs to be revised anyway)

451 ↗(On Diff #4066)

I still find this getItems function odd. Is it only me or can that be simplified? (Maybe the name likely wasn't the ideal recommendation. Possibly needs a rename or value inversion)
Thought about only making the loop determine two variables displayLock and displayUnlock and returning the array with the two objects or an empty array, but I got to doubt whether that would finally improve it.
(Also having only false and true seems easier than also using undefined)

temple updated this revision to Diff 4094.Nov 4 2017, 10:13 PM
temple marked an inline comment as done.
temple added inline comments.
binaries/data/mods/public/gui/session/selection_panels.js
462 ↗(On Diff #4072)

This was a clever way of handling the case when data.item.displayLocked = undefined, where we want to show the selection on both, meaning hidden should be false.

temple updated this revision to Diff 4095.Nov 5 2017, 1:35 AM

Another version.

elexis added a comment.Nov 5 2017, 9:22 AM

That is much easier to comprehend!
!some = every
It might be irrelevant, but iirc the selection panel code is performance-critical and executed for all entities in the selection, regardless on whether it's a gate.
So either a quick performance test ruling out the performance aspect of using two loops, or use only one loop / array function.
(reduce could do it, but that is not always readable.)

binaries/data/mods/public/gui/session/selection_panels.js
462 ↗(On Diff #4072)

path + (locked ? file1 : file2) was nicer IMO (filenames should be easily to search & replace in the code in case the icon changes)
Making the icon and tooltip part of the returned object didn't seem wrong.
The one thing that is duplicate is the callback function and can be inlined to begin with.
locked can be removed then too afaics.

wraitii added a subscriber: wraitii.Nov 5 2017, 9:33 AM
In D1004#39776, @elexis wrote:

It might be irrelevant, but iirc the selection panel code is performance-critical and executed for all entities in the selection, regardless on whether it's a gate.

I think the issue we had was from calling GetEntityState() through the GUI Interface. Unless you're selecting a stupid amount of entities, I don't believe it'd matter in this case (then again, checking never hurts).

temple updated this revision to Diff 4098.EditedNov 5 2017, 4:42 PM

For 100 entities, took 0ms or occasionally 1ms. Alert does some() three times, that's where I got the idea.

temple updated this revision to Diff 4099.Nov 5 2017, 4:46 PM
elexis added a comment.Nov 5 2017, 5:04 PM
In D1004#39818, @temple wrote:

Alert does some() three times, that's where I got the idea.

Ah, that was rP18773. (That added a lot of overhead as it requested the extended entity state of all entities to determine whether an action is possible whereas before it only looked for the first selected entity, which can change easily depending on the selection order.)

For 100 entities, took 0ms or occasionally 1ms.

A cpu cycle consumes more than 0. We have Engine.GetMicroseconds(); for a higher precision.
We intend to reduce the turn length from 500ms down to 100-200ms eventually, so a millisecond is not irrelevant.
Also missing a comparison to using only one loop.

I don't know, I got a complaint once for doing two loops where one is sufficient. Someone else said it's ok because O(n) + O(n) = O(n).
Patch looks very good to me, I'll test it for correctness and performance later.

Imarok added a subscriber: Imarok.Nov 5 2017, 5:06 PM
In D1004#39822, @elexis wrote:
In D1004#39818, @temple wrote:

Alert does some() three times, that's where I got the idea.

Ah, that was rP18773. (That added a lot of overhead as it requested the extended entity state of all entities to determine whether an action is possible whereas before it only looked for the first selected entity, which can change easily depending on the selection order.)

No it was rP18733...

elexis accepted this revision.Nov 5 2017, 5:08 PM

(Well my working copy is empty and I was curious.)

Not sure how you got to 1ms, it consumes < 10 microseconds on my end.

Thanks for the fix and the wonderful cleanup!

This revision is now accepted and ready to land.Nov 5 2017, 5:08 PM
temple added a comment.Nov 5 2017, 5:31 PM
In D1004#39826, @elexis wrote:

Not sure how you got to 1ms, it consumes < 10 microseconds on my end.

I have an old computer, plus I said "occasionally". :)

Fluctuates but maybe 25 microseconds with the patch, 15 with a loop, with 200 entities.

Thanks for the suggestions and review.

elexis added a comment.Nov 5 2017, 5:50 PM

(Also there are many more possible performance optimizations. For instance Im not sure if creating an array in getItems and then parsing that in setupButton is better than doing both in the same function and updating the GUI objects directly.)
(jshint can find such things, one can run it from command line. ah well, we got it on phabricator meanwhile :P)

binaries/data/mods/public/gui/session/selection_panels.js
450 ↗(On Diff #4099)

(removing trailing commas and putting that opening brace on a separate line)

462 ↗(On Diff #4072)

Unifying session/ and icons/file.png.
Somone should take all png paths from gui/ as absolute paths and move them to a JSON file so mods can replace them easily.

This revision was automatically updated to reflect the committed changes.
elexis added a comment.Nov 5 2017, 6:26 PM

(Also I may not claim readability, but the formula is now in Prenex normal form following the !some to every change, so yay.)

In D1004#39823, @Imarok wrote:
In D1004#39822, @elexis wrote:
In D1004#39818, @temple wrote:

Alert does some() three times, that's where I got the idea.

Ah, that was rP18773. (That added a lot of overhead as it requested the extended entity state of all entities to determine whether an action is possible whereas before it only looked for the first selected entity, which can change easily depending on the selection order.)

No it was rP18733...

The three some calls come from rP18773 (last time I checked).
The second sentence would be more accurate by stating that rP18733 made it slow without a good reason and rP18773 added few more non-good reasons.
As I saw you assigned yourself to #4322, tell me if you need assistance.
(I expect it should be possible to do the GUIInterface querying more concisely (which is currently massive object construction + parsing from many simulation component JS objects + clone + all of that for hundreds entities).
For instance having a getter for each component of an entity, or getters for a set of properties (i.e. more groups than "simple" and "extended"). Needs exploration on feasibility and a performance evaluation though.)