From 37268060a21f48b8696ee86d75458e47f0df31ae Mon Sep 17 00:00:00 2001 From: Rares Bozga Date: Fri, 9 Jan 2026 12:00:54 +0200 Subject: [PATCH 1/2] Initial variant of atomicity --- scripts/storyboard/ch1/ch1_1_preassign.dsc | 4 ++ .../dialogue/dialogue_npc_kobayashi.dsc | 2 + .../dialogue/dialogue_npc_patchouli.dsc | 2 + .../dialogue/dialogue_npc_ryuko.dsc | 2 + .../storyboard/intro/intro_interactions.dsc | 6 +++ .../tasks/storyboard_player_tasks.dsc | 39 +++++++++++++++++++ 6 files changed, 55 insertions(+) diff --git a/scripts/storyboard/ch1/ch1_1_preassign.dsc b/scripts/storyboard/ch1/ch1_1_preassign.dsc index 45afbaa..fea857d 100644 --- a/scripts/storyboard/ch1/ch1_1_preassign.dsc +++ b/scripts/storyboard/ch1/ch1_1_preassign.dsc @@ -34,6 +34,7 @@ ch1_1_marie_interact: 1: click trigger: script: + - run storyboard_player_begin_atomic_sequence def.queue: def.player: - if != null: - stop - engage player duration:999999s @@ -97,9 +98,11 @@ ch1_1_marie_interact: - run storyboard_npc_state_set def.player: def.name:marie def.key:opinion def.value:-1 - zap 2 - disengage player + - run storyboard_player_end_atomic_sequence def.queue: def.player: 2: click trigger: script: + - run storyboard_player_begin_atomic_sequence def.queue: def.player: - if != null: - stop - engage player duration:999999s @@ -235,3 +238,4 @@ ch1_1_marie_interact: - inventory update - zap 3 - disengage player + - run storyboard_player_end_atomic_sequence def.queue: def.player: diff --git a/scripts/storyboard/dialogue/dialogue_npc_kobayashi.dsc b/scripts/storyboard/dialogue/dialogue_npc_kobayashi.dsc index 632faf6..b3d252b 100644 --- a/scripts/storyboard/dialogue/dialogue_npc_kobayashi.dsc +++ b/scripts/storyboard/dialogue/dialogue_npc_kobayashi.dsc @@ -14,6 +14,7 @@ dialogue_npc_kobayashi: 1: click trigger: script: + - run storyboard_player_begin_atomic_sequence def.queue: def.player: - if != null: - stop - engage player @@ -45,3 +46,4 @@ dialogue_npc_kobayashi: - ~run textbox_write def.player: def.queue: "def.line3s:Indeed, luv." - wait 1s - disengage player + - run storyboard_player_end_atomic_sequence def.queue: def.player: diff --git a/scripts/storyboard/dialogue/dialogue_npc_patchouli.dsc b/scripts/storyboard/dialogue/dialogue_npc_patchouli.dsc index a65c9a5..9a259cb 100644 --- a/scripts/storyboard/dialogue/dialogue_npc_patchouli.dsc +++ b/scripts/storyboard/dialogue/dialogue_npc_patchouli.dsc @@ -14,6 +14,7 @@ dialogue_npc_patchouli: 1: click trigger: script: + - run storyboard_player_begin_atomic_sequence def.queue: def.player: - if != null: - stop - engage player @@ -23,3 +24,4 @@ dialogue_npc_patchouli: - wait 1s - disengage player - ratelimit 10t + - run storyboard_player_end_atomic_sequence def.queue: def.player: diff --git a/scripts/storyboard/dialogue/dialogue_npc_ryuko.dsc b/scripts/storyboard/dialogue/dialogue_npc_ryuko.dsc index d2343cb..33d56ee 100644 --- a/scripts/storyboard/dialogue/dialogue_npc_ryuko.dsc +++ b/scripts/storyboard/dialogue/dialogue_npc_ryuko.dsc @@ -14,6 +14,7 @@ dialogue_npc_ryuko: 1: click trigger: script: + - run storyboard_player_begin_atomic_sequence def.queue: def.player: - if != null: - stop - engage player @@ -29,3 +30,4 @@ dialogue_npc_ryuko: - wait 1s - disengage player - ratelimit 10t + - run storyboard_player_end_atomic_sequence def.queue: def.player: diff --git a/scripts/storyboard/intro/intro_interactions.dsc b/scripts/storyboard/intro/intro_interactions.dsc index 16a90fd..4145a2f 100644 --- a/scripts/storyboard/intro/intro_interactions.dsc +++ b/scripts/storyboard/intro/intro_interactions.dsc @@ -15,11 +15,13 @@ intro_interact_posters_task: debug: false type: task script: + - run storyboard_player_begin_atomic_sequence def.queue: def.player: - ~run textbox_write def.player: def.queue: "def.line3s:Book-related posters are on the wall." - ~run textbox_write def.player: def.queue: "def.line3s:<&o><&dq>Screw that. I'm running away.<&dq>" - ~run textbox_write def.player: def.queue: def.line3s:<&o><&dq>Where?<&dq> - ~run textbox_write def.player: def.queue: "def.line3s:<&o><&dq>Dunno. Do you want to come?<&dq>" - ~run textbox_write def.player: def.queue: "def.line3s:<&o><&dq>Yes,<&dq> I said without thinking." + - run storyboard_player_end_atomic_sequence def.queue: def.player: # Cirno intro_interact_cirno: @@ -38,8 +40,10 @@ intro_interact_cirno_task: debug: false type: task script: + - run storyboard_player_begin_atomic_sequence def.queue: def.player: - ~run textbox_write def.player: def.queue: "def.line3s:A quality, soft plushie of a beloved$$nlcharacter." - ~run textbox_write def.player: def.queue: "def.line3s:It seems familiar, as if there are a$$nlsubstantial amount of images circulating$$nlaround with this character." + - run storyboard_player_end_atomic_sequence def.queue: def.player: # Laptop intro_interact_laptop: @@ -58,6 +62,7 @@ intro_interact_laptop_task: debug: false type: task script: + - run storyboard_player_begin_atomic_sequence def.queue: def.player: - ~run textbox_write def.player: def.queue: "def.line3s:It looks like a game is booted up.$$nlYou can see a city, and it looks like..." - ~run textbox_write def.player: def.queue: "def.line3s:. . ." - ~run textbox_write def.player: def.queue: "def.line3s:It's you!$$nl. . .$$nlWell, it's your character." @@ -197,3 +202,4 @@ intro_interact_laptop_task_role_callback: - adjust show_to_players - flag intro:done - execute as_player player: spawn + - run storyboard_player_end_atomic_sequence def.queue: def.player: diff --git a/scripts/storyboard/tasks/storyboard_player_tasks.dsc b/scripts/storyboard/tasks/storyboard_player_tasks.dsc index 9023fbd..1295fd1 100644 --- a/scripts/storyboard/tasks/storyboard_player_tasks.dsc +++ b/scripts/storyboard/tasks/storyboard_player_tasks.dsc @@ -60,6 +60,36 @@ storyboard_player_unfreeze: - adjust walk_speed: - flag storyboard_freeze_speed:! +# Marks the script after this task as an atomic sequence, meaning that +# the script either fully completes or is restored back to this point. +# This task does not ensure the atomicity, instead it will block any +# futher executions of the given script (deduced from the queue) until +# storyboard_player_end_atomic_sequence is called, or until the player +# logs off (which basically negates the atomicity). The developer must +# ensure that the script enclosed by the begin and end tasks is atomic. +storyboard_player_begin_atomic_sequence: + debug: false + type: task + definitions: queue|player + script: + - announce to_ops <[queue].script.name> + - if <[player].flag[storyboard_atomic].if_null[].contains[<[queue].script.name>]>: + - queue <[queue]> stop + - stop + - flag <[player]> storyboard_atomic:<[player].flag[storyboard_atomic].if_null[].with[<[queue].script.name>].as[]> + +# Ends the atomic sequence above this task. See the sibling task +# storyboard_player_begin_atomic_sequence for more details. +storyboard_player_end_atomic_sequence: + debug: false + type: task + definitions: queue|player + script: + - if !<[player].flag[storyboard_atomic].if_null[].contains[<[queue].script.name>]>: + - debug error "Tried ending storyboard atomic sequence <[queue].script.name> before storyboard_player_begin_atomic_sequence was called! (Player UUID <[player].uuid>)" + - stop + - flag <[player]> storyboard_atomic:<[player].flag[storyboard_atomic].if_null[].exclude[<[queue].script.name>]> + ## Internal only! storyboard_player_freeze_check: debug: false @@ -68,3 +98,12 @@ storyboard_player_freeze_check: on player joins: - if : - run storyboard_player_unfreeze def.player: + +storyboard_player_atomic_sequence_disconnect_handler: + debug: false + type: world + events: + on player quit: + - flag storyboard_atomic:! + on player joins: + - flag storyboard_atomic:! From 01a4e7414c30881711acf0a87d6414a2daf14413 Mon Sep 17 00:00:00 2001 From: Rares Bozga Date: Fri, 9 Jan 2026 13:24:07 +0200 Subject: [PATCH 2/2] Various bugfixes --- scripts/lib/textbox.dsc | 50 +++++++++++-------- scripts/misc/compatibility_check.dsc | 2 +- .../storyboard/intro/intro_interactions.dsc | 5 ++ .../tasks/storyboard_player_tasks.dsc | 3 +- scripts/tabcomplete/tabcomplete_data.dsc | 3 ++ 5 files changed, 39 insertions(+), 24 deletions(-) diff --git a/scripts/lib/textbox.dsc b/scripts/lib/textbox.dsc index 2b47816..b0e715b 100644 --- a/scripts/lib/textbox.dsc +++ b/scripts/lib/textbox.dsc @@ -35,7 +35,7 @@ textbox_write: - queue stop <[queue]> - run textbox_flush def.player:<[player]> - stop - - define lines <[line3s].split[$$nl].parse_tag[<[parse_value].trim>]> + - define lines <[line3s].split[$$nl].parse_tag[<[parse_value].trim.replace[<&0>].with[<&6>]>]> - flag <[player]> textbox_state:writing - flag <[player]> textbox_input:<[lines]> - flag <[player]> textbox_lines:<[lines].size> @@ -57,7 +57,7 @@ textbox_write: - stop - if !<[player].is_online>: - stop - - bossbar update textbox_<[player].uuid>_<[loop_index]> title:<[line].substring[1,<[value]>]> + - bossbar update textbox_<[player].uuid>_<[loop_index]> title:<&6><&l><[line].substring[1,<[value]>]> - if <[value].sub[1].mod[3]> == 0: - playsound sound:textbox.text <[player]> custom pitch: volume:|sound_textbox_volume].div[100].if_null[1]> - wait <[write_speed]>t @@ -100,7 +100,7 @@ textbox_skip: - bossbar create textbox_<[player].uuid>_<[value]> players:<[player]> title: - define lines <[player].flag[textbox_input]> - foreach <[lines]> as:line: - - bossbar update textbox_<[player].uuid>_<[loop_index]> title:<[line]> + - bossbar update textbox_<[player].uuid>_<[loop_index]> title:<&6><&l><[line]> - flag <[player]> textbox_state:continue # Clears textbox and flushes all flag memory values @@ -208,12 +208,12 @@ textbox_handle_click: - ratelimit 5t - else if <[state]> == continue: - determine cancelled passively - - playsound sound:textbox.close custom volume:|sound_textbox_volume].div[100].if_null[1]> + - playsound sound:textbox.close custom volume:|sound_textbox_volume].div[100].if_null[1]> - ~run textbox_flush def.player: - ratelimit 10t - else if <[state]> == choice: - determine cancelled passively - - playsound sound:input.ok custom volume:|sound_textbox_volume].div[100].if_null[1]> + - playsound sound:input.ok custom volume:|sound_textbox_volume].div[100].if_null[1]> - flag textbox_choice_select: - ~run textbox_flush def.player: - ratelimit 10t @@ -250,7 +250,13 @@ textbox_choice: - teleport <[player]> <[player].location.below.above.with_y[<[player].location.below.above.y.round_down>]> - else: - stop - - waituntil <[player].flag[textbox_state].if_null[null]> == null + - waituntil <[player].flag[textbox_state].if_null[null]> == null || !<[player].is_online> + - if !<[player].is_online>: + - if <[queue].if_null[null]> != null: + - debug log "[Textbox] Choice; cancelled queue <[queue].numeric_id><&at><[queue].script.name> for <[player].name>; offline" + - queue stop <[queue]> + - run textbox_flush def.player:<[player]> + - stop - ~run textbox_flush def.player:<[player]> - flag <[player]> textbox_state:choice - flag <[player]> textbox_choices:].with[current].as[left]> @@ -284,35 +290,35 @@ textbox_internal_choice_select: - bossbar create textbox_<[player].uuid>_bottom players:<[player]> title: - define choices <[player].flag[textbox_choices].get[data]> # - - define left <&0><&l><[choices].get[left].get[text].if_null[null]> - - define right <&0><&l><[choices].get[right].get[text].if_null[null]> - - define top <&0><&l><[choices].get[top].get[text].if_null[null]> - - define bottom <&0><&l><[choices].get[bottom].get[text].if_null[null]> + - define left <&6><&l><[choices].get[left].get[text].if_null[null]> + - define right <&6><&l><[choices].get[right].get[text].if_null[null]> + - define top <&6><&l><[choices].get[top].get[text].if_null[null]> + - define bottom <&6><&l><[choices].get[bottom].get[text].if_null[null]> # - if <[choice_dir]> == left: - - if <[left]> == <&0><&l>null: + - if <[left]> == <&6><&l>null: - stop - - define left "<&4>❤ <&0><&l><[left]>" + - define left "<&4>❤ <&6><&l><[left]>" - else if <[choice_dir]> == right: - - if <[right]> == <&0><&l>null: + - if <[right]> == <&6><&l>null: - stop - - define right "<&4>❤ <&0><&l><[right]>" + - define right "<&4>❤ <&6><&l><[right]>" - else if <[choice_dir]> == top: - - if <[top]> == <&0><&l>null: + - if <[top]> == <&6><&l>null: - stop - - define top "<&4>❤ <&0><&l><[top]>" + - define top "<&4>❤ <&6><&l><[top]>" - else: - - if <[bottom]> == <&0><&l>null: + - if <[bottom]> == <&6><&l>null: - stop - - define bottom "<&4>❤ <&0><&l><[bottom]>" + - define bottom "<&4>❤ <&6><&l><[bottom]>" # - define mid_padding ].repeat[].sub[<[right].strip_color.length>]>]> # - - if <[top]> != <&0><&l>null: + - if <[top]> != <&6><&l>null: - bossbar update textbox_<[player].uuid>_top title:<[top]> - - if <[left]> != <&0><&l>null || <[right]> != <&0><&l>null: + - if <[left]> != <&6><&l>null || <[right]> != <&6><&l>null: - bossbar update textbox_<[player].uuid>_mid title:<[left]><[mid_padding]><[right]> - - if <[bottom]> != <&0><&l>null: + - if <[bottom]> != <&6><&l>null: - bossbar update textbox_<[player].uuid>_bottom title:<[bottom]> - flag <[player]> textbox_choices:].with[current].as[<[choice_dir]>]> - - playsound BLOCK_NOTE_BLOCK_BIT <[player]> pitch:2 volume:|sound_textbox_volume].div[100].if_null[1]> + - playsound BLOCK_NOTE_BLOCK_BIT <[player]> pitch:2 volume:|sound_textbox_volume].div[100].if_null[1]> \ No newline at end of file diff --git a/scripts/misc/compatibility_check.dsc b/scripts/misc/compatibility_check.dsc index d1ca357..df45608 100644 --- a/scripts/misc/compatibility_check.dsc +++ b/scripts/misc/compatibility_check.dsc @@ -22,7 +22,7 @@ compatibility_check_world: after player joins: - if |general_ignore_version_compatibility_check]>: - stop - - define player_version + - define player_version - define server_version - if |<[server_version]>]> == -1: - wait 5s diff --git a/scripts/storyboard/intro/intro_interactions.dsc b/scripts/storyboard/intro/intro_interactions.dsc index 4145a2f..e6c8174 100644 --- a/scripts/storyboard/intro/intro_interactions.dsc +++ b/scripts/storyboard/intro/intro_interactions.dsc @@ -78,6 +78,11 @@ intro_interact_laptop_task_name_callback: script: - define __player <[player]> - define name <[input].substring[1,24]> + - if ]>: + - narrate targets:<[player]> "<&c>That RP name is already taken. Try a different one!" + - wait 1s + - run anvil_input def.player: "def.prompt:Character Name" def.callback:intro_interact_laptop_task_name_callback + - stop - execute as_player player:<[player]> "rpname <[name]>" - ~run textbox_write def.player: def.queue: def.line3s:<[name]> - ~run textbox_write def.player: def.queue: "def.line3s:How nice!" diff --git a/scripts/storyboard/tasks/storyboard_player_tasks.dsc b/scripts/storyboard/tasks/storyboard_player_tasks.dsc index 1295fd1..c44ca20 100644 --- a/scripts/storyboard/tasks/storyboard_player_tasks.dsc +++ b/scripts/storyboard/tasks/storyboard_player_tasks.dsc @@ -72,7 +72,6 @@ storyboard_player_begin_atomic_sequence: type: task definitions: queue|player script: - - announce to_ops <[queue].script.name> - if <[player].flag[storyboard_atomic].if_null[].contains[<[queue].script.name>]>: - queue <[queue]> stop - stop @@ -88,6 +87,8 @@ storyboard_player_end_atomic_sequence: - if !<[player].flag[storyboard_atomic].if_null[].contains[<[queue].script.name>]>: - debug error "Tried ending storyboard atomic sequence <[queue].script.name> before storyboard_player_begin_atomic_sequence was called! (Player UUID <[player].uuid>)" - stop + - waituntil ! + - wait 5t - flag <[player]> storyboard_atomic:<[player].flag[storyboard_atomic].if_null[].exclude[<[queue].script.name>]> ## Internal only! diff --git a/scripts/tabcomplete/tabcomplete_data.dsc b/scripts/tabcomplete/tabcomplete_data.dsc index 2252cd3..c41cedb 100644 --- a/scripts/tabcomplete/tabcomplete_data.dsc +++ b/scripts/tabcomplete/tabcomplete_data.dsc @@ -4,7 +4,10 @@ tabcomplete_config: groups: default: commands: + # please keep these here... - plugins + - denizenclickable + # anything else - sit - lay - crawl