-
-
Notifications
You must be signed in to change notification settings - Fork 67
Environment Checks #1093
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: update-26.1
Are you sure you want to change the base?
Environment Checks #1093
Changes from all commits
42e3278
789f736
aa913a2
2c9fdca
150fc11
aead807
fbe6524
4c6f346
52a3dd5
220ec34
6fd28f6
6b7610d
f0a2d53
b4e796d
c56f0f1
11fdc5c
fb74ace
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,17 @@ | ||
| # Copies the results of environment checks into the log queue to prepare for printing to chat | ||
| # @s = none | ||
| # at unspecified | ||
| # run from await_echeck_results | ||
|
|
||
| # if no check failed, no need to print | ||
| execute unless data storage gm4:log echecks[{result:{passed:0}}] unless data storage gm4:log echecks[{result:{passed:-1}}] run return 0 | ||
|
|
||
| # copy results into queue, KEEP VERSION IN echecks, SO WE CAN INSPECT IT FOR DEBUGGING | ||
| data modify storage gm4:log queue set from storage gm4:log echecks | ||
|
|
||
| # add extra text around warnings | ||
| data modify storage gm4:log queue prepend value {type:"text",message:{"text":"[GM4]: Some environment checks have not succeeded:","color":"#4AA0C7"}} | ||
| data modify storage gm4:log queue append value {type:"text",message:{"text":"[GM4]: This may lead to unintended behavior.","color":"#4AA0C7"}} | ||
|
|
||
| # start announcing | ||
| function gm4:log_start | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,12 @@ | ||
| # Waits until all environment checks have returned their results | ||
| # run from post_load | ||
|
|
||
| # maintain timeout timer | ||
| scoreboard players remove $echeck_timeout gm4_data 1 | ||
| execute if score $echeck_timeout gm4_data matches ..0 run return run function gm4:announce_echeck_results | ||
|
|
||
| # Peek if any environment checks are still pending (passed:-1), if so, continue waiting | ||
| execute if data storage gm4:log echecks[{result:{passed:-1}}] run return run schedule function gm4:await_echeck_results 1t | ||
|
|
||
| # all test have returned, print to chat | ||
| function gm4:announce_echeck_results |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,17 @@ | ||
| # Assigns a score to this marker and reads it back. Kills the marker afterwards | ||
| # @s = test marker, just summoned | ||
| # at @s | ||
| # run from gm4:echeck/non_player_entity_has_score | ||
| # set up marker & run test | ||
| scoreboard players set @s gm4_data 1 | ||
| # depending on test outcome, set the 'result' object in storage. Base uses this to test if the check has completed. | ||
|
|
||
| # if the score is present, mark the check as passed by removing it from storage | ||
| execute if score @s gm4_data matches 1 run data modify storage gm4:log echecks[{echeck_id:"gm4:echeck/non_player_entity_has_score"}].result set value {passed:1,probable_cause:""} | ||
|
|
||
| # if no score is present, we don't know why this would happen. Good luck. | ||
| execute unless score @s gm4_data matches 1 run data modify storage gm4:log echecks[{echeck_id:"gm4:echeck/non_player_entity_has_score"}].result set value {passed:0,probable_cause:""} | ||
|
|
||
| # clean up marker | ||
| scoreboard players reset @s gm4_data | ||
| kill @s |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,19 @@ | ||
| # Assigns a score to this marker and reads it back. Kills the marker afterwards | ||
| # @s = test marker, just summoned | ||
| # at @s | ||
| # run from gm4:echeck/non_player_entity_has_score | ||
| # set up marker & run test | ||
| team add gm4_echeck_non_player_entity_on_team_temp | ||
| team join gm4_echeck_non_player_entity_on_team_temp @s | ||
|
|
||
| # depending on test outcome, set the 'result' object in storage. Base uses this to test if the check has completed. | ||
|
|
||
| # if the marker is now on the team, mark the check as passed by removing it from storage | ||
| execute if entity @s[team=gm4_echeck_non_player_entity_on_team_temp] run data modify storage gm4:log echecks[{echeck_id:"gm4:echeck/non_player_entity_has_score"}].result set value {passed:1,probable_cause:""} | ||
|
|
||
| # if the marker is not on the team, provide a probable cause message to the user | ||
| execute unless entity @s[team=gm4_echeck_non_player_entity_on_team_temp] run data modify storage gm4:log echecks[{echeck_id:"gm4:echeck/non_player_entity_has_score"}].result set value {passed:0,probable_cause:"This may be caused by the Paper/Spigot setting 'scoreboards.allow-non-player-entities-on-scoreboards=false'."} | ||
|
|
||
| # clean up | ||
| team remove gm4_echeck_non_player_entity_on_team_temp | ||
| kill @s |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| # Tests if non-player entities can hold scores. We think spigot might have done this at some point, but are not sure. | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. After thinking about this again, we should probably just remove this check. I'll get annoying adding this to every module when it doesn't even matter in the current versions. |
||
| # @s = unspecified | ||
| # at unspecified | ||
| # run from modules which require this environment check | ||
|
|
||
| # start environment check as marker | ||
| execute summon marker run function gm4:echeck/assign_score | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| # Tests if non-player entities can be on teams. Spigot prevents non-players on teams if the config is changed. | ||
| # @s = unspecified | ||
| # at unspecified | ||
| # run from modules which require this environment check | ||
|
|
||
| # start environment check as marker | ||
| execute summon marker run function gm4:echeck/join_team |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,4 +1,6 @@ | ||
| data merge storage gm4:log {queue:[],versions:[]} | ||
| data modify storage gm4:log echecks set value [] | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This command can be combined into the above command |
||
| schedule clear gm4:await_echeck_results | ||
| data modify storage gm4:log queue append value {type:"text",message:{"text":"[GM4]: Checking for updates...","color":"#4AA0C7"}} | ||
|
|
||
| scoreboard objectives add gm4_modules dummy | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,4 +1,9 @@ | ||
| scoreboard players reset * gm4.echeck_results | ||
| execute unless data storage gm4:log queue[{type:"install"}] run data modify storage gm4:log queue append value {type:"text",message:{"text":"[GM4]: No updates found.","color":"#4AA0C7"}} | ||
| execute if data storage gm4:log queue[{type:"install"}] run data modify storage gm4:log queue append value {type:"text",message:{"text":"[GM4]: Updates completed.","color":"#4AA0C7"}} | ||
|
|
||
| function gm4:log_wait | ||
|
|
||
| function #gm4:evaluate_echecks | ||
| scoreboard players set $echeck_timeout gm4_data 600 | ||
| schedule function gm4:await_echeck_results 1t |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| { | ||
| "values": [ | ||
| "gm4:echeck/non_player_entity_has_score" | ||
| ] | ||
| } |
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We'll want to update the tag lists in this file to reflect changes in #1264 |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,130 @@ | ||
| # Utilities | ||
| Chances are, the tough problem you are trying to tackle has been solved by someone else working on Gamemode 4 long before you did. | ||
| This document will give you an overview of utilities and tools that have been developed over the years and which may help you when making a module. | ||
|
|
||
| ## Table of contents | ||
| * [Common Tags](#common-tags) | ||
| * [Blocks Tags](#block-tags) | ||
| * [Entity Tags](#entity-tags) | ||
| * [Environment Checks]() | ||
| * [Base Checks]() | ||
| * [Other Notable Checks]() | ||
| * [Creating New Checks]() | ||
| * [Upgrade Paths]() | ||
|
|
||
| ## Common Tags | ||
| Selecting blocks or entities with common properties is an error prone task, and subsequent updates often miss module-specific, hardcoded tags. | ||
| As such, `base` provides various tags that are maintained through updates and which should be prioritized over module-specific solutions. | ||
|
|
||
| ### Block Tags | ||
| Gamemode 4's default block tags are located at `base/data/gm4/tags/block/`. | ||
|
|
||
| | Tag Name | Source | Description | | ||
| |---------------------|---------------------|------------------------------------------------------------------------------------------------------| | ||
| | #gm4:air | air.json | All air types. | | ||
| | #gm4:foliage | foliage.json | Naturally generating decoration on surfaces, which are easily broken, i.e. are washed away by water. | | ||
| | #gm4:full_collision | full_collision.json | All blocks that have a full-block collision box. | | ||
| | #gm4:no_collision | no_collision.json | All blocks without any collision, including air. | | ||
| | #gm4:replaceable | replaceable.json | Blocks that can be replaced by placing another block inside it, including air. | | ||
| | #gm4:water | water.json | Blocks that act as a water source. | | ||
| | #gm4:waterloggable | waterloggable.json | Blocks which can be water-logged. | | ||
|
|
||
| ### Entity Tags | ||
| Gamemode 4's default entity tags are located at `base/data/gm4/tags/block/`. | ||
|
|
||
| | Tag Name | Source | Description | | ||
| |----------------------|----------------------|--------------------------------------------------------------------------------------------------------------------------------------| | ||
| | #gm4:boats | boats.json | All boat variations, including rafts. | | ||
| | #gm4:boss | boss.json | Bosses, namely the Ender Dragon and the Wither. | | ||
| | #gm4:chest_boats | chest_boats.json | All boat variations with a chest. | | ||
| | #gm4:hostile | hostile.json | Living entities that are hostile towards player by default. | | ||
| | #gm4:minecarts | minecarts.json | All minecart variations. | | ||
| | #gm4:neutral_hostile | neutral_hostile.json | Hostile living entities that may be, given the right conditions, neutral towards the player by default but turn hostile if provoked. | | ||
| | #gm4:neutral_passive | neutral_passive.json | Entities that are normally neutral, but turn hostile if provoked. | | ||
| | #gm4:neutral | neutral.json | Entities that may be neutral given the right conditions. | | ||
| | #gm4:non-living | non-living.json | Entities that are not considered living. | | ||
| | #gm4:passive | passive.json | Entities that are normally friendly and do not turn hostile, even if provoked. | | ||
|
|
||
| ## Environment Checks | ||
| The environment a data pack is installed into may affect its performance. | ||
| Servers may have command blocks disabled, or mods may change the way the game reacts to changes made by commands. | ||
| Not all users are aware of this, which can lead to rather frustrating debugging experiences. | ||
| To counteract this, modules may include environment checks which warn the user of the data pack if certain conditions are not met. | ||
|
|
||
| Environment checks are included by specifying them by name (including namespace) inside a module's `beet.yaml`, e.g. | ||
| ```yaml | ||
| id: gm4_double_doors | ||
| name: Double Doors | ||
| version: 1.2.X | ||
|
|
||
| data_pack: | ||
| load: . | ||
|
|
||
| require: | ||
| - bolt | ||
|
|
||
| pipeline: | ||
| - gm4_double_doors.generate | ||
| - gm4.plugins.extend.module | ||
|
|
||
| meta: | ||
| gm4: | ||
| versioning: | ||
| schedule_loops: [] | ||
|
|
||
| # List of environment checks to include | ||
| echecks: [gm4:non_player_entity_has_score] | ||
| website: | ||
| description: Tired of clicking twice to open a double door? Annoyed by the fact that doors are only two blocks tall? This data pack automatically opens adjacent doors, making double doors fully functional! Additionally, bottom trapdoors of matching wood type placed above a door are opened alongside the door when it is opened by a player. | ||
| recommended: [] | ||
| notes: [] | ||
| modrinth: | ||
| project_id: Vx4zJ1Np | ||
| smithed: | ||
| pack_id: gm4_double_doors | ||
| video: null | ||
| wiki: https://wiki.gm4.co/wiki/Double_Doors | ||
| credits: | ||
| Creator: | ||
| - Bloo | ||
| Icon Design: | ||
| - venomousbirds | ||
| ``` | ||
|
|
||
| Multiple checks may be included, however, the order they will be executed in is arbitrary: | ||
| ```yaml | ||
| echecks: [gm4:non_player_entity_has_score, gm4_double_doors:bloo_is_not_online, lib_forceload:command_blocks_enabled] | ||
| ``` | ||
|
|
||
| On reload, `base` obtains a list of environment checks requested by all installed modules and libraries. During `post_load` this list is then executed. | ||
| Announcements of the test results are only made if at least one test did not succeed and may not be instantaneous, as environment checks are allowed 30s of runtime. | ||
| If any check does not return after 30s it is marked as "timed-out" and will be announced as such. | ||
|
|
||
| For debug purposes, you may inspect the contents of storage `gm4:log echecks` to see the results of the latest environment checks. This storage is only cleared before new checks are executed. | ||
|
|
||
| ### Base Environment Checks | ||
| `base` comes with some fundamental environment checks that can be referenced by the `gm4:` namespace. | ||
|
|
||
| | Check Name | Description | | ||
| |--------------------------------|--------------------------------------------------------------------------------------------------------------------------| | ||
| | gm4:non_player_entity_has_score | Checks if non-player entities can be added to a scoreboard. Fails if a test marker's score can not be set and read back. | | ||
|
|
||
| ### Creating New Environment Checks | ||
| Modules may also introduce their own environment checks. Environment checks are defined as a single `.mcfunction` entry point, but may call other `.mcfunction` files, predicates, etc. from their entry point. | ||
| Caching of environment check results is provided automatically, you do not have to implement caching. | ||
|
|
||
| When introducing an environment check, the corresponding module must add the environment check's entry point to the `#gm4:evaluate_echecks` function tag. | ||
| Upon completion of the test (failure or success), the environment check needs to add a `result` object to its entry in the `gm4:log echeck` storage. | ||
|
|
||
| For example, the test with entry point located at `gm4:echeck/non_player_entity_has_score` may indicate a test failure as follows | ||
| ```mcfunction | ||
| data modify storage gm4:log echecks[{echeck_id:"gm4:echeck/non_player_entity_has_score"}].result set value {passed:0,probable_cause:"This may be caused by the Paper/Spigot setting 'scoreboards.allow-non-player-entities-on-scoreboards=false'."} | ||
| ``` | ||
| Or a test success as | ||
| ```mcfunction | ||
| data modify storage gm4:log echecks[{echeck_id:"gm4:echeck/non_player_entity_has_score"}].result set value {passed:1,probable_cause:""} | ||
| ``` | ||
|
|
||
| The `result.probable_cause` is shown to the user in chat in case the test fails. | ||
|
|
||
| For a textbook example of an environment check, inspect `gm4:non_player_entity_has_score` in `base`. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This feels really weird and hacky. The NBT objects in
echecksdon't have the same shape as what is expected byqueue. This could cause subtle bugs in the future.This command also completely overwrites the
queuefield. That feels wrong and might cause problems. For example GM4 base log printing is already delayed to wait for at least one player. Environment checks could finish in between and cause the normal logs to be overwritten.I would suggest adding a separate recursive function that iterates over the echecks list, or alternatively appending to the existing queue and making sure that it runs a second time if necessary.