WIP
This commit is contained in:
@@ -1,7 +1,4 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { login, setupWebsocket } from '~/netcode';
|
|
||||||
const lobby = await login()
|
|
||||||
|
|
||||||
// import goStore, { oauth2_register_discord, setup_websocket, heron_cookie_login } from "@/netcode";
|
// import goStore, { oauth2_register_discord, setup_websocket, heron_cookie_login } from "@/netcode";
|
||||||
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|||||||
@@ -1,10 +1,5 @@
|
|||||||
import goStore, { oauth2_register_discord, setup_websocket, heron_cookie_login, join_game } from "@/netcode";
|
|
||||||
|
|
||||||
export default defineNuxtRouteMiddleware
|
export default defineNuxtRouteMiddleware
|
||||||
(async (to, from) => {
|
(async (to, from) => {
|
||||||
await setup_websocket()
|
|
||||||
|
|
||||||
|
|
||||||
if (to.path == '/login') {
|
if (to.path == '/login') {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,29 +0,0 @@
|
|||||||
import type { ClientMessage, ServerMessage } from "./interfaces/generic/index"
|
|
||||||
type Callbacks = {
|
|
||||||
resolve: (value: ServerMessage) => void;
|
|
||||||
reject: (reason?: any) => void;
|
|
||||||
}
|
|
||||||
export class Query {
|
|
||||||
static readonly callbacks = new Map<string, Callbacks>()
|
|
||||||
readonly uuid: string
|
|
||||||
readonly message: Omit<ClientMessage, "uuid">
|
|
||||||
private readonly socket: WebSocket
|
|
||||||
constructor(socket: WebSocket, message: Omit<ClientMessage, "uuid">) {
|
|
||||||
this.uuid = crypto.randomUUID()
|
|
||||||
this.message = message
|
|
||||||
this.socket = socket
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private serialize() {
|
|
||||||
return JSON.stringify({ uuid: this.uuid, ...this.message })
|
|
||||||
}
|
|
||||||
|
|
||||||
send() {
|
|
||||||
return new Promise<ServerMessage>((resolve, reject) => {
|
|
||||||
const callbacks = { resolve, reject }
|
|
||||||
this.socket.send(this.serialize())
|
|
||||||
Query.callbacks.set(this.uuid, callbacks)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,402 +0,0 @@
|
|||||||
import { Lobby } from "./model/Lobby";
|
|
||||||
import type { ServerMessage } from "./interfaces/generic";
|
|
||||||
import { ServerQueryType, ClientQueryType } from "./interfaces/generic";
|
|
||||||
import { Query } from "./Query";
|
|
||||||
|
|
||||||
import { type Ref } from "vue";
|
|
||||||
|
|
||||||
const socketTimeout = 1000
|
|
||||||
let socket: WebSocket;
|
|
||||||
|
|
||||||
export class GameObjectRegister {
|
|
||||||
readonly effects: Map<string, Effect>;
|
|
||||||
readonly cards: Map<string, Card>;
|
|
||||||
readonly teams: Map<string, Team>;
|
|
||||||
readonly players: Map<string, Player>;
|
|
||||||
readonly turns: Map<string, Turn>;
|
|
||||||
readonly games: Map<string, Game>;
|
|
||||||
|
|
||||||
readonly gameRoutingCallbacks: Map<string, [() => void, () => void]>;
|
|
||||||
readonly loginCallbacks: Set<() => void>;
|
|
||||||
context: "lobby" | "login" | "pregame" | "game" | "rules" = "login";
|
|
||||||
private readonly objects: Map<string, GameObjectNetcode>;
|
|
||||||
current_game: Ref<Game | null>;
|
|
||||||
lobby: Ref<Lobby | null>;
|
|
||||||
self: Ref<Player | null>;
|
|
||||||
zoomKeyPressed: Ref<boolean>
|
|
||||||
hoveredCard: Ref<number | undefined>
|
|
||||||
|
|
||||||
clientMouseX: Ref<number>
|
|
||||||
clientMouseY: Ref<number>
|
|
||||||
discordId: Ref<string>
|
|
||||||
constructor() {
|
|
||||||
this.gameRoutingCallbacks = new Map();
|
|
||||||
this.loginCallbacks = new Set();
|
|
||||||
|
|
||||||
this.effects = reactive(new Map());
|
|
||||||
this.cards = reactive(new Map());
|
|
||||||
this.teams = reactive(new Map());
|
|
||||||
this.players = reactive(new Map());
|
|
||||||
this.turns = reactive(new Map());
|
|
||||||
this.games = reactive(new Map());
|
|
||||||
|
|
||||||
this.objects = reactive(new Map());
|
|
||||||
this.current_game = ref(null);
|
|
||||||
this.lobby = ref(null);
|
|
||||||
this.self = ref(null);
|
|
||||||
this.zoomKeyPressed = ref(false);
|
|
||||||
this.hoveredCard = ref()
|
|
||||||
this.clientMouseX = ref(0)
|
|
||||||
this.clientMouseY = ref(0)
|
|
||||||
this.discordId = ref("")
|
|
||||||
}
|
|
||||||
|
|
||||||
update_object(obj: GameObjectNetcode) {
|
|
||||||
// console.log(obj);
|
|
||||||
// console.log(obj.uuid);
|
|
||||||
// console.log(this.objects.get(obj.uuid));
|
|
||||||
Object.assign(this.objects.get(obj.uuid) as GameNetcode, obj);
|
|
||||||
if (unref(this.current_game)?.uuid === obj.uuid) {
|
|
||||||
triggerRef(this.current_game);
|
|
||||||
} else if (unref(this.lobby)?.uuid === obj.uuid) {
|
|
||||||
triggerRef(this.lobby);
|
|
||||||
} else if (unref(this.self)?.uuid === obj.uuid) {
|
|
||||||
triggerRef(this.self);
|
|
||||||
} else if (unref(this.self)?.turn?.uuid === obj.uuid) {
|
|
||||||
triggerRef(this.self);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
createObject = {
|
|
||||||
effect: (data: EffectNetcode) => {
|
|
||||||
const effect = create_effect(data, this);
|
|
||||||
this.effects.set(data.uuid, effect);
|
|
||||||
this.objects.set(data.uuid, data);
|
|
||||||
},
|
|
||||||
card: (data: CardNetcode) => {
|
|
||||||
const card = create_card(data, this);
|
|
||||||
this.cards.set(data.uuid, card);
|
|
||||||
this.objects.set(data.uuid, card);
|
|
||||||
},
|
|
||||||
player: (data: PlayerNetcode) => {
|
|
||||||
const player = create_player(data, this);
|
|
||||||
this.players.set(data.uuid, player);
|
|
||||||
this.objects.set(data.uuid, player);
|
|
||||||
},
|
|
||||||
team: (data: TeamNetcode) => {
|
|
||||||
const team = create_team(data, this);
|
|
||||||
this.teams.set(data.uuid, team);
|
|
||||||
this.objects.set(data.uuid, team);
|
|
||||||
},
|
|
||||||
game: (data: GameNetcode) => {
|
|
||||||
const game = create_game(data, this);
|
|
||||||
this.games.set(data.uuid, game);
|
|
||||||
this.objects.set(data.uuid, game);
|
|
||||||
},
|
|
||||||
turn: (data: any) => {
|
|
||||||
const turn = create_turn(data, this);
|
|
||||||
this.turns.set(data.uuid, turn);
|
|
||||||
this.objects.set(data.uuid, turn);
|
|
||||||
},
|
|
||||||
lobby: (data: LobbyNetcode) => {
|
|
||||||
this.lobby.value = create_lobby(data, this);
|
|
||||||
this.objects.set(data.uuid, this.lobby.value);
|
|
||||||
},
|
|
||||||
} as { [id: string]: (data: any) => any };
|
|
||||||
|
|
||||||
setSelf = (uuid: string) => {
|
|
||||||
this.self.value = this.players.get(uuid) ?? null;
|
|
||||||
};
|
|
||||||
|
|
||||||
setDiscordId = (username: string) => {
|
|
||||||
this.discordId.value = username
|
|
||||||
}
|
|
||||||
setCurrentGame = (uuid: string) => {
|
|
||||||
this.current_game.value = this.games.get(uuid) ?? null;
|
|
||||||
this.gameRoutingCallbacks.get(uuid)?.[0]()
|
|
||||||
this.gameRoutingCallbacks.delete(uuid)
|
|
||||||
for (let [_key, value] of this.gameRoutingCallbacks) {
|
|
||||||
value[1]()
|
|
||||||
this.gameRoutingCallbacks.delete(_key)
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
const goStore = reactive(new GameObjectRegister());
|
|
||||||
|
|
||||||
export const setup_websocket = () =>
|
|
||||||
new Promise<void>((resolve, reject) => {
|
|
||||||
if (socket) {
|
|
||||||
return resolve();
|
|
||||||
}
|
|
||||||
const config = useRuntimeConfig();
|
|
||||||
const heron_session = useCookie("heron_session");
|
|
||||||
socket = new WebSocket(config.public.websocketEndpoint);
|
|
||||||
|
|
||||||
socket.onopen = function (e) {
|
|
||||||
if (socket.readyState == 1) {
|
|
||||||
resolve();
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log("[open] Connection established");
|
|
||||||
};
|
|
||||||
|
|
||||||
socket.onclose = function (event) {
|
|
||||||
if (event.wasClean) {
|
|
||||||
console.warn(
|
|
||||||
`[close] Connection closed cleanly, code=${event.code} reason=${event.reason}`
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
// e.g. server process killed or network down
|
|
||||||
// event.code is usually 1006 in this case
|
|
||||||
console.error("[close] Connection died");
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
socket.onerror = function (error) {
|
|
||||||
console.error(error);
|
|
||||||
};
|
|
||||||
|
|
||||||
socket.onmessage = function (event) {
|
|
||||||
const data = JSON.parse(event.data);
|
|
||||||
|
|
||||||
if (data.type == "create" && data.data_type == "object") {
|
|
||||||
if (!(data.data.object_type in goStore.createObject)) {
|
|
||||||
throw new Error(
|
|
||||||
`Object ${data.data.object_type} couldn't be created`
|
|
||||||
);
|
|
||||||
}
|
|
||||||
goStore.createObject[data.data.object_type](data.data);
|
|
||||||
} else if (data.type == "update" && data.data_type == "object") {
|
|
||||||
goStore.update_object(data.data);
|
|
||||||
} else if (data.type === "context") {
|
|
||||||
goStore.context = data.data;
|
|
||||||
// console.log(data.data);
|
|
||||||
} else if (data.type === "set") {
|
|
||||||
if (data.data_type == "self") {
|
|
||||||
goStore.setSelf(data.data);
|
|
||||||
} else if (data.data_type == "current_game") {
|
|
||||||
goStore.setCurrentGame(data.data);
|
|
||||||
} else if (data.data_type == "session_cookie") {
|
|
||||||
heron_session.value = data.data;
|
|
||||||
} else if (data.data_type == "self_discord_id") {
|
|
||||||
goStore.setDiscordId(data.data)
|
|
||||||
goStore.loginCallbacks.forEach(c => c())
|
|
||||||
goStore.loginCallbacks.clear()
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function heron_cookie_login(cookie: string) {
|
|
||||||
await setup_websocket();
|
|
||||||
return new Promise<void>((resolve, reject) => {
|
|
||||||
goStore.loginCallbacks.add(resolve)
|
|
||||||
socket.send(
|
|
||||||
JSON.stringify({
|
|
||||||
type: "cookie_login",
|
|
||||||
data_type: "cookie",
|
|
||||||
data: cookie,
|
|
||||||
})
|
|
||||||
);
|
|
||||||
setTimeout(() => {
|
|
||||||
goStore.loginCallbacks.delete(resolve);
|
|
||||||
reject()
|
|
||||||
}
|
|
||||||
, socketTimeout)
|
|
||||||
})
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function oauth2_register_discord(code: string) {
|
|
||||||
await setup_websocket();
|
|
||||||
return new Promise<void>((resolve, reject) => {
|
|
||||||
goStore.loginCallbacks.add(resolve)
|
|
||||||
|
|
||||||
socket.send(
|
|
||||||
JSON.stringify({
|
|
||||||
type: "discord_login",
|
|
||||||
data_type: "code",
|
|
||||||
data: code,
|
|
||||||
})
|
|
||||||
);
|
|
||||||
setTimeout(() => {
|
|
||||||
goStore.loginCallbacks.delete(resolve);
|
|
||||||
reject()
|
|
||||||
}
|
|
||||||
, socketTimeout)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function register(username: string) {
|
|
||||||
await setup_websocket();
|
|
||||||
|
|
||||||
socket.send(
|
|
||||||
JSON.stringify({
|
|
||||||
type: "register",
|
|
||||||
data_type: "username",
|
|
||||||
data: username,
|
|
||||||
})
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function login(username: string) {
|
|
||||||
await setup_websocket();
|
|
||||||
socket.send(
|
|
||||||
JSON.stringify({
|
|
||||||
type: "login",
|
|
||||||
data_type: "username",
|
|
||||||
data: username,
|
|
||||||
})
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function setReady(value: boolean) {
|
|
||||||
await setup_websocket();
|
|
||||||
socket.send(
|
|
||||||
JSON.stringify({
|
|
||||||
type: "ready",
|
|
||||||
data_type: "ready_state",
|
|
||||||
data: value,
|
|
||||||
})
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function buy(card: Card) {
|
|
||||||
await setup_websocket();
|
|
||||||
socket.send(
|
|
||||||
JSON.stringify({
|
|
||||||
type: "action",
|
|
||||||
data_type: "buy",
|
|
||||||
data: card.uuid,
|
|
||||||
})
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function endTurn() {
|
|
||||||
await setup_websocket();
|
|
||||||
socket.send(
|
|
||||||
JSON.stringify({
|
|
||||||
type: "action",
|
|
||||||
data_type: "end_turn",
|
|
||||||
data: true,
|
|
||||||
})
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function playAllCards(cards: Card[]) {
|
|
||||||
cards.forEach((c: any) => {
|
|
||||||
playCard(c);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function playCard(card: Card) {
|
|
||||||
// console.log(card.uuid);
|
|
||||||
await setup_websocket();
|
|
||||||
socket.send(
|
|
||||||
JSON.stringify({
|
|
||||||
type: "action",
|
|
||||||
data_type: "play_card",
|
|
||||||
data: card.uuid,
|
|
||||||
})
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function lockCard(card: Card) {
|
|
||||||
await setup_websocket();
|
|
||||||
socket.send(
|
|
||||||
JSON.stringify({
|
|
||||||
type: "action",
|
|
||||||
data_type: "lock_card",
|
|
||||||
data: card.uuid,
|
|
||||||
})
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function useEffect(
|
|
||||||
effect: Effect,
|
|
||||||
target?: Effect | Card | Player | Team
|
|
||||||
) {
|
|
||||||
await setup_websocket();
|
|
||||||
socket.send(
|
|
||||||
JSON.stringify({
|
|
||||||
type: "action",
|
|
||||||
data_type: "use_effect",
|
|
||||||
data: { effect_id: effect.uuid, target: target?.uuid },
|
|
||||||
})
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function discard(card: Card) {
|
|
||||||
await setup_websocket();
|
|
||||||
socket.send(
|
|
||||||
JSON.stringify({
|
|
||||||
type: "action",
|
|
||||||
data_type: "discard",
|
|
||||||
data: card.uuid,
|
|
||||||
})
|
|
||||||
);
|
|
||||||
}
|
|
||||||
h;
|
|
||||||
export async function heal() {
|
|
||||||
await setup_websocket();
|
|
||||||
socket.send(
|
|
||||||
JSON.stringify({
|
|
||||||
type: "action",
|
|
||||||
data_type: "heal",
|
|
||||||
data: 1,
|
|
||||||
})
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function damage_team(target: Team) {
|
|
||||||
await setup_websocket();
|
|
||||||
socket.send(
|
|
||||||
JSON.stringify({
|
|
||||||
type: "action",
|
|
||||||
data_type: "damage_team",
|
|
||||||
data: target.uuid,
|
|
||||||
})
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function damage_champion(target: Card) {
|
|
||||||
await setup_websocket();
|
|
||||||
socket.send(
|
|
||||||
JSON.stringify({
|
|
||||||
type: "action",
|
|
||||||
data_type: "damage_champion",
|
|
||||||
data: target.uuid,
|
|
||||||
})
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function netcode_create_game() {
|
|
||||||
await setup_websocket();
|
|
||||||
socket.send(
|
|
||||||
JSON.stringify({
|
|
||||||
type: "create",
|
|
||||||
data_type: "game",
|
|
||||||
data: "bite",
|
|
||||||
})
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function join_game(game_uuid: string) {
|
|
||||||
await setup_websocket();
|
|
||||||
return new Promise<void>(((resolve, reject) => {
|
|
||||||
goStore.gameRoutingCallbacks.set(game_uuid, [resolve, reject])
|
|
||||||
setTimeout(() => {
|
|
||||||
const cb = goStore.gameRoutingCallbacks.get(game_uuid)
|
|
||||||
if (!cb) { return }
|
|
||||||
cb[1]()
|
|
||||||
}, socketTimeout)
|
|
||||||
socket.send(
|
|
||||||
JSON.stringify({
|
|
||||||
type: "join",
|
|
||||||
data_type: "game",
|
|
||||||
data: game_uuid,
|
|
||||||
})
|
|
||||||
);
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
export default goStore;
|
|
||||||
+1
-1
Submodule netcode/interfaces updated: 89c03fe650...9248bf70af
+1
-1
@@ -4,7 +4,7 @@ export default defineNuxtConfig({
|
|||||||
ssr: false,
|
ssr: false,
|
||||||
runtimeConfig: {
|
runtimeConfig: {
|
||||||
public: {
|
public: {
|
||||||
websocketEndpoint: 'ws://127.0.0.1:8765', // can be overridden by NUXT_PUBLIC_API_BASE environment variable
|
endpoint: 'http://localhost:8765', // can be overridden by NUXT_PUBLIC_ENDPOINT environment variable
|
||||||
discordLoginEndpoint: ''
|
discordLoginEndpoint: ''
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -0,0 +1,33 @@
|
|||||||
|
import path from "path"
|
||||||
|
import type { IUser } from "~/netcode/interfaces"
|
||||||
|
|
||||||
|
|
||||||
|
enum HTTPMethods {
|
||||||
|
GET = "GET",
|
||||||
|
POST = "POST"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const Endpoints = {
|
||||||
|
LOGIN: { url: "/login", method: HTTPMethods.POST, body: null }
|
||||||
|
} as const
|
||||||
|
|
||||||
|
type ReturnTypes = {
|
||||||
|
LOGIN: IUser
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
type EnpointsNames = keyof typeof Endpoints
|
||||||
|
|
||||||
|
|
||||||
|
const config = useRuntimeConfig();
|
||||||
|
|
||||||
|
export default async function api<T extends EnpointsNames>(target: T, body?: typeof Endpoints[T]["body"]): Promise<ReturnTypes[T]> {
|
||||||
|
const data = await fetch(path.join(config.public.endpoint, Endpoints[target].url), {
|
||||||
|
credentials: "same-origin",
|
||||||
|
mode: "same-origin",
|
||||||
|
method: Endpoints[target].method,
|
||||||
|
body,
|
||||||
|
})
|
||||||
|
return await data.json() as ReturnTypes[T]
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
import path from "path";
|
||||||
|
import { defineStore } from "pinia";
|
||||||
|
import api from "~/services";
|
||||||
|
|
||||||
|
const config = useRuntimeConfig();
|
||||||
|
|
||||||
|
export const useAuthStore = defineStore("auth", {
|
||||||
|
state: () => ({
|
||||||
|
self: { id: 0, image: "" }
|
||||||
|
}),
|
||||||
|
actions: {
|
||||||
|
login: async () => {
|
||||||
|
await api("LOGIN")
|
||||||
|
},
|
||||||
|
oauth2_register_discord: () => {
|
||||||
|
throw Error("not implemented")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user