init
This commit is contained in:
commit
28b026a614
17 changed files with 895 additions and 0 deletions
125
client/main.ts
Executable file
125
client/main.ts
Executable file
|
@ -0,0 +1,125 @@
|
|||
#!/bin/env -S deno run --allow-net --allow-run
|
||||
import { MsgToClient, MsgToServer, mtc } from "../common/mod.ts";
|
||||
import { run } from "../common/utils.ts";
|
||||
import {
|
||||
channel,
|
||||
launch_caught,
|
||||
log_from,
|
||||
parsed_stream,
|
||||
Receiver,
|
||||
Sender,
|
||||
serialized_stream,
|
||||
wait,
|
||||
} from "../common/utils.ts";
|
||||
const log = log_from(import.meta);
|
||||
|
||||
async function main() {
|
||||
log("Client starting.");
|
||||
const interface_ = await ServerInterface.connect(9999);
|
||||
new InputHandler(interface_.outputs).spin();
|
||||
const display = new DisplayHandler(interface_.outputs);
|
||||
display.spin();
|
||||
new MsgHandler(interface_.inputs, display).spin();
|
||||
log("Connected.");
|
||||
|
||||
interface_.outputs.send({ kind: "ping", content: { message: "Machin." } });
|
||||
log("Sent ping.");
|
||||
}
|
||||
|
||||
class MsgHandler {
|
||||
receiver;
|
||||
display;
|
||||
|
||||
constructor(receiver: Receiver<MsgToClient>, display: DisplayHandler) {
|
||||
this.receiver = receiver;
|
||||
this.display = display;
|
||||
}
|
||||
|
||||
async spin() {
|
||||
for await (const event of this.receiver.iter()) {
|
||||
if (event.kind === "ping_response") log("Received ping response :", event.content);
|
||||
if (event.kind === "display") this.display.refresh(event.content.raw);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class InputHandler {
|
||||
outputs;
|
||||
|
||||
constructor(outputs: Sender<MsgToServer>) {
|
||||
this.outputs = outputs;
|
||||
}
|
||||
|
||||
async read_one_char() {
|
||||
const args = ["-i0", "sh", "-c", "read -n 1 OUT; echo -n $OUT"];
|
||||
const command = new Deno.Command("stdbuf", { args, stdin: "inherit", stdout: "piped" });
|
||||
const output = await command.output();
|
||||
const result = new TextDecoder().decode(output.stdout);
|
||||
console.log(`${String.fromCharCode(0x08)} `);
|
||||
return result[0];
|
||||
}
|
||||
|
||||
async spin() {
|
||||
while (true) {
|
||||
const read = await this.read_one_char();
|
||||
if (read === "z") this.outputs.send({ kind: "input", content: { control: "up" } });
|
||||
if (read === "s") this.outputs.send({ kind: "input", content: { control: "down" } });
|
||||
if (read === "q") this.outputs.send({ kind: "input", content: { control: "left" } });
|
||||
if (read === "d") this.outputs.send({ kind: "input", content: { control: "right" } });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class DisplayHandler {
|
||||
outputs;
|
||||
|
||||
constructor(outputs: Sender<MsgToServer>) {
|
||||
this.outputs = outputs;
|
||||
}
|
||||
|
||||
async spin() {
|
||||
while (true) {
|
||||
await wait(100);
|
||||
const [width, height] = await this.get_res();
|
||||
this.outputs.send({ kind: "request_display", content: { width, height } });
|
||||
}
|
||||
}
|
||||
|
||||
async get_res() {
|
||||
const width = parseInt(await run("tput", "cols")) / 2 - 2; // note : tiles are 2 char wide
|
||||
const height = parseInt(await run("tput", "lines")) - 2;
|
||||
return [width, height];
|
||||
}
|
||||
|
||||
refresh(raw: string) {
|
||||
const clear_sequence = String.fromCharCode(0o033) + String.fromCharCode(0o143);
|
||||
console.log(clear_sequence + raw);
|
||||
}
|
||||
}
|
||||
|
||||
class ServerInterface {
|
||||
inputs;
|
||||
outputs;
|
||||
|
||||
constructor(inputs: Receiver<MsgToClient>, outputs: Sender<MsgToServer>) {
|
||||
this.inputs = inputs;
|
||||
this.outputs = outputs;
|
||||
}
|
||||
|
||||
static async connect(port: number) {
|
||||
const connection = await Deno.connect({ port });
|
||||
return await ServerInterface.init(connection);
|
||||
}
|
||||
|
||||
// deno-lint-ignore require-await
|
||||
static async init(connection: Deno.Conn) {
|
||||
// TODO : handshake ?
|
||||
const [input_sender, input_receiver] = channel<MsgToClient>();
|
||||
const [output_sender, output_receiver] = channel<MsgToServer>();
|
||||
launch_caught(() => input_sender.send_all(parsed_stream(mtc.message_to_client_parser())(connection.readable)));
|
||||
launch_caught(() => serialized_stream(output_receiver.iter())(connection.writable));
|
||||
return new ServerInterface(input_receiver, output_sender);
|
||||
}
|
||||
}
|
||||
|
||||
if (import.meta.main) await main();
|
Loading…
Add table
Add a link
Reference in a new issue