Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[v2] WIP: Scaffolds new room/match #1878

Open
wants to merge 9 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 66 additions & 0 deletions v2/fbg-web/infra/hooks/useCredential.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import { useState, useEffect } from "react";

export interface Credential {
playerID: string;
playerCredentials: string;
}

export interface FbgCredentialResult {
loaded: boolean;
credential?: Credential;
error?: string;
}

export interface FbgCredentialInput {
hostname: string;
serverId: number;
gameId: string;
roomId: string;
nickname: string;
}

export function useCredential(input: FbgCredentialInput): FbgCredentialResult {
const initialState: FbgCredentialResult = { loaded: false };
const [credential, setCredential] = useState(initialState);
useEffect(() => {
const savedCredential = localStorage.getItem(getKey(input));
if (savedCredential) {
const credential: Credential = JSON.parse(savedCredential);
setCredential({ loaded: true, credential });
return;
}
join(input).then(
(credential) => {
setCredential({ loaded: true, credential });
},
(error: any) => {
setCredential({ loaded: true, error: `${error}` });
}
);
});
return credential;
}

function getKey(input: FbgCredentialInput) {
return `credential-${input.serverId}-${input.roomId}`;
}

async function join(input: FbgCredentialInput): Promise<Credential> {
const protocol = location.protocol || "http:";
const url = `${protocol}//${input.hostname}/games/${input.gameId}/${input.roomId}/join`;
const response = await fetch(url, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
playerID: "1", // TODO new to detect next playerID
playerName: input.nickname,
}),
});
if (!response.ok) {
const text = await response.text();
throw new Error(`Join failed: ${response.status}, ${text}`);
}
return (await response.json()) as Credential;
}
28 changes: 18 additions & 10 deletions v2/fbg-web/infra/hooks/useLogin.ts
Original file line number Diff line number Diff line change
@@ -1,27 +1,35 @@
import { useState, useEffect } from "react";

const LOCALSTORAGE_KEY = "fbgNickname2";

export interface FbgLogin {
loaded: boolean;
loggedIn: boolean;
resolved: boolean;
nickname?: string;
}
const LOCALSTORAGE_KEY = "fbgNickname2";

function getNickname(): string | null {
const savedNickname = localStorage.getItem(LOCALSTORAGE_KEY);
return savedNickname;
}

function setNickname(nickname: string) {
localStorage.setItem(LOCALSTORAGE_KEY, nickname);
}

export function useLogin(): [FbgLogin, (nickname: string) => void] {
const initialState: FbgLogin = { loaded: false, loggedIn: false };
const initialState: FbgLogin = { resolved: false };
const [login, setLogin] = useState(initialState);
useEffect(() => {
const savedNickname = localStorage.getItem(LOCALSTORAGE_KEY);
const savedNickname = getNickname();
if (savedNickname) {
setLogin({ loaded: true, loggedIn: true, nickname: savedNickname });
setLogin({ resolved: true, nickname: savedNickname });
} else {
setLogin({ loaded: true, loggedIn: false });
setLogin({ resolved: true });
}
return () => {};
}, []);
const setAndSaveLogin = (nickname: string) => {
localStorage.setItem(LOCALSTORAGE_KEY, nickname);
setLogin({ loaded: true, loggedIn: true, nickname });
setNickname(nickname);
setLogin({ resolved: true, nickname });
};
return [login, setAndSaveLogin];
}
73 changes: 35 additions & 38 deletions v2/fbg-web/infra/hooks/useNewRoom.ts
Original file line number Diff line number Diff line change
@@ -1,47 +1,44 @@
import { FbgNewRoomResult, getNewRoom } from "infra/promises/getNewRoom";
import { useState, useEffect } from "react";

export interface FbgNewRoomResult {
loaded: boolean;
success?: boolean;
roomId?: string;
export interface NewRoomState {
resolved: boolean;
result?: FbgNewRoomResult;
error?: string;
}

export interface FbgNewRoomInput {
hostname: string;
export function useNewRoom({
gameId,
numPlayers,
nickname,
}: {
gameId: string;
nickname: string;
numPlayers: number;
}

export function useNewRoom(): [
FbgNewRoomResult,
(input: FbgNewRoomInput) => void
] {
const initialState: FbgNewRoomResult = { loaded: false };
nickname?: string;
}): NewRoomState {
const initialState: NewRoomState = { resolved: false };
const [newRoom, setNewRoom] = useState(initialState);
const createNewRoom = (input: FbgNewRoomInput) => {
const data = { numPlayers: input.numPlayers };
fetch(
`${location.protocol}//${input.hostname}/games/${input.gameId}/create`,
{
method: "POST",
body: JSON.stringify(data),
headers: {
"Content-Type": "application/json",
},
useEffect(() => {
if (!nickname) {
return;
}
const abortController = new AbortController();
getNewRoom({
signal: abortController.signal,
gameId,
numPlayers,
nickname,
}).then(
(result) => {
setNewRoom({ resolved: true, result });
},
(error) => {
setNewRoom({ resolved: true, error: error.toString() });
}
)
.then((response) => response.json())
.then(
(responseJson) => {
const roomId = responseJson["matchID"];
setNewRoom({ loaded: true, success: true, roomId });
},
(error) => {
console.error(error);
setNewRoom({ loaded: true, success: false });
}
);
};
return [newRoom, createNewRoom];
);
return () => {
abortController.abort();
};
}, [nickname]);
return newRoom;
}
21 changes: 21 additions & 0 deletions v2/fbg-web/infra/hooks/useRoom.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { useState, useEffect } from "react";
import { useCredential } from "./useCredential";

export interface FbgRoomResult {
loaded: boolean;
credential: any;
matchStarted?: boolean;
}

export interface FbgRoomInput {
hostname: string;
nickname: string;
serverId: number;
gameId: string;
roomId: string;
}

export function useRoom(input: FbgRoomInput): FbgRoomResult {
const credential = useCredential(input);
return { loaded: true, matchStarted: false, credential };
}
90 changes: 0 additions & 90 deletions v2/fbg-web/infra/hooks/useServer.ts

This file was deleted.

37 changes: 37 additions & 0 deletions v2/fbg-web/infra/promises/getNewRoom.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { getServer } from "./getServer";

export interface FbgNewRoomResult {
roomID: string;
serverIndex: number;
}

export interface FbgNewRoomInput {
signal: AbortSignal;
gameId: string;
nickname: string;
numPlayers: number;
}

export async function getNewRoom(
input: FbgNewRoomInput
): Promise<FbgNewRoomResult> {
const server = await getServer(input.signal);
const data = { numPlayers: input.numPlayers, unlisted: true };
const response = await fetch(
`${location.protocol}//${server.hostname}/games/${input.gameId}/create`,
{
signal: input.signal,
method: "POST",
body: JSON.stringify(data),
headers: {
"Content-Type": "application/json",
},
}
);
if (!response.ok) {
throw new Error(`New Room failed: ${response.status}, ${response.body}`);
}
const json = await response.json();
const roomID = json["matchID"] as string;
return { roomID, serverIndex: server.index };
}
Loading