Skip to content

bofh69/crossfire-web-client

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2,149 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Crossfire Web Client

This is a conversion of the Crossfire GTK-v2 client to TypeScript and Svelte.

Vite is used for the building everything.

Almost everything was done by GitHub Copilot with Claude Opus or Sonnet, and me just testing the different versions.

There is a test server at crossfire.diegeekdie.com. It is just for testing and can go down at any time.

Old screenshot of the client

Connecting to a specific server

Append a ?server= query parameter to the page URL to pre-fill (and automatically initiate) the connection to a particular server, e.g.:

https://example.com/?server=wss://crossfire.example.com/ws

When this parameter is present the server-address input field is hidden and the client connects automatically, bypassing the manual "Enter" step.

Choose login method

The client supports both the old login method of logging in to the character and the latest where new characters are created in the client. Add a query parameter ?loginmethod=0 to use the old login method. The new one is the default.

Convert websocket recording logs

When recording is enabled (?record), downloaded logs are in the compact format:

<timestamp>\t<TX|RX>\t<byte_length>\t<base64_payload>
<timestamp>\t<MARK>\t<json_marker_text>

Use this converter to transform them into:

timestamp TX/RX/MARK text

where text is C-string escaped (\n for newline, \xXX for non-printables).

npm run recording:convert -- input.log output.txt

If output.txt is omitted, converted output is written to stdout.

Replay ws-recording logs

There is also a separate replay page at:

/replay.html

It accepts both the compact downloaded ws-recording logs and the converted text format from npm run recording:convert.

The replay page can export state snapshot files in the same format as used by the mapdata replay tests.

More marks can be added by editing the logfile.

One-command Playwright replay automation

Run an end-to-end replay with:

npm run replay:playwright -- --log tests/replay-mapdata/logs/scorn.converted.log --mark-regex ".*"

This command starts:

  • a local Vite dev server
  • a replay WebSocket server that replays the logfile to the client
  • a Playwright Chromium browser connected to that replay server

Behavior:

  • For each TX line in the logfile, replay waits for the client to send a matching command (or timeout).
  • Matching is command-only, except for ncom where the embedded command text is also matched (ncom.north, ncom.apply, etc.).
  • The next replayed RX comc packet is sequence-patched to the sequence sent by the client for that matched ncom.
  • Every MARK line whose label matches --mark-regex saves a screenshot in screenshots/replay-playwright/.

Optional JSON instructions

Use --instructions to apply Playwright actions synchronized to TX lines:

npm run replay:playwright -- \
  --log tests/replay-mapdata/logs/scorn.converted.log \
  --instructions scripts/replay-playwright.instructions.example.json \
  --mark-regex ".*"

Instruction format (JSON):

  • top-level tx array
  • each entry has:
    • match: regex string tested against replay command key
      • normal commands: accountlogin, accountplay
      • ncom commands: ncom.<embedded command>, e.g. ncom.north
    • actions: list of actions (clickRole, clickText, fillRole, clickSelector, fillSelector, press, keyDown, keyUp, waitForTimeout, screenshot)
      • Action string values support regex captures from match via $1, $2, etc.

Built-in actions already exist for accountlogin (click Log In) and accountplay (click matching character button), and can be extended with instruction rules.

Mapdata replay tests

Run the mapdata replay tests with:

npm run test:mapdata

Test cases are listed in:

tests/replay-mapdata/tests.json

Each case has:

  • name: test name
  • log: replay log file path (in compact or converted format)
  • mark: MARK label to replay the log up to
  • state: path to expected mapdata state file

Only cells listed in the state file are compared.

Protocol changes

Web pages can't use raw TCP sockets so WebSockets has to be used.

The public crossfire clients don't support WebSockets, so a WebSocket proxy has to be used when connecting to them. There is one included in the repo (under scripts/) that also handles crossfire's protocol's length header.

The crossfire-server fork has a branch with built in support for WebSockets. It is not thoroughly reviewed yet, but it works well.

UX differences compared to GTK client.

The client doesn't contact a metaserver as the normal servers don't use support WebSockets anyway.

A web page can't override all the browser's built in hot keys, so ALT is used instead of CTRL for running. That way it hopefully leads to fewer conflicts with the browser.

There is a "Keyboard" menu for handling key bindings.

Key bindings are stored locally in the browser. If playing from different computers/browsers, the bindings will have to be redone.

Bindings can be stored for all characters or the current logged in one.

Press Tab to enter UI navigation mode. In that mode the visible UI can be navigated with mode-specific keyboard or gamepad controls, Escape leaves the mode. Return selects items/shows menus in the UI navigation mode.

The local commands ui_nav is used to enter the mode. ui_nav --stay keeps the mode active after running a UI command; by default it exits automatically after a UI command is sent.

Left clicking on items activates them.

Right clicking on items and skills brings up a menu.

Left clicking on a spell selects it.

Right clicking on skills brings up a menu for use/ready of it.

Music & sfx

The client supports music and sfx, they are downloaded as needed from the server. Both can be muted.

Magic mapping

It works somewhat like the DockWindow client, the map is integrated into the unseen parts of the main map. Walls are drawn as thin lines.

Gamepad support

There is simple gamepad support built in. Currently it only has default bindings for my XBox One controller.

When UI navigation mode is active, the controller switches to UI navigation bindings instead of the normal gameplay bindings. By default the left stick or D-pad moves between UI elements, A activates the current element, X opens the current element's menu, and B exits UI navigation mode.

It is possible to configure the client for more controllers, but it takes some time. It is probably easier to change it in the code instead.

PRs for more controllers are welcome.

About

Web Client for Crossfire

Topics

Resources

License

GPL-2.0, GPL-2.0 licenses found

Licenses found

GPL-2.0
LICENSE
GPL-2.0
COPYING

Stars

Watchers

Forks

Contributors