Release Healer Man 0.1.16
This commit is contained in:
1 parent
f49e54f35f
commit
b57d2b2839
89 files changed
+6055
-17
No files matched your search
@@ -0,0 +1,76 @@
|
||||
import type { PlayerSession } from "./types";
|
||||
import { onlineApiOrigin, requestOnlineJson } from "./onlineAccountClient";
|
||||
import type { ArenaLoadout, ArenaQueueRequest, ArenaQueueState, ArenaStageManifest } from "../game/arenaTypes";
|
||||
|
||||
export interface ArenaStateResponse {
|
||||
characterId: string | null;
|
||||
loadouts: ArenaLoadout[];
|
||||
ratings: Record<"2v2" | "3v3", { bracket: "2v2" | "3v3"; rating: number; title: string; updatedAt: number | null } | null>;
|
||||
queue: ArenaQueueState;
|
||||
stages: ArenaStageManifest[];
|
||||
}
|
||||
|
||||
function token(session: PlayerSession): string {
|
||||
if (session.kind !== "account" || !session.accessToken) throw new Error("Rated arenas require an online account.");
|
||||
return session.accessToken;
|
||||
}
|
||||
|
||||
export function fetchArenaState(session: PlayerSession, characterId: string): Promise<ArenaStateResponse> {
|
||||
return requestOnlineJson(`/api/arena/state?characterId=${encodeURIComponent(characterId)}`, {}, token(session));
|
||||
}
|
||||
|
||||
export function putArenaLoadout(
|
||||
session: PlayerSession,
|
||||
characterId: string,
|
||||
slot: number,
|
||||
loadout: Omit<ArenaLoadout, "slot" | "characterId" | "level" | "version" | "selected" | "updatedAt"> & { selected?: boolean },
|
||||
): Promise<ArenaLoadout> {
|
||||
return requestOnlineJson(`/api/arena/loadouts/${slot}`, {
|
||||
method: "PUT",
|
||||
body: JSON.stringify({ ...loadout, characterId }),
|
||||
}, token(session));
|
||||
}
|
||||
|
||||
export function deleteArenaLoadout(session: PlayerSession, characterId: string, slot: number) {
|
||||
return requestOnlineJson<{ ok: true }>(`/api/arena/loadouts/${slot}`, {
|
||||
method: "DELETE",
|
||||
body: JSON.stringify({ characterId }),
|
||||
}, token(session));
|
||||
}
|
||||
|
||||
export function enterArenaQueue(session: PlayerSession, request: ArenaQueueRequest): Promise<ArenaQueueState> {
|
||||
return requestOnlineJson("/api/arena/queue", { method: "POST", body: JSON.stringify(request) }, token(session));
|
||||
}
|
||||
|
||||
export function leaveArenaQueue(session: PlayerSession): Promise<ArenaQueueState> {
|
||||
return requestOnlineJson("/api/arena/queue", { method: "DELETE" }, token(session));
|
||||
}
|
||||
|
||||
export function acceptArenaReadyCheck(session: PlayerSession): Promise<ArenaQueueState> {
|
||||
return requestOnlineJson("/api/arena/ready", { method: "POST" }, token(session));
|
||||
}
|
||||
|
||||
interface ArenaSocketTicket { ticket: string; expiresAt: number; path: string }
|
||||
|
||||
export async function openArenaSocket(
|
||||
session: PlayerSession,
|
||||
onMessage: (message: unknown) => void,
|
||||
onClose: () => void,
|
||||
): Promise<WebSocket> {
|
||||
const response = await requestOnlineJson<ArenaSocketTicket>("/api/arena/socket-ticket", { method: "POST" }, token(session));
|
||||
const origin = onlineApiOrigin();
|
||||
const base = origin || window.location.origin;
|
||||
const url = new URL(response.path, base);
|
||||
url.protocol = url.protocol === "https:" ? "wss:" : "ws:";
|
||||
url.searchParams.set("ticket", response.ticket);
|
||||
const socket = new WebSocket(url);
|
||||
socket.addEventListener("message", (event) => {
|
||||
try { onMessage(JSON.parse(String(event.data))); } catch { /* Ignore malformed server messages. */ }
|
||||
});
|
||||
socket.addEventListener("close", onClose);
|
||||
await new Promise<void>((resolve, reject) => {
|
||||
socket.addEventListener("open", () => resolve(), { once: true });
|
||||
socket.addEventListener("error", () => reject(new Error("Could not connect to the arena server.")), { once: true });
|
||||
});
|
||||
return socket;
|
||||
}
|
||||
@@ -40,7 +40,7 @@ let pendingCharacters: CharacterProfile[] | null = null;
|
||||
let saveTimer: ReturnType<typeof setTimeout> | null = null;
|
||||
let saveQueue = Promise.resolve();
|
||||
|
||||
function apiOrigin(): string {
|
||||
export function onlineApiOrigin(): string {
|
||||
const configured = String(import.meta.env.VITE_API_BASE_URL ?? "").replace(/\/+$/, "");
|
||||
if (configured) return configured;
|
||||
return Capacitor.isNativePlatform() ? NATIVE_API_ORIGIN : "";
|
||||
@@ -53,7 +53,7 @@ export async function requestOnlineJson<T>(pathname: string, init: RequestInit =
|
||||
if (token) headers.set("Authorization", `Bearer ${token}`);
|
||||
let response: Response;
|
||||
try {
|
||||
response = await fetch(`${apiOrigin()}${pathname}`, { ...init, headers });
|
||||
response = await fetch(`${onlineApiOrigin()}${pathname}`, { ...init, headers });
|
||||
} catch {
|
||||
throw new OnlineApiError("The online server is unavailable. Check your connection or play offline.", 0);
|
||||
}
|
||||
|
||||
@@ -86,6 +86,7 @@ export interface ShellState {
|
||||
openMainMenu: () => boolean;
|
||||
openDungeons: () => boolean;
|
||||
openManastorms: () => boolean;
|
||||
openArenas: () => boolean;
|
||||
openGmAdmin: () => boolean;
|
||||
openClassHall: () => boolean;
|
||||
changeSelectedSpecialization: (specializationId: string, resetTalents: boolean) => boolean;
|
||||
@@ -333,6 +334,15 @@ export const useShellStore = create<ShellState>((set, get) => ({
|
||||
set({ phase: "manastorms", activeCharacter: null, notice: "" });
|
||||
return true;
|
||||
},
|
||||
openArenas: () => {
|
||||
const { session, selectedCharacterId, characters } = get();
|
||||
if (!session || !selectedCharacterId || !characters.some((character) => character.id === selectedCharacterId)) {
|
||||
set({ phase: session ? "characters" : "login", notice: "Select or create a character first." });
|
||||
return false;
|
||||
}
|
||||
set({ phase: "arenas", activeCharacter: null, notice: "" });
|
||||
return true;
|
||||
},
|
||||
openGmAdmin: () => {
|
||||
const { session, selectedCharacterId, characters } = get();
|
||||
if (!isGameMasterSession(session)) {
|
||||
|
||||
+1
-1
@@ -5,7 +5,7 @@ import type { EquipmentAssignments } from "../game/equipment";
|
||||
import type { GameplaySettings } from "../game/combatStore";
|
||||
import type { ManastormProgress } from "../game/manastormProgress";
|
||||
|
||||
export type ShellPhase = "login" | "characters" | "create-character" | "main-menu" | "class-hall" | "dungeons" | "manastorms" | "gm-admin" | "game";
|
||||
export type ShellPhase = "login" | "characters" | "create-character" | "main-menu" | "class-hall" | "dungeons" | "manastorms" | "arenas" | "arena-game" | "gm-admin" | "game";
|
||||
export type SessionKind = "account" | "offline";
|
||||
export type AccountRole = "gm";
|
||||
|
||||
|
||||
Reference in new issue
Block a user