diff --git a/.env.production b/.env.production index f8a939f..4577712 100644 --- a/.env.production +++ b/.env.production @@ -1,5 +1,5 @@ -REACT_APP_BROKER_URL=https://test.owlbear.rodeo -REACT_APP_ICE_SERVERS_URL=https://test.owlbear.rodeo/iceservers +REACT_APP_BROKER_URL=https://connect.owlbear.rodeo +REACT_APP_ICE_SERVERS_URL=https://connect.owlbear.rodeo/iceservers REACT_APP_STRIPE_API_KEY=pk_live_MJjzi5djj524Y7h3fL5PNh4e00a852XD51 REACT_APP_STRIPE_URL=https://payment.owlbear.rodeo REACT_APP_VERSION=$npm_package_version diff --git a/src/docs/faq/connection.md b/src/docs/faq/connection.md new file mode 100644 index 0000000..7fa5d0b --- /dev/null +++ b/src/docs/faq/connection.md @@ -0,0 +1,7 @@ +## Connection + +--- + +### WebRTC not supported. + +If you see a WebRTC not supported message ensure you are using a browser that supports [WebRTC](https://caniuse.com/rtcpeerconnection) and also ensure that you don't have an extension that is blocking WebRTC connections. Some VPN extensions can cause this. diff --git a/src/docs/faq/maps.md b/src/docs/faq/maps.md index 6194ff7..d6e35e5 100644 --- a/src/docs/faq/maps.md +++ b/src/docs/faq/maps.md @@ -2,15 +2,15 @@ --- -### I’ve added a map to my game, why can’t my players see it? +### I’ve added a map to my game, why can’t my players see it? This could be because it’s taking a while to upload. Ensure that your players can see a loading bar at the top of the site. Owlbear Rodeo will do its best to load a lower quality map, before continuing to load in higher quality. See 'How big can my maps be?' in our faqs. -If your players do not see a loading bar at the top of their screen ensure that you don't have an extension that is blocking WebRTC connections. Some VPN extensions can causes this. +If your players do not see a loading bar at the top of their screen ensure that you don't have an extension that is blocking WebRTC connections. Some VPN extensions can cause this. ### Why do some of my tokens have a question mark on them? -This means that the token hasn’t loaded in just yet. If they still haven’t loaded in after some time, try giving the page a refresh. You should see load progress on the loading bar at the top of the website. +This means that the token hasn’t loaded in just yet. If they still haven’t loaded in after some time, try giving the page a refresh. You should see load progress on the loading bar at the top of the website. ### How big can my maps be? @@ -18,7 +18,7 @@ Owlbear Rodeo doesn't impose a limit on map sizes but keep in mind the larger th ### Where are my maps stored? -Your maps are stored on your local device. This means that clearing your site data will delete your maps, so please only do so if you have no other options. +Your maps are stored on your local device. This means that clearing your site data will delete your maps, so please only do so if you have no other options. ### Why am I being prompted for a password when I didn't set one? @@ -30,4 +30,4 @@ We encourage users to create games every 24hrs. Any maps you have added or made ### I can join my game but the spinner is constantly loading, why? -This could mean that the service is currently down. Please visit us on Twitter or Reddit and let us know. \ No newline at end of file +This could mean that the service is currently down. Please visit us on Twitter or Reddit and let us know. diff --git a/src/docs/releaseNotes/v1.7.0.md b/src/docs/releaseNotes/v1.7.0.md index bd9ef33..6b89316 100644 --- a/src/docs/releaseNotes/v1.7.0.md +++ b/src/docs/releaseNotes/v1.7.0.md @@ -56,6 +56,10 @@ In this update the fog tool has been changed to hopefully help work better with - Fixed a bug causing the colour of the glass and gemstone dice to be wrong. - Fixed a bug that would cause custom tokens to not load until a refresh. +[Reddit](https://www.reddit.com/r/OwlbearRodeo/comments/l15n7n/beta_v170_release_notes_fog_enhancements/) +[Twitter](https://twitter.com/OwlbearRodeo/status/1351819654113554434) +[Patreon](https://www.patreon.com/posts/v1-7-0-released-46437122) + --- Jan 20 2021 diff --git a/src/helpers/drawing.js b/src/helpers/drawing.js index 69853b2..4731f4e 100644 --- a/src/helpers/drawing.js +++ b/src/helpers/drawing.js @@ -208,6 +208,9 @@ export function drawActionsToShapes(actions, actionIndex) { let shapesById = {}; for (let i = 0; i <= actionIndex; i++) { const action = actions[i]; + if (!action) { + continue; + } if (action.type === "add" || action.type === "edit") { for (let shape of action.shapes) { shapesById[shape.id] = shape; diff --git a/src/helpers/useNetworkedState.js b/src/helpers/useNetworkedState.js index df3e7f7..6f93308 100644 --- a/src/helpers/useNetworkedState.js +++ b/src/helpers/useNetworkedState.js @@ -88,7 +88,7 @@ function useNetworkedState( function handleSocketUpdateEvent(update) { _setState((prevState) => { - if (prevState[partialUpdatesKey] === update.id) { + if (prevState && prevState[partialUpdatesKey] === update.id) { let newState = { ...prevState }; applyChanges(newState, update.changes); lastSyncedStateRef.current = newState; diff --git a/src/index.js b/src/index.js index a503ace..8a7a4ad 100644 --- a/src/index.js +++ b/src/index.js @@ -25,6 +25,7 @@ if (process.env.REACT_APP_LOGGING === "true") { "QuotaExceededError", "XDR encoding failure", "Assertion failed: Input argument is not an HTMLInputElement", + "ERR_WEBRTC_SUPPORT", ], }); } diff --git a/src/network/NetworkedMapAndTokens.js b/src/network/NetworkedMapAndTokens.js index 8d39b50..a27ee9c 100644 --- a/src/network/NetworkedMapAndTokens.js +++ b/src/network/NetworkedMapAndTokens.js @@ -50,7 +50,7 @@ function NetworkedMapAndTokens({ session }) { "mapId" ); const [assetManifest, setAssetManifest] = useNetworkedState( - [], + null, session, "manifest", 100, @@ -94,15 +94,17 @@ function NetworkedMapAndTokens({ session }) { function addAssetIfNeeded(asset) { // Asset needs updating - const exists = assetManifest.some((oldAsset) => + const exists = assetManifest?.some((oldAsset) => compareAssets(oldAsset, asset) ); - const needsUpdate = assetManifest.some((oldAsset) => + const needsUpdate = assetManifest?.some((oldAsset) => assetNeedsUpdate(oldAsset, asset) ); if (!exists || needsUpdate) { setAssetManifest((prevAssets) => [ - ...prevAssets.filter((prevAsset) => !compareAssets(prevAsset, asset)), + ...(prevAssets || []).filter( + (prevAsset) => !compareAssets(prevAsset, asset) + ), asset, ]); } @@ -273,6 +275,9 @@ function NetworkedMapAndTokens({ session }) { */ async function handleMapTokenStateCreate(tokenState) { + if (!currentMap || !currentMapState) { + return; + } // If file type token send the token to the other peers const token = getToken(tokenState.tokenId); if (token && token.type === "file") { @@ -283,7 +288,7 @@ function NetworkedMapAndTokens({ session }) { } function handleMapTokenStateChange(change) { - if (currentMapState === null) { + if (!currentMapState) { return; } setCurrentMapState((prevMapState) => ({ diff --git a/src/network/Session.js b/src/network/Session.js index e38ea6e..d8c941c 100644 --- a/src/network/Session.js +++ b/src/network/Session.js @@ -119,7 +119,9 @@ class Session extends EventEmitter { */ sendTo(sessionId, eventId, data, channel) { if (!(sessionId in this.peers)) { - this._addPeer(sessionId, true); + if (!this._addPeer(sessionId, true)) { + return; + } } if (!this.peers[sessionId].ready) { @@ -146,7 +148,9 @@ class Session extends EventEmitter { */ startStreamTo(sessionId, track, stream) { if (!(sessionId in this.peers)) { - this._addPeer(sessionId, true); + if (!this._addPeer(sessionId, true)) { + return; + } } if (!this.peers[sessionId].ready) { @@ -192,6 +196,12 @@ class Session extends EventEmitter { this.socket.emit("join_game", gameId, password); } + /** + * Add a new peer connection + * @param {string} id + * @param {boolean} initiator + * @returns {boolean} True if peer was added successfully + */ _addPeer(id, initiator) { try { const connection = new Connection({ @@ -322,13 +332,15 @@ class Session extends EventEmitter { peer.connection.on("error", handleError.bind(this)); this.peers[id] = peer; + + return true; } catch (error) { logError(error); this.emit("peerError", { error }); - this.emit("disconnected"); for (let peer of Object.values(this.peers)) { peer.connection && peer.connection.destroy(); } + return false; } } @@ -374,7 +386,9 @@ class Session extends EventEmitter { _handleSignal(data) { const { from, signal } = data; if (!(from in this.peers)) { - this._addPeer(from, false); + if (!this._addPeer(from, false)) { + return; + } } this.peers[from].connection.signal(signal); } diff --git a/src/routes/FAQ.js b/src/routes/FAQ.js index 6d1ebb1..29c90e7 100644 --- a/src/routes/FAQ.js +++ b/src/routes/FAQ.js @@ -11,6 +11,7 @@ const database = raw("../docs/faq/database.md"); const maps = raw("../docs/faq/maps.md"); const audioSharing = raw("../docs/faq/audio-sharing.md"); const general = raw("../docs/faq/general.md"); +const connection = raw("../docs/faq/connection.md"); function FAQ() { return ( @@ -45,6 +46,9 @@ function FAQ() { + + +