diff --git a/resources/scripts/components/server/features/HytaleOauthRequireFeature.tsx b/resources/scripts/components/server/features/HytaleOauthRequireFeature.tsx new file mode 100644 index 000000000..9ce32570a --- /dev/null +++ b/resources/scripts/components/server/features/HytaleOauthRequireFeature.tsx @@ -0,0 +1,112 @@ +import { useEffect, useState } from 'react'; + +import FlashMessageRender from '@/components/FlashMessageRender'; +import Button from '@/components/elements/ActionButton'; +// assuming this is your styled button +import Modal from '@/components/elements/Modal'; +import { SocketEvent } from '@/components/server/events'; + +import { ServerContext } from '@/state/server'; + +import useFlash from '@/plugins/useFlash'; + +const HytaleOauthRequireFeature = () => { + const [visible, setVisible] = useState(false); + const [userCode, setUserCode] = useState(''); + const [verificationUri, setVerificationUri] = useState(''); + + const status = ServerContext.useStoreState((state) => state.status.value); + const { clearFlashes } = useFlash(); + const { connected, instance } = ServerContext.useStoreState((state) => state.socket); + + useEffect(() => { + if (!connected || !instance || status === 'running') return; + + const listener = (line: string) => { + const urlMatch = line.match( + /https:\/\/oauth\.accounts\.hytale\.com\/oauth2\/device\/verify\?user_code=([a-zA-Z0-9\s]+)/i, + ); + if (urlMatch) { + const code = urlMatch[1]?.trim() || ''; + setUserCode(code); + setVerificationUri(urlMatch[0] || ''); + setVisible(true); + return; + } + }; + + instance.addListener(SocketEvent.CONSOLE_OUTPUT, listener); + return () => { + instance.removeListener(SocketEvent.CONSOLE_OUTPUT, listener); + }; + }, [connected, instance, status]); + + useEffect(() => { + clearFlashes('feature:hytaleOauth'); + }, []); + + const handleAuthenticate = () => { + if (verificationUri) { + window.open(verificationUri, '_blank', 'noopener,noreferrer'); + setVisible(false); + } + }; + + return ( + { + setVisible(false); + setUserCode(''); + setVerificationUri(''); + }} + closeOnBackground={false} + showSpinnerOverlay={false} + title='Hytale Authentication' + > + +
+
+

+ Server requires authentication to start. Click below to verify this device. +

+
+ + +
+
+
+
+ +
+ OR ENTER CODE MANUALLY +
+
+ +
+
DEVICE CODE
+ {userCode ? ( +
navigator.clipboard.writeText(userCode)} + > + {userCode} +
+ ) : ( +
•••• ••••
+ )} +
+ +

Only required once per server

+
+
+ ); +}; + +export default HytaleOauthRequireFeature; diff --git a/resources/scripts/components/server/features/index.ts b/resources/scripts/components/server/features/index.ts index af1303fee..d9bdf0774 100644 --- a/resources/scripts/components/server/features/index.ts +++ b/resources/scripts/components/server/features/index.ts @@ -10,10 +10,9 @@ const features: Record = { eula: lazy(() => import('@feature/eula/EulaModalFeature')), java_version: lazy(() => import('@feature/JavaVersionModalFeature')), gsl_token: lazy(() => import('@feature/GSLTokenModalFeature')), - // Why are you broken? - // Not anymore, there's a fix! pid_limit: lazy(() => import('@feature/PIDLimitModalFeature')), steam_disk_space: lazy(() => import('@feature/SteamDiskSpaceFeature')), + hytale_oauth: lazy(() => import('@feature/HytaleOauthRequireFeature')), }; export default features;