diff --git a/components/Map.tsx b/components/Map.tsx index 3c8923b..abdd416 100644 --- a/components/Map.tsx +++ b/components/Map.tsx @@ -143,6 +143,7 @@ const Map: React.FC = () => { const selectCells = useCallback( (cells: { x: number; y: number }[]) => { + console.log("selectCells"); if (!map.current) return; if (map.current && !map.current.getSource("grid-source")) return; @@ -233,6 +234,7 @@ const Map: React.FC = () => { ); const clearSelectedCell = useCallback(() => { + console.log("clearSelectedCell"); setSelectedCell(null); if (map.current) map.current.removeFeatureState({ source: "grid-source" }); if (map.current) { @@ -245,6 +247,7 @@ const Map: React.FC = () => { }, [map]); const clearSelectedCells = useCallback(() => { + console.log("clearSelectedCells"); setSelectedCells(null); if (map.current) { map.current.removeFeatureState({ source: "selected-cell-source" }); @@ -295,24 +298,45 @@ const Map: React.FC = () => { clearSelectedCell(); setSidebarOpen(true); selectCells(selectedCells); + } else if (router.query.plugin && typeof router.query.plugin === "string") { + clearSelectedCells(); + setSidebarOpen(true); + if (plugins && plugins.length > 0 && pluginsPending === 0) { + const plugin = plugins.find((p) => p.hash === router.query.plugin); + if (plugin && plugin.parsed) { + const cells = []; + const cellSet = new Set(); + for (const cell of plugin.parsed.cells) { + if ( + cell.x !== undefined && + cell.y !== undefined && + cell.world_form_id === 60 && + cellSet.has(cell.x + cell.y * 1000) === false + ) { + cells.push({ x: cell.x, y: cell.y }); + cellSet.add(cell.x + cell.y * 1000); + } + } + selectCells(cells); + } + } } else { - if (selectedCell) { - clearSelectedCell(); - } - if (selectedCells) { - clearSelectedCells(); - } + clearSelectedCell(); + clearSelectedCells(); } }, [ selectedCell, selectedCells, router.query.cell, router.query.mod, + router.query.plugin, selectCell, selectCells, clearSelectedCell, clearSelectedCells, heatmapLoaded, + plugins, + pluginsPending, ]); useEffect(() => { @@ -324,7 +348,14 @@ const Map: React.FC = () => { useEffect(() => { if (!heatmapLoaded) return; // wait for all map layers to load - if (plugins && plugins.length > 0 && pluginsPending === 0) { + if ( + plugins && + plugins.length > 0 && + pluginsPending === 0 && + !router.query.cell && + !router.query.mod && + !router.query.plugin + ) { clearSelectedCells(); const cells = plugins.reduce( (acc: { x: number; y: number }[], plugin: PluginFile) => { @@ -347,7 +378,16 @@ const Map: React.FC = () => { ); selectCells(cells); } - }, [plugins, pluginsPending, heatmapLoaded, clearSelectedCells, selectCells]); + }, [ + plugins, + pluginsPending, + heatmapLoaded, + clearSelectedCells, + selectCells, + router.query.cell, + router.query.mod, + router.query.plugin, + ]); useEffect(() => { if (map.current) return; // initialize map only once diff --git a/components/PluginData.tsx b/components/PluginData.tsx new file mode 100644 index 0000000..98fa4f1 --- /dev/null +++ b/components/PluginData.tsx @@ -0,0 +1,115 @@ +import Head from "next/head"; +import React from "react"; + +import { useAppSelector } from "../lib/hooks"; +import styles from "../styles/PluginData.module.css"; + +export interface CellCoord { + x: number; + y: number; +} + +const NEXUS_MODS_URL = "https://www.nexusmods.com/skyrimspecialedition"; + +type Props = { + hash: string; + counts: Record | null; +}; + +const PluginData: React.FC = ({ hash, counts }) => { + const plugins = useAppSelector((state) => state.plugins.plugins); + const plugin = plugins.find((plugin) => plugin.hash === hash); + + if (!plugin) { + return

Plugin could not be found

; + } + + return ( + <> + + {`Modmapper - ${plugin.filename}`} + + + + + + + +

{plugin.filename}

+ {plugin.parsed && ( +
+ Version:  + {plugin.parsed.header.version} +
+ )} + {plugin.parsed && plugin.parsed.header.author && ( +
+ Author:  + {plugin.parsed.header.author} +
+ )} + {plugin.parsed && plugin.parsed.header.masters && ( +
+ Master plugins:  + {plugin.parsed.header.masters.join(", ")} +
+ )} + {plugin.parsed && ( +
+ Cell edits:  + {plugin.parsed.cells.length} +
+ )} + {plugin.parsed && ( +
+ World edits:  + {plugin.parsed.worlds.length} +
+ )} + {plugin.parsed && plugin.parsed.header.description && ( +
+

Description:

+

{plugin.parsed.header.description}

+
+ )} + {plugin.parseError && ( +
+

Failed to parse plugin:

+

{plugin.parseError}

+
+ )} + + ); +}; + +export default PluginData; diff --git a/components/Sidebar.tsx b/components/Sidebar.tsx index b07777c..c0ac091 100644 --- a/components/Sidebar.tsx +++ b/components/Sidebar.tsx @@ -4,6 +4,7 @@ import { formatRelative } from "date-fns"; import CellData from "./CellData"; import ModData from "./ModData"; +import PluginData from "./PluginData"; import PluginsLoader from "./PluginsLoader"; import styles from "../styles/Sidebar.module.css"; @@ -56,6 +57,13 @@ const Sidebar: React.FC = ({ ); }; + const renderPluginData = (plugin: string) => { + if (countsError) return renderLoadError(countsError); + if (!counts) return renderLoading(); + + return ; + }; + const renderOpenSidebar = () => { if (selectedCell) { return ( @@ -89,6 +97,24 @@ const Sidebar: React.FC = ({ {!Number.isNaN(modId) && renderModData(modId)} ); + } else if (router.query.plugin) { + return ( +
+
+ +
+ {renderPluginData( + typeof router.query.plugin === "string" + ? router.query.plugin + : router.query.plugin[0] + )} +
+ ); } else { return (