diff --git a/package.json b/package.json index 96153b64..6b1f871d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "sandstone", - "version": "0.4.3", + "version": "0.4.4", "main": "dist/src/index.js", "types": "dist/src/index.d.ts", "license": "MIT", diff --git a/src/_internals/arguments/resources/predicate.ts b/src/_internals/arguments/resources/predicate.ts index a7ad9051..fd704022 100644 --- a/src/_internals/arguments/resources/predicate.ts +++ b/src/_internals/arguments/resources/predicate.ts @@ -97,6 +97,6 @@ export type PredicateCondition = ( /** If true, the condition evaluates to true only if it's thundering. */ thundering?: boolean }> -) +) |never export type PredicateType = ObjectOrArray diff --git a/src/_internals/datapack/Datapack.ts b/src/_internals/datapack/Datapack.ts index 27e4c66c..40e237d3 100644 --- a/src/_internals/datapack/Datapack.ts +++ b/src/_internals/datapack/Datapack.ts @@ -3,20 +3,18 @@ import type { AdvancementType, JsonTextComponent, LootTableType, OBJECTIVE_CRITERION, PredicateType, RecipeType, TAG_TYPES, } from '@arguments' import { CommandsRoot } from '@commands' -import { RecipeCommand } from '@commands/implementations' import { Flow } from '@flow' -import type { HintedTagValues, McFunctionOptions } from '@resources' +import type { HintedTagStringType, McFunctionOptions } from '@resources' import { - Recipe, - Advancement, LootTable, McFunction, Predicate, Tag, + Advancement, LootTable, McFunction, Predicate, Recipe, + Tag, } from '@resources' - import type { ObjectiveClass } from '@variables' import { Objective, SelectorCreator } from '@variables' import type { CommandArgs } from './minecraft' import { toMcFunctionName } from './minecraft' import type { - FunctionResource, ResourceOnlyTypeMap, ResourcePath, ResourceTypes, TagObjectValue, + FunctionResource, ResourceOnlyTypeMap, ResourcePath, ResourceTypes, TagSingleValue, } from './resourcesTree' import { ResourcesTree } from './resourcesTree' import type { SaveOptions } from './saveDatapack' @@ -27,7 +25,7 @@ export interface McFunctionReturn { schedule: (delay: number | LiteralUnion<'1t' | '1s' | '1d'>, type?: 'append' | 'replace', ...callbackArgs: T) => void - getNameFromArgs: (...args: T) => string + getName: (...args: T) => string clearSchedule: (...args: T) => void } @@ -361,7 +359,7 @@ export default class Datapack { Predicate = (name: string, predicate: PredicateType) => new Predicate(this.commandsRoot, name, predicate) - Tag = (type: T, name: string, values: HintedTagValues, replace?: boolean) => new Tag(this, type, name, values as TagObjectValue[], replace) + Tag = (type: T, name: string, values: TagSingleValue>[], replace?: boolean) => new Tag(this, type, name, values, replace) LootTable = (name: string, lootTable: LootTableType) => new LootTable(this, name, lootTable) diff --git a/src/_internals/datapack/resourcesTree.ts b/src/_internals/datapack/resourcesTree.ts index 94c21489..7f9beeb1 100644 --- a/src/_internals/datapack/resourcesTree.ts +++ b/src/_internals/datapack/resourcesTree.ts @@ -29,8 +29,8 @@ export type File, P extends ResourcePath = Res type FunctionProperties = { commands: CommandArgs[] } export type FunctionResource = FolderOrFile -export type TagObjectValue = { id: T, required: boolean } -type TagProperties = { values: (TagObjectValue | string)[], replace?: boolean } +export type TagSingleValue = T | { id: T, required: boolean } +type TagProperties = { values: TagSingleValue[], replace?: boolean } type TagPath = readonly [ namespace: string, type: TAG_TYPES, diff --git a/src/_internals/generalTypes.ts b/src/_internals/generalTypes.ts index 07cea8f7..c82aab9f 100644 --- a/src/_internals/generalTypes.ts +++ b/src/_internals/generalTypes.ts @@ -2,12 +2,15 @@ * Allows to get autocompletion on string unions, while still allowing generic strings. * @see https://github.com/microsoft/TypeScript/issues/29729#issuecomment-700527227 */ -export type LiteralUnion = T | (Pick & { +export type LiteralUnion = T | (Omit & { /** * Ignore this property. * @deprecated + * @internal + * @hidden + * @ignore */ - _?: never + trimStart: string['trimStart'] }); export type AtLeastOne = [T, ...T[]] diff --git a/src/_internals/resources/McFunction.ts b/src/_internals/resources/McFunction.ts index e6f49ba0..2b49b741 100644 --- a/src/_internals/resources/McFunction.ts +++ b/src/_internals/resources/McFunction.ts @@ -200,15 +200,15 @@ export class McFunction { } getNameFromArgs = (...args: T): string => { - const jsonRepresentation = JSON.stringify(args) - const mcfunction = this.alreadyInitializedParameters.get(jsonRepresentation) + const repr = hash(args) + const mcfunction = this.alreadyInitializedParameters.get(repr) if (mcfunction) { return mcfunction.name } this.callAndRegister(args) - return this.alreadyInitializedParameters.get(jsonRepresentation)?.name as string + return this.alreadyInitializedParameters.get(repr)?.name as string } generateInitialFunction = () => { diff --git a/src/_internals/resources/Predicate.ts b/src/_internals/resources/Predicate.ts index c41dde2f..949ce940 100644 --- a/src/_internals/resources/Predicate.ts +++ b/src/_internals/resources/Predicate.ts @@ -29,4 +29,8 @@ export class Predicate extends ConditionClass { value: ['predicate', this.name], } } + + toString() { + return this.name + } } diff --git a/src/_internals/resources/Tag.ts b/src/_internals/resources/Tag.ts index 3ad5b666..3c14db39 100644 --- a/src/_internals/resources/Tag.ts +++ b/src/_internals/resources/Tag.ts @@ -3,36 +3,51 @@ import type { BLOCKS, ENTITY_TYPES, FLUIDS, ITEMS, TAG_TYPES, } from '@arguments' import type { Datapack } from '@datapack' -import type { TagObjectValue } from '@datapack/resourcesTree' - -type HintedTagStringType = ( - T extends 'blocks' ? BLOCKS : - T extends 'fluids' ? FLUIDS : - T extends 'entity_types' ? ENTITY_TYPES : - T extends 'functions' ? string : - T extends 'items' ? ITEMS : +import type { McFunctionReturn } from '@datapack/Datapack' +import type { TagSingleValue } from '@datapack/resourcesTree' + +export type HintedTagStringType = ( + T extends 'blocks' ? LiteralUnion : + T extends 'fluids' ? LiteralUnion : + T extends 'entity_types' ? LiteralUnion : + T extends 'functions' ? (LiteralUnion | McFunctionReturn<[]>) : + T extends 'items' ? LiteralUnion : string ) -export type HintedTagValues = ( - LiteralUnion> | - TagObjectValue< - LiteralUnion> - > -)[] +function isMcFunctionReturn(v: unknown): v is McFunctionReturn<[]> { + return typeof v === 'function' +} + +function isTagObject(v: TagSingleValue): v is Exclude, T> { + return typeof v === 'object' +} -export class Tag { +export class Tag { readonly type - readonly values + readonly values: TagSingleValue[] readonly name readonly datapack - constructor(datapack: Datapack, type: TAG_TYPES, name: string, values: TagObjectValue[], replace?: boolean) { + constructor(datapack: Datapack, type: TYPE, name: string, values: readonly TagSingleValue>[], replace?: boolean) { this.type = type - this.values = values + + this.values = values.map((v) => { + if (isMcFunctionReturn(v)) { + return v.getName() + } + if (isTagObject(v) && isMcFunctionReturn(v.id)) { + return { + id: v.id.getName(), + required: v.required, + } + } + return v as string | TagSingleValue + }) + this.name = name this.datapack = datapack @@ -42,7 +57,7 @@ export class Tag { children: new Map(), isResource: true, path: [namespace, type, ...fullPath], - values, + values: this.values, replace, }) } diff --git a/src/_internals/variables/Selector.ts b/src/_internals/variables/Selector.ts index 03a1889c..496dd027 100644 --- a/src/_internals/variables/Selector.ts +++ b/src/_internals/variables/Selector.ts @@ -4,6 +4,7 @@ import type { ENTITY_TYPES, TextComponentObject, } from '@arguments' import type { CommandsRoot } from '@commands' +import type { Predicate } from '@resources' import type { LiteralUnion } from '../generalTypes' import type { ConditionClass } from './abstractClasses' import { ComponentClass } from './abstractClasses' @@ -116,7 +117,7 @@ export type SelectorProperties '', Infinity => '', any number => itself +function sanitizeValue(value: number | null): string { + if (value === undefined || value === null) { + return '' + } + + if (Number.isFinite(value)) { + return value.toString() + } + + // Value is Infinity or -Infinity + return '' +} + +// Returns the string representation of a score range. [0, null] => '0..', [-Infinity, 5] => '..5', 8 => '8' function parseScore(scores: ScoreArgument): string { return `{${Object.entries(scores).map(([scoreName, value]) => { if (Array.isArray(value)) { - return [scoreName, `${value[0] ?? ''}..${value[1] ?? ''}`].join('=') + return [scoreName, `${sanitizeValue(value[0])}..${sanitizeValue(value[1])}`].join('=') } return [scoreName, value].join('=') }).join(', ')}}` } +// Returns the string representation of advancements function parseAdvancements(advancements: AdvancementsArgument): string { return `{${Object.entries(advancements).map(([advancementName, value]) => { if (typeof value === 'boolean') { diff --git a/tests/test.ts b/tests/test.ts index 487d6685..b6b3352b 100644 --- a/tests/test.ts +++ b/tests/test.ts @@ -1,20 +1,31 @@ +import type { LiteralUnion } from '../src/arguments' import { execute, gamerule, give, raw, say, tellraw, } from '../src/commands' import { - mcfunction, Recipe, saveDatapack, _, + mcfunction, Predicate, Recipe, saveDatapack, Tag, _, } from '../src/core' import { createObjective, Selector } from '../src/variables' -Recipe('test', { - type: 'blasting', - ingredient: { item: 'minecraft:acacia_boat' }, - result: 'minecraft:coal', - experience: 0, +const myPredicate = Predicate('mypred', { + condition: 'minecraft:entity_scores', + entity: 'killer', + scores: { + cc: { + max: 0, + min: 2, + }, + }, }) -mcfunction('cc', () => { - give(Selector('@s', { scores: { xx: [0, 1] } }), 'minecraft:blue_ice') -}) +const myScore = createObjective('aa', 'dummy') + +const cc = mcfunction('cc', () => {}) + +Tag('functions', 'hi2', [ + 'test:mc', + 'minecraft:acacia_button', + cc, +]) saveDatapack('My datapack', { verbose: true, world: 'Crea1_15' })