import createDebug from "debug";
import {
MessagePacket,
MessageType,
Packet,
PacketType,
PartPositionsPacket,
PlanetPositionsPacket,
PlayerLeavePacket,
PlayerListPacket,
SpawnPlayerPacket,
} from "./protocol.ts";
import {appendPacket} from "./packet_ui.ts";
import {global} from "./main.ts";
import {startRender} from "./rendering.ts";
const logger = createDebug("hub");
export interface ClientHub {
socket: WebSocket;
}
export function sendPacket(client: ClientHub, packet: Packet) {
client.socket.send(JSON.stringify(packet));
appendPacket(packet);
}
export async function hub_connect(url: string, username: string): Promise<ClientHub | null> {
logger("connecting to client hub at " + url)
let ws = new WebSocket(url);
ws.onerror = (e) => {
console.error(e);
throw e;
}
ws.onopen = () => {
logger("connected to client hub, sending username and auth details");
let client: ClientHub = {
socket: ws
};
let packet: Packet = {
t: PacketType.ClientLogin,
c: {
username,
jwt: null
}
};
sendPacket(client, packet);
document.getElementById("chatentry")!.onkeydown = (e) => {
if (e.key === 'Enter') {
let value = (<HTMLInputElement>document.getElementById("chatentry")!).value;
if (value.startsWith(".msg")) {
let args = value.split(" ");
if (args.length < 3) {
document.getElementById("chatbox")!.innerHTML += `<p class="message server-error">Command error</p>`;
(<HTMLInputElement>document.getElementById("chatentry")!).value = "";
return;
}
let target = args[1];
let message = args.slice(2).join(" ");
let chat_packet: Packet = {
t: PacketType.SendMessage,
c: {
target: target,
content: message
}
};
sendPacket(client, chat_packet);
document.getElementById("chatbox")!.innerHTML += `<p class="message direct-message">${global.me!.username} -> ${target}: ${message}</p>`;
} else {
let chat_packet: Packet = {
t: PacketType.SendMessage,
c: {
target: null,
content: value
}
};
sendPacket(client, chat_packet);
}
(<HTMLInputElement>document.getElementById("chatentry")!).value = "";
}
}
ws.onmessage = (e) => {
let packet: Packet = JSON.parse(e.data);
appendPacket(packet);
if (packet.t == PacketType.SpawnPlayer) {
let p = <SpawnPlayerPacket> packet.c;
if (p.username === username) {
global.me = {
username: p.username,
part_id: p.id
};
logger(`client spawned (username=${p.username} part_id=${p.id})`);
startRender();
} else {
global.players_map.set(p.id, p.username);
global.inverse_players_map.set(p.username, p.id);
logger(`player joined (username=${p.username} part_id=${p.id})`);
}
} else if (packet.t == PacketType.PlayerList) {
let p = <PlayerListPacket> packet.c;
for (let i = 0; i < p.players.length; i++) {
global.players_map.set(p.players[i][0], p.players[i][1]);
global.inverse_players_map.set(p.players[i][1], p.players[i][0]);
}
logger(`added ${p.players.length} existing players to player list`);
} else if (packet.t == PacketType.PlanetPositions) {
let p = <PlanetPositionsPacket> packet.c;
for (let i = 0; i < p.planets.length; i++) {
global.planets_map.set(p.planets[i][0], p.planets[i][1]);
}
} else if (packet.t == PacketType.PartPositions) {
let p = <PartPositionsPacket> packet.c;
for (let i = 0; i < p.parts.length; i++) {
global.parts_map.set(p.parts[i][0], p.parts[i][1]);
}
} else if (packet.t == PacketType.PlayerLeave) {
let p = <PlayerLeavePacket>packet.c;
let username = global.players_map.get(p.id)!;
global.inverse_players_map.delete(username);
global.players_map.delete(p.id);
logger(`player removed (id=${p.id})`);
} else if (packet.t == PacketType.Message) {
let p = <MessagePacket>packet.c;
logger(`message type=${p.message_type} actor=${p.actor} content=${p.content}`);
let chatbox = document.getElementById("chatbox")!;
if (p.message_type == MessageType.Server) {
chatbox.innerHTML += `<p class="message server-message">[SERVER] ${p.content}</p>`;
} else if (p.message_type == MessageType.Chat) {
chatbox.innerHTML += `<p class="message global-message">${p.actor}: ${p.content}</p>`;
} else if (p.message_type == MessageType.Direct) {
// actor is who sent the message. destination is not included in this packet
if (p.actor === global.me!.username) {
// skip (shown above)
} else {
chatbox.innerHTML += `<p class="message direct-message">${p.actor} -> ${global.me!.username}: ${p.content}</p>`;
}
} else {
chatbox.innerHTML += `<p class="message server-error">[SERVER] ${p.content}</p>`;
}
} else {
logger(`unrecognized packet type ${packet.t}`);
}
}
return client;
};
return null;
}