357 lines
11 KiB
JavaScript
357 lines
11 KiB
JavaScript
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;
|
|
LOAD_STACK(SCENES.Offline);
|
|
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) {
|
|
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 + 3) {
|
|
let move = new Uint8Array(3);
|
|
for(let i = 0; i < 3; ++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: {
|
|
console.log("RECV SessionCreate/Join");
|
|
|
|
if(bytes.length - index == 11) {
|
|
data = {
|
|
status:0,
|
|
token:new Uint8Array(8),
|
|
mode:2,
|
|
};
|
|
|
|
result = UNPACK.u16(bytes, index);
|
|
index = result.index;
|
|
data.status = result.data;
|
|
|
|
result = UNPACK.u8(bytes, index);
|
|
index = result.index;
|
|
data.mode = result.data;
|
|
|
|
for(let i = 0; i < 8; ++i) { data.token[i] = bytes[index++]; }
|
|
}
|
|
} break;
|
|
|
|
case OpCode.GameState: {
|
|
console.log("RECV GameState");
|
|
|
|
//if(bytes.length - index >= 22) {
|
|
data = {
|
|
status:0,
|
|
turn:0,
|
|
dawn:"",
|
|
dusk:"",
|
|
pool_dawn:[ ],
|
|
pool_dusk:[ ],
|
|
pieces:[ ],
|
|
};
|
|
|
|
// Status
|
|
result = UNPACK.u16(bytes, index);
|
|
index = result.index;
|
|
data.status = result.data;
|
|
|
|
// Turn
|
|
result = UNPACK.u16(bytes, index);
|
|
index = result.index;
|
|
data.turn = result.data;
|
|
|
|
// Handles
|
|
result = UNPACK.string(bytes, index);
|
|
index = result.index;
|
|
data.dawn = result.data;
|
|
|
|
result = UNPACK.string(bytes, index);
|
|
index = result.index;
|
|
data.dusk = result.data;
|
|
|
|
// Dawn pool
|
|
result = UNPACK.u16(bytes, index);
|
|
index = result.index;
|
|
let dawn_pool_bits = result.data;
|
|
|
|
data.pool_dawn.push(dawn_pool_bits & 0x1F);
|
|
data.pool_dawn.push((dawn_pool_bits >> 5) & 0x3);
|
|
data.pool_dawn.push((dawn_pool_bits >> 7) & 0x3);
|
|
data.pool_dawn.push((dawn_pool_bits >> 9) & 0x3);
|
|
data.pool_dawn.push((dawn_pool_bits >> 11) & 0x3);
|
|
data.pool_dawn.push((dawn_pool_bits >> 13) & 0x1);
|
|
|
|
// Dusk pool
|
|
result = UNPACK.u16(bytes, index);
|
|
index = result.index;
|
|
let dusk_pool_bits = result.data;
|
|
|
|
data.pool_dusk.push(dusk_pool_bits & 0x1f);
|
|
data.pool_dusk.push((dusk_pool_bits >> 5) & 0x3);
|
|
data.pool_dusk.push((dusk_pool_bits >> 7) & 0x3);
|
|
data.pool_dusk.push((dusk_pool_bits >> 9) & 0x3);
|
|
data.pool_dusk.push((dusk_pool_bits >> 11) & 0x3);
|
|
data.pool_dusk.push((dusk_pool_bits >> 13) & 0x1);
|
|
|
|
// Pieces
|
|
for(let i = 0; i < 38; ++i) {
|
|
result = UNPACK.u16(bytes, index);
|
|
index = result.index;
|
|
let piece_data = result.data;
|
|
|
|
if((piece_data & 1) != 0) {
|
|
let piece = new GAME.Piece((piece_data >> 1) & 0x7, (piece_data >> 5) & 1);
|
|
piece.promoted = ((piece_data >> 4) & 1) != 0;
|
|
piece.tile = (piece_data >> 6) & 0x3F;
|
|
|
|
data.pieces.push(piece);
|
|
} else {
|
|
data.pieces.push(null);
|
|
}
|
|
}
|
|
//}
|
|
} break;
|
|
|
|
case OpCode.GamePlay: {
|
|
console.log("RECV GamePlay");
|
|
|
|
data = {
|
|
status:0,
|
|
move:new GAME.Play(0, 0, 0),
|
|
};
|
|
|
|
// Status
|
|
result = UNPACK.u16(bytes, index);
|
|
index = result.index;
|
|
data.status = result.data;
|
|
|
|
// Turn
|
|
result = UNPACK.u16(bytes, index);
|
|
index = result.index;
|
|
data.turn = result.data;
|
|
|
|
// Play description
|
|
result = UNPACK.u16(bytes, index);
|
|
index = result.index;
|
|
data.move.source = result.data & 1;
|
|
data.move.from = (result.data >> 1) & 0x3F;
|
|
data.move.to = (result.data >> 7) & 0x3F;
|
|
} break;
|
|
|
|
default:
|
|
console.log("RECV Undefined " + code);
|
|
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),
|
|
]);
|
|
}
|