Giter VIP home page Giter VIP logo

dfhack-remote's Introduction

dfhack-remote

This project provides browser-side JavaScript bindings to Dwarf Fortress, using RemoteFortressReader ("RFR"), the protobuf-based remote access interface to DFHack. With this API, you can talk to Dwarf Fortress from your browser, your phone, your TV, your car display… any browser that supports WebSockets (all of them, even IE).

It may also demo a browser-based fortress viewer someday.

How it works

You run websockify, and then open an HTML page that uses dfhack-remote. The page connects to DFHack through the websockify proxy, and loads your fortress.

websockify is just a passthrough, and dfhack-remote is just a thin wrapper around DFHack. Your webpage has full, direct access to DFHack. It could make Armok Vision in the browser with threejs/voxeljs-next.

Setup

Prerequisites

  • Node.js, for protobuf libraries and websockify

These are available on most package managers. For example,

brew install node
choco install -y nodejs

Compile Browser Bindings

Setup your development environment:

  • Install node dependencies with npm install.
    • Note: this also compiles RFR's protobufs (from proto/) into build/.

Run the example:

  • Compile the JavaScript example to build/bundle.js and launch the websockify server with npm test

Running the Example

Run Dwarf Fortress with DFHack and load a fort. Then run the example with npm test. Now you can open index.html. Try this in your browser's Inspector:

df = new DwarfClient()
x = await df.GetMapInfo()

Pass arguments to RFR methods with a dictionary:

x = await df.GetUnitListInside({ minX: 1, minY: 1, minZ: 50, maxX: 9, maxY: 9, maxZ: 56 })
x = await df.GetBlockList({minX: 1, minY: 1, minZ: 50, maxX: 9, maxY: 9, maxZ: 56})

Documentation

The API defines one class, DwarfClient:

/**
 * @struct
 */
class DwarfClient {
    /**
     * Upon construction, immediately tries to connect to DFHack.
     * @param {?(number|string)} host An optional numeric port, or string like "127.0.0.1:8080"
     */
    constructor (host = null) {
        ...
    }
    ...
}

It has one async method for every RFR method. Pass arguments to RFR methods with a dictionary:

df = new DwarfClient()
await df.GetMapInfo()
await df.GetUnitListInside({ minX: 1, minY: 1, minZ: 50, maxX: 9, maxY: 9, maxZ: 56 })
await df.GetBlockList({ minX: 1, minY: 1, minZ: 50, maxX: 9, maxY: 9, maxZ: 56 })

The RFR methods are (sort of) listed in FUNC_DEFS in main.js. The RFR types are defined in the protobuf files in proto/.

note: if necessary, parameter names must be converted to camel-case (e.g: list_start->listStart)

Running a Websockify Wrapper

As browsers can only talk to WebSocket ports, not RFR's raw TCP ports, you must run a websockify gateway to forward browser requests to RFR.

RFR listens on 127.0.0.1 on TCP port 5000 by default. To wrap that with WebSockets on TCP port 8080, run:

npx websockify --web=. 127.0.0.1:8080 127.0.0.1:5000

npm test automatically runs this.

Now you can run Dwarf Fortress with DFHack and access data from http://127.0.0.1:8080.

Issues

RemoteFortressReader has a strange bug where it "remembers" what it returned to GetBlockList, and never returns a block again unless it changes. That's a buggy way to implement "change-driven notifications" and should be fixed there. For now, remember GetBlockList only returns changes since the last call!

-- This was adressed in later version by adding the flag "force_reload" which can force a reload. It's now available here as well (camel case converted to forceReload)

TODO

  • Make the client an actual JavaScript module. Right now, it's stuffed into window.DwarfClient.
  • Optionally print the CoreTextNotification responses somewhere. Right now, they're just thrown away.
  • Embed dfhack as a subrepository, and dynamically find protobuf's. Right now, they're just copied.
  • Optimize, like java -jar closure-compiler-v20200517.jar -O ADVANCED --js_output_file build/bundle.min.js --js build/bundle.js

dfhack-remote's People

Contributors

alexchandel avatar arfost avatar dependabot[bot] avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.