Skip to content

Game: Rework keypads and route ShowImage through the Dialog API - #3337

Merged
Flamtky merged 9 commits into
masterfrom
flamtky/dialog-api-keypad-showimage
Oct 30, 2026
Merged

Flamtky merged 9 commits into
masterfrom
flamtky/dialog-api-keypad-showimage

Conversation

@Flamtky

@Flamtky Flamtky commented Oct 30, 2026 •

Copy link
Copy Markdown
Member

Closes #2734

Keypad, Text Keypad und ShowImage laufen vollständig über die Dialog API (DialogFactory.show, DialogContext). Kein System und keine Komponente verwaltet mehr eigene Dialog- oder Overlay-Entities. Beide Keypads funktionieren gleich und prüfen über Tasks.

ShowImage

  • ShowImageUI ist der Renderer für DialogType.DefaultTypes.IMAGE und liest Bildpfad und IMAGE_TRANSITION_SPEED aus dem DialogContext. ShowImageComponent, ShowImageSystem und ShowImageText entfallen.
  • DialogUtils.showImagePopUp zeigt das Bild über DialogFactory.show. Die unbenutzte ShowImageFactory entfällt; Bilder an Objekten entstehen über das Prefab „Show Image“.

Keypads

  • Keypad und Text Keypad haben dieselbe KeypadComponent. Sie hält nur Eingabe und Anzeige: eingegebener Text, entsperrt, maximale Länge, ob die Länge mit * angezeigt wird, und ob eine falsche Antwort die Eingabe leert.
  • Geprüft wird über die TaskComponent des Keypads: NumericCodeTask beim Keypad, FreeTextTask beim Text Keypad. NumericCodeTask löst den Code bei jeder Prüfung auf, sodass das Keypad-Prefab seinen Code weiter von einem anderen Prefab bekommen kann. Reaktionen auf Antworten hängen an TaskComponent.onCorrect/onWrong.
  • KeypadFactory.submit ist der eine Absende-Pfad: Erst laufen die Task-Callbacks, dann wird das Keypad bei richtiger Antwort entsperrt oder bei falscher Antwort geleert. Das Leeren lässt sich abschalten; die Prefabs Keypad und Text Keypad haben dafür die Property „Clear On Wrong“ (Standard: an).
  • Beide Keypads haben einen gemeinsamen Dialog KeypadUI mit je einem Tastenlayout. KeypadFactory wendet die Tasten auf dem Server an und nimmt nur die Tasten des jeweiligen Layouts an. Codes haben höchstens 8 Ziffern, Text-Keypad-Antworten höchstens 32 Zeichen; Factory und Prefabs lehnen längere ab. Bis der erste Zustand ankommt, zeigt der Client ein leeres Keypad.
  • KeypadSync überträgt den Anzeigezustand beider Keypad-Arten in Spawn- und Snapshot-Metadaten. Codes und Antworten bleiben auf dem Server; vom Zahlencode kennt der Client nur die Länge.
  • The Last Hour und System Recovery nutzen diese Synchronisation statt eigener. Ihre Tür-Aktionen und das Tracking laufen in den Task-Callbacks; The Last Hour zählt vollständige falsche Codes für Achievement und Speicherstand selbst.
  • Foundation-Keypads nutzen den Standard-Keypad-Dialog und KeypadSync; FoundationSnapshotTranslator entfällt, der Wizard-Runner nutzt den Standard-Snapshot-Translator. Foundation wendet die Tasten über KeypadFactory.press an; die Auswertung bleibt bei Foundation.
  • PROTOCOL_VERSION ist 18, weil sich die Keypad-Metadaten geändert haben.

Bilder

Bild-Dialog, Keypad nach richtigem Code, Text Keypad nach richtiger Antwort (GameOfGames, gehostet mit zweitem Client)

Bild-Dialog
Keypad
Text Keypad

Image dialogs are shown through DialogFactory.show only. ShowImageUI
reads its image and transition speed from the DialogContext, so the
ShowImageComponent/ShowImageSystem path that managed its own overlay
entity is removed, together with ShowImageText, which only that path
used. DialogUtils.showImagePopUp and ShowImageFactory use
DialogFactory.show.

KeypadComponent and TextKeyPadComponent no longer hold overlay or
UI-open state; their dialogs are already owned by the Dialog API.

Refs #2734
KeypadUI renders from the client-side KeypadComponent, which no generic
sync created, so opening a numeric keypad without a room-specific sync
(e.g. the Keypad prefab) crashed the multiplayer client.

KeypadSync encodes the entered digits, code length, digit-count flag and
unlocked state in snapshot metadata, like TextKeypadSync does for text
keypads. The code itself stays on the server; the client component uses
placeholder digits of the synced length.
Spawn events carry the KeypadSync metadata and the room clients apply it,
like TextKeypadSync, so a keypad has its client component even when its
first snapshot state arrived before the spawn.
@Flamtky Flamtky self-assigned this Oct 30, 2026
LastHour already sends keypad.* metadata with a different encoding, so the
generic numeric keypad keys use numericKeypad.*, matching textKeypad.*.
Numeric and text keypads use the same KeypadComponent for their input
and display state and check answers through their TaskComponent:
NumericCodeTask for numeric keypads, FreeTextTask for text keypads.
NumericCodeTask resolves its code on every check, so the Keypad prefab
can still take its code from another prefab.

* KeypadFactory.submit unlocks the keypad on a correct answer and clears
  the input after a wrong one unless clearOnWrong is off. The Keypad and
  Text Keypad prefabs expose this as a property, defaulting to clearing.
* The keypad dialogs accept only their own buttons from clients and
  render an empty keypad until the first synchronized state arrives.
* KeypadSync replaces TextKeypadSync and covers both keypad kinds,
  including the default spawn handler in GameLoop.
* The Last Hour and System Recovery use the generic keypad sync instead
  of their own, so clients no longer receive the door codes. Their
  door actions and tracking run in the task callbacks; The Last Hour
  counts complete wrong codes for its achievement and save itself.
* Foundation keeps its own keypad dialog, evaluation and sync on top of
  the shared component.
The server now caps text keypad input like numeric input, so a client
cannot grow the synchronized text without bound. Keypad dialogs read the
optional component directly, and both System Recovery keypads share one
door helper.
@Flamtky Flamtky changed the title Game: Route Keypad and ShowImage dialogs through the Dialog API Game: Rework keypads and route ShowImage through the Dialog API Oct 30, 2026
Numeric and text keypads render through one KeypadUI with a layout per
kind, and KeypadFactory applies their buttons on the server, accepting
only the buttons of the layout.

* Text keypad answers must fit the 32-character input limit; the factory
  throws IllegalArgumentException and the prefab rejects longer answers.
* KeypadComponent uses unlocked() / unlocked(boolean).
* Foundation keypads use the default keypad dialog type and the generic
  KeypadSync, so FoundationSnapshotTranslator is gone and the Wizard
  runner uses the default snapshot translator. Foundation keeps its own
  keypad evaluation.
* The System Recovery keypad callbacks read their components directly.
Images are shown through the Show Image prefab or
DialogUtils.showImagePopUp.
Foundation keypads apply their buttons through KeypadFactory.press, so
both kinds of keypads accept and sound the same buttons. Numeric codes
are limited to 8 digits like the hidden input limit, and the Keypad
prefab validates its code with KeypadFactory.isNumericCode.
@Flamtky
Flamtky requested review from AMatutat and viddie October 30, 2026 04:28
@Flamtky
Flamtky marked this pull request as ready for review October 30, 2026 04:28

@viddie viddie left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm

@Flamtky
Flamtky merged commit 1d37fbd into master Oct 30, 2026
20 checks passed
@Flamtky
Flamtky deleted the flamtky/dialog-api-keypad-showimage branch October 30, 2026 16:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Keypad/ShowImage auf neue DialogAPI umschreiben

2 participants