@articles-media/articles-dev-box 1.2.0 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -51,6 +51,9 @@ npm run dev
51
51
  | SettingsModal | All in one component to handle game settings UI across multiple games. | |
52
52
  | CreditsModal | All in one component to handle game credits UI across multiple games. | |
53
53
  | InfoModal | All in one component to handle game info modal across multiple games. | USA Tycoon |
54
+ | FriendsList | List and Modal for showing friends. | Auto imported via GlobalClientModals |
55
+ | InviteModal | Modal for showing FriendsList with allowInvite | Normally used via GlobalClientModals |
56
+ | ReusedSocketLogicHandler | Sets up a lot of common websocket logic | Catching Game, Ocean Rings |
54
57
  | DarkModeHandler | Consumes a Zustand store, detects prefers-color-scheme, sets data-bs-theme on body element. | |
55
58
  | ToontownModeHandler | Handles setting zustand state from url params if toontownMode is passed. | |
56
59
  | SocketServerUrlHandler | Handles setting socket server state from url params if socketServerUrl is passed. | |
@@ -91,7 +91,8 @@ function PageTemplateLandingPage({ useStore, useSocketStore, RotatingMascot, Lin
91
91
  }), /* @__PURE__ */ jsx("div", {
92
92
  className: "servers",
93
93
  children: Array.from({ length: multiplayerConfig?.defaultServers }).map((_, id) => {
94
- let lobbyLookup = lobbyDetails?.games?.find((lobby) => parseInt(lobby.server_id) == id);
94
+ const serverNumber = id + 1;
95
+ let lobbyLookup = lobbyDetails?.games?.find((lobby) => parseInt(lobby.server_id) == serverNumber);
95
96
  return /* @__PURE__ */ jsxs("div", {
96
97
  className: "server",
97
98
  children: [
@@ -100,7 +101,7 @@ function PageTemplateLandingPage({ useStore, useSocketStore, RotatingMascot, Lin
100
101
  children: [/* @__PURE__ */ jsx("div", {
101
102
  className: "mb-0",
102
103
  style: { fontSize: "0.9rem" },
103
- children: /* @__PURE__ */ jsxs("b", { children: ["Server ", id] })
104
+ children: /* @__PURE__ */ jsxs("b", { children: ["Server ", serverNumber] })
104
105
  }), /* @__PURE__ */ jsxs("div", {
105
106
  className: "mb-0",
106
107
  children: [lobbyLookup?.players?.length || 0, "/4"]
@@ -131,7 +132,7 @@ function PageTemplateLandingPage({ useStore, useSocketStore, RotatingMascot, Lin
131
132
  className: ``,
132
133
  href: {
133
134
  pathname: `/play`,
134
- query: { server: id }
135
+ query: { server: serverNumber }
135
136
  },
136
137
  style: { ...multiplayerConfig?.comingSoon ? { pointerEvents: "none" } : {} },
137
138
  children: /* @__PURE__ */ jsx(ArticlesButton, {
@@ -0,0 +1,151 @@
1
+ import useUserDetails from "./useUserDetails.js";
2
+ import useUserToken from "./useUserToken.js";
3
+ import { useEffect, useRef, useState } from "react";
4
+ import { jsxs } from "react/jsx-runtime";
5
+ //#region src/components/Games/Socket/ReusedSocketLogicHandler.jsx
6
+ function ReusedSocketLogicHandler({ pathname, useStore, useGameStore, useSocketStore, debugConfig, landingConfig, gameConfig, server }) {
7
+ const initialized = useRef(false);
8
+ const [isVisible, setIsVisible] = useState(true);
9
+ const socket = useSocketStore((state) => state.socket);
10
+ const connectSocket = useSocketStore((state) => state.connectSocket);
11
+ const loginSocket = useSocketStore((state) => state.loginSocket);
12
+ const connected = useSocketStore((state) => state.connected);
13
+ const setConnected = useSocketStore((state) => state.setConnected);
14
+ const authenticated = useSocketStore((state) => state.authenticated);
15
+ const setAuthenticated = useSocketStore((state) => state.setAuthenticated);
16
+ const setLobbyDetails = useStore((state) => state.setLobbyDetails);
17
+ const debug = useStore((state) => state.debug);
18
+ const nickname = useStore((state) => state.nickname);
19
+ const { data: userToken, error: userTokenError, isLoading: userTokenLoading, mutate: userTokenMutate } = useUserToken(process.env.NEXT_PUBLIC_GAME_PORT);
20
+ const { data: userDetails, error: userDetailsError, isLoading: userDetailsLoading, mutate: userDetailsMutate } = useUserDetails({ token: userToken });
21
+ function debugLog(...args) {
22
+ if (debug) console.log("[📶ReusedSocketLogicHandler]", ...args);
23
+ }
24
+ useEffect(() => {
25
+ if (!initialized.current) {
26
+ initialized.current = true;
27
+ connectSocket();
28
+ }
29
+ socket.on("connect", () => {
30
+ debugLog("Connected to server!");
31
+ setConnected(true);
32
+ });
33
+ socket.on("disconnect", () => {
34
+ debugLog("Disconnected from server!");
35
+ setConnected(false);
36
+ setAuthenticated(false);
37
+ });
38
+ socket.on("force-page", (data) => {
39
+ debugLog("You are being forced to a new page!", data);
40
+ window.location.href = data.page;
41
+ });
42
+ socket.on("authenticated", (data) => {
43
+ debugLog("Socket authenticated with server!");
44
+ setAuthenticated(true);
45
+ });
46
+ socket.on(`landing-details`, function(msg) {
47
+ debugLog(`landing-details`, msg);
48
+ if (landingConfig?.onLandingDetails) landingConfig.onLandingDetails(msg);
49
+ const currentLobbyDetails = useStore.getState().lobbyDetails;
50
+ if (JSON.stringify(msg) !== JSON.stringify(currentLobbyDetails)) setLobbyDetails(msg);
51
+ });
52
+ socket.on(`game-update`, function(msg) {
53
+ debugLog(`game-update`, msg);
54
+ if (gameConfig?.onGameUpdate) gameConfig.onGameUpdate(msg);
55
+ const currentGameState = useGameStore.getState().gameState;
56
+ const setGameState = useGameStore.getState().setGameState;
57
+ if (JSON.stringify(msg) !== JSON.stringify(currentGameState)) {
58
+ debugLog("Updating game state with new data from server");
59
+ setGameState(msg);
60
+ }
61
+ });
62
+ return () => {
63
+ socket.off("connect");
64
+ socket.off("disconnect");
65
+ socket.off("force-page");
66
+ socket.off("authenticated");
67
+ socket.off(`landing-details`);
68
+ socket.off(`game-update`);
69
+ };
70
+ }, [socket]);
71
+ useEffect(() => {
72
+ if (pathname == "/" && landingConfig?.handleLandingDetails) {
73
+ if (socket.connected) socket.emit("join-room", `game:${process.env.NEXT_PUBLIC_GAME_KEY}-landing`);
74
+ return function cleanup() {
75
+ socket.emit("leave-room", `game:${process.env.NEXT_PUBLIC_GAME_KEY}-landing`);
76
+ setLobbyDetails({
77
+ players: [],
78
+ games: []
79
+ });
80
+ };
81
+ }
82
+ }, [
83
+ connected,
84
+ landingConfig?.handleLandingDetails,
85
+ pathname
86
+ ]);
87
+ useEffect(() => {
88
+ if (server && connected && gameConfig?.handleGameUpdates && pathname == "/play") {
89
+ const roomName = `game:${process.env.NEXT_PUBLIC_GAME_KEY}-room-${server}`;
90
+ debugLog("Joining game room: ", roomName);
91
+ socket.emit("join-room", roomName, {
92
+ game_id: server,
93
+ nickname,
94
+ client_version: "1"
95
+ });
96
+ return function cleanup() {
97
+ socket.emit("leave-room", roomName);
98
+ };
99
+ }
100
+ }, [
101
+ server,
102
+ connected,
103
+ nickname,
104
+ gameConfig?.handleGameUpdates,
105
+ pathname
106
+ ]);
107
+ useEffect(() => {
108
+ if (connected && !authenticated && userDetails?.user_id) {
109
+ debugLog("Socket is now connected and not authenticated with a logged in user!");
110
+ loginSocket({
111
+ user_id: userDetails?.user_id,
112
+ socket_id: socket.id,
113
+ token: userToken
114
+ });
115
+ }
116
+ }, [
117
+ connected,
118
+ authenticated,
119
+ userDetails?.user_id
120
+ ]);
121
+ useEffect(() => {
122
+ if (debugConfig.enabled && debugConfig.autoHide) {
123
+ const timer = setTimeout(() => {
124
+ setIsVisible(false);
125
+ }, debugConfig.autoHideDelay);
126
+ return () => clearTimeout(timer);
127
+ }
128
+ }, [debugConfig.enabled]);
129
+ if (debugConfig.enabled && isVisible && process.env.NODE_ENV !== "production") return /* @__PURE__ */ jsxs("div", {
130
+ style: {
131
+ position: "fixed",
132
+ bottom: 0,
133
+ left: 0,
134
+ color: "white",
135
+ fontSize: "11px",
136
+ zIndex: 9999,
137
+ backgroundColor: "rgba(0,0,0,0.5)",
138
+ padding: "2px",
139
+ display: "flex",
140
+ gap: "8px"
141
+ },
142
+ children: [
143
+ /* @__PURE__ */ jsxs("div", { children: ["Connected: ", connected ? "Yes" : "No"] }),
144
+ /* @__PURE__ */ jsxs("div", { children: ["Authenticated: ", authenticated ? "Yes" : "No"] }),
145
+ /* @__PURE__ */ jsxs("div", { children: ["ID: ", socket.id] }),
146
+ /* @__PURE__ */ jsxs("div", { children: ["Host: ", socket.io.uri] })
147
+ ]
148
+ });
149
+ }
150
+ //#endregion
151
+ export { ReusedSocketLogicHandler as default };
@@ -246,7 +246,7 @@ function OtherTab({ useStore, config }) {
246
246
  var package_default = {
247
247
  name: "@articles-media/articles-dev-box",
248
248
  description: "Shared code, functions, and components for different Articles Media projects.",
249
- version: "1.2.0",
249
+ version: "1.3.0",
250
250
  type: "module",
251
251
  sideEffects: false,
252
252
  imports: { "#root/src/*": "./src/*" },
@@ -282,6 +282,7 @@ var package_default = {
282
282
  "./HasNoMouseHandler": "./dist/HasNoMouseHandler.js",
283
283
  "./FriendsList": "./dist/FriendsList.js",
284
284
  "./InviteModal": "./dist/InviteModal.js",
285
+ "./ReusedSocketLogicHandler": "./dist/ReusedSocketLogicHandler.js",
285
286
  "./useUserDetails": "./dist/useUserDetails.js",
286
287
  "./useUserToken": "./dist/useUserToken.js",
287
288
  "./useUserFriends": "./dist/useUserFriends.js",
@@ -1,2 +1,2 @@
1
- import { t as SettingsModal } from "./SettingsModal-DT698FfY.js";
1
+ import { t as SettingsModal } from "./SettingsModal-DIMbVw4n.js";
2
2
  export { SettingsModal as default };
package/dist/index.js CHANGED
@@ -16,7 +16,7 @@ import { t as GameScoreboard } from "./GameScoreboard-CYuTBE_E.js";
16
16
  import PageTemplateLandingPage from "./PageTemplateLandingPage.js";
17
17
  import GlobalHead from "./GlobalHead.js";
18
18
  import GlobalBody_default from "./GlobalBody.js";
19
- import { t as SettingsModal } from "./SettingsModal-DT698FfY.js";
19
+ import { t as SettingsModal } from "./SettingsModal-DIMbVw4n.js";
20
20
  import CreditsModal from "./CreditsModal.js";
21
21
  import InfoModal from "./InfoModal.js";
22
22
  import DarkModeHandler from "./DarkModeHandler.js";
@@ -24,10 +24,11 @@ import ToontownModeHandler from "./ToontownModeHandler.js";
24
24
  import SocketServerUrlHandler from "./SocketServerUrlHandler.js";
25
25
  import HasNoMouseHandler from "./HasNoMouseHandler.js";
26
26
  import InviteModal from "./InviteModal.js";
27
+ import ReusedSocketLogicHandler from "./ReusedSocketLogicHandler.js";
27
28
  import typicalZustandStoreExcludes from "./typicalZustandStoreExcludes.js";
28
29
  import typicalZustandStoreStateSlice from "./typicalZustandStoreStateSlice.js";
29
30
  import defaultGameNextConfig from "./defaultGameNextConfig.js";
30
31
  import getTheme from "./defaultGameThemeConfig.js";
31
32
  import getSignOutRedirectUrl from "./getSignOutRedirectUrl.js";
32
33
  import generateRandomNickname from "./generateRandomNickname.js";
33
- export { Ad_default as Ad, ArticlesAd, CreditsModal, DarkModeHandler, FriendsList, GameMenu, PrimaryButtonGroup as GameMenuPrimaryButtonGroup, GameScoreboard, GlobalBody_default as GlobalBody, GlobalHead, HasNoMouseHandler, InfoModal, InviteModal, NicknameInput, PageTemplateLandingPage, ReturnToLauncherButton, SessionButton, SettingsModal, SignInButton, SocketServerUrlHandler, ToontownModeHandler, ViewUserModal, defaultGameNextConfig, getTheme as defaultGameThemeConfig, generateRandomNickname, getSignOutRedirectUrl, typicalZustandStoreExcludes, typicalZustandStoreStateSlice, useFullscreen, useUserDetails, useUserFriends, useUserToken };
34
+ export { Ad_default as Ad, ArticlesAd, CreditsModal, DarkModeHandler, FriendsList, GameMenu, PrimaryButtonGroup as GameMenuPrimaryButtonGroup, GameScoreboard, GlobalBody_default as GlobalBody, GlobalHead, HasNoMouseHandler, InfoModal, InviteModal, NicknameInput, PageTemplateLandingPage, ReturnToLauncherButton, ReusedSocketLogicHandler, SessionButton, SettingsModal, SignInButton, SocketServerUrlHandler, ToontownModeHandler, ViewUserModal, defaultGameNextConfig, getTheme as defaultGameThemeConfig, generateRandomNickname, getSignOutRedirectUrl, typicalZustandStoreExcludes, typicalZustandStoreStateSlice, useFullscreen, useUserDetails, useUserFriends, useUserToken };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@articles-media/articles-dev-box",
3
3
  "description": "Shared code, functions, and components for different Articles Media projects.",
4
- "version": "1.2.0",
4
+ "version": "1.3.0",
5
5
  "type": "module",
6
6
  "sideEffects": false,
7
7
  "imports": {
@@ -41,6 +41,7 @@
41
41
  "./HasNoMouseHandler": "./dist/HasNoMouseHandler.js",
42
42
  "./FriendsList": "./dist/FriendsList.js",
43
43
  "./InviteModal": "./dist/InviteModal.js",
44
+ "./ReusedSocketLogicHandler": "./dist/ReusedSocketLogicHandler.js",
44
45
  "./useUserDetails": "./dist/useUserDetails.js",
45
46
  "./useUserToken": "./dist/useUserToken.js",
46
47
  "./useUserFriends": "./dist/useUserFriends.js",