verb seek complete
This commit is contained in:
parent
12f1283e4e
commit
534ffeaf8e
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,6 +1,7 @@
|
||||
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
|
||||
|
||||
the_big_db.db
|
||||
dump*.json
|
||||
|
||||
# dependencies
|
||||
node_modules
|
||||
|
@ -19,7 +19,7 @@ function Live({editing, ...props}) {
|
||||
const [ currentNumber, setCurrentNumber ] = useState(1);
|
||||
const [ connecting, setConnecting ] = useState(true);
|
||||
|
||||
const { sendMessage, lastMessage, readyState } = useWebSocket(`${wsUrl}/embody`, {
|
||||
const { sendMessage, lastMessage, lastJsonMessage, readyState } = useWebSocket(`${wsUrl}/embody`, {
|
||||
onClose: () => setConnecting(false)
|
||||
}, connecting);
|
||||
|
||||
@ -34,24 +34,35 @@ function Live({editing, ...props}) {
|
||||
}
|
||||
}
|
||||
}, [lastMessage]);
|
||||
|
||||
function handleSendMessage() {
|
||||
console.log("sending a message...");
|
||||
sendMessage("button got clicked");
|
||||
}
|
||||
|
||||
// spread this return value on <a/> elements in order to make them navigate
|
||||
const commandLinkClick = (e) => {
|
||||
if (e.target.tagName != "A") { return; }
|
||||
if (!e.target.href.includes(window.location.origin)) { return; }
|
||||
e.preventDefault();
|
||||
|
||||
const localLink = e.target.href.replace(window.location.origin, "");
|
||||
const targetString = localLink.replace("/", "");
|
||||
const targetNumber = Number(targetString);
|
||||
|
||||
if (targetNumber != 0 && targetNumber != NaN) {
|
||||
const warpMessage = `warp #${targetString}`;
|
||||
console.log(`clicked a link, executing "warp #${targetString}"`);
|
||||
sendMessage(warpMessage);
|
||||
return;
|
||||
}
|
||||
|
||||
navigate(e.target.href.replace(window.location.origin, ""));
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<Page editing={editing} number={currentNumber} {...props}/>
|
||||
<Page editing={editing} number={currentNumber} linkClick={commandLinkClick} {...props} />
|
||||
<MessageFeed messages={messageHistory}>
|
||||
<button disabled={readyState!=ReadyState.OPEN} onClick={handleSendMessage}>send a message to the server!</button>
|
||||
<button disabled={connecting} onClick={() => setConnecting(true)}>Reconnect</button>
|
||||
<button onClick={()=> setMessageHistory([])}>Clear History</button>
|
||||
</MessageFeed>
|
||||
<Sidebar pagenumber={currentNumber} hidden="true" sendWord={(word) => setCommand((command + " " + word).trim())}>
|
||||
{!editing && <li><button onClick={() => navigate(`/${currentNumber}/edit`)}>edit</button></li>}
|
||||
{editing && <li><button disabled={postMutation.isPending} onClick={submitChanges}>save</button></li>}
|
||||
{editing && <li><button onClick={() => navigate(`/${currentNumber}`)}>return</button></li>}
|
||||
</Sidebar>
|
||||
<CommandEntry onSubmit={sendMessage}/>
|
||||
</>
|
||||
|
@ -2,7 +2,6 @@ import { useState } from 'react';
|
||||
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
|
||||
import { useParams, useNavigate } from 'react-router-dom';
|
||||
import { apiUrl, fetchPage, fetchPageAtEdit, postPage, deletePage } from '../apiTools.jsx';
|
||||
import { useFixLinks } from '../clientStuff.jsx';
|
||||
import { useLoggedIn } from '../AuthProvider.jsx';
|
||||
import Page from './Page.jsx';
|
||||
|
||||
@ -10,10 +9,21 @@ import './Pages.css';
|
||||
|
||||
function GhostPage({editing, ...props}) {
|
||||
const { pagenumber, editid } = useParams();
|
||||
const navigate = useNavigate();
|
||||
|
||||
return (
|
||||
<Page number={pagenumber} editid={editid} editing={editing} {...props}/>
|
||||
);
|
||||
const linkClick = (e) => {
|
||||
if (e.target.tagName != "A") { return; }
|
||||
if (!e.target.href.includes(window.location.origin)) { return; }
|
||||
e.preventDefault();
|
||||
navigate(e.target.href.replace(window.location.origin, ""));
|
||||
};
|
||||
|
||||
return <Page
|
||||
number={pagenumber}
|
||||
editid={editid}
|
||||
editing={editing}
|
||||
linkClick={linkClick}
|
||||
{...props}/>;
|
||||
}
|
||||
|
||||
export default GhostPage;
|
@ -6,11 +6,10 @@ import { useLoggedIn } from '../AuthProvider.jsx';
|
||||
|
||||
import './Pages.css';
|
||||
|
||||
function Page({ editing, number, editid=null}) {
|
||||
function Page({ editing, number, editid=null, linkClick=()=>{} }) {
|
||||
const queryClient = useQueryClient();
|
||||
const navigate = useNavigate();
|
||||
const loggedIn = useLoggedIn();
|
||||
const noLoad = useFixLinks();
|
||||
|
||||
const fetchQuery = useQuery({ // fetch the currrent values
|
||||
queryKey: ['page', number, editid],
|
||||
@ -61,7 +60,7 @@ function Page({ editing, number, editid=null}) {
|
||||
<div className="main-column">
|
||||
<header>
|
||||
<h1>
|
||||
<a href="/" {...noLoad}>🌳</a>
|
||||
<a href="/" onClick={linkClick}>🌳</a>
|
||||
{number}.
|
||||
<span
|
||||
contentEditable={editing}
|
||||
@ -80,7 +79,7 @@ function Page({ editing, number, editid=null}) {
|
||||
:
|
||||
<div
|
||||
dangerouslySetInnerHTML={{__html: html}}
|
||||
{...noLoad} />
|
||||
onClick={linkClick} />
|
||||
)
|
||||
:
|
||||
"..."
|
||||
|
11
server/db_scripts/dump_24-10-10.js
Normal file
11
server/db_scripts/dump_24-10-10.js
Normal file
@ -0,0 +1,11 @@
|
||||
const sqlite = require("better-sqlite3");
|
||||
const db = new sqlite('the_big_db.db', { verbose: console.log });
|
||||
|
||||
const fs = require('node:fs');
|
||||
|
||||
const dump = {
|
||||
pages: db.prepare('select * from pages').all(),
|
||||
users: db.prepare('select * from users').all()
|
||||
};
|
||||
|
||||
fs.writeFile(`dump_${new Date().toISOString()}.json`, JSON.stringify(dump), (err) => console.log(err) );
|
187
server/db_scripts/initialize_db-24-10-10.1.js
Normal file
187
server/db_scripts/initialize_db-24-10-10.1.js
Normal file
@ -0,0 +1,187 @@
|
||||
// wipe and load the database from a dump file created by dump_blahblah.js
|
||||
const hljs = require('highlight.js/lib/core');
|
||||
hljs.registerLanguage('lua', require('highlight.js/lib/languages/lua'));
|
||||
|
||||
const fs = require('node:fs');
|
||||
const sqlite = require("better-sqlite3");
|
||||
const showdown = require("showdown");
|
||||
const db = new sqlite('the_big_db.db', { verbose: console.log });
|
||||
|
||||
const converter = new showdown.Converter();
|
||||
|
||||
const dump_file_name = process.argv[2]
|
||||
//get argument out of 'node db_scripts/initialize_db-blah-blah.js dumpfile'
|
||||
|
||||
let data = "{}";
|
||||
try {
|
||||
data = fs.readFileSync(dump_file_name, 'utf8');
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
return;
|
||||
}
|
||||
//open that file as text (unicode i guess?)
|
||||
console.log("opened file");
|
||||
const filejson = JSON.parse(data);
|
||||
//parse it as json
|
||||
|
||||
|
||||
const pages = filejson["pages"];
|
||||
|
||||
const createPages = db.prepare(`
|
||||
create table if not exists pages (
|
||||
id integer primary key,
|
||||
number integer,
|
||||
|
||||
title varchar(255),
|
||||
|
||||
description text,
|
||||
html text,
|
||||
lua text,
|
||||
|
||||
time timestamp default current_timestamp,
|
||||
author integer,
|
||||
|
||||
type integer
|
||||
)
|
||||
`);
|
||||
/* an object has:
|
||||
id = primary key
|
||||
number = object identifier number
|
||||
|
||||
title / NAME = a short display name for an object, or the title of a page
|
||||
description / TEXT? = the markdown description of an object, or the lua script of the source code of a verb
|
||||
|
||||
html / HTML_MARKDOWN? = the markdown for that object, rendered into html for display as a page
|
||||
HTML_LUA? = the lua source code of the object, rendered into html with syntax highlighting?
|
||||
|
||||
time = when this edit was saved
|
||||
author = the user id of whoever authored this revision
|
||||
|
||||
TYPE = whether this represents an object or a verb
|
||||
*/
|
||||
|
||||
function migratePages(pages) {
|
||||
console.log("moving old table to a temporary");
|
||||
console.log(db.prepare(`alter table pages rename to old_pages`).run())
|
||||
|
||||
console.log("creating new page table")
|
||||
console.log(createPages.run());
|
||||
|
||||
console.log('iterating over dump pages');
|
||||
|
||||
const insertPage = db.prepare(`insert into pages
|
||||
(id, number, title, description, html, lua, time, author, type)
|
||||
values (:id, :number, :title, :description, :html, :lua, :time, :author, :type)`);
|
||||
|
||||
pages.forEach((pageData) => {
|
||||
let {id, number, description} = pageData;
|
||||
console.log(`rendering page number ${number}.${id}`)
|
||||
description = description.replace(/<br>/g, "\n");
|
||||
|
||||
const renderedPage = converter.makeHtml(description);
|
||||
|
||||
const highlightedLua = hljs.highlight(description, {language: 'lua'}).value;
|
||||
|
||||
args = { ...pageData, description: description, html: renderedPage, lua: highlightedLua, type: "noun"};
|
||||
|
||||
console.log("inserting args", args);
|
||||
insertPage.run(args);
|
||||
});
|
||||
|
||||
console.log("getting rid of old table");
|
||||
console.log(db.prepare("drop table old_pages").run());
|
||||
|
||||
//throw new Error("blahhh i'm a dracula");
|
||||
}
|
||||
try {
|
||||
db.transaction(migratePages)(filejson["pages"]);
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
}
|
||||
|
||||
const createAttributesQuery = db.prepare(`
|
||||
create table if not exists attributes (
|
||||
number integer unique,
|
||||
contents json
|
||||
)
|
||||
`);
|
||||
/* an attribute store has:
|
||||
number = the object number it's attached to
|
||||
contents = a `text` object holding a json store of attributes defined on object #number, containing:
|
||||
LOCATION? = the object which contains this object? should this be in the DB or in the json store?
|
||||
PROTOTYPE = the number of the prototype for this object, to which we should look for attributes not found here
|
||||
ATTRIBUTES? = json object of attached, script-controlled attributes.
|
||||
|
||||
CONTENTS = json array of objectss contained inside this one
|
||||
VERBS = json array of objecsts which are verbs on this one
|
||||
*/
|
||||
function createAttributes() {
|
||||
console.log("creating new attribute table")
|
||||
console.log(createAttributesQuery.run());
|
||||
|
||||
console.log('iterating over all pages');
|
||||
|
||||
const insertAttribute = db.prepare(`insert into attributes
|
||||
(number, contents) values (:number, :contents)`);
|
||||
|
||||
db.prepare(`select * from pages`).all().forEach((pageData) => {
|
||||
let { number } = pageData;
|
||||
|
||||
let args = {contents: JSON.stringify({}), number: number};
|
||||
|
||||
console.log("inserting args", args);
|
||||
insertAttribute.run(args);
|
||||
});
|
||||
|
||||
//throw new Error("blahhh i'm a dracula");
|
||||
}
|
||||
|
||||
try {
|
||||
db.transaction(createAttributes)();
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
}
|
||||
|
||||
|
||||
|
||||
const createUsers = db.prepare(`
|
||||
create table if not exists users (
|
||||
id integer primary key,
|
||||
|
||||
name varchar(64) unique,
|
||||
password varchar(128),
|
||||
|
||||
character integer
|
||||
)
|
||||
`);
|
||||
/* a user has:
|
||||
id = primary key
|
||||
name = name string
|
||||
password = argon2 hash of their password
|
||||
|
||||
character = object in the game world representing your character
|
||||
*/
|
||||
|
||||
|
||||
|
||||
function migrateUsers(users) {
|
||||
console.log("moving old users");
|
||||
console.log(db.prepare("alter table users rename to old_users").run());
|
||||
|
||||
console.log("creating new users table");
|
||||
console.log(createUsers.run());
|
||||
|
||||
const insertUser = db.prepare("insert into users (name, password) values (:name, :password)")
|
||||
users.forEach((user) => {
|
||||
console.log(insertUser.run(user));
|
||||
});
|
||||
|
||||
console.log("clearing old table");
|
||||
console.log(db.prepare("drop table old_users").run());
|
||||
//throw new Error("i'm dracula 2");
|
||||
}
|
||||
try {
|
||||
db.transaction(migrateUsers)(filejson["users"]);
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
}
|
@ -22,6 +22,34 @@ create table if not exists pages (
|
||||
author integer
|
||||
)
|
||||
`);
|
||||
/* an object has:
|
||||
id = primary key
|
||||
number = object identifier number
|
||||
|
||||
title / NAME = a short display name for an object, or the title of a page
|
||||
description / TEXT? = the markdown description of an object, or the lua script of the source code of a verb
|
||||
|
||||
html / HTML_MARKDOWN? = the markdown for that object, rendered into html for display as a page
|
||||
HTML_LUA? = the lua source code of the object, rendered into html with syntax highlighting?
|
||||
|
||||
time = when this edit was saved
|
||||
author = the user id of whoever authored this revision
|
||||
|
||||
TYPE = whether this represents an object or a verb
|
||||
|
||||
*/
|
||||
|
||||
/* an attribute store has:
|
||||
number = the object number it's attached to
|
||||
contents = a `text` object holding a json store of attributes defined on object #number, containing:
|
||||
LOCATION? = the object which contains this object? should this be in the DB or in the json store?
|
||||
PROTOTYPE = the number of the prototype for this object, to which we should look for attributes not found here
|
||||
ATTRIBUTES? = json object of attached, script-controlled attributes.
|
||||
|
||||
CONTENTS = json array of objectss contained inside this one
|
||||
VERBS = json array of objecsts which are verbs on this one
|
||||
*/
|
||||
|
||||
|
||||
const createUsers = db.prepare(`
|
||||
create table if not exists users (
|
||||
@ -31,7 +59,13 @@ create table if not exists users (
|
||||
password varchar(128)
|
||||
)
|
||||
`);
|
||||
/* a user has:
|
||||
id = primary key
|
||||
name = name string
|
||||
password = argon2 hash of their password
|
||||
|
||||
character = object in the game world representing your character
|
||||
*/
|
||||
|
||||
function migratePages() {
|
||||
console.log("moving old table to a temporary");
|
||||
|
@ -10,19 +10,27 @@ function interpret(context, player, command) {
|
||||
// may be null if it's executing from a script?
|
||||
// player: the id of the player object who typed in the command.
|
||||
// may? be null if it's executing from a script? used for output.
|
||||
// so arguably
|
||||
// command: the full string typed in by the player
|
||||
|
||||
const socket = sockets.get(player)
|
||||
const words = command.trim().split(' ');
|
||||
|
||||
socket?.send(`interpreting and executing the received command: ${command}`);
|
||||
try {
|
||||
socket?.send(`interpreting and executing the received command: ${command}`);
|
||||
|
||||
//for the moment we'll only allow statements of the form "go north" with implicit subject: the player
|
||||
const [first, second, third, ...rest] = words;
|
||||
|
||||
const verbs = findAvailableVerbs(context, player, command);
|
||||
socket?.send(`found these verbs: ${Array.from(verbs.keys()).join(', ')}`)
|
||||
|
||||
// first word is either a subject or a verb. either way there must be a verb.
|
||||
const [first, second, third, ...rest] = words;
|
||||
const verb = findVerb(first, context, player);
|
||||
|
||||
console.log(`executing verb ${verb} towards ${player} on ${player} ${second} ${third}`);
|
||||
executeVerb(player, verb, player, second, third, ...rest)
|
||||
} catch (error) {
|
||||
socket?.send(`got an error! ${error.mesage}`);
|
||||
}
|
||||
|
||||
/*
|
||||
// if the second word is a verb, but the first word is also a verb, what do we do?
|
||||
if (second in verbs) {
|
||||
// for now, assume that if the second word is a verb, it's the verb we want.
|
||||
@ -31,16 +39,54 @@ function interpret(context, player, command) {
|
||||
// if the second word is not a verb, then the first word is the verb, and the player is the implied subject.
|
||||
executeVerb(player, verbs.get(first), player, second, third, ...rest)
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
function findAvailableVerbs(location, actor, command) {
|
||||
function findVerb(word, location, actor) {
|
||||
// returns the number of a verb which matches the requested word.
|
||||
// check for verbs on actor
|
||||
// check for verbs on objects in location
|
||||
// check for verbs on location
|
||||
const out = new Map();
|
||||
out.set("look", 29);
|
||||
out.set("warp", 31);
|
||||
return out;
|
||||
let verb = findVerbOnObject(word, actor);
|
||||
if (verb) return verb;
|
||||
|
||||
const actorContents = getAttribute(actor, "contents");
|
||||
for (const obj of (actorContents || [])) {
|
||||
verb = findVerbOnObject(word, obj);
|
||||
if (verb) return verb;
|
||||
}
|
||||
|
||||
const locationContents = getAttribute(location, "contents");
|
||||
for (const obj of (locationContents || [])) {
|
||||
verb = findVerbOnObject(word, obj);
|
||||
if (verb) return verb;
|
||||
}
|
||||
|
||||
verb = findVerbOnObject(word, location);
|
||||
if (verb) return verb;
|
||||
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function findVerbOnObject(word, object) {
|
||||
// check for verbs on a single object, and its chain of parents. return a matching verbId, or undefined
|
||||
if (!word) return undefined;
|
||||
|
||||
let focus = object;
|
||||
while (focus) {
|
||||
const focusVerbs = getAttribute(focus, "verbs");
|
||||
for (const verbId of (focusVerbs || [])) {
|
||||
const fullVerb = lookUpObject(verbId);
|
||||
|
||||
if (!fullVerb) continue;
|
||||
|
||||
// test our word against
|
||||
if (word.toLowerCase() == fullVerb.title.toLowerCase()) {
|
||||
return verbId;
|
||||
}
|
||||
}
|
||||
focus = getAttribute(focus, "parent");
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function executeVerb(outputObject, verbId, subject, object, ...rest) {
|
||||
@ -56,28 +102,99 @@ function executeVerb(outputObject, verbId, subject, object, ...rest) {
|
||||
return fullVerb.fn(outputObject, subject, object, ...rest);
|
||||
}
|
||||
|
||||
const objectQuery = db.prepare('select * from pages where id=?');
|
||||
function lookUpObject(id) {
|
||||
const objectQuery = db.prepare('select * from pages where number=? order by time desc');
|
||||
function lookUpObject(number) {
|
||||
return hardCodedObjects(number) || objectQuery.get(number);
|
||||
}
|
||||
|
||||
const attributeQuery = db.prepare(`select * from attributes where number=?`);
|
||||
function lookUpObjectAttributes(number) {
|
||||
return JSON.parse(attributeQuery.get(number).contents);
|
||||
}
|
||||
|
||||
|
||||
function hardCodedObjects(id) {
|
||||
// return objectQuery.get(id);
|
||||
if (id == 30) return {name: "shoofle", contents: "this is a shoofle", location: 1};
|
||||
if (id == 29) return {
|
||||
name: "look",
|
||||
verb: false,
|
||||
contents: "send description of direct object to subject's socket",
|
||||
title: "look",
|
||||
verb: true,
|
||||
description: "send description of direct object to subject's socket",
|
||||
fn: (logReceiver, subject, object, ...rest) => {
|
||||
sockets.get(logReceiver)?.send(`you looked around! subject ${subject} object: ${object} args: ${rest}`);
|
||||
console.log(`${subject} looked at ${object} with args ${rest}, and output was directed to ${logReceiver}`);
|
||||
}
|
||||
}
|
||||
if (id == 31) return {
|
||||
name: "warp",
|
||||
title: "warp",
|
||||
verb: true,
|
||||
contents: "this built-in function changes the player's location, as well as telling their client to move",
|
||||
description: "this built-in function changes the player's location, as well as telling their client to move",
|
||||
fn: (logReceiver, subject, object, ...rest) => {
|
||||
// TODO: change subject's location
|
||||
const objectNum = verifyObjectReference(object);
|
||||
const subjectNum = verifyObjectReference(subject);
|
||||
setAttribute(subjectNum, "location", objectNum);
|
||||
|
||||
sockets.get(logReceiver)?.send(`location change to: ${object}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = { interpret, sockets, lookUpObject };
|
||||
|
||||
|
||||
|
||||
const pullAttribute = db.prepare(`select * from attributes where number=?`);
|
||||
function getAttribute(obj, attributeName) {
|
||||
const attributeStore = pullAttribute.get(verifyObjectReference(obj));
|
||||
const contents = JSON.parse(attributeStore.contents);
|
||||
|
||||
if (contents.hasOwnProperty(attributeName)) {
|
||||
return contents[attributeName];
|
||||
}
|
||||
|
||||
if (contents.hasOwnProperty("parent")) {
|
||||
return getAttribute(contents.parent, attributeName);
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function hasOwnAttribute(obj, attributeName) {
|
||||
const attributeStore = pullAttribute.get(verifyObjectReference(obj));
|
||||
const contents = JSON.parse(attributeStore.contents);
|
||||
|
||||
return contents.hasOwnProperty(attributeName);
|
||||
}
|
||||
|
||||
const insertAttribute = db.prepare(`update or replace attributes set contents=:contents where number=:number`);
|
||||
function setAttribute(obj, attributeName, value) {
|
||||
const attributeStore = pullAttribute.get(verifyObjectReference(obj));
|
||||
const contents = JSON.parse(attributeStore.contents);
|
||||
|
||||
contents[attributeName] = value;
|
||||
|
||||
insertAttribute.run({...attributeStore, contents: JSON.stringify(contents)});
|
||||
}
|
||||
|
||||
function deleteAttribute(obj, attributeName) {
|
||||
const attributeStore = pullAttribute.get(verifyObjectReference(obj));
|
||||
const contents = JSON.parse(attributeStore.contents);
|
||||
|
||||
delete contents["attributeName"];
|
||||
|
||||
insertAttribute.run({...attributeStore, contents: JSON.stringify(contents)});
|
||||
}
|
||||
|
||||
function verifyObjectReference(obj) {
|
||||
try {
|
||||
if (typeof(obj) === "string") {
|
||||
return Number(obj.replace("#", ""));
|
||||
} else if (typeof(obj) === "number") {
|
||||
return obj;
|
||||
} else if (typeof(obj.number) == "number") {
|
||||
return obj.number;
|
||||
}
|
||||
} catch (error) {
|
||||
throw new Error("Tried to get an attribute from something which wasn't an object");
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = { interpret, sockets, lookUpObject, getAttribute, setAttribute, deleteAttribute, hasOwnAttribute };
|
9
server/package-lock.json
generated
9
server/package-lock.json
generated
@ -21,6 +21,7 @@
|
||||
"graphology-layout": "^0.6.1",
|
||||
"graphology-layout-force": "^0.2.4",
|
||||
"graphology-layout-forceatlas2": "^0.10.1",
|
||||
"highlight.js": "^11.10.0",
|
||||
"jsdom": "^25.0.0",
|
||||
"nodemon": "^3.1.5",
|
||||
"showdown": "^2.1.0"
|
||||
@ -1128,6 +1129,14 @@
|
||||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/highlight.js": {
|
||||
"version": "11.10.0",
|
||||
"resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-11.10.0.tgz",
|
||||
"integrity": "sha512-SYVnVFswQER+zu1laSya563s+F8VDGt7o35d4utbamowvUNLLMovFqwCLSocpZTz3MgaSRA1IbqRWZv97dtErQ==",
|
||||
"engines": {
|
||||
"node": ">=12.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/html-encoding-sniffer": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-4.0.0.tgz",
|
||||
|
@ -26,6 +26,7 @@
|
||||
"graphology-layout": "^0.6.1",
|
||||
"graphology-layout-force": "^0.2.4",
|
||||
"graphology-layout-forceatlas2": "^0.10.1",
|
||||
"highlight.js": "^11.10.0",
|
||||
"jsdom": "^25.0.0",
|
||||
"nodemon": "^3.1.5",
|
||||
"showdown": "^2.1.0"
|
||||
|
@ -7,7 +7,8 @@ const db = new sqlite('the_big_db.db', { verbose: console.log });
|
||||
|
||||
const { loginRequired } = require('../authStuff.js');
|
||||
|
||||
const { interpret, sockets, lookUpObject } = require('../interpreter.js');
|
||||
const { interpret, sockets, lookUpObject,
|
||||
getAttribute, setAttribute, hasOwnAttribute, deleteAttribute } = require('../interpreter.js');
|
||||
|
||||
|
||||
|
||||
@ -15,6 +16,7 @@ app.ws('/embody', (ws, req) => {
|
||||
// const { playerObject } = db.prepare('select playerObject from users where id=?').get(req.session.userId)
|
||||
const playerObjectId = 30; // mocked out for now!
|
||||
sockets.set(playerObjectId, ws);
|
||||
ws.send(`location change to: #${getAttribute(playerObjectId, "location")}`);
|
||||
|
||||
ws.on('message', (msg) => {
|
||||
const location = lookUpObject(playerObjectId).location;
|
||||
|
Loading…
Reference in New Issue
Block a user