Merge pull request #11 from mitchemmc/feature/disconnect-detection
v1.3.3
This commit is contained in:
commit
97dfc9f673
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "owlbear-rodeo",
|
||||
"version": "1.3.2",
|
||||
"version": "1.3.3",
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"@msgpack/msgpack": "^1.12.1",
|
||||
|
@ -2,7 +2,7 @@ import React from "react";
|
||||
import Modal from "react-modal";
|
||||
import { useThemeUI, Close } from "theme-ui";
|
||||
|
||||
function Banner({ isOpen, onRequestClose, children }) {
|
||||
function Banner({ isOpen, onRequestClose, children, allowClose }) {
|
||||
const { theme } = useThemeUI();
|
||||
|
||||
return (
|
||||
@ -15,7 +15,7 @@ function Banner({ isOpen, onRequestClose, children }) {
|
||||
backgroundColor: theme.colors.highlight,
|
||||
top: "initial",
|
||||
left: "50%",
|
||||
right: 0,
|
||||
right: "initial",
|
||||
// Offset for iOS safe zone
|
||||
bottom: "env(safe-area-inset-bottom)",
|
||||
border: "none",
|
||||
@ -28,13 +28,19 @@ function Banner({ isOpen, onRequestClose, children }) {
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
{allowClose && (
|
||||
<Close
|
||||
m={0}
|
||||
sx={{ position: "absolute", top: "4px", right: 0 }}
|
||||
onClick={onRequestClose}
|
||||
/>
|
||||
)}
|
||||
</Modal>
|
||||
);
|
||||
}
|
||||
|
||||
Banner.defaultProps = {
|
||||
allowClose: true,
|
||||
};
|
||||
|
||||
export default Banner;
|
||||
|
8
src/docs/releaseNotes/v1.3.3.md
Normal file
8
src/docs/releaseNotes/v1.3.3.md
Normal file
@ -0,0 +1,8 @@
|
||||
# v1.3.3
|
||||
|
||||
## Minor Changes
|
||||
|
||||
- Fixed a bug that would cause the game to crash when a player would lose internet connection.
|
||||
- Added an automatic reconnection feature for when internet connection is lost. This should also help when players put the site into the background and try and return to the game later.
|
||||
|
||||
[Reddit]()
|
@ -1,4 +1,4 @@
|
||||
import { useEffect, useState, useContext } from "react";
|
||||
import { useEffect, useState, useContext, useCallback } from "react";
|
||||
import io from "socket.io-client";
|
||||
|
||||
import { omit } from "../helpers/shared";
|
||||
@ -19,17 +19,24 @@ function useSession(
|
||||
) {
|
||||
const { password, setAuthenticationStatus } = useContext(AuthContext);
|
||||
const [iceServers, setIceServers] = useState([]);
|
||||
const [connected, setConnected] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
async function joinParty() {
|
||||
const joinParty = useCallback(async () => {
|
||||
try {
|
||||
const response = await fetch(process.env.REACT_APP_ICE_SERVERS_URL);
|
||||
const data = await response.json();
|
||||
setIceServers(data.iceServers);
|
||||
socket.emit("join party", partyId, password);
|
||||
} catch (e) {
|
||||
console.error("Unable to join party:", e.message);
|
||||
setConnected(false);
|
||||
}
|
||||
joinParty();
|
||||
}, [partyId, password]);
|
||||
|
||||
useEffect(() => {
|
||||
joinParty();
|
||||
}, [partyId, password, joinParty]);
|
||||
|
||||
const [peers, setPeers] = useState({});
|
||||
|
||||
// Signal connected peers of a closure on refresh
|
||||
@ -78,6 +85,8 @@ function useSession(
|
||||
|
||||
function handleClose() {
|
||||
onPeerDisconnected && onPeerDisconnected(peer);
|
||||
peer.connection.destroy();
|
||||
setPeers((prevPeers) => omit(prevPeers, [peer.id]));
|
||||
}
|
||||
|
||||
function handleError(error) {
|
||||
@ -153,9 +162,9 @@ function useSession(
|
||||
function handlePartyMemberLeft(id) {
|
||||
if (id in peers) {
|
||||
peers[id].connection.destroy();
|
||||
}
|
||||
setPeers((prevPeers) => omit(prevPeers, [id]));
|
||||
}
|
||||
}
|
||||
|
||||
function handleJoinedParty(otherIds) {
|
||||
for (let [index, id] of otherIds.entries()) {
|
||||
@ -164,6 +173,7 @@ function useSession(
|
||||
addPeer(id, true, sync);
|
||||
}
|
||||
setAuthenticationStatus("authenticated");
|
||||
setConnected(true);
|
||||
}
|
||||
|
||||
function handleSignal(data) {
|
||||
@ -177,21 +187,36 @@ function useSession(
|
||||
setAuthenticationStatus("unauthenticated");
|
||||
}
|
||||
|
||||
function handleSocketDisconnect() {
|
||||
setConnected(false);
|
||||
}
|
||||
|
||||
function handleSocketReconnect() {
|
||||
setConnected(true);
|
||||
joinParty();
|
||||
}
|
||||
|
||||
socket.on("disconnect", handleSocketDisconnect);
|
||||
socket.on("reconnect", handleSocketReconnect);
|
||||
|
||||
socket.on("party member joined", handlePartyMemberJoined);
|
||||
socket.on("party member left", handlePartyMemberLeft);
|
||||
socket.on("joined party", handleJoinedParty);
|
||||
socket.on("signal", handleSignal);
|
||||
socket.on("auth error", handleAuthError);
|
||||
return () => {
|
||||
socket.removeListener("party member joined", handlePartyMemberJoined);
|
||||
socket.removeListener("party member left", handlePartyMemberLeft);
|
||||
socket.removeListener("joined party", handleJoinedParty);
|
||||
socket.removeListener("signal", handleSignal);
|
||||
socket.removeListener("auth error", handleAuthError);
|
||||
};
|
||||
}, [peers, setAuthenticationStatus, iceServers]);
|
||||
socket.off("disconnect", handleSocketDisconnect);
|
||||
socket.off("reconnect", handleSocketReconnect);
|
||||
|
||||
return { peers, socket };
|
||||
socket.off("party member joined", handlePartyMemberJoined);
|
||||
socket.off("party member left", handlePartyMemberLeft);
|
||||
socket.off("joined party", handleJoinedParty);
|
||||
socket.off("signal", handleSignal);
|
||||
socket.off("auth error", handleAuthError);
|
||||
};
|
||||
}, [peers, setAuthenticationStatus, iceServers, joinParty]);
|
||||
|
||||
return { peers, socket, connected };
|
||||
}
|
||||
|
||||
export default useSession;
|
||||
|
@ -35,7 +35,7 @@ function Game() {
|
||||
);
|
||||
const { assetLoadStart, assetLoadFinish } = useContext(MapLoadingContext);
|
||||
|
||||
const { peers, socket } = useSession(
|
||||
const { peers, socket, connected } = useSession(
|
||||
gameId,
|
||||
handlePeerConnected,
|
||||
handlePeerDisconnected,
|
||||
@ -421,18 +421,6 @@ function Game() {
|
||||
const [peerError, setPeerError] = useState(null);
|
||||
function handlePeerError({ error, peer }) {
|
||||
console.error(error.code);
|
||||
if (
|
||||
error.code === "ERR_ICE_CONNECTION_FAILURE" ||
|
||||
error.code === "ERR_CONNECTION_FAILURE"
|
||||
) {
|
||||
setPeerError(
|
||||
`${
|
||||
peer.id === socket.id
|
||||
? ""
|
||||
: `(${partyNicknames[peer.id] || "Unknown"})`
|
||||
} Connection failure`
|
||||
);
|
||||
}
|
||||
if (error.code === "ERR_WEBRTC_SUPPORT") {
|
||||
setPeerError("WebRTC not supported");
|
||||
}
|
||||
@ -558,6 +546,17 @@ function Game() {
|
||||
</Text>
|
||||
</Box>
|
||||
</Banner>
|
||||
<Banner
|
||||
isOpen={!connected && authenticationStatus === "authenticated"}
|
||||
onRequestClose={() => {}}
|
||||
allowClose={false}
|
||||
>
|
||||
<Box p={1}>
|
||||
<Text as="p" variant="body2">
|
||||
Disconnected. Attempting to reconnect...
|
||||
</Text>
|
||||
</Box>
|
||||
</Banner>
|
||||
<AuthModal isOpen={authenticationStatus === "unauthenticated"} />
|
||||
{authenticationStatus === "unknown" && <LoadingOverlay />}
|
||||
</MapStageProvider>
|
||||
|
@ -51,7 +51,7 @@ function Home() {
|
||||
Join Game
|
||||
</Button>
|
||||
<Text variant="caption" as="p" sx={{ textAlign: "center" }}>
|
||||
Beta v1.3.2
|
||||
Beta v1.3.3
|
||||
</Text>
|
||||
<Button
|
||||
m={2}
|
||||
|
@ -11,6 +11,7 @@ const v121 = raw("../docs/releaseNotes/v1.2.1.md");
|
||||
const v130 = raw("../docs/releaseNotes/v1.3.0.md");
|
||||
const v131 = raw("../docs/releaseNotes/v1.3.1.md");
|
||||
const v132 = raw("../docs/releaseNotes/v1.3.2.md");
|
||||
const v133 = raw("../docs/releaseNotes/v1.3.3.md");
|
||||
|
||||
function ReleaseNotes() {
|
||||
return (
|
||||
@ -33,6 +34,9 @@ function ReleaseNotes() {
|
||||
<Text mb={2} variant="heading" as="h1" sx={{ fontSize: 5 }}>
|
||||
Release Notes
|
||||
</Text>
|
||||
<div id="v133">
|
||||
<Markdown source={v133} />
|
||||
</div>
|
||||
<div id="v132">
|
||||
<Markdown source={v132} />
|
||||
</div>
|
||||
|
Loading…
Reference in New Issue
Block a user