[Scarpet] Add advancements API
Firigion opened this issue ยท 0 comments
Right now the only way to handle advancements from carpet is through run('advacement grant|revoke ...')
, which is always undesirable. There's also no way to hook into the event of a player earning and advancement, which is usually the vanilla commands way to detect a bunch of things. To use that in scarpet, the current way is to hook into that event through a datapack that runs a scarpet command, which is less than optimal. Addig this API would grant a lot of flexibility, the same way adding the __on_statistic
API did.
For instance, here's an example by the discord duser @chyx that uses advancements to detect inventory changes: they created the custom advancement (see here for orignial message).
{ "rewards":{"function":"chyx:invupd"},
"criteria": {
"example": {
"trigger": "minecraft:inventory_changed",
"conditions": {
}
}
}
}
and packed a function that simply signlas an event and removes the advancement
script run signal_event('invupd', null, player())
advancement revoke @s only chyx:xd
I suggest an API that follows something like the following. Keep in mind this is a suggestion from someone that barely ever used vanilla advancements, so I might be missing something.
- An event:
__on_advancement(player, advancement)
, mimicking the__on_statistic
event. Not sure if the callback is gonna need more arguments, it will depend on what the MC API exposes, I assume. - A way to get advancement trees:
advancement_tree(advancement, direction)
. Heredirection
is one of'up'
or'down'
, to return the parent and children advancements of the given one, respectively. Ifadvancement
isnull
, return a list of all root advancements. The return format for this is not gonna be user friendly, because scarpet doesn't have many data structure options, but I think a nested list should be okay. - A way to grant and revoke advancements:
advancement_grant(player, advancement, direction?, end?)
and the accompanyingadvancement_revoke(player, advancement, direction?, end?)
. Ifmode
isnull
it only grants/revokes the given advancement,'up'
to affect all parent advancements,'down'
for all children. Optionalend
parameter indicates where to stop granting or revoking advancements. Has to be a parent if mode is'up'
or child if it's'down'
.end
can also be an integer to indicate ammount of layers to remove. The two functions can be merged intoadvancement(player, mode, direction?, end?)
but i think it makes the API a bit less readable. Maybeadvancement_modify
. - A way to query advancements, which could either be baked into the current
querry
functionality (query(player, 'advancement', advancement?)
or into the proposed new API, like it's the case for scoreboards right now (advancement_query(player, adcanvement?)
. If queried withnull
, returns a list of all the advancements the player has. I don't think there's a need to query for multiple advancemets at once. - A way to define new advancements: signature for this one is difficult, but it's a key function for this API to be useful and I don't think adding it will be much of a stretch, seeing how there's already a
create_datapack
function in scarpet. Easiest way to implement it is to just have a map as input data and have scarpet format the map into json, likecreate_datapack
currently works:advancement_new(resource_name, data)
. - A way to read an advancement's properties. Not sure if this one is needed, but it would be something like
advancement_properties(advancement, props?)
. If queried withnull
it gives a list of all the non empty properties of the advancement, or a map of all of them. If queried with a property (string), returns the value. If queried with a lsit of properties, returns a map of property:value pairs. The Wiki lists all the properties an advancement can have. - An additional option is to have another event
__on_advancement_trigger(player, trigger, data)
that listens to the triggers that advancements use. Using this one could void the need for theadvancement_new
function and maybe even for the__on_advancement
event, while also making the mechanics that makes advancements so useful easily available. In particular, it would be nice to not need to create a new advancement only to know when a player bred two animals (minecraft:bred_animals
), which currently can only be detected through advancements. How to formatdata
is gonna be a hard question to answer, tho, since triggers are usually defined with a bunch of contidions.
Of course like with everything in scarpet, all advancements have an implied minecraft:
namespace, but should allow for arbitrary namespaces for customa dvancements both added through scarpet and manually through a datapck.