Skip to content

Commit

Permalink
Finish Flow, debug
Browse files Browse the repository at this point in the history
  • Loading branch information
MulverineX committed Feb 23, 2023
1 parent aba6b1f commit 4d56757
Show file tree
Hide file tree
Showing 17 changed files with 210 additions and 102 deletions.
6 changes: 3 additions & 3 deletions src/commands/implementations/entity/execute.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ export class ExecuteCommandNode extends ContainerCommandNode<SubCommand[]> {
}

// Create a new MCFunctionNode with the body of the ExecuteNode.
const mcFunction = new MCFunctionClass(this.sandstoneCore, `${currentMCFunction.resource.path.slice(1).join('/')}/${this.callbackName}`, {
const mcFunction = new MCFunctionClass(this.sandstoneCore, `${currentMCFunction.resource.path.slice(2).join('/')}/${this.callbackName}`, {
addToSandstoneCore: false,
creator: 'sandstone',
onConflict: 'rename',
Expand Down Expand Up @@ -401,7 +401,7 @@ export class ExecuteCommand extends ExecuteCommandPart {

positioned(pos?: Coordinates) {
if (pos) {
return this.nestedExecute(['as', coordinatesParser(pos)])
return this.nestedExecute(['positioned', coordinatesParser(pos)])
}
return this.subCommand([['as']], ExecutePositionedAsCommand, false)
}
Expand All @@ -420,7 +420,7 @@ export class ExecuteCommand extends ExecuteCommandPart {

rotated(rotation?: Rotation) {
if (rotation) {
return this.nestedExecute(['as', rotationParser(rotation)])
return this.nestedExecute(['rotated', rotationParser(rotation)])
}
return this.subCommand([['as']], ExecuteRotatedAsCommand, false)
}
Expand Down
27 changes: 24 additions & 3 deletions src/core/resources/mcfunction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ export class MCFunctionNode extends ContainerNode implements ResourceNode {
return this.contextStack.pop()
}

getValue = () => this.body.map((node) => node.getValue()).join('\n')
getValue = () => this.body.filter((node) => node.getValue() !== null).map((node) => node.getValue()).join('\n')
}

export type MCFunctionClassArguments = ({
Expand Down Expand Up @@ -185,8 +185,6 @@ export class _RawMCFunctionClass extends CallableResourceClass<MCFunctionNode> {

protected lazy: boolean

protected addToSandstoneCore: boolean

constructor(core: SandstoneCore, name: string, args: MCFunctionClassArguments) {
super(core, { packType: core.pack.dataPack(), extension: 'mcfunction' }, MCFunctionNode, core.pack.resourceToPath(name, ['functions']), {
...args,
Expand Down Expand Up @@ -305,6 +303,29 @@ export class _RawMCFunctionClass extends CallableResourceClass<MCFunctionNode> {
}
}, true)
}

splice(start: number, removeItems: number | 'auto', ...contents: _RawMCFunctionClass[] | [() => void]) {
const fake = new MCFunctionClass(this.core, 'fake', {
addToSandstoneCore: false,
creator: 'sandstone',
onConflict: 'ignore',
})

const fullBody: Node[] = []

if (contents[0] instanceof _RawMCFunctionClass) {
for (const mcfunction of contents as _RawMCFunctionClass[]) {
fullBody.push(...mcfunction.node.body)
}
} else {
this.core.enterMCFunction(fake)
this.core.insideContext(fake.node, contents[0], false)
this.core.exitMCFunction()
fullBody.push(...fake.node.body)
}

this.node.body.splice(start, removeItems === 'auto' ? fullBody.length : removeItems, ...fullBody)
}
}

export const MCFunctionClass = makeClassCallable(_RawMCFunctionClass)
Expand Down
1 change: 0 additions & 1 deletion src/core/resources/predicate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,6 @@ export class PredicateClass extends ResourceClass<PredicateNode> implements List
} else {
predicateJSON = predicate
}
console.log(predicateJSON)
if (Array.isArray(predicateJSON)) {
this.predicateJSON.push(...predicateJSON)
} else {
Expand Down
102 changes: 54 additions & 48 deletions src/core/resources/resource.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ export abstract class ResourceClass<N extends ResourceNode = ResourceNode<any>>

path

addToSandstoneCore: boolean

onConflict: LiteralUnion<BASIC_CONFLICT_STRATEGIES>

renameIndex = 2
Expand All @@ -72,62 +74,66 @@ export abstract class ResourceClass<N extends ResourceNode = ResourceNode<any>>

this.path = path

this.addToSandstoneCore = args.addToSandstoneCore

this.creator = args.creator ?? 'sandstone'

this.onConflict = args.onConflict || process.env[`${this.node.resource.path[1].toUpperCase()}_CONFLICT_STRATEGY`] || process.env.DEFAULT_CONFLICT_STRATEGY || 'throw'
}

protected handleConflicts() {
const resourceType = this.node.resource.path[1]

const conflict = [...this.core.resourceNodes].find((node) => node.resource.path.join('') === this.node.resource.path.join(''))

if (conflict) {
const oldResource = conflict.resource
const newResource = this.node.resource

switch (this.onConflict) {
case 'throw': {
// eslint-disable-next-line max-len
throw new Error(`Created a ${resourceType.substring(0, resourceType.length - 1)} with the duplicate name ${newResource.name}, and onConflict was set to "throw".`)
if (this.addToSandstoneCore) {
const resourceType = this.node.resource.path[1]

const conflict = [...this.core.resourceNodes].find((node) => node.resource.path.join('') === this.node.resource.path.join(''))

if (conflict) {
const oldResource = conflict.resource
const newResource = this.node.resource

switch (this.onConflict) {
case 'throw': {
// eslint-disable-next-line max-len
throw new Error(`Created a ${resourceType.substring(0, resourceType.length - 1)} with the duplicate name ${newResource.name}, and onConflict was set to "throw".`)
}
case 'replace': {
this.core.resourceNodes.forEach((node) => {
if (node.resource.path.join('') === oldResource.path.join('')) {
this.core.resourceNodes.delete(node)
}
})
this.core.resourceNodes.add(this.node)
} break
case 'warn': {
console.warn([
'Warning:',
`Tried to create a ${resourceType.substring(0, resourceType.length - 1)} named "${newResource.name}", but found an already existing one.`,
"The new one has replaced the old one. To remove this warning, please change the options of the resource to { onConflict: '/* other option */' }.",
].join('\n'))
this.core.resourceNodes.forEach((node) => {
if (node.resource.path.join('') === oldResource.path.join('')) {
this.core.resourceNodes.delete(node)
}
})
this.core.resourceNodes.add(this.node)
} break
case 'rename': {
// eslint-disable-next-line no-plusplus
this.path[this.path.length - 1] += `${oldResource.renameIndex++}`

this.core.resourceNodes.add(this.node)
} break
case 'prepend': {
(oldResource as unknown as ListResource).unshift(newResource)
} break
case 'append': {
(oldResource as unknown as ListResource).push(newResource)
} break
default: break
}
case 'replace': {
this.core.resourceNodes.forEach((node) => {
if (node.resource.path.join('') === oldResource.path.join('')) {
this.core.resourceNodes.delete(node)
}
})
this.core.resourceNodes.add(this.node)
} break
case 'warn': {
console.warn([
'Warning:',
`Tried to create a ${resourceType.substring(0, resourceType.length - 1)} named "${newResource.name}", but found an already existing one.`,
"The new one has replaced the old one. To remove this warning, please change the options of the resource to { onConflict: '/* other option */' }.",
].join('\n'))
this.core.resourceNodes.forEach((node) => {
if (node.resource.path.join('') === oldResource.path.join('')) {
this.core.resourceNodes.delete(node)
}
})
this.core.resourceNodes.add(this.node)
} break
case 'rename': {
// eslint-disable-next-line no-plusplus
this.path[this.path.length - 1] += `${oldResource.renameIndex++}`

this.core.resourceNodes.add(this.node)
} break
case 'prepend': {
(oldResource as unknown as ListResource).unshift(newResource)
} break
case 'append': {
(oldResource as unknown as ListResource).push(newResource)
} break
default: break
} else {
this.core.resourceNodes.add(this.node)
}
} else {
this.core.resourceNodes.add(this.node)
}
}

Expand Down
23 changes: 19 additions & 4 deletions src/core/sandstoneCore.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/* eslint-disable operator-linebreak */
import fs from 'fs-extra'
import path from 'path'

Expand Down Expand Up @@ -123,17 +124,31 @@ export class SandstoneCore {
return finalResources
}

// TODO: Support dry & verbose runs
save = async (cliOptions: { fileHandler: (relativePath: string, content: any) => Promise<void> }, opts: { visitors: GenericCoreVisitor[] }) => {
save = async (cliOptions: { fileHandler: (relativePath: string, content: any) => Promise<void>, dry: boolean, verbose: boolean }, opts: { visitors: GenericCoreVisitor[] }) => {
const resources = this.generateResources(opts)

for await (const node of resources) {
const resourcePath = path.join(node.resource.packType.type, ...node.resource.path)
const { packType, fileExtension } = node.resource
const _path = [packType.type, ...node.resource.path]

if (packType.resourceSubFolder) {
_path.splice(1, 0, packType.resourceSubFolder)
}
const resourcePath = path.join(..._path)

const value = node.getValue()

if (cliOptions.verbose) {
console.log(
`Path: ${resourcePath}.${fileExtension}\n\n` +
`${typeof value === 'string' ? value : '<Buffer>'}`,
)
}

/* @ts-ignore */
await cliOptions.fileHandler(`${resourcePath}.${node.resource.fileExtension}`, value)
if (!cliOptions.dry) {
await cliOptions.fileHandler(`${resourcePath}.${fileExtension}`, value)
}
}
}
}
9 changes: 5 additions & 4 deletions src/flow/Flow.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
import { ConditionClass } from '../variables/index'
import { AndNode, NotNode, OrNode } from './conditions'
import {
AndNode, ConditionNode, NotNode, OrNode,
} from './conditions'
import { IfStatement } from './if_else'

import type { SandstoneCore } from '../core'
import type { ConditionNode } from './conditions'
import type { ConditionClass } from '../variables/index'

type Condition = ConditionNode | ConditionClass
export class Flow {
constructor(public sandstoneCore: SandstoneCore) { }

conditionToNode(condition: Condition) {
if (condition instanceof ConditionClass) {
if (!(condition instanceof ConditionNode)) {
return condition._toMinecraftCondition()
}
return condition
Expand Down
2 changes: 1 addition & 1 deletion src/flow/conditions/and.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,5 @@ export class AndNode extends ConditionNode {
super(sandstoneCore)
}

getValue = (negated = false) => this.conditions.join(' ')
getValue = (negated = false) => this.conditions.map((condition) => condition.getValue(negated)).join(' ')
}
6 changes: 6 additions & 0 deletions src/flow/conditions/condition.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,9 @@ export abstract class SingleConditionNode extends ConditionNode {
return [keyword, ...this.getCondition()].join(' ')
}
}

export abstract class SingleExecuteNode extends ConditionNode {
abstract getCondition(): unknown[]

getValue = (negated = false) => this.getCondition().join(' ')
}
22 changes: 19 additions & 3 deletions src/flow/conditions/or.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,29 @@
import { IfNode } from '../if_else'
import { ConditionNode } from './condition'

import type { SandstoneCore } from '#core'

export class OrNode extends ConditionNode {
variable

constructor(sandstoneCore: SandstoneCore, public conditions: ConditionNode[]) {
super(sandstoneCore)
}

getValue = (negated?: boolean | undefined) => {
throw new Error('OR conditions must be postprocessed.')
const { Variable, _ } = sandstoneCore.pack

this.variable = Variable(undefined, 'condition')

const currentNode = this.sandstoneCore.getCurrentMCFunctionOrThrow()

currentNode.resource.push(() => {
this.variable.reset()

for (const condition of conditions) {
// eslint-disable-next-line no-new
new IfNode(sandstoneCore, condition, () => this.variable.add(1), false)
}
})
}

getValue = (negated?: boolean | undefined) => this.variable.matches('1..')._toMinecraftCondition().getValue(negated)
}
14 changes: 14 additions & 0 deletions src/flow/conditions/success.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { SingleExecuteNode } from './condition'

import type { Score } from 'sandstone/variables/Score'
import type { SandstoneCore } from '#core'

export class SuccessConditionNode extends SingleExecuteNode {
constructor(sandstoneCore: SandstoneCore, readonly score: Score) {
super(sandstoneCore)
}

getCondition(): unknown[] {
return ['store', 'success', 'score', this.score]
}
}
22 changes: 14 additions & 8 deletions src/flow/if_else.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,21 @@ import type { ConditionNode } from './conditions'
export class IfNode extends ContainerNode {
nextFlowNode?: IfNode | ElseNode

constructor(sandstoneCore: SandstoneCore, public condition: ConditionNode, public callback: () => void) {
constructor(sandstoneCore: SandstoneCore, public condition: ConditionNode, public callback: () => void, reset = true) {
super(sandstoneCore)

// Generate the body of the If node.
this.sandstoneCore.getCurrentMCFunctionOrThrow().enterContext(this)
this.callback()
this.sandstoneCore.currentMCFunction?.exitContext()
const currentNode = this.sandstoneCore.getCurrentMCFunctionOrThrow()

if (reset) {
currentNode.resource.push(() => sandstoneCore.pack.flowVariable.reset())
}

if (callback.toString() !== '() => {}') {
// Generate the body of the If node.
currentNode.enterContext(this)
this.callback()
currentNode.exitContext()
}
}

getValue = () => {
Expand Down Expand Up @@ -53,9 +61,7 @@ export class ElseNode extends ContainerNode {
this.sandstoneCore.currentMCFunction?.exitContext()
}

getValue = () => {
throw new Error('Minecraft does not support else statements. This must be postprocessed.')
}
getValue = () => null
}

export class ElseStatement {
Expand Down
Loading

0 comments on commit 4d56757

Please sign in to comment.