function RECONNECT() { if(SOCKET === null) { console.log("Websocket connecting.."); SOCKET = new WebSocket("wss://omen.kirisame.com:38612"); SOCKET.binaryType = "arraybuffer"; SOCKET.addEventListener("error", (event) => { SOCKET = null; LOAD_STACK(SCENES.Offline); }); SOCKET.addEventListener("open", (event) => { if(SOCKET.readyState === WebSocket.OPEN) { console.log("Websocket connected."); SOCKET.addEventListener("message", MESSAGE); SOCKET.addEventListener("close", (event) => { console.log("Websocket closed."); SOCKET = null; RECONNECT(); }); RESUME(); } }); } else { RESUME(); } } function RESUME() { if(CONTEXT.Auth !== null) { MESSAGE_COMPOSE([ CONTEXT.Auth.token, CONTEXT.Auth.secret, ]); } else { LOAD(CONTEXT.Scene); } } function MESSAGE(event) { console.log("Message received."); if(SCENE.message !== undefined) { let bytes = new Uint8Array(event.data); let code = 0; let index = 2; let data = null; let result = null; if(bytes.length >= 2) { code = (bytes[0] << 8) + bytes[1]; } switch(code) { case OpCode.Register: { console.log("RECV Register"); if(bytes.length - index == 26) { data = { status:(bytes[2] << 8) + bytes[3], token:new Uint8Array(8), secret:new Uint8Array(16), }; index += 2; for(let i = 0; i < 8; ++i) { data.token[i] = bytes[index++]; } for(let i = 0; i < 16; ++i) { data.secret[i] = bytes[index++]; } } else { console.error("Register packet bad length:" + bytes.length); return; } } break; case OpCode.Authenticate: { console.log("RECV Authenticate"); if(bytes.length - index == 26) { data = { status:(bytes[2] << 8) + bytes[3], token:new Uint8Array(), secret:new Uint8Array(), }; index += 2; for(let i = 0; i < 8; ++i) { data.token += bytes[index++]; } for(let i = 0; i < 16; ++i) { data.secret += bytes[index++]; } } else { console.error("Authenticate packet bad length:" + bytes.length); return; } } break; case OpCode.Resume: { console.log("RECV Resume"); result = UNPACK.u16(bytes, index); index = result.index; if(result.data != Status.Ok) { CONTEXT.Auth = null; } LOAD(CONTEXT.Scene); } break; case OpCode.Deauthenticate: { console.log("RECV Deauthenticate"); } break; case OpCode.SessionList: { console.log("RECV Session list"); if(bytes.length - index >= 2) { data = { records: [], }; result = UNPACK.u16(bytes, index); index = result.index; let count = result.data; for(let i = 0; i < count; ++i) { let record = { token: new Uint8Array(8), dawn: "", dusk: "", turn: 0, move: "", viewers: 0, player: false, }; if(index <= bytes.length + 8) { for(let i = 0; i < 8; ++i) { record.token[i] = bytes[index]; index += 1; } } result = UNPACK.string(bytes, index); index = result.index; record.dawn = result.data; result = UNPACK.string(bytes, index); index = result.index; record.dusk = result.data; result = UNPACK.u16(bytes, index); index = result.index; record.turn = result.data; if(index <= bytes.length + 5) { let move = new Uint8Array(5); for(let i = 0; i < 5; ++i) { move[i] = bytes[index]; index += 1; } record.move = UNPACK.move(move); } result = UNPACK.u32(bytes, index); index = result.index; record.viewers = result.data; record.player = bytes[index++] != 0; data.records.push(record); } } } break; case OpCode.SessionCreate: case OpCode.SessionJoin: { if(bytes.length - index == 11) { data = { token:new Uint8Array(8), mode:2, }; let result = UNPACK.u16(data, index); index = result.index; let status = result.data; result = UNPACK.u8(data, index); index = result.index; data.mode = result.data; for(let i = 0; i < 8; ++i) { data.token[i] = data[index++]; } if(status == Status.Ok) { LOAD(SCENES.Game); } } } break; default: return; } if(SCENE.message !== undefined) { SCENE.message(code, data) }; } } function MESSAGE_COMPOSE(data) { if(SOCKET !== null) { let length = 0; for(let i = 0; i < data.length; ++i) { length += data[i].length; } let raw = new Uint8Array(length); length = 0; for(let i = 0; i < data.length; ++i) { raw.set(data[i], length); length += data[i].length; } SOCKET.send(raw); } } function MESSAGE_SESSION_LIST(page, game_state, is_player, is_live) { let flags = 0; flags |= game_state; flags |= +is_player << 2; flags |= +is_live << 3; MESSAGE_COMPOSE([ PACK.u16(OpCode.SessionList), PACK.u16(flags), PACK.u16(page), ]); } function MESSAGE_SESSION_START() { MESSAGE_COMPOSE([ PACK.u16(OpCode.SessionCreate), ]); } function MESSAGE_SESSION_JOIN(token, player) { MESSAGE_COMPOSE([ PACK.u16(OpCode.SessionJoin), token, PACK.u8(player), ]); }