public bool?GetOnActionStage()
        {
            StaticField current = GetCurrentScene();
            StaticField action  = GetActionStage();

            return(current.Value.Value.Address == action.Value.Value.Address);
        }
        public StaticField GetCachedStaticField(string klass, string fieldName)
        {
            // Some static fields such as the `ActionStage` are read multiple times in a single update
            // loop. We therefore cache these results to limit the number of values we have to read
            // from memory. This is done because external memory reads like we are doing are slow
            // so we'd like to reduce the number of them we make as much as possible.
            string key = string.Format("{0}.{1}", klass, fieldName);

            if (!staticCache.ContainsKey(key))
            {
                try {
                    staticCache[key] = new StaticField(pm.Runtime, klass, fieldName);
                } catch (Exception e) {
                    LogWriter.WriteLine(key);
                    throw e;
                }
            }
            return(staticCache[key]);
        }
        public ValuePointer?GetCachedValuePointer(StaticField field, string fieldName)
        {
            // See `GetCachedStaticField` for the explanation for why we want to cache `ValuePointer`.
            string key = string.Format("{0}.{1}", field.Value.Value.Type.Name, fieldName);

            if (!pointerCache.ContainsKey(key))
            {
                try {
                    ValuePointer?vp = field.Value.Value[fieldName];
                    if (vp == null)
                    {
                        return(null);
                    }
                    pointerCache[key] = vp.Value;
                } catch (Exception e) {
                    LogWriter.WriteLine(key);
                    throw e;
                }
            }
            return(pointerCache[key]);
        }