]> git.lizzy.rs Git - hydra-dragonfire.git/commitdiff
Add documentation
authorElias Fleckenstein <eliasfleckenstein@web.de>
Mon, 30 May 2022 14:18:00 +0000 (16:18 +0200)
committerElias Fleckenstein <eliasfleckenstein@web.de>
Mon, 30 May 2022 14:18:00 +0000 (16:18 +0200)
README.md
doc/api.md [new file with mode: 0644]
doc/auth.md [new file with mode: 0644]
doc/client.md [new file with mode: 0644]
doc/client_pkts.md [new file with mode: 0644]
doc/escapes.md [new file with mode: 0644]
doc/hydra.md [new file with mode: 0644]
doc/poll.md [new file with mode: 0644]
doc/server_pkts.md [new file with mode: 0644]
doc/vector.md [new file with mode: 0644]

index 0990a8788b2b8232b760789a2f99ff9232276f6e..2b75b0d3b49818ad3fe578201459068b285d9d0a 100644 (file)
--- a/README.md
+++ b/README.md
@@ -7,17 +7,17 @@ Capable of deserializing ToClt packets and serializing ToSrv packets.
 Main use case are bot clients. Multiple clients can easily be spawend and polled from one script - hence the name "Hydra".
 Hydra may also be useful for integration testing or network debugging.
 
-Hydra is WIP: there are bugs, API may change any time, some packets are unimplemented and many components are yet to be added.
+Hydra is WIP: there are bugs, API may change any time, doc is incomplete, some packets are unimplemented and many components are yet to be added. However, hydra can already be used and big parts of it's main functionality are implemented.
 
 # Installation
 Go 1.18 is required.
 `go install github.com/dragonfireclient/hydra-dragonfire@latest`
 
 # Invocation
-Due to limitations of Go, hydra can not simply be required from a Lua script. Instead, the hydra binary has to be invoked with a script as argument:
+Due to limitations of Go, hydra unfortunately cannot be `require()`'d from a Lua script. Instead, the hydra binary has to be invoked with a script as argument:
 `hydra-dragonfire file.lua <args>`. Any additional arguments `<args>` are provided to the script.
 
-# Architecture
+# Architecture Overview
 By default, hydra will only take care of connection and packet serialization, no state management takes place.
 Hydra is a library, not a framework: it does not organize your code and there is no module system.
 
@@ -30,9 +30,5 @@ Additionally, different native components can be enabled per-client to manage st
 Currently only the `auth` component is available, but components like `map`, `objs`, `inv`, `pos`, `playerlist` etc. will be added in the future.
 Components handle packets asynchronously, they will process them even if poll is not called.
 
-# Documentation
-For available packets, see `spec/client` and `spec/server`.
-
-For available utilities, see `builtin`.
-
-Documentation for native functions is yet TODO.
+# Further Documentation
+[API documentation](doc/api.md)
diff --git a/doc/api.md b/doc/api.md
new file mode 100644 (file)
index 0000000..13516ec
--- /dev/null
@@ -0,0 +1,34 @@
+# Hydra API documentation
+
+## Lua version
+Hydra uses gopher-lua, Lua 5.1
+
+## Globals
+
+- `arg`: table containing command line arguments
+- `hydra`: contains minetest protocol API, see [hydra.md](hydra.md)
+- `vec2`, `vec3`, `box`: vector library, see [vector.md](vector.md)
+
+## Additional packages
+
+`require()` can be used to import these modules.
+
+- `escapes`: contains utility functions to deal with minetest escape sequences, see [escapes.md](escapes.md)
+- `client`: a function to create a client from command line arguments in the form `<server> <username> <password>`. This is trivial but so commonly used that this function was added to avoid repetition in scripts.
+
+## Standard library additions
+
+Source: [builtin/luax](../bultin/luax).
+
+- `table.indexof(list, val)`
+- `table.copy(t, seen)`
+- `table.insert_all(t, other)`
+- `table.key_value_swap(t)`
+- `table.shuffle(t, from, to, random)`
+- `string.split(str, delim, include_empty, max_splits, sep_is_pattern)`
+- `string.trim(str)`
+- `math.hypot(x, y)`
+- `math.sign(x, tolerance)`
+- `math.factorial(x)`
+- `math.round(x)`
+- `math.clamp(min, max, v)`
diff --git a/doc/auth.md b/doc/auth.md
new file mode 100644 (file)
index 0000000..f496632
--- /dev/null
@@ -0,0 +1,19 @@
+# Authentication Component
+Source code: [auth.go](../auth.go)
+
+Handles packets necessary to complete authentication and responds with according packets. Sends the `init` packet unpon connection open.
+Invalid packets related to auth received from server or detected incompabilities may result in the client being closed. In this case, an error state is set that can be read using the `self:state()` method.
+
+**Important: ** the auth component does not automatically disconnect if authentication fails due to an invalid password or already being logged in; it is up to the API user to handle these cases by subscribing to the `kick` and `legacy_kick` packets.
+
+Authentication handles the `hello`, `srp_bytes_salt_b`, `accept_auth` and `time_of_day` packets (the last one is only handled when received the first time and sets the state to active).
+
+Authentication may send `init`, `first_srp`, `srp_bytes_a`, `srp_bytes_m`, `init2` and `ready` packets.
+
+## Functions
+
+`self:username([username])`: Sets or gets the username (string). Setting may not occur after having connected the client. A username must be set before connecting.
+`self:password([password])`: Sets or gets the password (string). Setting may not occur after having connected the client. By default, an empty password is used.
+`self:language([language])`: Sets or gets the language sent to server. Setting may not occur after having connected the client. By default, "en_US" is used.
+`self:version([version])`: Sets or gets the version string sent to server. Setting may not occur after having connected the client. By default, "hydra-dragonfire" is used.
+`self:state()`: Returns `state, error`. State is one of "init", "requested", "verified", "active", "error". If state is "error", error is a string containing a description of the problem that occured. Otherwise, error is nil.
diff --git a/doc/client.md b/doc/client.md
new file mode 100644 (file)
index 0000000..9844591
--- /dev/null
@@ -0,0 +1,24 @@
+# Client interface
+Source code: [client.go](../client.go)
+
+A client represents a connection state. A client may not yet be connected, or it may be already disconnected.
+After being disconnect, a client cannot be reconnected.
+
+## Functions
+
+- `self:address()`: Returns address passed to `hydra.client` upon creation as a string.
+- `self:state()`: Returns current connection state as a string ("new", "connected", "disconnected")
+- `self:connect()`: Connects to server. Throws an error if the client is not in "new" state OR address resolution / dial fails (Note: If required, you can use `pcall` to catch and handle errors instead of crashing the script). Connection failure (= host found, but no minetest server running on port) is equivalent to an immediate disconnect and does not cause an error to be thrown.
+- `self:poll([timeout])`: Polls packets from client. See [poll.md](poll.md) for behavior and return values.
+- `self:close()`: Closes the network connection if in `connected` state. The client remains in `connected` state until passed to poll.
+- `self:enable(component)`: Enables the component with the name `component` (string), if not already enabled. By default, no components are enabled. See Components section.
+- `self:subscribe(pkt1, [pkt2, ...])`: Subscribes to all packet passed as arguments (strings). For available packets, see [client_pkts.md](client_pkts.md). By default, the client is not subscribed to any packets.
+- `self:unsubscribe(pkt1, [pkt2, ...])`: Unsubscribes from all packet passed as arguments (strings).
+- `self:wildcard(wildcard)`: Sets wildcard mode to `wildcard` (boolean). If wildcard is enabled, ALL packets are returned by poll, even those that the client did not subscribe to. It is not recommended to use this without a reason since converting packets to Lua costs performance and creates and overhead due to poll returning more often. `wildcard` is unnecessary if only certain packets are handled anyway, but it is useful for traffic inspection and debugging.
+- `self:send(pkt_name, pkt_data, [ack])`: Sends a packet to server. Throws an error if the client is not connected. `pkt_name` is the type of the packet as string. `pkt_data` is a table containing packet parameters. Some packets don't have parameters (e.g. `respawn`) - in this case, `pkt_data` can be omitted. See [server_pkts.md](server_pkts.md) for available packets. If `ack` is true, this function will block until acknowledgement from server is received.
+
+## Components
+
+Enabled components can be accessed by using `self.<component name>`.
+
+- `self.auth`: Handles authentication. Recommended for the vast majority of scripts. See [auth.md](auth.md).
diff --git a/doc/client_pkts.md b/doc/client_pkts.md
new file mode 100644 (file)
index 0000000..a326ff3
--- /dev/null
@@ -0,0 +1,4 @@
+# Client Packets
+TODO: automatically generate documentation from spec.
+
+For now, have a look at [spec](spec/client/)
diff --git a/doc/escapes.md b/doc/escapes.md
new file mode 100644 (file)
index 0000000..5491a4d
--- /dev/null
@@ -0,0 +1,4 @@
+# Escape sequence library
+Source code: [builtin/escapes.lua](../builtin/escapes.lua)
+
+TODO: Write documentation
diff --git a/doc/hydra.md b/doc/hydra.md
new file mode 100644 (file)
index 0000000..4eac2cf
--- /dev/null
@@ -0,0 +1,18 @@
+# Hydra namespace
+Source code: [hydra.go](../hydra.go)
+
+The `hydra` table contains functions necessary to handle connections.
+
+## Constants
+
+- `hydra.BS`: (`= 10.0`) Size of node in floating-point units. Many floating point positions contained in packets received need to be divided by this constant to obtain a position in node space. Likewise, many positions contained in packets sent need to be multiplied by this constant.
+- `hydra.serialize_ver`: Supported serialization version.
+- `hydra.proto_ver`: Supported protocol version.
+
+## Functions
+
+- `hydra.client(address)`: Returns a new client. Address must be a string. For client functions, see [client.md](client.md).
+- `hydra.dtime()`: Utility function that turns the elapsed time in seconds (floating point) since it was last called (or since program start).
+- `hydra.canceled()`: Utility function that returns true if the program was interrupted (SIGINT, SIGTERM, SIGHUP).
+- `hydra.poll(clients, [timeout])`: Polls subscribed packets from all clients in `clients` (table). For behavior and return value, see [poll.md](poll.md).
+- `hydra.close(clients)`: Closes all clients in `clients` (table) that are currently connected. See `client:close()` in [client.md](client.md) for more info.
diff --git a/doc/poll.md b/doc/poll.md
new file mode 100644 (file)
index 0000000..494fe48
--- /dev/null
@@ -0,0 +1,49 @@
+# Polling API
+Source code: [poll.go](../poll.go)
+
+**TL;DR**: poll is complex and has many different cases, but in general, it returns the received packet and the associated client; if one of the clients closes, a nil packet is returned once. client may also be nil in some cases so watch out for that.
+
+Together with sending, polling is the core function of hydra. It is used to receive packets from a packet queue.
+
+For each client, only packets that the client has subscribed to are inserted into that queue, unless wildcard is enabled.
+
+Packet receival from network happens asynchronously. When a packet is received and has been processed by components, it is enqueued for polling if the client is subscribed to it. **Because of the poll queue, packets may be returned by poll that the client was subscribed to in the past but unsubscribed recently.** Since the queue has a limited capacity of 1024 packets (this may change in the future), it is your responsibility to actually poll in a frequency suitable to keep up with the amount of packets you expect based on what you are subscribed to. If the queue is full, the thread responsible for receival will block.
+
+Clients that are not in `connected` state are ignored by poll.
+
+Poll blocks until one of these conditions is met (in this order). The return value depends on which condition is met:
+
+1. No clients are available when the function is called. This happens if either no clients were passed to poll or none of them is connected.
+
+2. One of the clients closes. In this case, the client that closed is set to `disconnected` state. The close may happen before or during the call to poll, but it has effect only once.
+
+3. A packet is in queue for one of the clients (Main case).
+
+4. An interrupt signal is received during polling (See `hydra.canceled`).
+
+5. The configured timeout elapses.
+
+## Different versions
+
+There is two different versions of poll: `client:poll` for polling a single client and `hydra.poll` for polling multiple clients.
+They are mostly equivalent but differ in return values and arguments:
+
+- `client:poll([timeout])` polls from the client `client` and returns `pkt, interrupted`
+
+- `hydra.poll(clients, [timeout])` takes table of clients as argument and returns `pkt, client, interrupted`
+
+## Arguments and return values
+
+The timeout argument is an optional floating point number holding the timeout in seconds, if `nil`, poll will block until one of the conditions 1.-4. are met. Timeout may be `0`, in this case poll returns immediately even if none of the other conditions are met immediately.
+
+Return values for different cases:
+
+1. If no clients are available, `nil, nil, false` (or `nil, false` respectively) is returned.
+
+2. If a client closes, `nil, client, false` (or `nil, false` respectively) is returned.
+
+3. If a packet is available, poll returns `pkt, client, false` (or `pkt, false` respectively). `pkt` is a table containing the received packet (see [client_pkts.md](client_pkts.md)) and `client` is the client reference that has received the packet.
+
+4. If the program is interrupted, poll returns `nil, nil, true` (or `nil, true` respectively).
+
+5. If the timeout elapses, poll returns `nil, nil, true` (or `nil, true` respectively).
diff --git a/doc/server_pkts.md b/doc/server_pkts.md
new file mode 100644 (file)
index 0000000..9f9875a
--- /dev/null
@@ -0,0 +1,4 @@
+# Server Packets
+TODO: automatically generate documentation from spec.
+
+For now, have a look at [spec](spec/server/)
diff --git a/doc/vector.md b/doc/vector.md
new file mode 100644 (file)
index 0000000..67191b4
--- /dev/null
@@ -0,0 +1,4 @@
+# Vector library
+Source code: [builtin/vector.lua](../builtin/vector.lua)
+
+TODO: Write documentation