@@ 1,13 1,26 @@
import {Logger} from "./logger";
-import {MessageC2SHello, MessageC2SHello_packetInfo} from "./protocol/message_c2s";
+import {
+ MessageC2SGoodbye, MessageC2SGoodbye_packetInfo,
+ MessageC2SHello,
+ MessageC2SHello_packetInfo, MessageC2SPing,
+ MessageC2SPing_packetInfo
+} from "./protocol/message_c2s";
import {State} from "./protocol/state";
import {decode, encode} from "./serde";
import {
+ MessageS2CChat,
+ MessageS2CChat_packetInfo,
MessageS2CGoodbye,
MessageS2CGoodbye_packetInfo,
MessageS2CHello,
- MessageS2CHello_packetInfo
+ MessageS2CHello_packetInfo,
+ MessageS2CPlanetData, MessageS2CPlanetData_packetInfo,
+ MessageS2CPlayersUpdate,
+ MessageS2CPlayersUpdate_packetInfo,
+ MessageS2CPong_packetInfo
} from "./protocol/message_s2c";
+import {GoodbyeReason} from "./protocol/goodbye_reason";
+import {global} from "./index";
const logger = new Logger("Gateway");
@@ 16,15 29,10 @@ export interface GatewayClient {
socket: WebSocket;
username: string | null;
version: number | null;
+ ping_timeout: Timeout | null; // i am aware that these types dont exist
+ ping_timeout_left: Timeout; // its fine
}
-function toHexString(byteArray) {
- return Array.from(byteArray, function(byte) {
- return ('0' + (byte & 0xFF).toString(16)).slice(-2);
- }).join('')
-}
-
-
export async function gateway_connect(gateway_url: string, username: string): GatewayClient {
logger.info("FAST CONNECT - Connecting to gateway socket at " + gateway_url);
@@ 36,9 44,29 @@ export async function gateway_connect(gateway_url: string, username: string): Ga
state: State.Handshake,
socket: ws,
username: null,
- version: null
+ version: null,
+ ping_timeout: null,
+ ping_timeout_left: null
};
+ let ping_timeout_fn = () => {
+ logger.error("Server didn't send back pong in time.");
+ let cya = MessageC2SGoodbye.encode({reason: GoodbyeReason.PingPongTimeout}).finish();
+ client.socket.send(encode(MessageC2SGoodbye_packetInfo.type, cya));
+ client.state = State.Handshake;
+ client.username = null;
+ client.version = null;
+ client.socket.close();
+ }
+ client.ping_timeout_left = setTimeout(ping_timeout_fn, 10 * 1000);
+
+ let ping_fn = () => {
+ let ping = MessageC2SPing.encode({}).finish();
+ client.socket.send(encode(MessageC2SPing_packetInfo.type, ping));
+ setTimeout(ping_fn, 5 * 1000);
+ }
+ client.ping_timeout = setTimeout(ping_fn, 5 * 1000);
+
let handshake_start_msg = MessageC2SHello.encode({
version: 1,
requestedUsername: username,
@@ 79,9 107,44 @@ export async function gateway_connect(gateway_url: string, username: string): Ga
logger.warn(`server sent unexpected packet ${pkt_id} for state Handshake`);
}
} else if (client.state == State.Play) {
- // TODO
+ if (pkt_id == MessageS2CGoodbye_packetInfo.type) {
+ let pkt = MessageS2CGoodbye.decode(pkt_data);
+
+ logger.error(`Disconnected by server. Reason: ${pkt.reason}`);
+
+ client.state = State.Handshake;
+ client.username = null;
+ client.version = null;
+
+ throw "Disconnected by server";
+ } else if (pkt_id == MessageS2CChat_packetInfo.type) {
+ let pkt = MessageS2CChat.decode(pkt_data);
+
+ logger.info(`CHAT: [${pkt.from}] ${pkt.message}`);
+ } else if (pkt_id == MessageS2CPong_packetInfo.type) {
+ clearTimeout(client.ping_timeout_left);
+ client.ping_timeout_left = setTimeout(ping_timeout_fn, 10 * 1000);
+ } else if (pkt_id == MessageS2CPlayersUpdate_packetInfo.type) {
+ let pkt = MessageS2CPlayersUpdate.decode(pkt_data);
+ global.players = pkt.players;
+
+ for (let i = 0; i < pkt.players.length; i++) {
+ if (pkt.players[i].username == client.username) {
+ global.me = pkt.players[i];
+ }
+ }
+ } else if (pkt_id == MessageS2CPlanetData_packetInfo.type) {
+ let pkt = MessageS2CPlanetData.decode(pkt_data);
+ global.planets = pkt.planets;
+ } else {
+ logger.warn(`server sent unexpected packet ${pkt_id} for state Play`);
+ }
}
- })
+ });
+
+
+
+ return client;
}
let socket: WebSocket | undefined = undefined;
@@ 2,16 2,24 @@
import {Logger, logSetup} from "./logger";
import {gateway_connect, GatewayClient} from "./gateway";
+import {Player} from "./protocol/player";
+import {Planet} from "./protocol/planet";
logSetup();
const logger = new Logger("client");
export interface GlobalData {
- client: GatewayClient | null
+ client: GatewayClient | null,
+ players: Player[],
+ planets: Planet[],
+ me: Player | null
}
export const global: GlobalData = {
- client: null
+ client: null,
+ players: [],
+ planets: [],
+ me: null
}
async function client_main(server: string, username: string) {