From 7d8202c3bacf32f91db8e26de181e5b1569ebb09 Mon Sep 17 00:00:00 2001 From: Danielv123 Date: Tue, 6 Feb 2024 16:48:20 +0300 Subject: [PATCH] Fixed message serialization and made web interface load --- README.md | 21 +- gridworld.code-workspace | 13 +- index.js | 22 +- messages.js | 418 ++++++++++++------ module/gridworld.lua | 6 - .../info/MigrateInstanceRequest.js | 33 +- web/components/CreateGridworldForm.jsx | 12 +- web/components/GridVisualizer.jsx | 6 +- web/components/InstanceModal.jsx | 10 +- web/components/MigrateInstanceButton.jsx | 2 +- web/components/MigrateInstanceModal.jsx | 6 +- web/components/RefreshTileDataButton.jsx | 2 +- web/components/RefreshTileDataModal.jsx | 6 +- web/index.jsx | 5 +- web/model/mapData.jsx | 6 +- web/pages/CreateGridworldPage.jsx | 3 +- web/pages/FactionViewPage.jsx | 4 +- web/pages/FactionsPage.jsx | 11 +- web/pages/OverviewPage.jsx | 12 +- 19 files changed, 367 insertions(+), 231 deletions(-) diff --git a/README.md b/README.md index fba2754..33bf969 100644 --- a/README.md +++ b/README.md @@ -24,15 +24,22 @@ Substitute clusteriocontroller with clusteriohost or clusterioctl if this a dedi Clone the repository in clusterio/external_plugins/ - cd clusterio + git clone https://github.com/clusterio/clusterio + cd clusterio/external_plugins + git clone https://github.com/Danielv123/gridworld + git clone https://github.com/clusterio/edge_transports + cd .. pnpm install - node packages/create --dev # Interactive + +Interactive: + + node packages/create --dev + node packages/ctl plugin add ./external_plugins/gridworld - pnpm install @clusterio/plugin-edge_transports -w + node packages/ctl plugin add ./external_plugins/edge_transports pnpm install @hornwitser/server_select -w - node packages/controller bootstrap create-ctl-config Danielv123 node packages/controller bootstrap create-admin Danielv123 - node packages/controller plugin add @clusterio/plugin-edge_transports + node packages/controller bootstrap create-ctl-config Danielv123 node packages/controller plugin add @hornwitser/server_select node packages/controller plugin add ./plugins/global_chat node packages/controller plugin add ./plugins/inventory_sync @@ -51,8 +58,6 @@ Log into the webui with the token in token.txt and create a new host token with node packages/host config set host.name "Host 1" node packages/host config set host.public_address "localhost" -Luacheck can be downloaded from https://github.com/mpeterv/luacheck/releases/download/0.23.0/luacheck.exe or `sudo apt install lua-check` +Luacheck can be downloaded from https://github.com/mpeterv/luacheck/releases/download/0.23.0/luacheck.exe or `sudo apt install lua-check` or `brew install luacheck` Put it in your `%path%` and run `luacheck ./module` - -eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJ1c2VyIiwidXNlciI6IkRhbmllbHYxMjMiLCJpYXQiOjE3MDcwNjYwNDR9.g9iiIDvhX8GrEWGQQYig_smOdf212dmst6HKg9LKU3g \ No newline at end of file diff --git a/gridworld.code-workspace b/gridworld.code-workspace index d1a7542..7d96576 100644 --- a/gridworld.code-workspace +++ b/gridworld.code-workspace @@ -1,21 +1,24 @@ { "folders": [ { - "path": "." + "path": "." // Gridworld }, { - "path": "../.." - } + "path": "../edge_transports" // Edge transports + }, + { + "path": "../.." // Clusterio + }, ], "settings": { - "prettier.useTabs": true, "editor.insertSpaces": false }, "extensions": { "recommendations": [ "yzhang.markdown-all-in-one", "github.copilot", - "yinfei.luahelper" + "yinfei.luahelper", + "dbaeumer.vscode-eslint" ] } } \ No newline at end of file diff --git a/index.js b/index.js index 1710c98..bd54ac8 100644 --- a/index.js +++ b/index.js @@ -61,44 +61,44 @@ module.exports = { type: "number", title: "Server position on X axis", description: "Server position index along the X axis in the gridworld", - initial_value: 1000, + initialValue: 1000, }, "gridworld.grid_y_position": { type: "number", title: "Server position on Y axis", description: "Server position index along the Y axis in the gridworld", - initial_value: 1000, + initialValue: 1000, }, "gridworld.grid_x_size": { type: "number", title: "Server size on X axis", description: "Server size along the X axis", - initial_value: 512, + initialValue: 512, }, "gridworld.grid_y_size": { type: "number", title: "Server size on Y axis", description: "Server size along the Y axis", - initial_value: 512, + initialValue: 512, }, "gridworld.is_lobby_server": { type: "boolean", title: "Server is a lobby server", description: "Make this instance act as a lobby server for a gridworld", - initial_value: false, + initialValue: false, }, "gridworld.grid_id": { type: "number", title: "Grid ID", description: "Grid identifier - used to run multiple gridworlds on the same cluster", - initial_value: 0, + initialValue: 0, }, "gridworld.claimed_by_faction": { type: "string", title: "Claimed by faction", description: "Faction that has claimed this server", - initial_value: "", + initialValue: "", }, }, @@ -108,20 +108,20 @@ module.exports = { type: "number", title: "Autosave Interval", description: "Interval the gridworld data is autosaved at in seconds.", - initial_value: 600, // 10 minutes + initialValue: 600, // 10 minutes }, "gridworld.gridworld_seed": { type: "number", title: "Gridworld seed", description: "Seed for servers created using gridworld generator", - initial_value: 999, + initialValue: 999, }, "gridworld.gridworld_map_exchange_string": { type: "string", title: "Gridworld map exchange string", description: "Map exchange string for servers created using gridworld generator", - initial_value: + initialValue: // eslint-disable-next-line max-len ">>>eNpjZGBk0GIAgwZ7EOZgSc5PzIHwDjiAMFdyfkFBapFuflEqsjBnclFpSqpufiaq4tS81NxK3aTEYqhiiMkcmUX5eegmsBaX5OehipQUpaYWw5wCwtylRYl5maW5EL0H7OGqGb+qrnZoaJFjAOH/9QwK//+DMJD1AGgjCDMwNoBVMwLFYIA1OSczLY2BQcERiJ1A0owMjNUi69wfVk0BMsFAzwHK+AAVOZAEE/GEMfwccEqpwBgmSOYYg8FnJAbE0hKQ/RBVHA4IBkSyBSTJyNj7duuC78cu2DH+Wfnxkm9Sgj2joavIuw9G6+yAkuwgfzLBiVkzQWAnzCsMMDMf2EOlbtoznj0DAm/sGVlBOkRAhIMFkDjgzczAKMAHZC3oARIKMgwwp9nBjBFxYEwDg28wnzyGMS7bo/sDGBA2IMPlQMQJEAG2EO4yRgjTod+B0UEeJiuJUALUb8SA7IYUhA9Pwqw9jGQ/mkMwIwLZH2giKg5YooELZGEKnHjBDHcNMDwvsMN4DvMdGJlBDJCqL0AxCA8kAzMKQgs4gIObmQEBPtgzuMX47gAAJhSjWw==<<<", }, @@ -129,7 +129,7 @@ module.exports = { type: "string", title: "Tiles directory", description: "Folder to store map tiles relative to database", - initial_value: "tiles", + initialValue: "tiles", }, }, diff --git a/messages.js b/messages.js index a8213cc..49771ca 100644 --- a/messages.js +++ b/messages.js @@ -1,4 +1,5 @@ "use strict"; +const { plainJson } = require("@clusterio/lib"); const factionProperties = require("./src/factions/faction_message_properties"); const pluginName = "gridworld"; @@ -10,9 +11,6 @@ module.exports = { static dst = "controller"; static plugin = pluginName; static permission = "gridworld.create"; - constructor(data) { - this.data = data; - } static jsonSchema = { type: "object", properties: { @@ -23,6 +21,16 @@ module.exports = { host: { type: "integer" }, // hostID to use for instance creation }, }; + constructor(json) { + this.name_prefix = json.name_prefix; + this.use_edge_transports = json.use_edge_transports; + this.x_size = json.x_size; + this.y_size = json.y_size; + this.host = json.host; + } + static fromJSON(json) { + return new this(json); + } }, GetMapData: class GetMapData { static type = "request"; @@ -30,41 +38,39 @@ module.exports = { static dst = "controller"; static plugin = pluginName; static permission = "gridworld.overview.view"; - static Response = { - jsonSchema: { - type: "object", - properties: { - map_data: { - type: "array", - items: { - type: "object", - additionalProperties: false, - properties: { - instance_id: { type: "integer" }, - center: { type: "array", items: { type: "number" } }, - bounds: { + static Response = plainJson({ + type: "object", + properties: { + map_data: { + type: "array", + items: { + type: "object", + additionalProperties: false, + properties: { + instance_id: { type: "integer" }, + center: { type: "array", items: { type: "number" } }, + bounds: { + type: "array", + items: { type: "array", - items: { - type: "array", - items: { type: "number" }, - }, + items: { type: "number" }, }, - edges: { - type: "array", - items: { - type: "object", - properties: { - id: { type: "integer" }, - origin: { - type: "array", - items: { type: "integer" }, - }, - surface: { type: "integer" }, - direction: { type: "integer" }, - length: { type: "integer" }, - target_instance: { type: "integer" }, - target_edge: { type: "integer" }, + }, + edges: { + type: "array", + items: { + type: "object", + properties: { + id: { type: "integer" }, + origin: { + type: "array", + items: { type: "integer" }, }, + surface: { type: "integer" }, + direction: { type: "integer" }, + length: { type: "integer" }, + target_instance: { type: "integer" }, + target_edge: { type: "integer" }, }, }, }, @@ -72,10 +78,7 @@ module.exports = { }, }, }, - fromJson(data) { - return data; - }, - }; + }); }, PopulateNeighborData: class PopulateNeighborData { static type = "request"; @@ -91,6 +94,15 @@ module.exports = { west: { type: ["integer", "null"] }, }, }; + constructor(json) { + this.north = json.north; + this.south = json.south; + this.east = json.east; + this.west = json.west; + } + static fromJSON(json) { + return new this(json); + } }, UpdateEdgeTransportEdges: class UpdateEdgeTransportEdges { static type = "request"; @@ -103,6 +115,12 @@ module.exports = { instance_id: { type: "integer" }, }, }; + constructor(json) { + this.instance_id = json.instance_id; + } + static fromJSON(json) { + return new this(json); + } }, TeleportPlayer: class TeleportPlayer { static type = "request"; @@ -117,6 +135,14 @@ module.exports = { y: { type: "number" }, }, }; + constructor(json) { + this.player_name = json.player_name; + this.x = json.x; + this.y = json.y; + } + static fromJSON(json) { + return new this(json); + } }, PlayerPosition: class PlayerPosition { static type = "event"; @@ -132,6 +158,15 @@ module.exports = { y: { type: "number" }, }, }; + constructor(json) { + this.player_name = json.player_name; + this.instance_id = json.instance_id; + this.x = json.x; + this.y = json.y; + } + static fromJSON(json) { + return new this(json); + } }, SetWebSubscription: class SetWebSubscription { static type = "request"; @@ -146,6 +181,15 @@ module.exports = { faction_list: { type: "boolean" }, }, }; + constructor(json) { + this.data = json; + } + static fromJSON(json) { + return new this(json); + } + toJSON() { + return this.data; + } }, CreateFaction: class CreateFaction { static type = "request"; @@ -156,18 +200,25 @@ module.exports = { type: "object", properties: factionProperties, }; - static Response = { - jsonSchema: { - type: "object", - properties: { - ok: { type: "boolean" }, - faction: { - type: "object", - properties: factionProperties, - }, + constructor(json) { + // eslint-disable-next-line guard-for-in + for (let key in factionProperties) { + this[key] = json[key]; + } + } + static fromJSON(json) { + return new this(json); + } + static Response = plainJson({ + type: "object", + properties: { + ok: { type: "boolean" }, + faction: { + type: "object", + properties: factionProperties, }, }, - }; + }); }, // Send updated faction data to controller for propagation. Used to edit factions UpdateFaction: class UpdateFaction { @@ -191,20 +242,27 @@ module.exports = { }, }, }; - static Response = { - jsonSchema: { - type: "object", - required: ["ok", "message"], - properties: { - ok: { type: "boolean" }, - message: { type: "string" }, - faction: { - type: "object", - properties: factionProperties, - }, + constructor(json) { + this.faction_id = json.faction_id; + this.name = json.name; + this.open = json.open; + this.about = json.about; + } + static fromJSON(json) { + return new this(json); + } + static Response = plainJson({ + type: "object", + required: ["ok", "message"], + properties: { + ok: { type: "boolean" }, + message: { type: "string" }, + faction: { + type: "object", + properties: factionProperties, }, }, - }; + }); }, // Event notifying an instance of changes to a faction FactionUpdate: class FactionUpdate { @@ -221,6 +279,12 @@ module.exports = { }, }, }; + constructor(json) { + this.faction = json.faction; + } + static fromJSON(json) { + return new this(json); + } }, // Get changed factions RefreshFactionData: class RefreshFactionData { @@ -228,22 +292,20 @@ module.exports = { static src = "instance"; static dst = "controller"; static plugin = pluginName; - static Response = { - jsonSchema: { - type: "object", - properties: { - ok: { type: "boolean" }, - message: { type: "string" }, - factions: { - type: "array", - items: { - type: "object", - properties: factionProperties, - }, + static Response = plainJson({ + type: "object", + properties: { + ok: { type: "boolean" }, + message: { type: "string" }, + factions: { + type: "array", + items: { + type: "object", + properties: factionProperties, }, }, }, - }; + }); }, FactionInvitePlayer: class FactionInvitePlayer { static type = "request"; @@ -258,15 +320,21 @@ module.exports = { role: { type: "string" }, }, }; - static Response = { - jsonSchema: { - type: "object", - properties: { - ok: { type: "boolean" }, - message: { type: "string" }, - }, + constructor(json) { + this.faction_id = json.faction_id; + this.player_name = json.player_name; + this.role = json.role; + } + static fromJSON(json) { + return new this(json); + } + static Response = plainJson({ + type: "object", + properties: { + ok: { type: "boolean" }, + message: { type: "string" }, }, - }; + }); }, JoinFaction: class JoinFaction { static type = "request"; @@ -280,15 +348,20 @@ module.exports = { player_name: { type: "string" }, }, }; - static Response = { - jsonSchema: { - type: "object", - properties: { - ok: { type: "boolean" }, - message: { type: "string" }, - }, + constructor(json) { + this.faction_id = json.faction_id; + this.player_name = json.player_name; + } + static fromJSON(json) { + return new this(json); + } + static Response = plainJson({ + type: "object", + properties: { + ok: { type: "boolean" }, + message: { type: "string" }, }, - }; + }); }, LeaveFaction: class LeaveFaction { static type = "request"; @@ -302,15 +375,20 @@ module.exports = { player_name: { type: "string" }, }, }; - static Response = { - jsonSchema: { - type: "object", - properties: { - ok: { type: "boolean" }, - message: { type: "string" }, - }, + constructor(json) { + this.faction_id = json.faction_id; + this.player_name = json.player_name; + } + static fromJSON(json) { + return new this(json); + } + static Response = plainJson({ + type: "object", + properties: { + ok: { type: "boolean" }, + message: { type: "string" }, }, - }; + }); }, FactionChangeMemberRole: class FactionChangeMemberRole { static type = "request"; @@ -325,15 +403,21 @@ module.exports = { role: factionProperties.members.items.properties.role, }, }; - static Response = { - jsonSchema: { - type: "object", - properties: { - ok: { type: "boolean" }, - message: { type: "string" }, - }, + constructor(json) { + this.faction_id = json.faction_id; + this.player_name = json.player_name; + this.role = json.role; + } + static fromJSON(json) { + return new this(json); + } + static Response = plainJson({ + type: "object", + properties: { + ok: { type: "boolean" }, + message: { type: "string" }, }, - }; + }); }, ClaimServer: class ClaimServer { static type = "request"; @@ -348,15 +432,21 @@ module.exports = { faction_id: { type: "string" }, }, }; - static Response = { - jsonSchema: { - type: "object", - properties: { - ok: { type: "boolean" }, - message: { type: "string" }, - }, + constructor(json) { + this.instance_id = json.instance_id; + this.player_name = json.player_name; + this.faction_id = json.faction_id; + } + static fromJSON(json) { + return new this(json); + } + static Response = plainJson({ + type: "object", + properties: { + ok: { type: "boolean" }, + message: { type: "string" }, }, - }; + }); }, UnclaimServer: class UnclaimServer { static type = "request"; @@ -370,15 +460,20 @@ module.exports = { player_name: { type: "string" }, }, }; - static Response = { - jsonSchema: { - type: "object", - properties: { - ok: { type: "boolean" }, - message: { type: "string" }, - }, + constructor(json) { + this.instance_id = json.instance_id; + this.player_name = json.player_name; + } + static fromJSON(json) { + return new this(json); + } + static Response = plainJson({ + type: "object", + properties: { + ok: { type: "boolean" }, + message: { type: "string" }, }, - }; + }); }, JoinGridworld: class JoinGridworld { static type = "request"; @@ -392,18 +487,23 @@ module.exports = { grid_id: { type: "integer" }, }, }; - static Response = { - jsonSchema: { - type: "object", - properties: { - ok: { type: "boolean" }, - message: { type: "string" }, - connection_address: { type: "string" }, - server_name: { type: "string" }, - server_description: { type: "string" }, - }, + constructor(json) { + this.player_name = json.player_name; + this.grid_id = json.grid_id; + } + static fromJSON(json) { + return new this(json); + } + static Response = plainJson({ + type: "object", + properties: { + ok: { type: "boolean" }, + message: { type: "string" }, + connection_address: { type: "string" }, + server_name: { type: "string" }, + server_description: { type: "string" }, }, - }; + }); }, PerformEdgeTeleport: class PerformEdgeTeleport { static type = "request"; @@ -419,19 +519,26 @@ module.exports = { grid_id: { type: "integer" }, }, }; - static Response = { - jsonSchema: { - type: "object", - properties: { - ok: { type: "boolean" }, - message: { type: "string" }, - connection_address: { type: "string" }, - server_name: { type: "string" }, - server_description: { type: "string" }, - instance_id: { type: "integer" }, - }, + constructor(json) { + this.player_name = json.player_name; + this.player_x_position = json.player_x_position; + this.player_y_position = json.player_y_position; + this.grid_id = json.grid_id; + } + static fromJSON(json) { + return new this(json); + } + static Response = plainJson({ + type: "object", + properties: { + ok: { type: "boolean" }, + message: { type: "string" }, + connection_address: { type: "string" }, + server_name: { type: "string" }, + server_description: { type: "string" }, + instance_id: { type: "integer" }, }, - }; + }); }, GetTileData: class GetTileData { static type = "request"; @@ -446,6 +553,14 @@ module.exports = { position_b: { type: "array", items: { type: "number" } }, }, }; + constructor(json) { + this.instance_id = json.instance_id; + this.position_a = json.position_a; + this.position_b = json.position_b; + } + static fromJSON(json) { + return new this(json); + } }, RefreshTileData: class RefreshTileData { static type = "request"; @@ -459,6 +574,12 @@ module.exports = { instance_id: { type: "integer" }, }, }; + constructor(json) { + this.instance_id = json.instance_id; + } + static fromJSON(json) { + return new this(json); + } }, SetLoadFactor: class SetLoadFactor { static type = "event"; @@ -472,5 +593,12 @@ module.exports = { load_factor: { type: "number" }, }, }; + constructor(json) { + this.instance_id = json.instance_id; + this.load_factor = json.load_factor; + } + static fromJSON(json) { + return new this(json); + } }, }; diff --git a/module/gridworld.lua b/module/gridworld.lua index 8a1873f..88b074d 100644 --- a/module/gridworld.lua +++ b/module/gridworld.lua @@ -29,12 +29,6 @@ local set_player_permission_group = require("faction/building_restrictions/set_p local worldgen = require("worldgen/index") local load_balancing = require("load_balancing/load_balancing") --- Declare globals to make linter happy -game = game -global = global --- defines = defines -log = log - gridworld.events = {} gridworld.events[clusterio_api.events.on_server_startup] = function() -- Set up global table diff --git a/src/instance_migration/info/MigrateInstanceRequest.js b/src/instance_migration/info/MigrateInstanceRequest.js index 933d7b8..a1b4300 100644 --- a/src/instance_migration/info/MigrateInstanceRequest.js +++ b/src/instance_migration/info/MigrateInstanceRequest.js @@ -1,11 +1,17 @@ "use strict"; -const { libLink } = require("@clusterio/lib"); + +const { plainJson } = require("@clusterio/lib"); class MigrateInstanceRequest { static type = "request"; static src = "control"; static dst = "controller"; + static plugin = "gridworld"; static permission = "gridworld.migrate_instance"; + constructor(instance_id, host_id) { + this.instance_id = instance_id; + this.host_id = host_id; + } static jsonSchema = { type: "object", properties: { @@ -15,19 +21,20 @@ class MigrateInstanceRequest { required: ["instance_id", "host_id"], additionalProperties: false, }; - static Response = { - jsonSchema: { - type: "object", - properties: { - status: { - type: "string", - enum: ["success", "failure"], - }, + static fromJSON(json) { + return new this(json.instance_id, json.host_id); + } + static Response = plainJson({ + type: "object", + properties: { + status: { + type: "string", + enum: ["success", "failure"], }, - required: ["status"], - additionalProperties: false, }, - }; -} + required: ["status"], + additionalProperties: false, + }); +}; module.exports = MigrateInstanceRequest; diff --git a/web/components/CreateGridworldForm.jsx b/web/components/CreateGridworldForm.jsx index a3263df..9feff3e 100644 --- a/web/components/CreateGridworldForm.jsx +++ b/web/components/CreateGridworldForm.jsx @@ -1,7 +1,7 @@ import React, { useContext, useState } from "react"; -import { useHistory } from "react-router"; +import { useNavigate } from "react-router-dom"; -import { ControlContext, useHostList } from "@clusterio/web_ui"; +import { ControlContext, useHosts } from "@clusterio/web_ui"; import "../index.css"; import { Form, Input, Button, Select, InputNumber, Checkbox } from "antd"; @@ -17,10 +17,10 @@ const tailLayout = { }; function NewGridworldForm() { - let history = useHistory(); + let navigate = useNavigate(); let control = useContext(ControlContext); let [loading, setLoading] = useState(); - let [hostList] = useHostList(); + let [hostList] = useHosts(); async function onFinish(values) { // console.log("Success:", values); @@ -28,7 +28,7 @@ function NewGridworldForm() { await control.send(new messages.CreateFactionGrid(values)); setLoading(false); await new Promise(resolve => setTimeout(resolve, 1500)); - history.push("/gridworld"); + navigate("/gridworld"); }; function onFinishFailed(errorInfo) { @@ -77,7 +77,7 @@ function NewGridworldForm() { diff --git a/web/components/GridVisualizer.jsx b/web/components/GridVisualizer.jsx index 6879def..ef00463 100644 --- a/web/components/GridVisualizer.jsx +++ b/web/components/GridVisualizer.jsx @@ -1,6 +1,6 @@ import React, { useContext, useState } from "react"; import { Row, Col } from "antd"; -import { Map, Polyline, Rectangle, Tooltip, TileLayer, SVGOverlay, Marker, Popup, Circle } from "react-leaflet"; +import { MapContainer, Polyline, Rectangle, Tooltip, TileLayer, SVGOverlay, Marker, Popup, Circle } from "react-leaflet"; import { ControlContext, useInstance, statusColors } from "@clusterio/web_ui"; import { useMapData } from "../model/mapData"; @@ -37,7 +37,7 @@ export default function GridVisualizer(props) { - {mapData.map_data?.length ? )} {playerPositions.map(player => )} - : ""} + : ""} diff --git a/web/components/InstanceModal.jsx b/web/components/InstanceModal.jsx index f373a84..e5f85ba 100644 --- a/web/components/InstanceModal.jsx +++ b/web/components/InstanceModal.jsx @@ -1,6 +1,7 @@ import React, { useContext } from "react"; import { Button, Descriptions, Space, Popconfirm, Typography, Tabs } from "antd"; import DeleteOutlined from "@ant-design/icons/DeleteOutlined"; +import { useNavigate } from "react-router-dom"; import { ControlContext, @@ -14,15 +15,16 @@ import { LogConsole, InstanceConfigTree, } from "@clusterio/web_ui"; -import lib from "@clusterio/lib"; +import * as lib from "@clusterio/lib"; import MigrateInstanceButton from "./MigrateInstanceButton"; function InstanceModal(props) { let control = useContext(ControlContext); let [instance] = useInstance(props.instance_id); - let [host] = useHost(instance["assigned_host"]); + let [host] = useHost(instance?.["assigned_host"]); let account = useAccount(); + let navigate = useNavigate(); return <> {props.instance_id && <> @@ -44,9 +46,9 @@ function InstanceModal(props) { okButtonProps={{ danger: true }} onConfirm={() => { control.send( - new lib.InstanceDeleteRequest({ instanceId }) + new lib.InstanceDeleteRequest(instanceId) ).then(() => { - history.push("/instances"); + navigate("/instances"); }).catch(notifyErrorHandler("Error deleting instance")); }} > diff --git a/web/components/MigrateInstanceButton.jsx b/web/components/MigrateInstanceButton.jsx index 418ccd0..8f43d7e 100644 --- a/web/components/MigrateInstanceButton.jsx +++ b/web/components/MigrateInstanceButton.jsx @@ -16,7 +16,7 @@ export default function MigrateInstanceButton(props) { : "", showModal(false)} instanceId={props.instanceId} />, diff --git a/web/components/MigrateInstanceModal.jsx b/web/components/MigrateInstanceModal.jsx index 1588c3f..96898db 100644 --- a/web/components/MigrateInstanceModal.jsx +++ b/web/components/MigrateInstanceModal.jsx @@ -1,14 +1,14 @@ import React, { useContext, useState } from "react"; import { Modal, Form, Select } from "antd"; -import { ControlContext, useInstance, useHostList } from "@clusterio/web_ui"; +import { ControlContext, useInstance, useHosts } from "@clusterio/web_ui"; import MigrateInstanceRequest from "../../src/instance_migration/info/MigrateInstanceRequest"; export default function MigrateInstanceModal(props) { const control = useContext(ControlContext); let [isWorking, setWorking] = useState(false); - let [hostList] = useHostList(); + let [hostList] = useHosts(); let [instance] = useInstance(props.instanceId); let [form] = Form.useForm(); @@ -19,7 +19,7 @@ export default function MigrateInstanceModal(props) { return { if (isWorking) { document.location = document.location; diff --git a/web/components/RefreshTileDataButton.jsx b/web/components/RefreshTileDataButton.jsx index d61bfd8..045615d 100644 --- a/web/components/RefreshTileDataButton.jsx +++ b/web/components/RefreshTileDataButton.jsx @@ -16,7 +16,7 @@ export default function RefreshTileDataButton() { : "", showModal(false)} />, ]; diff --git a/web/components/RefreshTileDataModal.jsx b/web/components/RefreshTileDataModal.jsx index 3b8748c..5cdfeef 100644 --- a/web/components/RefreshTileDataModal.jsx +++ b/web/components/RefreshTileDataModal.jsx @@ -1,13 +1,13 @@ import React, { useContext, useState } from "react"; import { Progress, Modal, InputNumber } from "antd"; -import { ControlContext, useInstanceList, notifyErrorHandler } from "@clusterio/web_ui"; +import { ControlContext, useInstances, notifyErrorHandler } from "@clusterio/web_ui"; import ThrottledPromise from "../lib/ThrottledPromise"; import messages from "../../messages"; export default function RefreshTileDataModal(props) { const control = useContext(ControlContext); - let [instanceList] = useInstanceList(); + let [instanceList] = useInstances(); let [isWorking, setWorking] = useState(false); let [percent, setPercent] = useState(0); // Completed + in progress let [success, setSuccess] = useState(0); // Completed @@ -22,7 +22,7 @@ export default function RefreshTileDataModal(props) { return { if (isWorking) { document.location = document.location; diff --git a/web/index.jsx b/web/index.jsx index 9c05510..82ef91d 100644 --- a/web/index.jsx +++ b/web/index.jsx @@ -1,7 +1,6 @@ import React from "react"; -import { libPlugin } from "@clusterio/lib"; -import { notifyErrorHandler } from "@clusterio/web_ui"; +import { BaseWebPlugin, notifyErrorHandler } from "@clusterio/web_ui"; import OverviewPage from "./pages/OverviewPage"; import CreateGridworldPage from "./pages/CreateGridworldPage"; @@ -9,7 +8,7 @@ import FactionsPage from "./pages/FactionsPage"; import FactionViewPage from "./pages/FactionViewPage"; import messages from "../messages"; -export class WebPlugin extends libPlugin.BaseWebPlugin { +export class WebPlugin extends BaseWebPlugin { async init() { this.pages = [ { diff --git a/web/model/mapData.jsx b/web/model/mapData.jsx index ed225d1..d19f5bf 100644 --- a/web/model/mapData.jsx +++ b/web/model/mapData.jsx @@ -1,12 +1,12 @@ import React, { useEffect, useContext, useState } from "react"; -import { ControlContext, useInstanceList } from "@clusterio/web_ui"; +import { ControlContext, useInstances } from "@clusterio/web_ui"; import messages from "../../messages"; -const { logger } = libLogging; +const { logger } = require("@clusterio/lib"); export function useMapData(id) { - let [instances] = useInstanceList(); + let [instances] = useInstances(); let control = useContext(ControlContext); let [mapData, setMapData] = useState({ loading: true }); diff --git a/web/pages/CreateGridworldPage.jsx b/web/pages/CreateGridworldPage.jsx index bb36193..6bad80f 100644 --- a/web/pages/CreateGridworldPage.jsx +++ b/web/pages/CreateGridworldPage.jsx @@ -1,7 +1,6 @@ import React from "react"; -import { PageHeader } from "antd"; -import { PageLayout } from "@clusterio/web_ui"; +import { PageHeader, PageLayout } from "@clusterio/web_ui"; import "../index.css"; import NewGridworldForm from "../components/CreateGridworldForm"; diff --git a/web/pages/FactionViewPage.jsx b/web/pages/FactionViewPage.jsx index 0394060..e22d97e 100644 --- a/web/pages/FactionViewPage.jsx +++ b/web/pages/FactionViewPage.jsx @@ -1,8 +1,8 @@ import React, { useEffect, useContext, useState } from "react"; import { useParams } from "react-router-dom"; -import { Alert, Descriptions, Spin, Table, PageHeader } from "antd"; +import { Alert, Descriptions, Spin, Table } from "antd"; -import { ControlContext, PageLayout } from "@clusterio/web_ui"; +import { ControlContext, PageLayout, PageHeader } from "@clusterio/web_ui"; import useFactionList from "../providers/useFactionList"; export default function FactionViewPage() { diff --git a/web/pages/FactionsPage.jsx b/web/pages/FactionsPage.jsx index 002d1e6..fc56a2d 100644 --- a/web/pages/FactionsPage.jsx +++ b/web/pages/FactionsPage.jsx @@ -1,16 +1,15 @@ import React, { useContext } from "react"; -import { useHistory } from "react-router-dom"; -import { Button, PageHeader, Popconfirm, Table } from "antd"; +import { useNavigate } from "react-router-dom"; +import { Button, Popconfirm, Table } from "antd"; import DeleteOutlined from "@ant-design/icons/DeleteOutlined"; import "../index.css"; -import { libLink } from "@clusterio/lib"; -import { ControlContext, PageLayout, useAccount, notifyErrorHandler } from "@clusterio/web_ui"; +import { ControlContext, PageLayout, PageHeader, useAccount } from "@clusterio/web_ui"; import useFactionList from "../providers/useFactionList"; function FactionsPage() { const control = useContext(ControlContext); - const history = useHistory(); + const navigate = useNavigate(); const factions = useFactionList(control); let account = useAccount(); @@ -58,7 +57,7 @@ function FactionsPage() { rowKey="faction_id" onRow={faction => ({ onClick: event => { - history.push(`/gridworld/factions/${faction.faction_id}/view`); + navigate(`/gridworld/factions/${faction.faction_id}/view`); }, })} /> diff --git a/web/pages/OverviewPage.jsx b/web/pages/OverviewPage.jsx index 1984511..a5dd434 100644 --- a/web/pages/OverviewPage.jsx +++ b/web/pages/OverviewPage.jsx @@ -1,19 +1,19 @@ import React, { useContext } from "react"; -import { useHistory } from "react-router-dom"; -import { Button, PageHeader, Popconfirm } from "antd"; +import { useNavigate } from "react-router-dom"; +import { Button, Popconfirm } from "antd"; import GithubOutlined from "@ant-design/icons/GithubOutlined"; import DeleteOutlined from "@ant-design/icons/DeleteOutlined"; import lib from "@clusterio/lib"; -import { ControlContext, PageLayout, useInstanceList, useAccount, notifyErrorHandler } from "@clusterio/web_ui"; +import { ControlContext, PageLayout, PageHeader, useInstances, useAccount, notifyErrorHandler } from "@clusterio/web_ui"; import "../index.css"; import GridVisualizer from "../components/GridVisualizer"; import RefreshTileDataButton from "../components/RefreshTileDataButton"; function OverviewPage() { const control = useContext(ControlContext); - const history = useHistory(); - let [instanceList] = useInstanceList(); + const navigate = useNavigate(); + let [instanceList] = useInstances(); let account = useAccount(); return @@ -25,7 +25,7 @@ function OverviewPage() { , account.hasPermission("core.instance.delete")