diff --git a/components/actionRow/index.tsx b/components/actionRow/index.tsx
new file mode 100644
index 0000000..7790193
--- /dev/null
+++ b/components/actionRow/index.tsx
@@ -0,0 +1,33 @@
+import { Grid, GridItem, Center, Text, Circle } from "@chakra-ui/react";
+import { getThingName } from '../../lib/utils';
+import { getUrl, getStringNoLocale } from '@inrupt/solid-client';
+import { IRowComponent } from "../thingList";
+import { MUD_LOGIC } from "../../lib/MUD";
+
+/**
+ * component is responsible for displaying a mudlogic:Action in a row
+*/
+
+export default function ActionRow({thing, selectHandler} : IRowComponent): React.ReactElement {
+ const onRowSelect = (event) => {
+ selectHandler(thing);
+ }
+
+ return (
+
+
+ ;
+
+
+
+ {getThingName(thing)}
+
+
+
+ {getStringNoLocale(thing, MUD_LOGIC.actAt)}
+
+ );
+ }
\ No newline at end of file
diff --git a/components/character/index.tsx b/components/character/index.tsx
index 91b36e6..a553638 100644
--- a/components/character/index.tsx
+++ b/components/character/index.tsx
@@ -1,13 +1,16 @@
-import { Grid, GridItem, Center, Text, Container } from "@chakra-ui/react";
+import { Grid, GridItem, Center, Text, Button, useDisclosure } from "@chakra-ui/react";
import { getThingName } from '../../lib/utils';
import ThingDepiction from "../thingDepiction";
import { getUrl } from '@inrupt/solid-client';
import { IRowComponent } from "../thingList";
+import CharacterProfile from '../characterProfile';
import TimerProgressBar from "../timerProgressBar";
import { MUD_CHARACTER } from "../../lib/MUD";
import styles from "./character.module.css";
export default function Character({thing, selectHandler} : IRowComponent): React.ReactElement {
+ const { isOpen, onOpen, onClose } = useDisclosure();
+
const onCharacterSelect = (event) => {
selectHandler(thing);
}
@@ -25,7 +28,7 @@ export default function Character({thing, selectHandler} : IRowComponent): React
}
return (
-
+
@@ -39,5 +42,10 @@ export default function Character({thing, selectHandler} : IRowComponent): React
{taskComponent}
+
+
+
+
+
);
}
\ No newline at end of file
diff --git a/components/gameWindow/index.tsx b/components/gameWindow/index.tsx
index df10dea..60b0a79 100644
--- a/components/gameWindow/index.tsx
+++ b/components/gameWindow/index.tsx
@@ -1,4 +1,4 @@
-import {useState} from "react";
+import React from "react";
import {
Tabs,
@@ -7,29 +7,17 @@ import {
Tab,
TabPanel} from "@chakra-ui/react";
-import useTerminalFeed from "../../lib/hooks/useTerminalFeed";
-import styles from "./terminal.module.css";
-
-import { WindupChildren } from "windups";
-import VisuallyHidden from "@reach/visually-hidden";
-
import CharacterView from "../characterView";
-import WorldView from "../worldView";
export default function GameWindow(): React.ReactElement {
- // we duplicate it to display content differently visually and when accessing via screen reader
return (
- Settlements
Characters
-
-
-
diff --git a/components/tables/characterTable/index.tsx b/components/tables/characterTable/index.tsx
index 20a8406..f924e72 100644
--- a/components/tables/characterTable/index.tsx
+++ b/components/tables/characterTable/index.tsx
@@ -1,17 +1,29 @@
import { useState } from 'react';
import useMudAccount from '../../../lib/hooks/useMudAccount';
+import useMudAction from "../../../lib/hooks/useMudAction";
+import useMudScene from "../../../lib/hooks/useMudScene";
import { Box, Button, Input, useDisclosure } from "@chakra-ui/react"
import styles from "./characterTable.module.css";
import Character from "../../character";
-import CharacterProfile from '../../characterProfile';
+import ActionRow from "../../actionRow";
+
+import { MUD, MUD_CHARACTER } from "../../../lib/MUD";
+import {ThingListModal} from "../../modals/thingListModal";
import {ThingList} from "../../thingList";
-import { Thing } from '@inrupt/solid-client';
+import {
+ Thing,
+ getUrl,
+ SolidDataset
+} from "@inrupt/solid-client";
export default function CharactersTable({edit} : {edit: boolean}) : React.ReactElement {
const [ newCharName, setNewCharName] = useState("");
const { characters, addCharacter } = useMudAccount();
- const [ selectedCharacter, setSelectedCharacter ] = useState(null);
+ const { discoverActions } = useMudAction();
+ const { buildScene } = useMudScene();
+ const [ scene, setScene ] = useState(null);
+ const [ actions, setActions ] = useState([]);
const { isOpen, onOpen, onClose } = useDisclosure();
const onCharacterAdd = () => {
@@ -19,10 +31,28 @@ export default function CharactersTable({edit} : {edit: boolean}) : React.ReactE
}
const selectCharacter = (character: Thing): void => {
- if(character == null) return;
+ if(character == null || getUrl(character, MUD_CHARACTER.hasTask)) return;
+
+ // Construct a scene (an array of Things)
+ buildScene([character], true).then((builtScene) => {
+
+ setScene(builtScene);
+
+ // Discover actions associated to the scene
+ discoverActions(builtScene).then((actions) => {
+
+ // Open the modal to select the desired action
+ setActions(actions);
+ onOpen();
+ });
+ });
+ }
- setSelectedCharacter(character);
- onOpen();
+ // a scene has been built and an action discovered and selected, time to put it into action!
+ const selectAction = (action: Thing) : void => {
+ //TODO
+ console.log("selected action!");
+ console.log(action);
}
let editContent = null
@@ -44,7 +74,7 @@ export default function CharactersTable({edit} : {edit: boolean}) : React.ReactE
return (
<>
-
+
{editContent}
>
diff --git a/lib/MUD.tsx b/lib/MUD.tsx
index d48ee11..0d61313 100644
--- a/lib/MUD.tsx
+++ b/lib/MUD.tsx
@@ -48,4 +48,5 @@ export const MUD_LOGIC = {
Task: MUD_LOGIC_BASE_URL + "#Task",
Transit: MUD_LOGIC_BASE_URL + "#Transit",
actAt: MUD_LOGIC_BASE_URL + "#actAt",
+ parameterConstraintsShape: MUD_LOGIC_BASE_URL + "#parameterConstraintsShape",
}
\ No newline at end of file
diff --git a/lib/context/mudActionContext/index.tsx b/lib/context/mudActionContext/index.tsx
index b0798fc..6c5d08d 100644
--- a/lib/context/mudActionContext/index.tsx
+++ b/lib/context/mudActionContext/index.tsx
@@ -8,10 +8,12 @@ import axios, { AxiosResponse } from 'axios';
import {
Thing,
createSolidDataset,
- setThing
+ setThing,
+ getThingAll,
+ SolidDataset
} from '@inrupt/solid-client';
-import { triplesToTurtle } from "../../utils";
+import { triplesToTurtle, parseTurtleToSolidDataset } from "../../utils";
import { MUD_LOGIC } from "../../MUD";
import useMudFederation from '../../hooks/useMudFederation';
@@ -21,7 +23,7 @@ import useMudFederation from '../../hooks/useMudFederation';
*/
export interface IMUDActionContext {
- postTransitTask?: (subjectThing: Thing, destinationLocatable: Thing) => Promise;
+ discoverActions?: (scene: SolidDataset) => Promise;
};
export const MudActionContext = createContext({});
@@ -37,8 +39,6 @@ export const MudActionProvider = ({
const dataset = setThing(setThing(createSolidDataset(), subject), locatable);
return triplesToTurtle(Array.from(dataset));
}
-
-
const postTask = (data: any, taskUri: String) : Promise> => {
let endpoint = getFirstConfiguredEndpoint(MUD_LOGIC.Transit);
@@ -61,10 +61,39 @@ export const MudActionProvider = ({
});
}
+ const parseContent: (data: string) => Promise = (data) => {
+ return new Promise((resolve, reject) => {
+ parseTurtleToSolidDataset(data).then((dataset) => {
+ return resolve(getThingAll(dataset));
+ });
+ });
+ }
+
+ /**
+ * Action discovery
+ */
+ const discoverActions = (scene: SolidDataset) : Promise => {
+ return new Promise((resolve, reject) => {
+
+ triplesToTurtle(Array.from(scene)).then((requestData) => {
+
+ axios.post(getFirstConfiguredEndpoint(MUD_LOGIC.actionDiscoveryEndpoint), requestData).then((response) => {
+ if(response && response.data != null) {
+
+ // parseContent will transform the Turtle dataset into a list of things
+ parseContent(response.data).then((actions) => {
+ return resolve(actions);
+ });
+ }
+ });
+ });
+ });
+ }
+
return(
{children}
diff --git a/lib/context/mudContentContext/index.tsx b/lib/context/mudContentContext/index.tsx
index 6c2e8c5..191b434 100644
--- a/lib/context/mudContentContext/index.tsx
+++ b/lib/context/mudContentContext/index.tsx
@@ -13,15 +13,13 @@ import {
asUrl,
ThingPersisted,
getThingAll,
- SolidDataset,
- createSolidDataset,
- setThing,
getThing,
} from '@inrupt/solid-client';
import { MUD, MUD_CONTENT } from "../../MUD";
import { parseTurtleToSolidDataset, getThingName, triplesToTurtle } from "../../utils";
import useMudFederation from "../../hooks/useMudFederation";
+import useMudScene from "../../hooks/useMudScene";
/**
* The Content Context leverages the Federation to serve Content describing the users' perspective
@@ -53,6 +51,7 @@ export const MudContentProvider = ({
}): ReactElement => {
const { getFirstConfiguredEndpoint } = useMudFederation();
+ const { buildScene } = useMudScene();
let recentUris = [];
@@ -85,16 +84,6 @@ export const MudContentProvider = ({
});
}
- const buildSceneTurtleData = (things: Thing[]): Promise => {
- let scene: SolidDataset = createSolidDataset();
-
- for(let thing of things) {
- scene = setThing(scene, thing);
- }
-
- return triplesToTurtle(Array.from(scene));
- }
-
/**
* builds a list of ITerminalMessage objects by getting the primary content data from parameterised things
*/
@@ -142,19 +131,23 @@ export const MudContentProvider = ({
return new Promise((resolve, reject) => {
// build scene data
- buildSceneTurtleData(things).then((requestData) => {
- postScene(requestData).then((response) => {
- if(response && response.data != null) {
-
- // parseContent has turned the content graph into an array of messages
- parseContent(response.data).then((messages) => {
- for(let message of messages) {
- newMessages.push(getITerminalMessage(message));
- }
-
- return resolve(newMessages);
- });
- }
+ buildScene(things, true).then((scene) => {
+
+ triplesToTurtle(Array.from(scene)).then((requestData) => {
+
+ postScene(requestData).then((response) => {
+ if(response && response.data != null) {
+
+ // parseContent has turned the content graph into an array of messages
+ parseContent(response.data).then((messages) => {
+ for(let message of messages) {
+ newMessages.push(getITerminalMessage(message));
+ }
+
+ return resolve(newMessages);
+ });
+ }
+ });
});
});
});
diff --git a/lib/context/mudSceneContext/index.tsx b/lib/context/mudSceneContext/index.tsx
new file mode 100644
index 0000000..3170427
--- /dev/null
+++ b/lib/context/mudSceneContext/index.tsx
@@ -0,0 +1,65 @@
+import {
+ ReactElement,
+ createContext,
+} from 'react';
+
+import axios from 'axios';
+
+import {
+ Thing,
+ SolidDataset,
+ createSolidDataset,
+ setThing,
+} from '@inrupt/solid-client';
+
+import { MUD } from "../../MUD";
+import { triplesToTurtle, parseTurtleToSolidDataset } from "../../utils";
+import useMudFederation from "../../hooks/useMudFederation";
+
+export interface IMUDSceneContext {
+ buildScene?: (things: Thing[], expandFromWorldServer: boolean) => Promise;
+};
+
+export const MudSceneContext = createContext({});
+
+export const MudSceneProvider = ({
+ children
+}): ReactElement => {
+
+ const { getFirstConfiguredEndpoint } = useMudFederation();
+
+ const buildScene = (things: Thing[], postToWorldServer=true): Promise => {
+ return new Promise((resolve, reject) => {
+ let scene: SolidDataset = createSolidDataset();
+
+ // build the basic scene from parameterised things
+ for(let thing of things) {
+ scene = setThing(scene, thing);
+ }
+
+ if(!postToWorldServer) return resolve(scene);
+
+ triplesToTurtle(Array.from(scene)).then((sceneTurtle) => {
+ // post it to the scene building endpoint
+ axios.post(getFirstConfiguredEndpoint(MUD.sceneGenerationEndpoint), sceneTurtle).then((response) => {
+ if(!response || response.data == null) {
+ console.warn("attempted to generate scene but server response was empty");
+ return resolve(scene);
+ }
+
+ return resolve(parseTurtleToSolidDataset(response.data));
+ }).catch((err) => reject(err));
+ });
+ });
+ }
+
+ return(
+
+ {children}
+
+ );
+};
diff --git a/lib/hooks/useMudAction/index.tsx b/lib/hooks/useMudAction/index.tsx
index 2f0f513..2e02f6a 100644
--- a/lib/hooks/useMudAction/index.tsx
+++ b/lib/hooks/useMudAction/index.tsx
@@ -9,11 +9,11 @@ import {
export default function useMudAction() : IMUDActionContext {
const {
- postTransitTask
+ discoverActions
} = useContext(MudActionContext);
return {
- postTransitTask,
+ discoverActions,
};
}
\ No newline at end of file
diff --git a/lib/hooks/useMudScene/index.tsx b/lib/hooks/useMudScene/index.tsx
new file mode 100644
index 0000000..b12108d
--- /dev/null
+++ b/lib/hooks/useMudScene/index.tsx
@@ -0,0 +1,19 @@
+import {
+ useContext
+} from 'react';
+
+import {
+ IMUDSceneContext,
+ MudSceneContext
+} from '../../context/mudSceneContext';
+
+export default function useMudContent() : IMUDSceneContext {
+ const {
+ buildScene
+ } = useContext(MudSceneContext);
+
+ return {
+ buildScene
+ };
+}
+
\ No newline at end of file
diff --git a/lib/utils.tsx b/lib/utils.tsx
index 51a06f0..d576f04 100644
--- a/lib/utils.tsx
+++ b/lib/utils.tsx
@@ -11,7 +11,7 @@ import {
getStringNoLocale
} from "@inrupt/solid-client";
-import {RDF, VCARD, FOAF} from "@inrupt/lit-generated-vocab-common";
+import {RDF, VCARD, FOAF, RDFS} from "@inrupt/lit-generated-vocab-common";
/**
* @returns All Things from a given dataset if they are of parameterised type
@@ -110,7 +110,7 @@ export const parseTurtleToSolidDataset = async (turtle: string) : Promise {
- const NAME_PROPERTIES = [VCARD.fn, FOAF.name];
+ const NAME_PROPERTIES = [VCARD.fn, FOAF.name, RDFS.label];
for(let PROP of NAME_PROPERTIES) {
const name = getStringNoLocale(thing, PROP);
diff --git a/pages/index.tsx b/pages/index.tsx
index daab55d..f1ef7b0 100644
--- a/pages/index.tsx
+++ b/pages/index.tsx
@@ -24,6 +24,7 @@ import ActionMenu from "../components/actionMenu";
import Terminal from "../components/terminal";
import GameWindow from "../components/gameWindow";
import WorldFinder from "../components/worldFinder";
+import { MudSceneProvider } from "../lib/context/mudSceneContext";
export default function Home(): React.ReactElement {
const [ worldConnection, setWorldConnection ] = useState(null);
@@ -63,23 +64,25 @@ export default function Home(): React.ReactElement {
else {
inner = (
-
-
-
-
-
- {header}
-
-
-
+
+
+
+
+
-
+ {header}
+
+
+
+
+
+
-
-
-
-
-
+
+
+
+
+
);
}