sandstone-mc / sandstone Goto Github PK
View Code? Open in Web Editor NEWSandstone | Next Generation Framework for Minecraft
Home Page: https://sandstone.dev/
License: MIT License
Sandstone | Next Generation Framework for Minecraft
Home Page: https://sandstone.dev/
License: MIT License
I installed everything using the installation commands
PS F:\code\minecraft\Sandstone Projects> npx ts-node helloworld.ts
Error: Cannot find module '@commands'
Require stack:
- F:\code\minecraft\Sandstone Projects\node_modules\sandstone\_internals\datapack\Datapack.js
- F:\code\minecraft\Sandstone Projects\node_modules\sandstone\_internals\datapack\index.js
- F:\code\minecraft\Sandstone Projects\node_modules\sandstone\_internals\index.js
- F:\code\minecraft\Sandstone Projects\node_modules\sandstone\commands.js
- F:\code\minecraft\Sandstone Projects\helloworld.ts
at Function.Module._resolveFilename (internal/modules/cjs/loader.js:892:15)
at Function.Module._resolveFilename (F:\code\minecraft\Sandstone Projects\node_modules\module-alias\index.js:49:29)
at Function.Module._load (internal/modules/cjs/loader.js:742:27)
at Module.require (internal/modules/cjs/loader.js:964:19)
at require (internal/modules/cjs/helpers.js:88:18)
at Object.<anonymous> (F:\code\minecraft\Sandstone Projects\src\_internals\datapack\Datapack.ts:5:1)
at Module._compile (internal/modules/cjs/loader.js:1075:30)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:1096:10)
at Module.load (internal/modules/cjs/loader.js:940:32)
at Function.Module._load (internal/modules/cjs/loader.js:781:14)
Add support for basePath`.name`
as discussed on the Discord server.
I'd like to create a custom data pack that boosts the amount of drops while mining. I'm able to get the loot tables generated under loot_tables/<block>.json
but I think it needs to be under loot_tables/blocks/<block>.json
. Is there a built-in way to put it under the blocks
folder? If not then I can make a post-build script, but I'm happy to try implementing a way to specify if there is interest. Thanks!
$('# Exclusive Inputs\n',
'Backward')
expected evaluation:
# # Exclusive Inputs
# Backward
received evaluation:
# # Exclusive Inputs
Backward
I expect a function tag to be callable just like a function.
I would argue that Coordinates
should include (or be renamed to and merged with) the below Vec3
in its union type, as defined below, and Rotation
should include the below Rotation
in its union type:
type AbsoluteFloat = number | `${number}`;
type RelativeFloat = `~${'' | number}`;
type LocalFloat = `^${'' | number}`;
type AbsoluteOrRelativeFloat = AbsoluteFloat | RelativeFloat;
type AbsoluteOrRelativeVec3 = `${AbsoluteOrRelativeFloat} ${AbsoluteOrRelativeFloat} ${AbsoluteOrRelativeFloat}`;
type LocalVec3 = `${LocalFloat} ${LocalFloat} ${LocalFloat}`;
type Vec3 = AbsoluteOrRelativeVec3 | LocalVec3;
type Rotation = `${AbsoluteOrRelativeVec3} ${AbsoluteOrRelativeVec3}`;
(These types partially are named based on the official brigadier IDs of argument types which can be found here.)
This is much more natural and readable, especially to those who are more familiar with vanilla syntax (like people outside the project who just want to learn how a data pack works despite it being written in Sandstone). It's also more concise and short in many cases.
For example:
setblock('~ ~ ~', 'minecraft:stone');
Code to reproduce:
MCFunction("test", () => {
const a = Variable(1, "test");
tellraw("@a", a);
})
Expected:
scoreboard players set test_id_0 sandstone 1
tellraw @a {"score":{"name":"test_id_0","objective":"sandstone"}}
Got:
scoreboard players set test_id_0 sandstone 1
tellraw @a {"type":"minecraft:score","target":{"type":"minecraft:fixed","name":"test_id_0"},"score":"sandstone","scale":1}
Scoreboard
operation
does not accept PlayerScore
, and PlayerScore.set
does not accept another PlayerScore
.
In Minecraft SNBT, "
and '
are not interchangeable. For example, this works (full double quotes):
/give @s minecraft:diamond_sword{display:{Name:"[{\"text\":\"foo\"}]"}} 1
This also works (double quotes surrounded by single quotes):
/give @s minecraft:diamond_sword{display:{Name:'[{"text":"foo"}]'}} 1
This does not work (single quotes surrounded by double quotes):
/give @s minecraft:diamond_sword{display:{Name:"[{'text':'foo\\nbar'}]"}} 1
At the moment, all custom resources have to be text ("json", "raw" string), but there are cases where a binary resource needs to be emitted, namely texture files. Texture files should have type Buffer
or Uint8Array
.
When I upgraded sandstone to 0.6.0 in my project, I got this error message.
Error: Cannot define namespace under a base path.
at BasePathClass.getName (C:\Users\Beatso\OneDrive\Documents\Minecraft\datapacks\SurvivalistsVsHitmen\src_internals\datapack\BasePath.ts:49:13)
at Object.BasePathClass.MCFunction (C:\Users\Beatso\OneDrive\Documents\Minecraft\datapacks\SurvivalistsVsHitmen\src_internals\datapack\BasePath.ts:137:64)
at Object. (C:\Users\Beatso\OneDrive\Documents\Minecraft\datapacks\SurvivalistsVsHitmen\index.ts:27:1)
at Module._compile (internal/modules/cjs/loader.js:1138:30)
at Module.m._compile (C:\Users\Beatso\OneDrive\Documents\Minecraft\datapacks\SurvivalistsVsHitmen\node_modules\ts-node\src\index.ts:1043:23)
at Module._extensions..js (internal/modules/cjs/loader.js:1158:10)
at Object.require.extensions. [as .ts] (C:\Users\Beatso\OneDrive\Documents\Minecraft\datapacks\SurvivalistsVsHitmen\node_modules\ts-node\src\index.ts:1046:12)
at Module.load (internal/modules/cjs/loader.js:986:32)
at Function.Module._load (internal/modules/cjs/loader.js:879:14)
at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:71:12)
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! [email protected] build: npx ts-node index.ts
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the [email protected] build script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.
npm ERR! A complete log of this run can be found in:
npm ERR! C:\Users\Beatso\AppData\Roaming\npm-cache_logs\2020-11-29T13_33_24_088Z-debug.log
After replacing all mcfunction
s with MCFunction
, i got this error:
C:\Users\Beatso\OneDrive\Documents\Minecraft\datapacks\SurvivalistsVsHitmen\node_modules\ts-node\src\index.ts:500
return new TSError(diagnosticText, diagnosticCodes)
^
TSError: ⨯ Unable to compile TypeScript:
index.ts:2:22 - error TS2305: Module '"./node_modules/sandstone/core"' has no exported member 'saveDatapack'.
2 import { MCFunction, saveDatapack } from "sandstone/core"
~~~~~~~~~~~~
at createTSError (C:\Users\Beatso\OneDrive\Documents\Minecraft\datapacks\SurvivalistsVsHitmen\node_modules\ts-node\src\index.ts:500:12)
at reportTSError (C:\Users\Beatso\OneDrive\Documents\Minecraft\datapacks\SurvivalistsVsHitmen\node_modules\ts-node\src\index.ts:504:19)
at getOutput (C:\Users\Beatso\OneDrive\Documents\Minecraft\datapacks\SurvivalistsVsHitmen\node_modules\ts-node\src\index.ts:739:36)
at Object.compile (C:\Users\Beatso\OneDrive\Documents\Minecraft\datapacks\SurvivalistsVsHitmen\node_modules\ts-node\src\index.ts:955:32)
at Module.m._compile (C:\Users\Beatso\OneDrive\Documents\Minecraft\datapacks\SurvivalistsVsHitmen\node_modules\ts-node\src\index.ts:1043:43)
at Module._extensions..js (internal/modules/cjs/loader.js:1158:10)
at Object.require.extensions.<computed> [as .ts] (C:\Users\Beatso\OneDrive\Documents\Minecraft\datapacks\SurvivalistsVsHitmen\node_modules\ts-node\src\index.ts:1046:12)
at Module.load (internal/modules/cjs/loader.js:986:32)
at Function.Module._load (internal/modules/cjs/loader.js:879:14)
at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:71:12)
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! [email protected] build: npx ts-node index.ts
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the [email protected] build script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.
npm ERR! A complete log of this run can be found in:
npm ERR! C:\Users\Beatso\AppData\Roaming\npm-cache_logs\2020-11-29T13_34_49_146Z-debug.log
what am I doing wrong, and how can I fix this issue? is this an issue with the release of sandstone, or what I'm doing?
link to my code
I am importing sandstone version 0.14.0-alpha.1
and using this tsconfig.json I get the following errors:
tsconfig:
{
"compilerOptions": {
"module": "CommonJS",
"moduleResolution": "node",
"target": "ESNext",
"sourceMap": true,
"outDir": "dist",
"rootDir": "src",
"strict": true,
"resolveJsonModule": true
}
}
node_modules/sandstone/arguments/resources/criteria/basic_criteria.d.ts:33:54 - error TS2344: Type 'LiteralUnion<MOB_EFFECTS>' does not satisfy the constraint 'string | number | symbol'.
Type 'Omit<string, number | unique symbol | "length" | "toString" | "charAt" | "charCodeAt" | "concat" | "indexOf" | "lastIndexOf" | "localeCompare" | "match" | "replace" | "search" | ... 37 more ... | "at"> & { ...; }' is not assignable to type 'string | number | symbol'.
Type 'Omit<string, number | unique symbol | "length" | "toString" | "charAt" | "charCodeAt" | "concat" | "indexOf" | "lastIndexOf" | "localeCompare" | "match" | "replace" | "search" | ... 37 more ... | "at"> & { ...; }' is not assignable to type 'string'.
33 export declare type EffectCriterion = Partial<Record<LiteralUnion<MOB_EFFECTS>, {
~~~~~~~~~~~~~~~~~~~~~~~~~
node_modules/sandstone/variables/Score.d.ts:57:78 - error TS2526: A 'this' type is available only in a non-static member of a class or interface.
57 (targets: PlayersTarget, objective?: ObjectiveArgument | undefined): this;
~~~~
node_modules/sandstone/variables/Score.d.ts:58:48 - error TS2526: A 'this' type is available only in a non-static member of a class or interface.
58 (amountOrTargetScore: number | Score): this;
~~~~
node_modules/sandstone/variables/Score.d.ts:59:63 - error TS2526: A 'this' type is available only in a non-static member of a class or interface.
59 (nbt: DataPointInstance, scale?: number | undefined): this;
~~~~
node_modules/sandstone/variables/Score.d.ts:76:89 - error TS2526: A 'this' type is available only in a non-static member of a class or interface.
76 (targets: MultipleEntitiesArgument, objective?: ObjectiveArgument | undefined): this;
~~~~
node_modules/sandstone/variables/Score.d.ts:77:48 - error TS2526: A 'this' type is available only in a non-static member of a class or interface.
77 (amountOrTargetScore: number | Score): this;
~~~~
node_modules/sandstone/variables/Score.d.ts:94:89 - error TS2526: A 'this' type is available only in a non-static member of a class or interface.
94 (targets: MultipleEntitiesArgument, objective?: ObjectiveArgument | undefined): this;
~~~~
node_modules/sandstone/variables/Score.d.ts:95:48 - error TS2526: A 'this' type is available only in a non-static member of a class or interface.
95 (amountOrTargetScore: number | Score): this;
~~~~
node_modules/sandstone/variables/Score.d.ts:112:89 - error TS2526: A 'this' type is available only in a non-static member of a class or interface.
112 (targets: MultipleEntitiesArgument, objective?: ObjectiveArgument | undefined): this;
~~~~
node_modules/sandstone/variables/Score.d.ts:113:48 - error TS2526: A 'this' type is available only in a non-static member of a class or interface.
113 (amountOrTargetScore: number | Score): this;
~~~~
node_modules/sandstone/variables/Score.d.ts:130:89 - error TS2526: A 'this' type is available only in a non-static member of a class or interface.
130 (targets: MultipleEntitiesArgument, objective?: ObjectiveArgument | undefined): this;
~~~~
node_modules/sandstone/variables/Score.d.ts:131:48 - error TS2526: A 'this' type is available only in a non-static member of a class or interface.
131 (amountOrTargetScore: number | Score): this;
~~~~
node_modules/sandstone/variables/Score.d.ts:148:89 - error TS2526: A 'this' type is available only in a non-static member of a class or interface.
148 (targets: MultipleEntitiesArgument, objective?: ObjectiveArgument | undefined): this;
~~~~
node_modules/sandstone/variables/Score.d.ts:149:48 - error TS2526: A 'this' type is available only in a non-static member of a class or interface.
149 (amountOrTargetScore: number | Score): this;
~~~~
node_modules/sandstone/variables/Score.d.ts:239:89 - error TS2526: A 'this' type is available only in a non-static member of a class or interface.
239 (targets: MultipleEntitiesArgument, objective?: ObjectiveArgument | undefined): this;
~~~~
node_modules/sandstone/variables/Score.d.ts:240:48 - error TS2526: A 'this' type is available only in a non-static member of a class or interface.
240 (amountOrTargetScore: number | Score): this;
~~~~
node_modules/sandstone/variables/Score.d.ts:257:89 - error TS2526: A 'this' type is available only in a non-static member of a class or interface.
257 (targets: MultipleEntitiesArgument, objective?: ObjectiveArgument | undefined): this;
~~~~
node_modules/sandstone/variables/Score.d.ts:258:48 - error TS2526: A 'this' type is available only in a non-static member of a class or interface.
258 (amountOrTargetScore: number | Score): this;
~~~~
Found 18 errors.
I already tried out different versions of typescript, neither versions 4.* or 3.* work.
Some blocks have block states. A minecraft:sandstone_slab
can for example be waterlogged and has a type (top, bottom, double). In mcfunction this can be done everywhere a block is placed or compared. There is currently no type-safe block-aware way to do this in Sandstone.
Using typescript it could be checked whether a block has the states that are specified. There is for example no type=bottom variant of a grass block.
Sandstone always deletes the datapack folder before regenerating it. There's currently no way to do this for custom resources (like Resourcepacks). Instantiating a CustomResourceRoot class could tell Sandstone to first clean up the location. Then, CustomResource instances need to receive the root class to retrieve their save location.
This would move the save function into the root class.
Example:
const resourcepackRoot = CustomResourceRoot(({ saveType, packName, saveLocation }): string => {
// ...
});
export const FontResource = CustomResource("font", {
// ...
root: resourcepackRoot
});
the code team.leave('@a')
will be in the data pack as team join @a
, rather than team leave @a
.
NBT.stringify is not typed to accept arrays, but it works at runtime.
/**
* Argument of type 'string[]' is not assignable to parameter of type 'RootNBT'.
* Index signature for type 'string' is missing in type 'string[]'
* ts(2345)
*/
NBT.stringify([ "hi" ])
Instead of number | LiteralUnion<'1t' | '1s' | '1d'>
, it could be number | `${number}${'t' | 's' | 'd'}`
(or something equally restrictive that still includes '1t'
, '1s'
, and '1d'
as auto-complete options).
All of these, for example, should be valid for some objective: ObjectiveInstance
and some score: Score
:
scoreboard.objectives.add(objective, 'dummy')
scoreboard.objectives.remove(objective)
scoreboard.objectives.setdisplay('list', objective)
scoreboard.players.set(score, 1)
scoreboard.players.set('a', objective, 1)
scoreboard.players.add(score, 1)
scoreboard.players.add('a', objective, 1)
scoreboard.players.remove(score, 1)
scoreboard.players.remove('a', objective, 1)
scoreboard.players.reset(score)
scoreboard.players.reset('a', objective)
scoreboard.players.operation(score, '=', score)
scoreboard.players.operation(score, '=', 'a', objective)
scoreboard.players.operation(score, '=', 'a', 'b')
scoreboard.players.operation('a', objective, '=', score)
scoreboard.players.operation('a', objective, '=', 'a', objective)
scoreboard.players.operation('a', objective, '=', 'a', 'b')
scoreboard.players.operation('a', 'b', '=', score)
scoreboard.players.operation('a', 'b', '=', 'a', objective)
execute.ifScore('@s', raw_direction.objective, 'matches', [ angle*10, (angle + 45)*10 ])
will evaluate to
execute if score @s mtwasd.input matches -1800,-1350
when the correct evaluation would be
execute if score @s mtwasd.input matches -1800..-1350
Additionally, a range Conditional for PlayerScore
is missing, I'd suggest between
, perhaps as an alias to inRange
Implement support for this being included in the Range
type:
type Range = `${number}` | `${number}..` | `..${number}` | `${number}..${number}`
It would allow more familiarity for those not fully comfortable with Sandstone's abstractions, and it would also simplify code in some cases.
NBT.stringify({ test: '\n' })
should output "{test:'\n'}"
when used in a JSON file, not "{test:'\\n'}"
. This input impossible to specify in commands validly though.
Minimal reproduction code:
LootTable('test:book', {
type: 'command',
pools: [{
rolls: 1,
entries: [{
type: 'minecraft:item',
name: 'minecraft:writable_book',
functions: [{
function: 'set_nbt',
tag: NBT.stringify({
pages: ['line 1\nline 2']
})
}]
}],
bonus_rolls: 0
}]
});
Minecraft does not recognize this NBT as valid. Entering /loot give @s loot test:book
will not work. Opening the outputted loot table file shows this error:
And Minecraft logs this error:
Add support for basePath`#name`
as discussed on the Discord server.
for (let i = 0; i < 5; i++) {
say('some string') // compiles incorrectly
kill('@e[tag=xjfjsdf]') // compiles correctly
setblock(abs(0, 100, 0), 'minecraft:air') // compiles correctly
_.if(someVariable.equalTo(1), () => { // arbitrary if statement
})
}
compiles into
say "some string"
kill @e[tag=xjfjsdf]
setblock 0 100 0 minecraft:air
run say "some string"
kill @e[tag=xjfjsdf]
setblock 0 100 0 minecraft:air
run say "some string"
kill @e[tag=xjfjsdf]
setblock 0 100 0 minecraft:air
run say "some string"
kill @e[tag=xjfjsdf]
setblock 0 100 0 minecraft:air
run say "some string"
kill @e[tag=xjfjsdf]
setblock 0 100 0 minecraft:air
The first say()
compiles correctly but the following ones are prefixed with run
which doesn't work. I only tested kill()
and setblock()
besides say()
but they both appeared to compile correctly.
It should accept function tags in addition to functions.
A loot table's type
doesn't need to be namespaced, but to be consistent with all other auto-complete options in Sandstone defaulting to being namespaced, it should be. Each of these auto-complete options should be prefixed with minecraft:
.
Additionally, when I try to add a namespace, it does not accept it.
It should be scoreboard.objectives.setdisplay
. Nothing else that I know of in the library takes the lowercase of vanilla Minecraft syntax and turns it into camel case where there are officially multiple words. For example, datapack
, gamerule
, tellraw
, playsound
, teammsg
, setworldspawn
, gamemode
, etc. are all lowercase despite officially containing multiple words. So why isn't setdisplay
?
The same reasoning that applies to doing this for execute.if
and execute.unless
subcommands also applies to these.
execute.facing.entity
execute.positioned.as
execute.rotated.as
worldborder.damage.amount
worldborder.damage.buffer
worldborder.warning.distance
worldborder.warning.time
BasePathClass.prototype.getResourceName
does not accept substitutions like template tags normally do. It only looks at the template parts of the inputted string.
name.join()
is the part of the code below causing this issue, in addition to the incorrect parameter types.
The correct signature of a template tag function should be this:
(template: TemplateStringsArray, ...substitutions: any[]) => string
Otherwise, for example, basePath`a${b}c`
will output the same thing as basePath`ac`
(or actually basePath`a,c`
since it's name.join()
and not name.join('')
) no matter what b
is.
Here is an example of a correct implementation for a template tag function which simply outputs exactly the string which is inputted:
(template, ...substitutions) => (
template.map((string, i) => string + (i in substitutions ? substitutions[i] : '')).join('')
)
Many of the current names are very unnatural to type and to read.
These should be renamed:
greaterOrEqualThan
-> greaterThanOrEqualTo
lowerOrEqualThan
-> lessThanOrEqualTo
lowerThan
-> lessThan
equalTo
-> equals
multipliedBy
-> times
modulo
-> mod
moduloBy
-> modBy
Any of the last four could be aliases instead if that's preferable to renaming. The first three are completely unnatural phrasings though.
tag.has(value)
would be a nice alias for this:
tag.values.some(tagValue => (
(
typeof tagValue !== 'string'
&& 'id' in tagValue
? tagValue.id
: tagValue
).toString() === value.toString()
))
value
could be a string, whatever object type the tag is made of (e.g. an MCFunction
), or the same type of tag (e.g. a function tag).
Here is an example to demonstrate that this method would be useful in general:
const someAbstraction = () => {
MCFunction('function', () => {}, {
tags: [tag]
});
// or
tag.add(
MCFunction('function', () => {})
);
};
If someAbstraction
is called multiple times, there will necessarily still only be one instance of the created function in-game, but it will be added to tag
multiple times regardless. It is necessary to be able to add the same function to one tag multiple times, so preventing that in general is not the solution here. Instead, because it isn't desirable in most cases that calling an abstraction multiple times would add a function it requires to a tag multiple times, it would be better to do this:
const someAbstraction = () => {
const mcFunction = MCFunction('function', () => {});
if (!tag.has(mcFunction)) {
tag.add(mcFunction);
}
};
An abstraction happening to need a function that needs to be in a function tag is a general use case, and tag.has
would make that use case much cleaner to implement, because currently it requires the ugly monster at the top of this post to check if something is in a tag.
The following example does not compile because the selector only accepts strings. It would be nice to be able to use selectors in JSON Text Components without appending .toString()
. This is already implemented for score components.
import { Selector, MCFunction, tellraw } from 'sandstone'
MCFunction('hello', () => {
const closest = Selector('@p', {distance: [.1, Infinity]})
tellraw(Selector('@a'), {
text: 'My closest friend is ',
extra: [
{ selector: closest }
]
})
})
The comment function isn't working.
Code to reproduce:
import { MCFunction, say, comment } from 'sandstone'
MCFunction("test", () => {
comment("clearly a test.");
say("This is a test!");
})
A blank line is written, where a comment should be.
Add an option to run some TS after compilation, like the savePack
callback.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.