Skip to content

Commit

Permalink
feat: implement chatting in multiplayer, add hooks which autodisconne…
Browse files Browse the repository at this point in the history
…cts on connection lost, add error modal;

refactor: App hooks
  • Loading branch information
LiprikON2 committed Jul 5, 2023
1 parent a9887e9 commit 2bc0781
Show file tree
Hide file tree
Showing 29 changed files with 199 additions and 145 deletions.
3 changes: 3 additions & 0 deletions client/.vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"exportall.config.relExclusion": ["/src/ui/components/ErrorModal"]
}
7 changes: 7 additions & 0 deletions client/src/game/scripts/scenes/preloadScene.ts
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,13 @@ export default class PreloadScene extends Phaser.Scene {
});
this.scene.start("MainScene", { channel });
});
// channel.onDisconnect(() => {
// this.game.outEmitter.emit("connectionError", {
// message: "Could not connect to the server",
// navigateToMode: "mainMenu",
// });
// this.game.destroy(true);
// });
});
} else {
this.game.outEmitter.emit("loading", { name: "Main Scene", progress: 100 });
Expand Down
21 changes: 14 additions & 7 deletions client/src/ui/App.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
import React, { useEffect } from "react";
import React from "react";
import { BackgroundImage, Group } from "@mantine/core";
import styled from "@emotion/styled";

import { syncSettingsToSession, useGame } from "./hooks";
import { useGame, useMultiplayerDisconnect, useSyncSettingsToSession } from "./hooks";
import { TopLeft } from "./scenes/TopLeft";
import { TopRight } from "./scenes/TopRight";
import { Center } from "./scenes/Center";
import { Right } from "./scenes/Right";
import { BottomLeft } from "./scenes/BottomLeft";
import { BottomRight } from "./scenes/BottomRight";
import background from "~/assets/ui/background-space.webp";
import { UnderTopRight } from "./scenes/UnderTopRight";
import background from "~/assets/ui/background-space.webp";
import { ErrorModal } from "./components";

// @ts-ignore
const StyledUI = styled(BackgroundImage)`
Expand Down Expand Up @@ -92,10 +93,12 @@ const StyledBottomRightGroup = styled(Group)`
`;

export const App = () => {
useEffect(() => {
const unsub = syncSettingsToSession();
return unsub;
}, []);
useSyncSettingsToSession();

const { connectionError, clearConnectionError } = useMultiplayerDisconnect();
const clearErrors = () => {
clearConnectionError();
};

const {
computed: { isLoaded },
Expand All @@ -110,6 +113,10 @@ export const App = () => {
<Right GroupComponent={StyledRightGroup} />
{isLoaded && <BottomLeft GroupComponent={StyledBottomLeftGroup} />}
<BottomRight GroupComponent={StyledBottomRightGroup} />
<ErrorModal
errors={[...(connectionError ? [connectionError] : [])]}
clearErrors={clearErrors}
/>
</StyledUI>
);
};
60 changes: 0 additions & 60 deletions client/src/ui/Root.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
//*

import "core-js/actual";
import React from "react";
import { createRoot } from "react-dom/client";
Expand Down Expand Up @@ -133,61 +131,3 @@ const events = ["mouseup", "mousedown", "touchstart", "touchmove", "touchend", "
events.forEach((event) => {
container.addEventListener(event, (e) => e.stopPropagation());
});

/*/
// import geckosClient from "@geckos.io/client";
// // @ts-ignore
// const channel = geckosClient({ url: "http://127.0.0.1:3010", port: null });
// console.log("client channel created", channel);
// channel.onConnect((error) => {
// console.log("CONNECT");
// if (error) console.error(error.message);
// // listens for a disconnection
// channel.onDisconnect(() => {
// console.log("diccsosn");
// });
// // listens for a custom event from the server
// channel.on("chat message", (data) => {
// console.log("is it truly over?", data);
// });
// // emits a message to the server
// channel.emit("chat message", "Hi!");
// });
const gg = async () => {
const host = `http://localhost:3010/.wrtc/v2`;
let headers: any = { "Content-Type": "application/json" };
let userData = {};
try {
console.log("trying");
const res = await fetch(`${host}/connections`, {
method: "POST",
headers,
});
console.log("Tried");
if (res.status >= 300) {
throw {
name: "Error",
message: `Connection failed with status code ${res.status}.`,
status: res.status,
statusText: res.statusText,
};
}
const json = await res.json();
userData = json.userData;
} catch (error: any) {
console.error("WHAT", error.message);
return { error };
}
};
gg();
//*/
38 changes: 38 additions & 0 deletions client/src/ui/components/ErrorModal/ErrorModal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import React, { useEffect } from "react";
import { Modal, Space, Title } from "@mantine/core";
import { useDisclosure } from "@mantine/hooks";

import { Errors } from "./components";

export const ErrorModal = ({ errors, clearErrors }) => {
const [opened, { close, open }] = useDisclosure(false);

useEffect(() => {
if (errors.length) {
open();
}
}, [errors]);

const handleClose = () => {
close();
clearErrors();
};

return (
<Modal.Root opened={opened} onClose={handleClose} centered size="auto">
<Modal.Overlay />
<Modal.Content>
<Modal.Header py={0}>
<Title c="red" order={2}>
Error
</Title>
<Modal.CloseButton />
</Modal.Header>
<Modal.Body>
<Space h="md" />
<Errors errors={errors} />
</Modal.Body>
</Modal.Content>
</Modal.Root>
);
};
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React from "react";
import { Text } from "@mantine/core";

export const NonFieldErrors = ({ errors }) => {
export const Errors = ({ errors }) => {
return (
<>
{errors &&
Expand Down
1 change: 1 addition & 0 deletions client/src/ui/components/ErrorModal/components/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from "./Errors";
2 changes: 2 additions & 0 deletions client/src/ui/components/ErrorModal/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from "./components";
export * from "./ErrorModal";
1 change: 1 addition & 0 deletions client/src/ui/components/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export * from "./ToggleButton";
export * from "./ErrorModal";
2 changes: 2 additions & 0 deletions client/src/ui/hooks/useGame/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from "./useGame";
export * from "./useMultiplayerDisconnect";
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from "./useMultiplayerDisconnect";
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { useDidUpdate } from "@mantine/hooks";

import { useGame } from "../";
import { useState } from "react";

export const useMultiplayerDisconnect = () => {
const [connectionError, setConnectionError] = useState<string | null>(null);
const {
gameManager,
loadMainMenu,
computed: { isLoaded },
} = useGame();

useDidUpdate(() => {
if (isLoaded) {
console.log("LOADED CHANGED");
const { channel } = gameManager.game;
channel.onDisconnect(() => {
loadMainMenu();
console.log("SET ERROR");
setConnectionError("Connection to server lost");
});
}
}, [isLoaded]);

const clearConnectionError = () => {
setConnectionError(null);
};

return { connectionError, clearConnectionError };
};
1 change: 1 addition & 0 deletions client/src/ui/hooks/useSettings/hooks/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from "./useSyncSettingsToSession";
20 changes: 20 additions & 0 deletions client/src/ui/hooks/useSettings/hooks/useSyncSettingsToSession.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { useEffect } from "react";

import { useSettings, settingsStorageKey } from "../";
import { setSessionStorage } from "../services/localStorage";

const syncSettingsToSession = () => {
const unsub = useSettings.subscribe(
(state) => state.settings,
(state) => setSessionStorage(settingsStorageKey, state)
);

return unsub;
};

export const useSyncSettingsToSession = () => {
return useEffect(() => {
const unsub = syncSettingsToSession();
return unsub;
}, []);
};
3 changes: 3 additions & 0 deletions client/src/ui/hooks/useSettings/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export * from "./hooks";
export * from "./services";
export * from "./useSettings";
1 change: 1 addition & 0 deletions client/src/ui/hooks/useSettings/services/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from "./localStorage";
23 changes: 23 additions & 0 deletions client/src/ui/hooks/useSettings/services/localStorage.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
export const setSessionStorage = (key, value) => {
sessionStorage.setItem(key, serializeJSON(value));
};

export const getSessionStorage = (key) => {
return deserializeJSON(sessionStorage.getItem(key) ?? "{}");
};

export const serializeJSON = (value: any) => {
try {
return JSON.stringify(value);
} catch (error) {
throw new Error("Failed to serialize the value");
}
};

export const deserializeJSON = (value: string) => {
try {
return JSON.parse(value);
} catch {
return value;
}
};
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import { create } from "zustand";
import { subscribeWithSelector } from "zustand/middleware";
import { produce } from "immer";

import { getSessionStorage } from "./services/localStorage";

const isTouchDevice = () =>
"ontouchstart" in window || navigator.maxTouchPoints > 0 || navigator["msMaxTouchPoints"] > 0;

Expand All @@ -16,30 +18,6 @@ interface SettingsStore {
toggleTouchControlsSetting: () => void;
}

const setSessionStorage = (key, value) => {
sessionStorage.setItem(key, serializeJSON(value));
};

const getSessionStorage = (key) => {
return deserializeJSON(sessionStorage.getItem(key) ?? "{}");
};

const serializeJSON = (value: any) => {
try {
return JSON.stringify(value);
} catch (error) {
throw new Error("Failed to serialize the value");
}
};

const deserializeJSON = (value: string) => {
try {
return JSON.parse(value);
} catch {
return value;
}
};

const defaultSettings = {
musicMute: false,
effectsMute: false,
Expand All @@ -51,11 +29,11 @@ const defaultSettings = {
showDeviceInfo: false,
};

const key = "settings";
export const settingsStorageKey = "settings";

export const useSettings = create<SettingsStore>()(
subscribeWithSelector((set) => ({
settings: { ...defaultSettings, ...getSessionStorage(key) },
settings: { ...defaultSettings, ...getSessionStorage(settingsStorageKey) },
toggleEffectsSetting: () =>
set(
produce((state) => {
Expand Down Expand Up @@ -100,12 +78,3 @@ export const useSettings = create<SettingsStore>()(
),
}))
);

export const syncSettingsToSession = () => {
const unsub = useSettings.subscribe(
(state) => state.settings,
(state) => setSessionStorage(key, state)
);

return unsub;
};
6 changes: 1 addition & 5 deletions client/src/ui/scenes/BottomRight/BottomRight.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,15 +26,11 @@ export const BottomRight = ({ GroupComponent }) => {
toggleProfileModal();
};

const handleMainMenu = () => {
loadMainMenu();
};

return (
<>
<GroupComponent>
{isLoaded && (
<Button isSquare onClick={handleMainMenu}>
<Button isSquare onClick={loadMainMenu}>
<Home />
</Button>
)}
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,7 @@ import { useDidUpdate } from "@mantine/hooks";
import { useForm } from "@mantine/form";
import { TextInput, PasswordInput, Space, Stack, Anchor } from "@mantine/core";

import { Button } from "~/ui/components";
import { NonFieldErrors } from "../../components";
import { Button, Errors } from "~/ui/components";
import { useLoginMutation } from "./hooks";

export const Login = ({ setShowLogIn, initEmailPass = {}, setInitEmailPass }) => {
Expand Down Expand Up @@ -32,7 +31,7 @@ export const Login = ({ setShowLogIn, initEmailPass = {}, setInitEmailPass }) =>
return (
<form onSubmit={form.onSubmit(handleLogin)}>
<Stack>
<NonFieldErrors errors={nonFieldErrors} />
<Errors errors={nonFieldErrors} />
<TextInput
placeholder="[email protected]"
label="Email"
Expand Down
Loading

0 comments on commit 2bc0781

Please sign in to comment.