|
| 1 | +# global.mcb — Minecraft 26.3. Shared `animated_java:global/*` functions: load/tick |
| 2 | +# dispatch, the entity-UUID helper (gu), the storage-backed per-entity data manager, |
| 3 | +# and the interaction/attack advancement plumbing. |
| 4 | +# |
| 5 | +# Changes from 26.2/global.mcb: |
| 6 | +# - Advancement entity conditions are a loot condition instead of a bare entity |
| 7 | +# predicate. |
| 8 | +# - Loot functions name their kind with `type` instead of `function`. |
| 9 | + |
| 10 | +import ./global.mcbt |
| 11 | + |
| 12 | +dir global { |
| 13 | + function on_load minecraft:load { |
| 14 | + # Initialize Scoreboards |
| 15 | + scoreboard objectives add <%OBJECTIVES.I()%> dummy |
| 16 | + scoreboard objectives add <%OBJECTIVES.ID()%> dummy |
| 17 | + scoreboard objectives add <%OBJECTIVES.IS_RIG_LOADED()%> dummy |
| 18 | + scoreboard objectives add <%OBJECTIVES.TWEEN_DURATION()%> dummy |
| 19 | + |
| 20 | + scoreboard players add aj.last_id <%OBJECTIVES.ID()%> 0 |
| 21 | + |
| 22 | + # Enforce loading order. |
| 23 | + function *global/gu/on_load |
| 24 | + function *global/data_manager/on_load |
| 25 | + function #*global/on_load |
| 26 | + |
| 27 | + IF (debug_mode) { |
| 28 | + scoreboard players reset * <%OBJECTIVES.IS_RIG_LOADED()%> |
| 29 | + execute as @e[type=item_display,tag=<%TAGS.GLOBAL_ROOT()%>] at @s run function *global/root/on_load |
| 30 | + } |
| 31 | + } |
| 32 | + |
| 33 | + function on_tick minecraft:tick { |
| 34 | + execute as @e[type=item_display,tag=<%TAGS.GLOBAL_ROOT()%>] at @s run function *global/root/on_tick |
| 35 | + } |
| 36 | + |
| 37 | + tag functions on_load { |
| 38 | + <%blueprint_id%>/on_load |
| 39 | + } |
| 40 | + |
| 41 | + dir root { |
| 42 | + function on_tick { |
| 43 | + data_manager prep read |
| 44 | + IF (debug_mode) { |
| 45 | + execute unless score @s <%OBJECTIVES.IS_RIG_LOADED()%> matches 1 run function *global/root/on_load |
| 46 | + } |
| 47 | + function *global/root/run_project_tick with storage <%temp_storage%> entry.data |
| 48 | + } |
| 49 | + |
| 50 | + function run_project_tick { |
| 51 | + $function $(blueprint_id)/root/on_tick |
| 52 | + } |
| 53 | + |
| 54 | + IF (debug_mode) { |
| 55 | + function on_load { |
| 56 | + # Check if the rig is outdated by comparing the function's rig_hash of the rig to the rig_hash stored in the entity data. |
| 57 | + execute if function animated_java:global/util/is_rig_outdated run block outdated_warning/modify_rig { |
| 58 | + data remove storage <%temp_storage%> args |
| 59 | + function *global/gu/get_entity_uuid_string |
| 60 | + data modify storage <%temp_storage%> args.uuid set from storage <%gu_storage%> out |
| 61 | + # Get position |
| 62 | + execute store result storage <%temp_storage%> args.x double 1 run data get entity @s Pos[0] 1 |
| 63 | + execute store result storage <%temp_storage%> args.y double 1 run data get entity @s Pos[1] 1 |
| 64 | + execute store result storage <%temp_storage%> args.z double 1 run data get entity @s Pos[2] 1 |
| 65 | + |
| 66 | + # No need to read here, since is_rig_outdated already reads the data. |
| 67 | + # data_manager prep read |
| 68 | + |
| 69 | + # Get export namespace |
| 70 | + data modify storage <%temp_storage%> args.blueprint_id set from storage <%temp_storage%> entry.data.blueprint_id |
| 71 | + # Overwrite the rig hash so the warning doesn't show again. |
| 72 | + data modify storage <%temp_storage%> entry.data.rig_hash set value '<%rig_hash%>' |
| 73 | + data_manager write |
| 74 | + block run_print { with storage <%temp_storage%> entry.data |
| 75 | + $function $(blueprint_id)/zzz/outdated_rig_warning with storage <%temp_storage%> args |
| 76 | + } |
| 77 | + |
| 78 | + # Loop over rig entities and glow them red. |
| 79 | + data modify storage <%temp_storage%> list set from storage <%temp_storage%> entry.data.uuids |
| 80 | + block loop { |
| 81 | + data modify storage <%temp_storage%> args.uuid set from storage <%temp_storage%> list[-1] |
| 82 | + data remove storage <%temp_storage%> list[-1] |
| 83 | + block as_uuid { with storage <%temp_storage%> args |
| 84 | + $data merge entity $(uuid) {Glowing: 1b, glow_color_override: <%0xff0000%>} |
| 85 | + } |
| 86 | + |
| 87 | + execute store result score #length <%OBJECTIVES.I()%> run data get storage <%temp_storage%> list |
| 88 | + execute if score #length <%OBJECTIVES.I()%> matches 1.. run function ^0 |
| 89 | + } |
| 90 | + |
| 91 | + summon minecraft:text_display ~ ~ ~ { \ |
| 92 | + Tags:[ \ |
| 93 | + '<%TAGS.GLOBAL_ENTITY()%>', \ |
| 94 | + '<%TAGS.OUTDATED_RIG_TEXT_DISPLAY()%>', \ |
| 95 | + '<%TAGS.NEW()%>' \ |
| 96 | + ], \ |
| 97 | + text:<%TELLRAW.RIG_OUTDATED_TEXT_DISPLAY()%>, \ |
| 98 | + alignment: 'center', \ |
| 99 | + billboard: 'vertical', \ |
| 100 | + shadow: true, \ |
| 101 | + transformation:{ \ |
| 102 | + translation:[0f,<%boundingBox[1]/16%>f,0f], \ |
| 103 | + left_rotation:[0f,0f,0f,1f], \ |
| 104 | + right_rotation:[0f,0f,0f,1f], \ |
| 105 | + scale:[1f,1f,1f] \ |
| 106 | + } \ |
| 107 | + } |
| 108 | + |
| 109 | + ride @n[ \ |
| 110 | + type=minecraft:text_display, \ |
| 111 | + tag=<%TAGS.OUTDATED_RIG_TEXT_DISPLAY()%>, tag=<%TAGS.NEW()%>, \ |
| 112 | + distance=..1 \ |
| 113 | + ] mount @s |
| 114 | + |
| 115 | + tag @n[ \ |
| 116 | + type=minecraft:text_display, \ |
| 117 | + tag=<%TAGS.OUTDATED_RIG_TEXT_DISPLAY()%>, tag=<%TAGS.NEW()%>, \ |
| 118 | + distance=..1 \ |
| 119 | + ] remove <%TAGS.NEW()%> |
| 120 | + } |
| 121 | + scoreboard players set @s <%OBJECTIVES.IS_RIG_LOADED()%> 1 |
| 122 | + } |
| 123 | + } |
| 124 | + } |
| 125 | + |
| 126 | + dir remove { |
| 127 | + # Removes every entity related to Animated Java. |
| 128 | + function everything { |
| 129 | + kill @e[tag=<%TAGS.GLOBAL_ENTITY()%>] |
| 130 | + } |
| 131 | + |
| 132 | + function entity_stack { |
| 133 | + execute on passengers if entity @s[type=!player] run function ^0 |
| 134 | + kill @s |
| 135 | + } |
| 136 | + |
| 137 | + function entity_stack_by_uuid { |
| 138 | + #ARGS: {uuid: string} |
| 139 | + $execute as $(uuid) run function ./entity_stack |
| 140 | + } |
| 141 | + |
| 142 | + # Removes locators and cameras owned by the rig, even if they're not included in the currently loaded export. |
| 143 | + function outdated_rig { |
| 144 | + data_manager prep read |
| 145 | + |
| 146 | + data remove storage <%temp_storage%> args |
| 147 | + data remove storage <%temp_storage%> uuids |
| 148 | + data modify storage <%temp_storage%> uuids set from entity @s data.uuids |
| 149 | + execute store result score #aj.length <%OBJECTIVES.I()%> run data get storage <%temp_storage%> uuids |
| 150 | + |
| 151 | + execute if score #aj.length <%OBJECTIVES.I()%> matches 1.. run block loop_over_uuids { |
| 152 | + data modify storage <%temp_storage%> args.current_uuid set from storage <%temp_storage%> uuids[-1].uuid |
| 153 | + data remove storage <%temp_storage%> uuids[-1] |
| 154 | + function ./entity_stack_by_uuid with storage <%temp_storage%> args |
| 155 | + |
| 156 | + scoreboard players remove #aj.length <%OBJECTIVES.I()%> 1 |
| 157 | + execute if score #aj.length <%OBJECTIVES.I()%> matches 1.. run function ^0 |
| 158 | + } |
| 159 | + |
| 160 | + function ./entity_stack |
| 161 | + } |
| 162 | + } |
| 163 | + |
| 164 | + dir util { |
| 165 | + # Recurses through the passengers of the context entity and appends their UUIDs to `storage <%temp_storage%> uuids`. |
| 166 | + function get_entity_stack_uuids { |
| 167 | + data remove storage <%temp_storage%> uuids |
| 168 | + execute on passengers run { |
| 169 | + function *global/gu/get_entity_uuid_string |
| 170 | + data modify storage <%temp_storage%> uuids append from storage <%gu_storage%> out |
| 171 | + execute on passengers run function ^0 |
| 172 | + } |
| 173 | + } |
| 174 | + # Returns 1 if the rig is outdated, else returns 0. |
| 175 | + function is_rig_outdated { |
| 176 | + data_manager prep read |
| 177 | + return run block { with storage <%temp_storage%> entry.data |
| 178 | + # REVIEW - The replace here is a bit hacky. |
| 179 | + # Because this is a core function, I need to create a generic version of |
| 180 | + # project_storage that uses a macro to get the blueprint ID instead of hardcoding it. |
| 181 | + $execute if data storage <%project_storage.replace(blueprint_id, '$(blueprint_id)')%> {rig_hash:'$(rig_hash)'} run return 0 |
| 182 | + return 1 |
| 183 | + } |
| 184 | + } |
| 185 | + } |
| 186 | + |
| 187 | + # Thanks Gibbsly for the original code! https://github.com/gibbsly/gu |
| 188 | + dir gu { |
| 189 | + function on_load { |
| 190 | + scoreboard players set 256 <%OBJECTIVES.I()%> 256 |
| 191 | + data modify storage <%gu_storage%> hex_chars set value \ |
| 192 | + <%JSON.stringify([...Array(0x100).keys()].map(v => {const x = v.toString(16); return x.length > 1 ? x : '0' + x}))%> |
| 193 | + } |
| 194 | + |
| 195 | + item_modifier entity_uuid { |
| 196 | + "type": "minecraft:set_name", |
| 197 | + "entity": "this", |
| 198 | + "target": "item_name", |
| 199 | + "name": {"selector": "@s"} |
| 200 | + } |
| 201 | + |
| 202 | + function get_entity_uuid_string { |
| 203 | + execute if entity @s[type=!minecraft:player] run return run { |
| 204 | + summon minecraft:item_display ~ ~ ~ {UUID:uuid('21e0f4fa-2970-4cba-be91-6a50cd9dd0eb'),item:{id:'minecraft:pufferfish'}} |
| 205 | + item modify entity 21e0f4fa-2970-4cba-be91-6a50cd9dd0eb container.0 animated_java:global/gu/entity_uuid |
| 206 | + data modify storage <%gu_storage%> out set from entity 21e0f4fa-2970-4cba-be91-6a50cd9dd0eb item.components.minecraft:item_name.insertion |
| 207 | + kill 21e0f4fa-2970-4cba-be91-6a50cd9dd0eb |
| 208 | + } |
| 209 | + |
| 210 | + data modify storage <%gu_storage%> temp set value {0:0,1:0,2:0,3:0,4:0,5:0,6:0,7:0,8:0,9:0,a:0,b:0,c:0,d:0,e:0,f:0} |
| 211 | + data modify storage <%gu_storage%> in set from entity @s UUID |
| 212 | + |
| 213 | + execute store result score 0= <%OBJECTIVES.I()%> store result score 1= <%OBJECTIVES.I()%> run data get storage <%gu_storage%> in[0] |
| 214 | + execute store result storage <%gu_storage%> temp.0 int 1 run scoreboard players operation 0= <%OBJECTIVES.I()%> %= 256 <%OBJECTIVES.I()%> |
| 215 | + execute store result score 2= <%OBJECTIVES.I()%> run scoreboard players operation 1= <%OBJECTIVES.I()%> /= 256 <%OBJECTIVES.I()%> |
| 216 | + execute store result storage <%gu_storage%> temp.1 int 1 run scoreboard players operation 1= <%OBJECTIVES.I()%> %= 256 <%OBJECTIVES.I()%> |
| 217 | + execute store result score 3= <%OBJECTIVES.I()%> run scoreboard players operation 2= <%OBJECTIVES.I()%> /= 256 <%OBJECTIVES.I()%> |
| 218 | + execute store result storage <%gu_storage%> temp.2 int 1 run scoreboard players operation 2= <%OBJECTIVES.I()%> %= 256 <%OBJECTIVES.I()%> |
| 219 | + execute store result storage <%gu_storage%> temp.3 int 1 run scoreboard players operation 3= <%OBJECTIVES.I()%> /= 256 <%OBJECTIVES.I()%> |
| 220 | + |
| 221 | + execute store result score 0= <%OBJECTIVES.I()%> store result score 1= <%OBJECTIVES.I()%> run data get storage <%gu_storage%> in[1] |
| 222 | + execute store result storage <%gu_storage%> temp.4 int 1 run scoreboard players operation 0= <%OBJECTIVES.I()%> %= 256 <%OBJECTIVES.I()%> |
| 223 | + execute store result score 2= <%OBJECTIVES.I()%> run scoreboard players operation 1= <%OBJECTIVES.I()%> /= 256 <%OBJECTIVES.I()%> |
| 224 | + execute store result storage <%gu_storage%> temp.5 int 1 run scoreboard players operation 1= <%OBJECTIVES.I()%> %= 256 <%OBJECTIVES.I()%> |
| 225 | + execute store result score 3= <%OBJECTIVES.I()%> run scoreboard players operation 2= <%OBJECTIVES.I()%> /= 256 <%OBJECTIVES.I()%> |
| 226 | + execute store result storage <%gu_storage%> temp.6 int 1 run scoreboard players operation 2= <%OBJECTIVES.I()%> %= 256 <%OBJECTIVES.I()%> |
| 227 | + execute store result storage <%gu_storage%> temp.7 int 1 run scoreboard players operation 3= <%OBJECTIVES.I()%> /= 256 <%OBJECTIVES.I()%> |
| 228 | + |
| 229 | + execute store result score 0= <%OBJECTIVES.I()%> store result score 1= <%OBJECTIVES.I()%> run data get storage <%gu_storage%> in[2] |
| 230 | + execute store result storage <%gu_storage%> temp.8 int 1 run scoreboard players operation 0= <%OBJECTIVES.I()%> %= 256 <%OBJECTIVES.I()%> |
| 231 | + execute store result score 2= <%OBJECTIVES.I()%> run scoreboard players operation 1= <%OBJECTIVES.I()%> /= 256 <%OBJECTIVES.I()%> |
| 232 | + execute store result storage <%gu_storage%> temp.9 int 1 run scoreboard players operation 1= <%OBJECTIVES.I()%> %= 256 <%OBJECTIVES.I()%> |
| 233 | + execute store result score 3= <%OBJECTIVES.I()%> run scoreboard players operation 2= <%OBJECTIVES.I()%> /= 256 <%OBJECTIVES.I()%> |
| 234 | + execute store result storage <%gu_storage%> temp.a int 1 run scoreboard players operation 2= <%OBJECTIVES.I()%> %= 256 <%OBJECTIVES.I()%> |
| 235 | + execute store result storage <%gu_storage%> temp.b int 1 run scoreboard players operation 3= <%OBJECTIVES.I()%> /= 256 <%OBJECTIVES.I()%> |
| 236 | + |
| 237 | + execute store result score 0= <%OBJECTIVES.I()%> store result score 1= <%OBJECTIVES.I()%> run data get storage <%gu_storage%> in[3] |
| 238 | + execute store result storage <%gu_storage%> temp.c int 1 run scoreboard players operation 0= <%OBJECTIVES.I()%> %= 256 <%OBJECTIVES.I()%> |
| 239 | + execute store result score 2= <%OBJECTIVES.I()%> run scoreboard players operation 1= <%OBJECTIVES.I()%> /= 256 <%OBJECTIVES.I()%> |
| 240 | + execute store result storage <%gu_storage%> temp.d int 1 run scoreboard players operation 1= <%OBJECTIVES.I()%> %= 256 <%OBJECTIVES.I()%> |
| 241 | + execute store result score 3= <%OBJECTIVES.I()%> run scoreboard players operation 2= <%OBJECTIVES.I()%> /= 256 <%OBJECTIVES.I()%> |
| 242 | + execute store result storage <%gu_storage%> temp.e int 1 run scoreboard players operation 2= <%OBJECTIVES.I()%> %= 256 <%OBJECTIVES.I()%> |
| 243 | + execute store result storage <%gu_storage%> temp.f int 1 run scoreboard players operation 3= <%OBJECTIVES.I()%> /= 256 <%OBJECTIVES.I()%> |
| 244 | + |
| 245 | + block { with storage <%gu_storage%> temp |
| 246 | + REPEAT (0, 15) as i { |
| 247 | + $data modify storage <%gu_storage%> temp.<%i.toString(16)%> set from storage <%gu_storage%> hex_chars[$(<%i.toString(16)%>)] |
| 248 | + } |
| 249 | + } |
| 250 | + |
| 251 | + block { with storage <%gu_storage%> temp |
| 252 | + $data modify storage <%gu_storage%> out set value "$(3)$(2)$(1)$(0)-$(7)$(6)-$(5)$(4)-$(b)$(a)-$(9)$(8)$(f)$(e)$(d)$(c)" |
| 253 | + } |
| 254 | + } |
| 255 | + } |
| 256 | + |
| 257 | + # Storage-based per-entity NBT storage. Thanks Xanbelor for the concept! |
| 258 | + dir data_manager { |
| 259 | + function on_load { |
| 260 | + scoreboard players add #aj.data_manager.index <%OBJECTIVES.I()%> 0 |
| 261 | + } |
| 262 | + |
| 263 | + function on_tick minecraft:tick { |
| 264 | + execute store result storage <%temp_storage%> args.id int 1 run scoreboard players get #aj.data_manager.index <%OBJECTIVES.I()%> |
| 265 | + block { with storage <%temp_storage%> args |
| 266 | + $data modify storage <%temp_storage%> args.uuid set from storage <%data_storage%> "$(id)".uuid |
| 267 | + scoreboard players set #success <%OBJECTIVES.I()%> 0 |
| 268 | + execute if data storage <%temp_storage%> args.uuid run { with storage <%temp_storage%> args |
| 269 | + $execute store success score #success <%OBJECTIVES.I()%> if score $(uuid) <%OBJECTIVES.ID()%> matches 1.. |
| 270 | + $execute if score #success <%OBJECTIVES.I()%> matches 0 run data remove storage <%data_storage%> "$(id)" |
| 271 | + } |
| 272 | + } |
| 273 | + scoreboard players add #aj.data_manager.index <%OBJECTIVES.I()%> 1 |
| 274 | + execute \ |
| 275 | + if score #aj.data_manager.index <%OBJECTIVES.I()%> > aj.last_id <%OBJECTIVES.ID()%> \ |
| 276 | + run scoreboard players set #aj.data_manager.index <%OBJECTIVES.I()%> 0 |
| 277 | + } |
| 278 | + |
| 279 | + function create_entry { |
| 280 | + $data modify storage <%data_storage%> "$(id)" set value {uuid: "$(uuid)", data: {}} |
| 281 | + } |
| 282 | + |
| 283 | + function read { |
| 284 | + data remove storage <%temp_storage%> entry |
| 285 | + $data modify storage <%temp_storage%> entry set from storage <%data_storage%> "$(id)" |
| 286 | + } |
| 287 | + |
| 288 | + function write { |
| 289 | + $data modify storage <%data_storage%> "$(id)" set from storage <%temp_storage%> entry |
| 290 | + } |
| 291 | + } |
| 292 | + |
| 293 | + dir interactions { |
| 294 | + REPEAT (['interaction', 'attack']) as direction { |
| 295 | + dir <%direction%> { |
| 296 | + advancement trigger { |
| 297 | + "criteria": { |
| 298 | + "player_<%direction%>_clicked_interaction_entity": { |
| 299 | + "trigger": "<%direction === 'interaction' ? 'minecraft:player_interacted_with_entity' : 'minecraft:player_hurt_entity'%>", |
| 300 | + "conditions": { |
| 301 | + "entity": { |
| 302 | + "type": "minecraft:entity_properties", |
| 303 | + "entity": "this", |
| 304 | + "predicate": { |
| 305 | + "minecraft:entity_type": "minecraft:interaction" |
| 306 | + } |
| 307 | + } |
| 308 | + } |
| 309 | + } |
| 310 | + }, |
| 311 | + "rewards": { |
| 312 | + "function": "<%context.namespace + ':' + context.path.join('/')%>/on" |
| 313 | + } |
| 314 | + } |
| 315 | + |
| 316 | + function on { |
| 317 | + advancement revoke @s only <%context.namespace + ':' + context.path.join('/')%>/trigger |
| 318 | + tag @s add <%TAGS.INTERACTING_PLAYER()%> |
| 319 | + execute \ |
| 320 | + as @e[type=interaction, tag=<%TAGS.GLOBAL_INTERACTION()%>, distance=..8] \ |
| 321 | + if data entity @s <%direction%> \ |
| 322 | + run function ./check |
| 323 | + tag @s remove <%TAGS.INTERACTING_PLAYER()%> |
| 324 | + } |
| 325 | + |
| 326 | + function check { |
| 327 | + execute store result score #gametime <%OBJECTIVES.I()%> run time query gametime |
| 328 | + execute \ |
| 329 | + store result score #timestamp <%OBJECTIVES.I()%> \ |
| 330 | + run data get entity @s <%direction%>.timestamp |
| 331 | + |
| 332 | + # Check that the interaction has a command to run, and |
| 333 | + # if this interaction is from the player being processed. |
| 334 | + scoreboard players set #check <%OBJECTIVES.I()%> 0 |
| 335 | + execute \ |
| 336 | + if score #timestamp <%OBJECTIVES.I()%> = #gametime <%OBJECTIVES.I()%> \ |
| 337 | + if data entity @s data.animated_java.on_<%direction === 'interaction' ? 'interact' : 'attack'%>_function \ |
| 338 | + store success score #check <%OBJECTIVES.I()%> \ |
| 339 | + on <%direction === 'interaction' ? 'target' : 'attacker'%> \ |
| 340 | + if entity @s[tag=<%TAGS.INTERACTING_PLAYER()%>] |
| 341 | + |
| 342 | + execute \ |
| 343 | + if score #check <%OBJECTIVES.I()%> matches 1 \ |
| 344 | + run function ./do |
| 345 | + } |
| 346 | + |
| 347 | + function do { |
| 348 | + scoreboard players set #check <%OBJECTIVES.I()%> 0 |
| 349 | + block execute { with entity @s data.animated_java |
| 350 | + $$(on_<%direction === 'interaction' ? 'interact' : 'attack'%>_function) |
| 351 | + scoreboard players set #check <%OBJECTIVES.I()%> 1 |
| 352 | + } |
| 353 | + execute if score #check <%OBJECTIVES.I()%> matches 0 run tellraw @a <%TELLRAW.INTERACTION_FUNCTION_FAILED(direction)%> |
| 354 | + # Only remove the interaction if it's consumed. |
| 355 | + data remove entity @s <%direction%> |
| 356 | + } |
| 357 | + } |
| 358 | + } |
| 359 | + } |
| 360 | +} |
0 commit comments