Larkinabout / fvtt-token-action-hud-core

Token Action HUD is a repositionable HUD of actions for a selected token.
13 stars 18 forks source link

[FEATURE] cache actions flag #104

Open dmrickey opened 1 year ago

dmrickey commented 1 year ago

Some actions that I build are never going to change for a given token. They're generic enough that they can be cached once and then just referenced from the flag that's currently stored on the actor. My "multi-token" actions never change at all, these could be stored in a non-visible game setting (I have no idea if/where those are stored now).

My build method looks like this

        /**
         * Build System Actions
         * @override
         * @param {array} subcategoryIds
         */
        async buildSystemActions(_subcategoryIds) {
            const { actor, token } = this;
            this.actorData = new ActionBuilderActorData({ actor, token });

            if (!this.actorData.isValid) {
                return;
            }

            this.#_buildSkills();
            this.#_buildSaves();
            this.#_buildChecks();
            this.#_buildConditions();

            this.#_buildCombat();
            this.#_buildBuffs();
            this.#_buildInventory();
            this.#_buildSpells();
            this.#_buildFeatures();
            this.#_buildOtherItems();
            this.#_buildUtils();
        }

But I'm thinking that if Core could pass in extra flag that says "hey I know about all of your static actions, I only need to know about actions that can change right now", then it could potentially save some time whenever the HUD needs refreshing.

I'm thinking something like this

        /**
         * Build System Actions
         * @override
         * @param {array} subcategoryIds
         * @param {bool} fullRefresh - if true then all actions should be built, if false only actions that can change should be built.
         */
        async buildSystemActions(_subcategoryIds, { fullRefresh }) {
            const { actor, token } = this;
            this.actorData = new ActionBuilderActorData({ actor, token });

            if (!this.actorData.isValid) {
                return;
            }

            // multi actions never change as they're generic enough to work for any group of tokens
            if (this.actorData.isMulti && !fullRefresh) {
                return;
            }

            // actions that are variable based on actor's Items and/or have variable data built into the name/info
            // i.e. always build
            this.#_buildCombat();
            this.#_buildBuffs();
            this.#_buildInventory();
            this.#_buildSpells();
            this.#_buildFeatures();
            this.#_buildOtherItems();
            this.#_buildSkills();

            // static actions that always exist
            // i.e. only build when action cache is invalidated
            if (fullRefresh) {
                this.#_buildSaves();
                this.#_buildChecks();
                this.#_buildConditions();
                this.#_buildUtils();
            }
        }

I can't think of a good name right now, but fullRefresh would be true whenever Core knows that the current actor hasn't had actions built for them yet (which would essentially be just the first time an actor is clicked on or whenever TAH is reset, maybe also if categories are hidden or actions are moved, I'm not sure how the internals for that work).

Probably the most important detail about this is that adding in a second "options" parameter means the method signature never has to change again if more optional params are passed in--they can just be added into the second object arg.

One last detail I'm not sure about -- actions themselves might need to be tagged with something like static: true to show that it's an action that won't change. That way if an action has static: false then Core knows for sure that the system is no longer building that (because maybe the actor no longer has that Item) instead of it not being returned because it's a static action that only needs to be built once.

Larkinabout commented 1 year ago

This could probably be better placed as a system-specific implementation by using a new flag against the actor for the system, e.g., actor.setFlag('token-action-hud-pf1', 'cachedActions'). You could then retrieve this data and pass it to Token Action HUD Core via addActionsToActionList.

Saying that, I've not noticed visible overhead to just rebuilding the actions everytime, although experience may vary depending on the complexity of the HUD and the resources available to the user's machine.

Larkinabout commented 1 year ago

Above comment is no longer applicable due to moving away from saving data to flags. As an alternative, a variable could be created within game.tokenActionHud.actionHandler to store the actions. I have just implemented this for compendium and macro actions within Token Action HUD Core.