Skip to content
This repository has been archived by the owner on Aug 30, 2022. It is now read-only.

Commit

Permalink
Merge pull request #152 from latitudegames/0.0.62
Browse files Browse the repository at this point in the history
0.0.62
  • Loading branch information
parzival418 authored Mar 8, 2022
2 parents cdb5cd9 + fcbbce8 commit 5cd3f2f
Show file tree
Hide file tree
Showing 13 changed files with 143 additions and 85 deletions.
10 changes: 1 addition & 9 deletions client/scripts/engine.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,7 @@
import thothCore from '@latitudegames/thoth-core/dist/server'

const {
components: {
moduleInput,
moduleOutput,
moduleTriggerIn,
moduleTriggerOut,
tenseTransformer,
},
components: { moduleInput, moduleOutput, tenseTransformer },
} = thothCore

export const components = [
Expand All @@ -26,8 +20,6 @@ export const components = [
// new ModuleComponent(),
moduleInput(),
moduleOutput(),
moduleTriggerOut(),
moduleTriggerIn(),
// new PlaytestPrint(),
// new PlaytestInput(),
// new RunInputComponent(),
Expand Down
2 changes: 1 addition & 1 deletion core/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@latitudegames/thoth-core",
"version": "0.0.61",
"version": "0.0.62",
"license": "Apache-2.0",
"author": "Michael Sharpe <[email protected]> (https://www.project89.org)",
"contributors": [
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,21 @@
import Rete from 'rete'
import {
NodeData,
ThothNode,
ThothWorkerInputs,
ThothWorkerOutputs,
} from '../../types'

import { SocketGeneratorControl } from '../dataControls/SocketGenerator'
import { EngineContext } from '../engine'
import { triggerSocket } from '../sockets'
import { ThothComponent } from '../thoth-component'

const info = `The State Write component allows you to define any number of inputs, and to write values to the state manager which correspond to the names of those inputs. If the value does not exist in the state, it will be written.
Note here that there are a few assumptions made, which will be changed once we have selectable socket types when generating inputs. If the key already exists in the state and it is an array, whatever value you insert will be added to the array. If the existing value is an object, the object will be updated by the incoming value.`

export class StateWrite extends ThothComponent {
export class StateWrite extends ThothComponent<void> {
constructor() {
// Name of the component
super('State Write')
Expand All @@ -22,7 +29,7 @@ export class StateWrite extends ThothComponent {
this.info = info
}

builder(node) {
builder(node: ThothNode) {
const dataInput = new Rete.Input('trigger', 'Trigger', triggerSocket, true)

const inputGenerator = new SocketGeneratorControl({
Expand All @@ -37,11 +44,16 @@ export class StateWrite extends ThothComponent {
return node
}

async worker(node, inputs, outputs, { thoth }) {
async worker(
node: NodeData,
inputs: ThothWorkerInputs,
outputs: ThothWorkerOutputs,
{ thoth }: { thoth: EngineContext }
) {
const { getCurrentGameState, updateCurrentGameState } = thoth

try {
const gameState = await getCurrentGameState()
const gameState = (await getCurrentGameState()) as Record<string, any>
let value

const updates = Object.entries(inputs).reduce((acc, [key, val]) => {
Expand All @@ -55,7 +67,7 @@ export class StateWrite extends ThothComponent {
}

// if it is an object, we assume that the incoming data is an object update
value = { ...gameState[key], ...val[0] }
value = { ...gameState[key], ...(val[0] as unknown[]) }

break
default:
Expand All @@ -66,7 +78,7 @@ export class StateWrite extends ThothComponent {
acc[key] = value

return acc
}, {})
}, {} as Record<string, any>)

await updateCurrentGameState(updates)
} catch (err) {
Expand Down
5 changes: 5 additions & 0 deletions core/src/engine.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ export abstract class ThothEngineComponent<WorkerReturnType> {
...args: unknown[]
): WorkerReturnType
}

// TODO separate the engine context out from the editor context for cleaner typing.
export type EngineContext = {
completion: (
body: ModelCompletionOpts
Expand All @@ -58,6 +60,9 @@ export type EngineContext = {
onAddModule?: Function
onUpdateModule?: Function
sendToPlaytest?: Function
onInspector?: Function
sendToInspector?: Function
clearTextEditor?: Function
}

export type InitEngineArguments = {
Expand Down
16 changes: 7 additions & 9 deletions core/src/plugins/debuggerPlugin/index.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,5 @@
import { NodeEditor } from 'rete/types'
import { EngineContext } from '../../engine'
import { IRunContextEditor } from '../../../types'
import { ThothComponent } from '../../thoth-component'
interface IRunContextEditor extends NodeEditor {
thoth: EngineContext
abort: Function
}

function install(
editor: IRunContextEditor,
Expand Down Expand Up @@ -48,9 +43,12 @@ function install(
if (!server) {
node.data.error = true

const nodeView = [...editor.view.nodes.values()].find(
n => n.node.id === node.id
)
const nodeValues = Array.from(editor.view.nodes)
const foundNode = nodeValues.find(([, n]) => n.node.id === node.id)

if (!foundNode) return

const nodeView = foundNode[1]

nodeView?.onStart()
nodeView?.node.update()
Expand Down
8 changes: 6 additions & 2 deletions core/src/plugins/inspectorPlugin/DataControl.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,25 @@
import { Node, NodeEditor, Component } from 'rete'
import { Node, NodeEditor } from 'rete'
import { ThothComponent } from '../../thoth-component'

import { Inspector } from './Inspector'
export type RestProps = {}
export abstract class DataControl {
inspector: Inspector | null = null
editor: NodeEditor | null = null
node: Node | null = null
component: Component | null = null
component: ThothComponent<unknown> | null = null
id: string | null = null
dataKey: string
key: string
name: string
defaultValue: unknown
componentData: object
componentKey: string
options: object
icon: string
write: boolean
//Jake added below
data: Record<string, unknown>

constructor({
dataKey,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,33 +1,52 @@
import deepEqual from 'deep-equal'
import Rete from 'rete'
import Rete, { Input, Output } from 'rete'
import { v4 as uuidv4 } from 'uuid'
import { DataSocketType, IRunContextEditor, ThothNode } from '../../../types'
import { ThothComponent } from '../../thoth-component'

import * as socketMap from '../../sockets'
import { DataControl } from './DataControl'

type InspectorConstructor = {
component: ThothComponent<unknown>
editor: IRunContextEditor
node: ThothNode
}

// todo improve this typing
type DataControlData = Record<string, any>

export class Inspector {
// Stub of function. Can be a nodes catch all onData
onData = () => {}
cache = {}

constructor({ component, editor, node }) {
onData = Function
cache: Record<string, any> = {}
node: ThothNode
component: ThothComponent<unknown>
editor: IRunContextEditor
dataControls: Map<string, DataControl>
category: string
info: string

constructor({ component, editor, node }: InspectorConstructor) {
this.component = component
this.editor = editor
this.dataControls = new Map()
this.node = node
this.category = component.category
this.info = component.info
}

_add(list, control, prop) {
// addede DataControl[]
_add(list: Map<string, DataControl>, control: DataControl) {
if (list.has(control.key))
throw new Error(
`Item with key '${control.key}' already been added to the inspector`
)

if (control[prop] !== null)
if (control['inspector'] !== null)
throw new Error('Inspector has already been added to some control')

// Attach the inspector to the incoming control instance
control[prop] = this
control['inspector'] = this
control.editor = this.editor
control.node = this.node
control.component = this.component
Expand All @@ -39,26 +58,31 @@ export class Inspector {
list.set(control.dataKey, control)
}

add(dataControl) {
this._add(this.dataControls, dataControl, 'inspector')
add(dataControl: DataControl) {
this._add(this.dataControls, dataControl)
dataControl.onAdd()
return this
}

handleSockets(sockets, control, type) {
handleSockets(
sockets: DataSocketType[],
control: DataControlData,
type: 'inputs' | 'outputs'
) {
// we assume all sockets are of the same type here
// and that the data key is set to 'inputs' or 'outputs'
const isOutput = type === 'outputs'

this.node.data[type] = sockets

// get all sockets currently on the node
const existingSockets = []
this.node[type].forEach(out => {
const existingSockets: string[] = []

this.node[type]?.forEach(out => {
existingSockets.push(out.key)
})

const ignored = (control && control?.data?.ignored) || []
const ignored: string[] = (control && control?.data?.ignored) || []

// outputs that are on the node but not in the incoming sockets is removed
existingSockets
Expand All @@ -74,10 +98,14 @@ export class Inspector {
.forEach(key => {
const socket = this.node[type].get(key)

if (!socket) return

// we get the connections for the node and remove that connection
const connections = this.node
.getConnections()
.filter(con => con[type.slice(0, -1)].key === key)
.filter(
con => con[type.slice(0, -1) as 'input' | 'output'].key === key
)

if (connections)
connections.forEach(con => {
Expand All @@ -86,9 +114,9 @@ export class Inspector {

// handle removing the socket, either output or input
if (isOutput) {
this.node.removeOutput(socket)
this.node.removeOutput(socket as Output)
} else {
this.node.removeInput(socket)
this.node.removeInput(socket as Input)
}
})

Expand All @@ -100,7 +128,8 @@ export class Inspector {
// Here we are running over and ensuring that the outputs are in the tasks outputs
// We only need to do this with outputs, as inputs don't need to be in the task
if (isOutput) {
this.component.task.outputs = this.node.data.outputs.reduce(
const dataOutputs = this.node.data.outputs as DataSocketType[]
this.component.task.outputs = dataOutputs.reduce(
(acc, out) => {
acc[out.socketKey] = out.taskType || 'output'
return acc
Expand All @@ -123,14 +152,14 @@ export class Inspector {
)

if (isOutput) {
this.node.addOutput(newSocket)
this.node.addOutput(newSocket as Output)
} else {
this.node.addInput(newSocket)
this.node.addInput(newSocket as Input)
}
})
}

cacheControls(dataControls) {
cacheControls(dataControls: DataControlData) {
const cache = Object.entries(dataControls).reduce(
(acc, [key, { expanded = true }]) => {
acc[key] = {
Expand All @@ -139,13 +168,13 @@ export class Inspector {

return acc
},
{}
{} as Record<string, any>
)

this.node.data.dataControls = cache
}

handleData(update) {
handleData(update: Record<string, any>) {
// store all data controls inside the nodes data
// WATCH in case our graphs start getting quite large.
if (update.dataControls) this.cacheControls(update.dataControls)
Expand All @@ -156,7 +185,8 @@ export class Inspector {
this.onData(data)

// go over each data control
for (const [key, control] of this.dataControls) {
const dataControlArray = Array.from(this.dataControls)
for (const [key, control] of dataControlArray) {
const isEqual = deepEqual(this.cache[key], data[key])

// compare agains the cache to see if it has changed
Expand Down Expand Up @@ -210,13 +240,13 @@ export class Inspector {
data() {
const dataControls = Array.from(this.dataControls.entries()).reduce(
(acc, [key, val]) => {
const cache = this.node?.data?.dataControls
const cache = this.node?.data?.dataControls as DataControlData
const cachedControl = cache && cache[key] ? cache[key] : {}
// use the data method on controls to get data shape
acc[key] = { ...val.control, ...cachedControl }
return acc
},
{}
{} as Record<string, any>
)

return {
Expand Down
Loading

0 comments on commit 5cd3f2f

Please sign in to comment.