import React, { useEffect, useState } from "react"; import { BaseWebPlugin, notifyErrorHandler } from "@clusterio/web_ui"; import { Alert, Button, Form, Input, Modal, Space, Spin, Typography } from "antd"; import { PlayerAuthServer } from "../messages"; import "./style.css"; const { Paragraph, Text } = Typography; interface LoginFormProps { setToken(token: string): void, } function LoginForm(props: LoginFormProps) { const [servers, setServers] = useState(null); let [playerCode, setPlayerCode] = useState(null); let [playerCodeError, setPlayerCodeError] = useState(null); let [verifyCode, setVerifyCode] = useState(); let [verifyToken, setVerifyToken] = useState(null); const [connectServer, setConnectServer] = useState<{ name: string, address: string } | null>(null); useEffect(() => { let cancelled = false; async function loadServers() { try { const response = await fetch(`${webRoot}api/player_auth/servers`); if (!response.ok) { throw new Error(`Bad server response: ${response.status}`); } const data = await response.json(); if (!cancelled) { setServers(data); } } catch (err) { if (!cancelled && err instanceof Error) { setServers([]); notifyErrorHandler("Error fetching servers")(err); } } } loadServers(); const interval = setInterval(loadServers, 15 * 1000); return () => { cancelled = true; clearInterval(interval); }; }, []); useEffect(() => { if (!verifyToken) { return undefined; } let cancelled = false; async function verify() { try { const response = await fetch(`${webRoot}api/player_auth/verify`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ verify_token: verifyToken, verify_code: verifyCode, player_code: playerCode, }), }); if (!response.ok) { throw new Error(`Bad server response: ${response.status}`); } const json = await response.json(); if (cancelled) { return; } if (json.error) { setPlayerCodeError("Code expired"); setVerifyToken(null); clearInterval(interval); return; } if (json.verified) { props.setToken(json.token); } } catch (err) { if (!cancelled && err instanceof Error) { clearInterval(interval); notifyErrorHandler("Error verifying code")(err); } } } verify(); const interval = setInterval(verify, 2 * 1000); return () => { cancelled = true; clearInterval(interval); }; }, [verifyToken]); if (!servers) { return ; } if (servers.length === 0) { return There are no running servers available for login via Factorio at the moment. Please try again later. ; } return <> setConnectServer(null)} onOk={() => { if (!connectServer) { return; } window.location.href = `steam://run/427520//--mp-connect=${connectServer.address}`; setConnectServer(null); }} > This button launches Factorio through Steam. It only works if you own and have installed the Steam version of Factorio, and Factorio is not already running. If you are using the standalone version, or Factorio is already running, use the following address with Multiplayer → Connect to address: {connectServer?.address} Login using your Factorio account is a 3 step process:
  1. Start Factorio, join one of the following multiplayer servers and type /web-login into the chat:
      {servers.map(server => (
    • {server.name} {server.factorioVersion && ( ({server.factorioVersion}) )} {server.address && ( )}
    • ))}
  2. Enter the code displayed in the in-game dialog here:
    { (async () => { let response = await fetch(`${webRoot}api/player_auth/player_code`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ player_code: values.player_code, }), }); if (!response.ok) { throw new Error(`Bad server response: ${response.status}`); } let json = await response.json(); if (json.error) { setPlayerCodeError("Invalid Code"); setVerifyToken(null); return; } setPlayerCodeError(null); setPlayerCode(values.player_code); setVerifyCode(json.verify_code); setVerifyToken(json.verify_token); })().catch(notifyErrorHandler("Error verifying code")); }} >
  3. Enter this code into the in-game dialog:
; } export class WebPlugin extends BaseWebPlugin { async init() { this.logger.info("Player Auth init"); this.loginForms = [{ name: "player_auth.factorio", title: "Factorio", Component: LoginForm, }]; } }