diff options
-rw-r--r-- | server/src/main.rs | 13 | ||||
-rw-r--r-- | server/src/protocol.rs | 1 | ||||
-rw-r--r-- | test-client/main.ts | 75 | ||||
-rw-r--r-- | test-client/protocol.ts | 24 |
4 files changed, 104 insertions, 9 deletions
diff --git a/server/src/main.rs b/server/src/main.rs index 0987e9ef..763ff03b 100644 --- a/server/src/main.rs +++ b/server/src/main.rs @@ -52,6 +52,11 @@ async fn main() -> Result<()> { let mut rx = rx.resubscribe(); info!("{addr} connected"); spawn(async move { + write + .write_all(serde_json::to_string(&PacketC::Joined { id }).unwrap().as_bytes()) + .await + .unwrap(); + write.write_all(b"\n").await.unwrap(); while let Ok(packet) = rx.recv().await { write .write_all(serde_json::to_string(&packet).unwrap().as_bytes()) @@ -70,7 +75,6 @@ async fn main() -> Result<()> { }); } r = ws_listener.accept() => { - // let (sock, addr) = ws_listener.accept().await?; let (sock, addr) = r?; let sock = tokio_tungstenite::accept_async(sock).await?; let (mut write, mut read) = sock.split(); @@ -78,6 +82,12 @@ async fn main() -> Result<()> { let mut rx = rx.resubscribe(); info!("{addr} connected via ws"); spawn(async move { + write + .send(tokio_tungstenite::tungstenite::Message::Text( + serde_json::to_string(&PacketC::Joined { id }).unwrap(), + )) + .await + .unwrap(); while let Ok(packet) = rx.recv().await { write .send(tokio_tungstenite::tungstenite::Message::Text( @@ -97,6 +107,5 @@ async fn main() -> Result<()> { } } } - Ok(()) } diff --git a/server/src/protocol.rs b/server/src/protocol.rs index 93d2afe9..dc2af7d6 100644 --- a/server/src/protocol.rs +++ b/server/src/protocol.rs @@ -21,6 +21,7 @@ pub enum PacketS { #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(rename_all = "snake_case")] pub enum PacketC { + Joined { id: ID }, AddPlayer { id: ID, name: String }, RemovePlayer { id: ID }, Position { player: ID, pos: Vec2, rot: f32 }, diff --git a/test-client/main.ts b/test-client/main.ts index bc0872a6..d093c62e 100644 --- a/test-client/main.ts +++ b/test-client/main.ts @@ -1,5 +1,7 @@ /// <reference lib="dom" /> +import { PacketC, PacketS } from "./protocol.ts"; + let ctx: CanvasRenderingContext2D; let canvas: HTMLCanvasElement; let ws: WebSocket @@ -7,10 +9,13 @@ document.addEventListener("DOMContentLoaded", () => { ws = new WebSocket(`${window.location.protocol.endsWith("s:") ? "wss" : "ws"}://${window.location.hostname}:27032/`) ws.onerror = console.error ws.onmessage = m => { - console.log(JSON.parse(m.data)); + packet(JSON.parse(m.data) as PacketC); + } + ws.onclose = () => console.log("close") + ws.onopen = () => { + console.log("open") + send({ join: { name: "test" } }) } - ws.onclose = () => console.warn("close") - ws.onopen = () => console.warn("open") canvas = document.createElement("canvas"); document.body.append(canvas) @@ -20,15 +25,75 @@ document.addEventListener("DOMContentLoaded", () => { draw() }) +interface Player { x: number; y: number, name: string, rot: number } +const players = new Map<number, Player>() +interface Item { x: number; y: number } +const items = new Map<number, Item>() +interface Tile { x: number; y: number } +const tiles = new Map<string, Tile>() +let my_id = undefined + +function send(p: PacketS) { ws.send(JSON.stringify(p)) } +function packet(p: PacketC) { + if ("joined" in p) { + my_id = p.joined.id + } else if ("add_player" in p) { + players.set(p.add_player.id, { x: 0, y: 0, name: p.add_player.name, rot: 0 }) + } else if ("remove_player" in p) { + players.delete(p.remove_player.id) + } else if ("position" in p) { + const pl = players.get(p.position.player)! + pl.x = p.position.pos[0] + pl.y = p.position.pos[1] + pl.rot = p.position.rot + } else if ("take_item" in p) { + } else if ("put_item" in p) { + } else if ("produce_item" in p) { + } else if ("consume_item" in p) { + } else if ("set_active" in p) { + } else if ("update_map" in p) { + } else console.warn("unknown packet", p); +} + + function resize() { canvas.width = globalThis.innerWidth canvas.height = globalThis.innerHeight } function draw() { - ctx.fillStyle = "black" + if (ws.readyState == ws.CONNECTING) draw_wait("Connecting...") + else if (ws.readyState == ws.CLOSING) draw_wait("Closing...") + else if (ws.readyState == ws.CLOSED) draw_wait("Disconnected") + else if (ws.readyState == ws.OPEN) draw_ingame() + else throw new Error(`ws state invalid`); + requestAnimationFrame(draw) +} +function draw_wait(text: string) { + ctx.fillStyle = "gray" ctx.fillRect(0, 0, canvas.width, canvas.height) + ctx.fillStyle = "#555" + ctx.font = "50px sans-serif" + ctx.strokeStyle = "black" + ctx.fillStyle = "white" + ctx.lineWidth = 10 + ctx.textAlign = "center" + ctx.textBaseline = "middle" + ctx.strokeText(text, canvas.width / 2, canvas.height / 2) + ctx.fillText(text, canvas.width / 2, canvas.height / 2) +} - requestAnimationFrame(draw) +function draw_ingame() { + ctx.fillStyle = "#111" + ctx.fillRect(0, 0, canvas.width, canvas.height) + + for (const [_, player] of players) { + ctx.save() + ctx.translate(player.x, player.y) + ctx.rotate(player.rot) + ctx.fillStyle = "rgb(226, 176, 26)" + ctx.fillRect(-0.5, -0.5, 1, 1) + ctx.restore() + } } diff --git a/test-client/protocol.ts b/test-client/protocol.ts index 9761f152..3b61ce94 100644 --- a/test-client/protocol.ts +++ b/test-client/protocol.ts @@ -1,4 +1,24 @@ +export type ID = number; +export type Vec2 = [number, number] +export type Item = string +export type Tile = string +export type PacketS = + { join: { name: string } } + | "leave" + | { position: { pos: Vec2, rot: number } } + | { interact: { pos: Vec2 } } + + +export type PacketC = + { joined: { id: ID } } + | { add_player: { id: ID, name: string } } + | { remove_player: { id: ID } } + | { position: { player: ID, pos: Vec2, rot: number } } + | { take_item: { item: ID, player: ID } } + | { put_item: { item: ID, pos: Vec2 } } + | { produce_item: { id: ID, pos: Vec2, kind: Item } } + | { consume_item: { id: ID, pos: Vec2 } } + | { set_active: { tile: Vec2 } } + | { update_map: { pos: Vec2, tile: Tile } } -export type PacketS = {} -export type PacketC = {} |