Bridge attachment, population and release

The DAAPI module factory can attach a Flash bridge with autoPopulate=False. Installing the Python script and populating the entity are separate steps. The module's creation guard follows bridge attachment; the bridge's initialized guard separately prevents normal repeated attachment from automatically rebinding it.

During destruction, the module catches an ordinary Flash-dispose exception and continues detaching. Superclass or detach errors are outside that local catch and can skip later release steps. DisposableEntity.destroy can log an escaping destruction error and still publish the disposed state. Inspect the actual cleanup path before using that state as proof that bridge and application references were released.

These boundaries were checked against current Python source and recording bridge substitutes. Actual Flash objects, native cleanup and client lifecycle behavior were not tested.

Provider refresh and row delivery

DAAPIDataProvider.refresh sends the current length to Flash when attached. It does not build, snapshot, sort or wrap the rows. The current lobby ActionScript provider invalidates its range cache and announces a change; a later range request can pull the rows.

Python pulls read the current collection and apply the item wrapper then. Sortable variants obtain their sorted collection on each pull, and range endpoints are inclusive. Setting sort fields with pySortOn does not itself refresh. Check subclass ordering overrides rather than assuming refresh fixes the order of later reads.

Partial updates forward the supplied row payload and index directly. They do not update the backing collection, apply its wrapper, resolve sorted positions or use the full-refresh absent-bridge guard. Keep backing rows consistent for future pulls and supply payloads and indices matching the displayed order. The inspected consumer explicitly supplies its own build, update and ordering policy.

Selected Python methods ran with recording bridges and list/wrapper substitutes; the frontend cache branches were source-inspected. Flash rendering, marshalling, runtime timing and installed bytecode parity were not tested.

Page rows, controls and saved queries have different meanings

The client ListPaginator base changes its offset before requesting a page. Its movement methods do not consult their movement predicates; the inspected view supplies its button and cooldown gates. Restoring an offset changes that position only, without restoring the previous result rows.

The concrete ClanFinder provider requests one more row than its page size. When the parsed row count equals that requested count, it sets its next-page flag and removes the final sentinel; the separately reported total does not calculate that flag. Its movement predicates also use the latest response status. Result rows, total and lookup mapping are replaced before any failure-driven offset rollback. A truthy envelope containing an empty items list follows a different rollback branch from a falsy response payload.

In this provider, requestLastSuccess() restores query fields and requests again; it does not replay cached rows. The saved record belongs to successful recommended-query mode, so a later successful ordinary search does not replace it. Verify the concrete provider's saved state rather than treating the method name as a complete success history.

Current-source and synthetic page/context checks establish these Python state boundaries. Real request ordering, server totals, item wrapping and native UI rendering were not tested.

Input and sizing

Overlay windows must publish their real size and avoid capturing input outside their visible panel. Fullscreen browser surfaces cannot provide true click-through to classic HUD elements underneath. See Gameface Modding for the complete resource, window, model, sizing, scaling, and lifecycle patterns.

Single-file UI ownership

_ui = {
    'window': None,
    'subscriptions': [],
}

def _show_window():
    if _ui['window'] is not None:
        return
    window = _create_verified_window()
    _ui['window'] = window
    window.load()

def _hide_window():
    window = _ui.pop('window', None)
    if window is not None:
        window.destroy()
    _unsubscribe_view_events()

Common mistakes

  • Using a Scaleform hook for a Gameface screen or vice versa.
  • Keeping generated view-model objects after their view closes.
  • Creating duplicate windows on repeated lifecycle events.
  • Assuming a loaded window has already published its final browser surface size.
  • Binding anonymous or freshly bound handlers that cannot later be removed.

Verification trail

Trace view registration, creation, model generation, resource loading, and destruction. Test navigation away and back, account/battle transitions, resolution changes, and repeated initialization.

Cross-runtime completion and layout

A Python-to-AS3 DAAPI call and the reverse callback form a transaction. Flash can visibly update while a missing reverse callback leaves Python logical state stale. Repeated native input can then keep calculating neighbors from one old index. Observe both directions and reconcile only through the original transaction after its normal completion opportunity.

Native layout can run after a display-coordinate write. If recovery needs a next-frame reapply, preserve it on both real-callback and bounded reconciliation paths. Root display scaling is not an interchangeable native interactive-size operation: previous scoped minimap observations changed hit bounds without cleanly restoring later native sizing.

A plugin parent can be a weak proxy, so Python is-identity is not automatically a valid attachment guard. Prefer the owner lifecycle and verified current attachment semantics. Keep this Scaleform transaction separate from Gameface model publication.