Paste #64273: syntax test

Date: 2020/01/17 08:14:14 UTC-08:00
Type: Denizen Script

View Raw Paste Download This Paste
Copy Link


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105


#todo
    #convert npc limit to map of profession/number and track the owned npc objects
    #implement npc death handling
    #todo add sensible spawn mechanic
    #clean up editing modes with a single action and id combination and change to choose command
mayor_script:
    type: world
    events:

        #gives mayor spawn item
        on player right clicks stone_bricks with wheat:
        - wait 1t
        - take iteminhand
        - drop mayor_placer <context.location>

        on player right clicks block with mayor_placer:
        #check if the player already has a mayor, if not take the spawn item and spawn the mayor
        - if !<player.has_flag[owned_npcs_mayor]>:
            - determine passively cancelled
            - wait 1t
            - take iteminhand
            - create player mayor <context.location.add[0,2,0]> save:mayor_obj
            - assignment set script:mayor_assignment npc:<entry[mayor_obj].created_npc>
            #set owner so the player can interact with the npc
            - adjust <entry[mayor_obj].created_npc> owner:<player>
            - adjust <entry[mayor_obj].created_npc> lookclose:true
            - flag player owned_npcs:->:<entry[mayor_obj].created_npc>
            - determine cancelled
        - else:
            - narrate "you already have a mayor<&nl>dismiss your mayor to be able to spawn a new one<&nl>or type /resetmayor to remove your mayor"
            - determine cancelled
        #
        #
        #mayor interactions
        #
        #
        #create a soldier npc
        on player clicks mayor_hire_soldier in mayor_menu:
        #check for hiring cost and soldier limit
        #todo make both configurable configurable
        - if  <player.inventory.quantity.material[wheat]> >= 64  && <player.flag[soldier]> < 5:
            - take wheat quantity:64
            - narrate "you hired a soldier"
            #summon the sentinel npc
            - create player soldier <player.location.add[0,2,0]> trait:sentinel save:soldier_obj
            #increment the amount of soldiers the players has
            - flag player soldier:++
            - flag player owned_npcs_soldier:->:<entry[soldier_obj].created_npc>
            - assignment set script:soldier_assignment npc:<entry[soldier_obj].created_npc>

            #set ownership so the player can interact with the npc
            - adjust <entry[soldier_obj].created_npc> owner:<player>
            #configure the npc
            - adjust <entry[soldier_obj].created_npc> speed:1.3
            - execute as_op "npc select <entry[soldier_obj].created_npc.id>" silent
            - execute as_op "npc skin --url https://i.imgur.com/nwUVLKc.png" silent
            - execute as_server "sentinel chaserange 15 --id <entry[soldier_obj].created_npc.id>"
            - execute as_server "sentinel addtarget monsters --id <entry[soldier_obj].created_npc.id>"
            - execute as_server "sentinel guard <player.name> --id <entry[soldier_obj].created_npc.id>"
            - execute as_server "sentinel attackrate 1 --id <entry[soldier_obj].created_npc.id>"
            - execute as_server "sentinel realistic --id <entry[soldier_obj].created_npc.id>"
            - execute as_server "sentinel safeshot true --id <entry[soldier_obj].created_npc.id>"
            - execute as_server "sentinel speed 1.5 --id <entry[soldier_obj].created_npc.id>"
            - execute as_server "sentinel respawntime -1 --id <entry[soldier_obj].created_npc.id>"
            #reopen the menu to refresh the total soldier count
            - inventory open d:mayor_menu
            - determine cancelled
        - else:
            - if <player.flag[soldier]> >= 5:
                - narrate "soldier limit reached for mayor(5)"
                - determine cancelled
            - else:
                - narrate "you dont have enough wheat"
                - determine cancelled

        #create a farmer npc
        on player clicks mayor_hire_farmer in mayor_menu:
        #check for hiring cost and farmer limit
        #todo make both configurable
        - if  <player.inventory.quantity.material[iron_ingot]> >= 10  && <player.flag[farmer]> < 3:
            - take iron_ingot quantity:10
            - narrate "you hired a farmer"
            - create player farmer <player.location.add[0,2,0]> save:farmer_obj
            #increment the amount of farmers the player has
            - flag player farmer:++
            - flag player owned_npcs_farmer:->:<entry[farmer_obj].created_npc>
            - assignment set script:farmer_assignment npc:<entry[farmer_obj].created_npc>
            - flag <entry[farmer_obj].created_npc> gather_seeds:true
            - flag <entry[farmer_obj].created_npc> profession:farmer
            - adjust <entry[farmer_obj].created_npc> owner:<player>
            - adjust <entry[farmer_obj].created_npc> speed:1.3
            - inventory open d:mayor_menu
            - determine cancelled
        - else:
            - if <player.flag[farmer]> > 3:
                - narrate "farmer limit reached for mayor(3)"
                - determine cancelled
            - else:
                - narrate "you dont have enough iron"
                - determine cancelled
        on player clicks mayor_hire_builder in mayor_menu:
        - if  <player.inventory.quantity.material[stone_bricks]> >= 10  && <player.flag[builder]> < 1:
            - take stone_bricks quantity:10
            - narrate "you hired a builder"
            - create player builder <player.location.add[0,2,0]> save:builder_obj
            #increment the amount of builders the player has
            - flag player builder:++
            - flag player owned_npcs_builder:<entry[builder_obj].created_npc>
            - flag rate:1s <entry[builder_obj].created_npc> updatequeue:true
            - flag <entry[builder_obj].created_npc> status:ready
            - assignment set script:builder_assignment npc:<entry[builder_obj].created_npc>
            - flag <entry[builder_obj].created_npc> profession:builder
            - adjust <entry[builder_obj].created_npc> owner:<player>
            - adjust <entry[builder_obj].created_npc> speed:1.3
            - inventory open d:mayor_menu
            - determine cancelled
        - else:
            - if <player.flag[builder]> > 1:
                - narrate "builder limit reached for mayor(1)"
                - determine cancelled
            - else:
                - narrate "you dont have enough stone bricks"
                - determine cancelled
        - determine cancelled
        #remove the npc the player is talking with
        on player clicks mayor_dismiss in mayor_menu:
        - narrate "goodbye"
        - remove <player.flag[last_interaction_id]>
        - flag player owned_npcs_mayor:!
        - inventory close
        - determine cancelled
soldier_script:
    type: world
    events:
        #
        #
        #soldier interactions
        #
        #
        on player clicks soldier_equip in soldier_menu:
        #check if theyre not already equiping or setting a path for this npc
        - if <player.flag[equiping]||null> != <player.flag[last_interaction_id]> && <player.flag[pathing]||null> != <player.flag[last_interaction_id]>:
        #enter equipment editor
            - execute as_op "npc select <player.flag[last_interaction_id].as_npc.id>" silent
            - execute as_op "npc equip"
            - narrate "<yellow>Shift left click <green>with an empty hand to exit"
            - flag player equiping:<player.flag[last_interaction_id]>
            - inventory close
            - determine cancelled
        - else:
            - if <player.flag[equiping]> == <player.flag[last_interaction_id]>:
                - narrate "already equiping this soldier, shift left click to cancel"
                - inventory close
                - determine cancelled
            - else:
                - narrate "already setting a path for this soldier, shift left click to cancel"
                - inventory close
                - determine cancelled

        on player clicks soldier_path in soldier_menu:
        - if <player.flag[equiping]||null> != <player.flag[last_interaction_id]> && <player.flag[pathing]||null> != <player.flag[last_interaction_id]>:
        #enter path editor
            - execute as_op "npc select <player.flag[last_interaction_id].as_npc.id>" silent
            - execute as_op "npc path"
            - flag player pathing:<player.flag[last_interaction_id]>
            - inventory close
            - determine cancelled
        - else:
            - if <player.flag[equiping]> == <player.flag[last_interaction_id]>:
                - narrate "already equiping this soldier, shift left click to cancel"
                - inventory close
                - determine cancelled
            - else:
                - narrate "already setting a path for this soldier, shift left click to cancel"
                - inventory close
                - determine cancelled


        on player clicks soldier_guard in soldier_menu:
        - execute as_op "sentinel guard <player.name> --id <player.flag[last_interaction_id].as_npc.id>"
        - narrate "soldier is now guarding you"
        - determine cancelled

        #remove the npc the player is interacting with
        on player clicks soldier_dismiss in soldier_menu:
        - narrate "goodbye"
        - drop <player.flag[last_interaction_id].as_npc.inventory.list_contents>
        - remove <player.flag[last_interaction_id]>
        - flag player owned_npcs_soldier:<-:<player.flag[last_interaction_id]>
        - flag player soldier:--
        - inventory close
        - determine cancelled
farmer_script:
    type: world
    debug: false
    events:
        #farmer interactions
        on player clicks farmer_area in farmer_menu:
        - if <player.flag[editing]||null> == null
        - narrate "right click corners with an empty hand to mark the area"
        - narrate "shift click with an empty hand to cancel"
        #flag the npc id the player is interacting with for referencing the npc
        - flag player editing:<player.flag[last_interaction_id]>
        #set the flag to enable area editing
        - flag player edit_farm_area:1
        - inventory close
        - determine cancelled

        on player clicks farmer_inventory in farmer_menu:
        - determine passively cancelled
        - inventory close
        #open the inventory of the npc the player is currently interacting with
        - inventory open d:<player.flag[last_interaction_id].as_npc.inventory>

        on player clicks farmer_seeds in farmer_menu:
        #toggles whether the npc should collect seeds
        - flag <player.flag[last_interaction_id]> gather_seeds:<player.flag[last_interaction_id].as_npc.flag[gather_seeds].as_boolean.not>
        #reopens the inventory to update the value
        - inventory open d:farmer_menu
        - determine cancelled

        on player clicks farmer_dismiss in farmer_menu:
        - narrate "goodbye"
        - if !<server.flag[farm_cuboids].map_get[<player.flag[last_interaction_id]>]||null> == null:
            #remove the npcs farm area from the area being checked for crop growth
            - note <cuboid[farmcube].remove_member[<server.flag[farm_cuboids].map_get[<player.flag[last_interaction_id]>]>]> as:farmcube
            #remove the farm area itself
            - note remove as:<server.flag[farm_cuboids].map_get[<player.flag[last_interaction_id]>]>
            #remove the owner npc id/area from the server flag
            - flag server farm_cuboids: <server.flag[farm_cuboids].exclude[<server.flag[farm_cuboids].map_get[<player.flag[last_interaction_id]>]>]>
            - flag server farm_cuboids: <server.flag[farm_cuboids].exclude[<player.flag[last_interaction_id]>]>
        - flag player owned_npcs_farner:<-:<player.flag[last_interaction_id]>
        - flag player farmer:--
        - inventory close
        - drop <player.flag[last_interaction_id].as_npc.inventory.list_contents>
        - remove <player.flag[last_interaction_id]>
        - determine cancelled
        #defining farm area and add to the area being checked for crop growth
        on player right clicks block with air:
        - if <player.flag[edit_farm_area]||0> == 1:
            - showfake redstone_block <context.location> duration:2s
            - narrate "corner set at <context.location.xyz.replace[,].with[ ]>"
            - flag player corner1:<context.location>
            - flag player edit_farm_area:++
            - determine cancelled
        - else:
            - if <player.flag[edit_farm_area]||0> == 2:
                - showfake redstone_block <context.location> duration:2s
                - define new_area:<cuboid[<player.flag[corner1]>|<context.location>]>
                - define area_name:<server.flag[farm_cuboids].map_get[<player.flag[editing]>]||null>
                - define area_index:<server.flag[farm_cuboids].map_get[<player.flag[editing]>].replace[farm_area_]||null>
                #checks if the area is too large
                - if <[new_area].size.x> > 18:
                    - narrate "error:x axis too long:<[new_area].size.x> blocks, maximum is 18 blocks<&nl> right click to select a new are <&nl> shift left click to cancel"
                    - determine cancelled
                    - stop
                - if <[new_area].size.z> > 18:
                    - narrate "error:z axis too long:<[new_area].size.z> blocks, maximum is 18 blocks<&nl> right click to select a new are <&nl> shift left click to cancel"
                    - determine cancelled
                    - stop
                - if <[new_area].size.x.mul_int[<[new_area].size.z>]> > 100:
                    - narrate "error:area is too large:<[new_area].size.x.mul_int[<[new_area].size.z>]> blocks maximum size is 100 blocks<&nl> right click to select a new are <&nl> shift left click to cancel"
                    - determine cancelled
                    - stop
                 #check if the player is overwriting a previous region(if null .length returns 4)
                - if <[area_name].length> > 4:
                    #removes the old cuboid so it does not intersect with the current area
                    - note <cuboid[farmcube].remove_member[<[area_index]>]> as:farmcube
                    #if the new area does not overlap another area replace the old area and add the new one to the area being checked for crop growth
                    - if !<cuboid[farmcube].intersects[<[new_area]>]>:
                        - note <[new_area]> as:farm_area_<[area_index]>
                        - note <cuboid[farmcube].add_member[<[new_area]>].at[<[area_index]>]> as:farmcube
                        #path the npc to the area
                        - walk <player.flag[editing]> <player.flag[corner1]> auto_range
                        - narrate "replaced old area with new area"
                        - flag player edit_farm_area:!
                        - flag player editing:!
                        - determine cancelled
                        #if it overlaps restore the previous area to the farm cube and return an error
                    - else:
                        - narrate "Error: this area overlaps another farm area <&nl> Restoring previous area <&nl> right click to select a new are <&nl> shift left click to cancel"
                        #restore the original farm area
                        - note <cuboid[farmcube].add_member[<[area_name]>].at[<[area_index]>]> as:farmcube
                        #restarts the new area creation
                        - flag player edit_farm_area:1
                        - determine cancelled
                #when there is no old area create a new one with the next available index
                - else:
                    - if !<cuboid[farmcube].intersects[<[new_area]>]>:
                        #create the farm area and add it to the area being checked for crop growth
                        - note <[new_area]> as:farm_area_<server.flag[farm_cuboids_next_index]>
                        - note <cuboid[farmcube].add_member[<[new_area]>]> as:farmcube
                        #list the npc that owns the area and its name, advance the index by 1
                        - flag server farm_cuboids:->:<player.flag[editing]>/farm_area_<server.flag[farm_cuboids_next_index]>
                        #path to the area
                        - walk <player.flag[editing]> <player.flag[corner1]> auto_range
                        - flag server farm_cuboids_next_index:++
                        - narrate "farm area created"
                        - flag player edit_farm_area:!
                        - flag player editing:!
                        - determine cancelled
                    - else:
                        - narrate "Error: this area overlaps another farm area <&nl> Restoring previous area <&nl> right click to select a new are <&nl> shift left click to cancel"
                        #restore the original farm area and restart area creation
                        - note <cuboid[farmcube].add_member[<cuboid[<area_name>]>]> as:farmcube
                        - flag player edit_farm_area:1
                        - determine cancelled
        #if wheat grows to its last stage in the farmcube area(containing all the farm areas)
        on wheat grows to:7 in:farmcube:
        #check in which area the wheat has grown(returns farmcube,farm_area)
        - define npc_tag:<server.flag[farm_cuboids].map_find_key[<context.location.farm_cuboids.get[2].notable_name>]>
        - wait 1t
        #always passes unless inventory is full, check every 10 seconds if inventory is no longer full
        - waituntil rate:10s <[npc_tag].inventory.can_fit[wheat]> && <[npc_tag].inventory.can_fit[wheat_seeds].quantity[3]>:
        - if <[npc_tag].flag[timeout]||null> == null && !<[npc_tag].flag[break_queue_finished]>:
            - run task_timeout def:<[npc_tag]>|10|1s
        #wait for the timeout or breakqueue to finish
        - waituntil rate:40t <[npc_tag].flag[break_queue_finished].get[1]||[npc_tag].flag[timeout]>
        - if <[npc_tag].flag[break_queue_finished].get[1]>:
            - flag <[npc_tag]> break_queue_finished:false
            - flag <[npc_tag]> timeout:!
            #flag all grown wheat for breaking
            - flag <[npc_tag]> targets:<context.location.farm_cuboids.get[2].blocks[wheat].filter[material.age.is[==].to[7]]>
            - foreach <[npc_tag].flag[targets].get[1]>:
                - if <[npc_tag].inventory.can_fit[wheat]> && <[npc_tag].inventory.can_fit[wheat_seeds].quantity[3]>:
                    #path the npc to the wheat
                    - ~walk <[npc_tag]> <[value]> auto_range
                    #remove the current target
                    - flag <[npc_tag]> targets[1]:<-
                    - if <[value].material.age> == 7:
                        #break wheat
                        - animate <[npc_tag]> animation:ARM_SWING
                        - playsound <[value]> sound:BLOCK_CROP_BREAK volume:5
                        - modifyblock <[value]> air
                        #simmulate the wheat drops and replant if seeds are available
                        - give wheat to:<[npc_tag].inventory>
                        - if <[npc_tag].flag[gather_seeds]>:
                            - give wheat_seeds quantity:<util.random.int[0].to[3]> to:<[npc_tag].inventory>
                        - else:
                            - give wheat_seeds to:<[npc_tag].inventory>
                        - if <[npc_tag].inventory.quantity.material[wheat_seeds]> > 0:
                            - wait 5t
                            - animate <[npc_tag]> animation:ARM_SWING
                            - playsound <[value]> sound:ITEM_CROP_PLANT volume:5
                            - modifyblock <[value]> wheat
                            - take wheat_seeds from:<[npc_tag].inventory>
                - else:
                    - flag <[npc_tag]> targets:!
            - flag <[npc_tag]> break_queue_finished:true
        #end
world_script:
    type: world
    debug: false
    events:
        #world events
        #create area/owner list, index of next available spot in the list and the area that is checked for crop growth, if they dont exist
        on world loads:
        #replace with config file and material file
        - flag server buildinglist:<list[hovel,farm,town_hall]>
        - flag server hovel_material_list:<list[dirt/block_grass_place/39|coarse_dirt/block_grass_place/10|oak_log/block_wood_place/32|oak_planks/block_wood_place/22|oak_slab/block_wood_place/8|ladder/block_wood_place/3|hay_block/block_grass_place/49|oak_door/block_wood_place/1].escaped>

        - flag server farm_material_list
        - flag server town_material_list
        - if <cuboid[farmcube]||null> == null:
            - note <cuboid[0,0,0,world|0,0,0,world]> as:farmcube
        - if <server.flag[farm_cuboids]||null> == null:
            - flag server farm_cuboids:server/farmcube
        - if <server.flag[farm_cuboids_next_index]>|| null> == null:
            - flag server farm_cuboids_next_index:2
        - if <cuboid[buildingcube]||null> == null:
            - note <cuboid[0,0,0,world|0,0,0,world]> as:buildingcube
        - if <server.flag[building_cuboids]||null> == null:
            - flag server building_cuboids:server/buildingcube
        - if <server.flag[building_cuboids_next_index]>|| null> == null:
            - flag server building_cuboids_next_index:2
        #set the amount of npcs to 0 so the menu shows it properly
        on player joins:
        - if <player.flag[new]||true>:
            - flag player new:false
            - flag player farmer:0
            - flag player builder:0
            - flag player soldier:0
            - flag player building_index:1


        #on npc death:
        #todo FIX
        #- flag <npc.owner> <npc.flag[profession]>:


        #cancelling editing modes
        on player left clicks with air:
        - if <player.is_sneaking>:
            - if <player.has_flag[equiping]>:
                - execute as_op "npc equip"
                - flag player equiping:!
                - determine cancelled
            - else:
                - if <player.has_flag[pathing]>:
                    - execute as_op "npc path"
                    - execute as_op "sentinel guard"
                    - narrate "stopped waypoint assignment"
                    - flag player pathing:!
                    - determine cancelled
                - else:
                    - if <player.has_flag[edit_farm_area]>:
                        - flag player edit_farm_area:!
                        - flag player editing:!
                        - narrate "cancelled area creation"
                        - determine cancelled
                    - else:
                        - if <player.has_flag[builder_pickup]>:
                            - flag player builder_pickup:!
                            - narrate "cancelled pickup point assignment"
                            - determine cancelled
builder_script:
    type: world
    events:
    #menu interactions
        on player clicks builder_available_buildings in builder_menu_main:
        - inventory open d:builder_menu_buildings
        - determine cancelled
        on player clicks builder_inventory in builder_menu_main:
        - inventory open d:<player.flag[last_interaction_id].as_npc.inventory>
        - determine cancelled
        on player clicks builder_pickup_point in builder_menu_main:
        - flag player builder_pickup:<player.flag[last_interaction_id]>
        - narrate "right click a chest to assign the resource pickup point"
        - determine cancelled
        on player right clicks chest with air:
        - if <player.has_flag[builder_pickup]||null>:
            - flag <player.flag[builder_pickup]> pickup_point:<context.location>
            - narrate "pickup point assigned"
            - flag player builder_pickup:!
            - determine cancelled
        #buildings menu
        on player clicks building_farm in builder_menu_buildings:
        - define structure:farm
        - give <item[builder_schematic]>
        - determine cancelled
        on player clicks building_hovel in builder_menu_buildings:
        - define structure:hovel
        - give <item[builder_schematic]>
        - determine cancelled
        on player clicks building_town_hall in builder_menu_buildings:
        - define structure:town_hall
        - give <item[builder_schematic]>
        - determine cancelled
        on player clicks builder_status in builder_menu_main:
        - if <player.flag[last_interaction_id].as_npc.flag[status]> == waiting:
            - flag <player.flag[last_interaction_id]> update_queue:true
        - determine cancelled
        on player clicks builder_dismiss in builder_menu_main:
        - narrate "goodbye"
        - drop <player.flag[last_interaction_id].inventory.list_contents>
        - remove <player.flag[last_interaction_id]>
        - flag player builder:--
        - flag player owner_npcs_builder:<-:<player.flag[last_interaction_id]>
        - inventory close
        - determine cancelled
    #building script
        on player right clicks block with builder_schematic:
        - if <context.item.nbt[builder].as_npc.flag[status]||false> != ready:
            - narrate "this builder is currently building a <context.item.nbt[builder].as_npc.flag[building]> <&nl>get another builder to construct this building or wait for this one to finish construction"
            - determine cancelled
        #if the player already placed a preview on this block
        - if <context.item.nbt[builder].as_npc.flag[building_location]||null> == <context.location> && <context.item.nbt[builder].as_npc.flag[building]||null> == <context.item.nbt[structure]>:
            - define new_area:<cuboid[<context.item.nbt[builder].as_npc.flag[origin].as_location>|<context.item.nbt[builder].as_npc.flag[origin].as_location.add[<schematic[<context.item.nbt[structure]>].width>,<schematic[<context.item.nbt[structure]>].height>,<schematic[<context.item.nbt[structure]>].length>]>]>
            - if <cuboid[buildingcube].intersects[<[new_area]>]>:
                - narrate "error: area intersects another buildings area"
                - determine cancelled
            #when no intersection with other buildings is found
            - else:
                #load a copy of the schematic if its not loaded already
                - if !<schematic.list.contains[<context.item.nbt[structure]>_<context.item.nbt[builder]>]||false>:
                    - ~schematic load name:<context.item.nbt[structure]>_<context.item.nbt[builder]> filename:<context.item.nbt[structure]>
                    - waituntil <schematic.list.contains[<context.item.nbt[structure]>_<context.item.nbt[builder]>]>
            #check builder inventory for needed materials
                - flag <context.item.nbt[builder]> has_materials:true
                - foreach <server.flag[<context.item.nbt[structure]>_material_list].unescaped.as_list>:
                    - define material_mask:<[value].unescaped.as_list.get_sub_items[1].get[1]>
                    - define material_quantity:<[value].unescaped.as_list.get_sub_items[3].get[1]>
                    - if <context.item.nbt[builder].as_npc.inventory.quantity.material[<[material_mask]>]> < <[material_quantity]> && <context.item.nbt[builder].as_npc.flag[has_materials]>:
                        - flag <context.item.nbt[builder]> has_materials:false
                - if !<context.item.nbt[builder].as_npc.flag[has_materials]>:
                    - if <context.item.nbt[builder].as_npc.has_flag[pickup_point]||null>:
                        - ~walk <context.item.nbt[builder]> <context.item.nbt[builder].as_npc.flag[pickup_point]> auto_range
                        #dump inventory if possible
                        - if <context.item.nbt[builder].as_npc.flag[pickup_point].as_location.inventory.can_fit[<context.item.nbt[builder].as_npc.inventory.list_contents>]||true>:
                            - inventory add origin:<context.item.nbt[builder].as_npc.inventory.list_contents> d:<context.item.nbt[builder].as_npc.flag[pickup_point].as_location.inventory>
                            - inventory clear d:<context.item.nbt[builder].as_npc.inventory>
                        - run task_timeout def:<context.item.nbt[builder].as_npc>|120|1s
                        - while !<context.item.nbt[builder].as_npc.flag[has_materials]>:
                            - waituntil rate:1s <context.item.nbt[builder].as_npc.flag[update_queue]> || <context.item.nbt[builder].as_npc.flag[timeout]>
                            - if <context.item.nbt[builder].as_npc.flag[timeout]>:
                                - flag <context.item.nbt[builder].as_npc> status:ready
                                - determine cancelled
                            - flag <context.item.nbt[builder]> has_materials:true
                            - flag <context.item.nbt[builder]> update_queue:false
                            - foreach <server.flag[<context.item.nbt[structure]>_material_list].unescaped.as_list>:
                                - define material_mask:<[value].unescaped.as_list.get_sub_items[1].get[1]>
                                - define material_quantity:<[value].unescaped.as_list.get_sub_items[3].get[1]>
                                - if <context.item.nbt[builder].as_npc.inventory.quantity.material[<[material_mask]>]> < <[material_quantity]>:
                                    - define needed_quantity:<[material_quantity].sub[<context.item.nbt[builder].as_npc.inventory.quantity.material[<[material_mask]>]>]>
                                    - if <context.item.nbt[builder].as_npc.flag[pickup_point].as_location.inventory.quantity.material[<[material_mask]>]> >= <[needed_quantity]>:
                                        - if <context.item.nbt[builder].as_npc.inventory.can_fit[<[material_mask]>].quantity[<[needed_quantity]>]>:
                                            - take <[material_mask]> quantity:<[needed_quantity]> from:<context.item.nbt[builder].as_npc.flag[pickup_point].as_location.inventory>
                                            - give <[material_mask]> quantity:<[needed_quantity]> to:<context.item.nbt[builder].as_npc.inventory>
                                        - else:
                                            - narrate "builder inventory and pickup point are too full"
                                            - flag <context.item.nbt[builder]> status:waiting
                                            - flag <context.item.nbt[builder]> has_materials:false
                                    - else:
                                        - narrate "insufficient materials in pick up point <&nl>need <[needed_quantity]> <[material_mask].as_material.name>"
                                        - flag <context.item.nbt[builder]> status:waiting
                                        - flag <context.item.nbt[builder].as_npc> required_quantity:<[needed_quantity].sub[<context.item.nbt[builder].as_npc.flag[pickup_point].as_location.inventory.quantity.material[<[material_mask]>]>]>
                                        - flag <context.item.nbt[builder].as_npc> required_material
                                        - flag <context.item.nbt[builder]> has_materials:false
                        - flag  <context.item.nbt[builder]> update_queue:true
                    - else:
                        - narrate "give the builder the necesarry items or assign a pickup point"
                        - determine cancelled
            #materials are available, start construction
                - wait 1t
                - flag <context.item.nbt[builder]> status:building
                - define structure:<context.item.nbt[structure]>
                - take scriptname:builder_schematic
                - narrate "construction started"
                - choose <context.item.nbt[builder].as_npc.flag[building_facing]>:
                    - case north:
                        - ~schematic rotate angle:180 name:<context.item.nbt[structure]>_<context.item.nbt[builder]>
                        - ~run task_rotation_map def:<context.item.nbt[builder]>|<context.item.nbt[structure]>_<context.item.nbt[builder]>
                        - ~run task_convert def:<context.item.nbt[builder]>|<context.item.nbt[structure]>_<context.item.nbt[builder]>
                        - ~run task_rotate_blocks def:<context.item.nbt[builder]>|<context.item.nbt[structure]>_<context.item.nbt[builder]>|180

                    - case east:
                        - flag <context.item.nbt[builder]> converted:false
                        - narrate "flag set"
                        - ~schematic rotate angle:90 name:<context.item.nbt[structure]>_<context.item.nbt[builder]>
                        - ~run task_rotation_map def:<context.item.nbt[builder]>|<context.item.nbt[structure]>_<context.item.nbt[builder]>
                        - ~run task_convert def:<context.item.nbt[builder]>|<context.item.nbt[structure]>_<context.item.nbt[builder]>
                        - waituntil rate:1s <context.item.nbt[builder].as_npc.flag[converted]||false>
                        - ~run task_rotate_blocks def:<context.item.nbt[builder]>|<context.item.nbt[structure]>_<context.item.nbt[builder]>|90

                    - case west:
                        - ~schematic rotate angle:270 name:<context.item.nbt[structure]>_<context.item.nbt[builder]>
                        - ~run task_rotation_map def:<context.item.nbt[builder]>|<context.item.nbt[structure]>_<context.item.nbt[builder]>
                        - ~run task_convert def:<context.item.nbt[builder]>|<context.item.nbt[structure]>_<context.item.nbt[builder]>
                        - ~run task_rotate_blocks def:<context.item.nbt[builder]>|<context.item.nbt[structure]>_<context.item.nbt[builder]>|270

                    - case south:
                        #buildings face north so no rotation required as the player is north of the building site
                        - ~run task_convert def:<context.item.nbt[builder]>|<context.item.nbt[structure]>_<context.item.nbt[builder]>
                - flag <context.item.nbt[builder]> status:ready
            #add clear flags at end of building

                - stop
                - ~run task_clear_area def:<context.item.nbt[builder]>|<context.item.nbt[structure]>_<context.item.nbt[builder]>|<context.item.nbt[builder].as_npc.flag[origin]>
                - foreach <server.flag[<context.item.nbt[structure]>_material_list].unescaped.as_list>:
                    - define material_mask:<[value].unescaped.as_list.get_sub_items[1].get[1]>
                    - define material_sound:<[value].unescaped.as_list.get_sub_items[2].get[1]>
                    - ~run task_build def:<context.item.nbt[builder].as_npc>|<context.item.nbt[structure]>_<context.item.nbt[builder]>|<context.item.nbt[builder].as_npc.flag[origin].as_location>|<material[<[material_mask]>]>|<[material_sound]>
                - note <[new_area]> as:<player>_building_<player.flag[building_index]>
                - note <cuboid[buildingcube].add_member[<[new_area]>]> as:buildingcube
                - flag server building_cuboids:->:<player>/<player>_building_<player.flag[building_index]>
                - flag <context.item.nbt[builder]> building:!
                - flag <context.item.nbt[builder]> status:ready
            - schematic unload name:<context.item.nbt[structure]>_<context.item.nbt[builder]>
        #else place a preview
        - else:
            - if !<schematic.list.contains[<context.item.nbt[structure]>]||false>:
                - ~schematic load name:<context.item.nbt[structure]>
                - waituntil <schematic.list.contains[<context.item.nbt[structure]>]>
            - if !<schematic.list.contains[<context.item.nbt[structure]>_<context.item.nbt[builder]>]||false>:
                - ~schematic load name:<context.item.nbt[structure]>_<context.item.nbt[builder]> filename:<context.item.nbt[structure]>
                - waituntil <schematic.list.contains[<context.item.nbt[structure]>_<context.item.nbt[builder]>]>
            - choose <player.location.direction>:
                - case north:
                    - narrate "preview placed, right click this location again to confirm this building location <&nl>shift left click to cancel"
                    - ~schematic rotate angle:180 name:<context.item.nbt[structure]>_<context.item.nbt[builder]>
                    - schematic paste fake_to:<player> fake_duration:5s name:<context.item.nbt[structure]>_<context.item.nbt[builder]> <context.location.sub[<schematic[<context.item.nbt[structure]>].width.div_int[2]>,0,<schematic[<context.item.nbt[structure]>].length.sub[1]>]>
                    - flag <context.item.nbt[builder].as_npc> building:<context.item.nbt[structure]>
                    - flag <context.item.nbt[builder].as_npc> building_location:<context.location>
                    - flag <context.item.nbt[builder].as_npc> origin:<context.location.sub[<schematic[<context.item.nbt[structure]>].width.div_int[2]>,0,<schematic[<context.item.nbt[structure]>].length.sub[1]>]>
                    - flag <context.item.nbt[builder].as_npc> building_facing:north
                    - schematic unload name:<context.item.nbt[structure]>_<context.item.nbt[builder]>
                    - stop
                - case east:
                    - narrate "preview placed, right click this location again to confirm this building location <&nl>shift left click to cancel"
                    - ~schematic rotate angle:90 name:<context.item.nbt[structure]>_<context.item.nbt[builder]>
                    - schematic paste fake_to:<player> fake_duration:5s name:<context.item.nbt[structure]>_<context.item.nbt[builder]> <context.location.sub[0,0,<schematic[<context.item.nbt[structure]>].length.div_int[2]>]>
                    - flag <context.item.nbt[builder].as_npc> building:<context.item.nbt[structure]>
                    - flag <context.item.nbt[builder].as_npc> building_location:<context.location>
                    - flag <context.item.nbt[builder].as_npc> origin:<context.location.sub[0,0,<schematic[<context.item.nbt[structure]>].length.div_int[2]>]>
                    - flag <context.item.nbt[builder].as_npc> building_facing:east
                    - schematic unload name:<context.item.nbt[structure]>_<context.item.nbt[builder]>
                    - stop
                - case south:
                    - narrate "preview placed, right click this location again to confirm this building location <&nl>shift left click to cancel"
                    - schematic paste fake_to:<player> fake_duration:5s name:<context.item.nbt[structure]>_<context.item.nbt[builder]> <context.location.sub[<schematic[<context.item.nbt[structure]>].width.div_int[2]>,0,0]>
                    - flag <context.item.nbt[builder].as_npc> building:<context.item.nbt[structure]>
                    - flag <context.item.nbt[builder].as_npc> building_location:<context.location>
                    - flag <context.item.nbt[builder].as_npc> origin:<context.location.sub[<schematic[<context.item.nbt[structure]>].width.div_int[2]>,0,0]>
                    - flag <context.item.nbt[builder].as_npc> building_facing:south
                    - schematic unload name:<context.item.nbt[structure]>_<context.item.nbt[builder]>
                    - stop
                - case west:
                    - narrate "preview placed, right click this location again to confirm this building location <&nl>shift left click to cancel"
                    - ~schematic rotate angle:270 name:<context.item.nbt[structure]>_<context.item.nbt[builder]>
                    - schematic paste fake_to:<player> fake_duration:5s name:<context.item.nbt[structure]>_<context.item.nbt[builder]> <context.location.sub[<schematic[<context.item.nbt[structure]>].width.sub[1]>,0,<schematic[<context.item.nbt[structure]>].length.div_int[2]>]>
                    - flag <context.item.nbt[builder].as_npc> building:<context.item.nbt[structure]>
                    - flag <context.item.nbt[builder].as_npc> building_location:<context.location>
                    - flag <context.item.nbt[builder].as_npc> origin:<context.location.sub[<schematic[<context.item.nbt[structure]>].width.sub[1]>,0,<schematic[<context.item.nbt[structure]>].length.div_int[2]>]>
                    - flag <context.item.nbt[builder].as_npc> building_facing:west
                    - schematic unload name:<context.item.nbt[structure]>_<context.item.nbt[builder]>
                    - stop
                - default:
                    - narrate "face north east south or west to place a preview"
                    - flag <context.item.nbt[builder].as_npc> building_location:!
                    - schematic unload name:<context.item.nbt[structure]>_<context.item.nbt[builder]>

#mayor interaction scripts
mayor_assignment:
    type: assignment
    actions:
        on assignment:
        - trigger name:click state:true
    interact scripts:
    - mayor_interact
mayor_interact:
    type: interact
    steps:
        1:
            click trigger:
                script:
                #open the menu and flag the npc as the one being interacted with if the player is the owner
                - if <player> == <npc.owner>:
                    - flag player last_interaction_id:<npc>
                    - inventory open d:mayor_menu
                - else:
                    - narrate "this mayor does not obey you"

mayor_menu:
    type: inventory
    inventory: chest
    title: Mayor
    size: 9
    slots:
    - "[mayor_dismiss] [] [] [] [mayor_hire_farmer] [mayor_hire_soldier] [mayor_hire_builder] [] []"
#menu items
mayor_placer:
    type: item
    material: bat_spawn_egg
    display name: Mayor spawner

mayor_hire_soldier:
    type: item
    material: stone_sword
    display name: Hire a soldier for 64 Wheat  (<player.flag[soldier]>/5)
mayor_hire_farmer:
    type: item
    material: stone_hoe
    display name: Hire a farmer for 10 iron ingots (<player.flag[farmer]>/3)
mayor_hire_builder:
    type: item
    material: brick
    display name: Hire a builder for 10 stone bricks (<player.flag[builder]>/1)
mayor_dismiss:
    type: item
    material: barrier
    display name: Dismiss the mayor
#soldier interaction scripts
soldier_assignment:
    type: assignment
    actions:
        on assignment:
        - trigger name:click state:true
    interact scripts:
    - soldier_interact
soldier_interact:
    type: interact
    steps:
        1:
            click trigger:
                script:
                #open the menu and flag the npc as the one being interacted with if the player is the owner
                - if <player> == <npc.owner>:
                    - flag player last_interaction_id:<npc>
                    - inventory open d:soldier_menu
                - else:
                    - narrate "this soldier does not obey you"
soldier_menu:
    type: inventory
    inventory: chest
    title: Soldier
    size: 9
    slots:
    - "[soldier_dismiss] [] [] [soldier_path] [soldier_guard] [soldier_equip] [] [] []"
#menu items
soldier_path:
    type: item
    material: stick
    display name: set the patrol path
soldier_guard:
    type: item
    material: shield
    display name: guard the player
soldier_equip:
    type: item
    material: iron_chestplate
    display name: equip your soldier
soldier_dismiss:
    type: item
    material: barrier
    display name: Dismiss this soldier
#farmer interaction scripts
farmer_assignment:
    type: assignment
    actions:
        on assignment:
        - trigger name:click state:true
    interact scripts:
    - farmer_interact
farmer_interact:
    type: interact
    steps:
        1:
            click trigger:
                script:
                #open the menu and flag the npc as the one being interacted with if the player is the owner
                - if <player> == <npc.owner>:
                    - flag player last_interaction_id:<npc>
                    - inventory open d:farmer_menu
                - else:
                    - narrate "this farmer does not obey you"
farmer_menu:
    type: inventory
    inventory: chest
    title: Farmer
    size: 9
    slots:
    - "[farmer_dismiss] [] [] [farmer_area] [farmer_seeds] [farmer_inventory] [] [] []"
#menu items
farmer_area:
    type: item
    material: iron_hoe
    display name: set farming area
farmer_seeds:
    type: item
    material: wheat_seeds
    display name: toggle seed collection (currently <player.flag[last_interaction_id].as_npc.flag[gather_seeds]>)
farmer_inventory:
    type: item
    material: chest
    display name: farmer inventory
farmer_deposit:
    type: item
    material: leather_boots
    display name: Change deposit location
farmer_interval:
    type: item
    material: clock
    display name: Change deposit interval
farmer_dismiss:
    type: item
    material: barrier
    display name: dismiss farmer
#builder interaction scripts
builder_assignment:
    type: assignment
    actions:
        on assignment:
        - trigger name:click state:true
    interact scripts:
    - builder_interact
builder_interact:
    type: interact
    steps:
        1:
            click trigger:
                script:
                #open the menu and flag the npc as the one being interacted with if the player is the owner
                - if <player> == <npc.owner>:
                    - flag player last_interaction_id:<npc>
                    - inventory open d:builder_menu_main
                - else:
                    - narrate "this builder does not obey you"
builder_menu_main:
    type: inventory
    inventory: chest
    title: builder
    size: 9
    slots:
    - "[builder_dismiss] [] [builder_status] [builder_available_buildings] [builder_inventory] [builder_pickup_point] [] [] []"
builder_menu_buildings:
    type: inventory
    title: available buildings
    size: 27
    slots:
    - "[] [] [building_farm] [building_hovel] [building_town_hall] [] [] [] [] "
    - "[] [] [] [] [] [] [] [] [] "
    - "[] [] [] [] [] [] [] [] [] "
#buildings
building_farm:
    type: item
    material: wheat
    display name: farm
building_hovel:
    type: item
    material: hay_block
    display name: basic house
building_town_hall:
    type: item
    material: iron_helmet
    display name: town hall
#menu items
builder_schematic:
    type: item
    material: paper
    mechanisms:
        nbt: structure/<[structure]>|builder/<player.flag[last_interaction_id]>
    display name: building schematic
    lore:
    - "<[structure]>"  
builder_pickup_point:
    type: item
    material: crafting_table
    display name: designate resource pick up point
builder_available_buildings:
    type: item
    material: bricks
    display name: order a new project
builder_inventory:
    type: item
    material: chest
    display name: builder inventory
builder_status:
    type: item
    material: <proc[builder_status_procedure].context[<player.flag[last_interaction_id].as_npc.flag[status]>|material_name]>
    display name: <proc[builder_status_procedure].context[<player.flag[last_interaction_id].as_npc.flag[status]>|item_name]>
builder_dismiss:
    type: item
    material: barrier
    display name: dismiss builder

builder_status_procedure:
    type: procedure
    definitions: status|return_type
    script:
    - if <[return_type]> == material_name:
        - choose <[status]>:
            - case ready:
                - determine green_stained_glass_pane
            - case building:
                - determine orange_stained_glass_pane
            - case collecting:
                - determine lime_stained_glass_pane
            - case waiting:
                - determine red_stained_glass_pane
    - else:
        - if <[return_type]> == item_name:
            - choose <[status]>:
                - case ready:
                    - determine "waiting for a new project"
                - case building:
                    - determine "constructing a <player.flag[last_interaction_id].as_npc.flag[building]>"
                - case collecting:
                    - determine "collecting resources for construction"
                - case waiting:
                    - determine "waiting for items"
task_timeout:
    type: task
    debug: false
    definitions: npc_tag|time|interval
    script:
    - flag <[npc_tag]>  timeout:false
    - while <[time]> > 0:
        - define time:<[time].sub[1]>
        - wait <[interval]>
    - if <[npc_tag].flag[timeout]||null> != null:
        - flag <[npc_tag]>  timeout:true
#builder tasks
task_convert:
    type: task
    definitions: builder_obj|passed_schematic
    debug: false
    script:
    #create a matrix containting the blocks from the schematic at their relative locations in the schematic
    # x y and z in the matrix are 1 higher since the schematic starts at 0,0,0 and the matrix starts at index 1,1,1
    - define x:0
    - define y:0
    - define z:0
    - while <[y]> < <schematic[<[passed_schematic]>].height>:
        - while <[x]> < <schematic[<[passed_schematic]>].width>:
            - wait 1t
            - while <[z]> < <schematic[<[passed_schematic]>].length>:
                #set the block in the row
                - flag <[builder_obj]> <[passed_schematic]>[<[z].add[1]>]:<schematic[<[passed_schematic]>].block[<[x]>,<[y]>,<[z]>]>
                - define z:<[z].add[1]>
            #add the row to the plane
            - flag <[builder_obj]> <[passed_schematic]>_square[<[x].add[1]>]:<[builder_obj].flag[<[passed_schematic]>].escaped>
            - define x:<[x].add[1]>
            - define z:0
        #add the plane to the square
        - flag <[builder_obj]> <[passed_schematic]>_cubic[<[y].add[1]>]:<[builder_obj].flag[<[passed_schematic]>_square].escaped>
        - define y:<[y].add[1]>
        - define x:0
    - flag <[builder_obj]> converted:true
task_rotation_map:
    type: task
    debug: false
    definitions: builder_obj|passed_schematic
    script:
    #create a matrix of rotatable blocks
    - define x:0
    - define y:0
    - define z:0
    - while <[y]> < <schematic[<[passed_schematic]>].height>:
        - while <[x]> < <schematic[<[passed_schematic]>].width>:
            - while <[z]> < <schematic[<[passed_schematic]>].length>:
                - if <schematic[<[passed_schematic]>].block[<[x]>,<[y]>,<[z]>].is_directional>:
                    - flag <[builder_obj]> <[passed_schematic]>_rotation[<[z].add[1]>]:<schematic[<[passed_schematic]>].block[<[x]>,<[y]>,<[z]>].direction>
                - else:
                    - flag <[builder_obj]> <[passed_schematic]>_rotation[<[z].add[1]>]:false
                - define z:<[z].add[1]>
            #add the row to the plane
            - flag <[builder_obj]> <[passed_schematic]>_rotation_square[<[x].add[1]>]:<[builder_obj].flag[<[passed_schematic]>_rotation].escaped>
            - define x:<[x].add[1]>
            - define z:0
        #add the plane to the square
        - flag <[builder_obj]> <[passed_schematic]>_rotation_cubic[<[y].add[1]>]:<[builder_obj].flag[<[passed_schematic]>_rotation_square].escaped>
        - define y:<[y].add[1]>
        - define x:0
task_rotate_blocks:
    type: task
    debug: true
    definitions: builder_obj|passed_schematic|rotation
    script:
    - define x:0
    - define y:0
    - define z:0
    #set the rotation
    - while <[y]> < <schematic[<[passed_schematic]>].height>:
        - while <[x]> < <schematic[<[passed_schematic]>].width>:
            - wait 1t
            - while <[z]> < <schematic[<[passed_schematic]>].length>:
                #define the current block rotation
                - define current_block_rotation:<[builder_obj].flag[<[passed_schematic]>_rotation_cubic].get[<[y].add[1]>].unescaped.as_list.get[<[x].add[1]>].unescaped.as_list.get[<[z].add[1]>]>
                - define square_plane:[builder_obj].flag[<[passed_schematic]>_cubic].get[<[y].add[1]>].unescaped.as_list
                - define current_material:<[builder_obj].flag[<[passed_schematic]>_cubic].get[<[y].add[1]>].unescaped.as_list.get[<[x].add[1]>].unescaped.as_list.get[<[z].add[1]>]>
                - if <[current_block_rotation]> != false:
                    - choose <[current_block_rotation]>:
                        #2 DIRECTIONAL MATERIALS SUCH AS LOGS
                        - case X:
                            - if <[rotation]> == 90 || <[rotation]> == 270:
                                - flag <[builder_obj]> <[passed_schematic]>_cubic[<[y].add[1]>]:<[square_plane].set[<[square_plane].get[<[x].add[1]>].unescaped.as_list.set[<[current_material].with[direction=Z]>].at[<[z].add[1]>].escaped>].at[<[x].add[1]>].escaped>
                        - case Z:
                            - if <[rotation]> == 90 || <[rotation]> == 270:
                                - flag <[builder_obj]> <[passed_schematic]>_cubic[<[y].add[1]>]:<[square_plane].set[<[square_plane].get[<[x].add[1]>].unescaped.as_list.set[<[current_material].with[direction=X]>].at[<[z].add[1]>].escaped>].at[<[x].add[1]>].escaped>
                        #4 DIRECTIONAL MATERIALS SUCH AS LADDERS
                        - case NORTH:
                            - if <[rotation]> == 90:
                                - flag <[builder_obj]> <[passed_schematic]>_cubic[<[y].add[1]>]:<[square_plane].set[<[square_plane].get[<[x].add[1]>].unescaped.as_list.set[<[current_material].with[direction=WEST]>].at[<[z].add[1]>].escaped>].at[<[x].add[1]>].escaped>
                            - if <[rotation]> == 180:
                                - flag <[builder_obj]> <[passed_schematic]>_cubic[<[y].add[1]>]:<[square_plane].set[<[square_plane].get[<[x].add[1]>].unescaped.as_list.set[<[current_material].with[direction=SOUTH]>].at[<[z].add[1]>].escaped>].at[<[x].add[1]>].escaped>
                            - if <[rotation]> == 270:
                                - flag <[builder_obj]> <[passed_schematic]>_cubic[<[y].add[1]>]:<[square_plane].set[<[square_plane].get[<[x].add[1]>].unescaped.as_list.set[<[current_material].with[direction=EAST]>].at[<[z].add[1]>].escaped>].at[<[x].add[1]>].escaped>
                        - case EAST:
                            - if <[rotation]> == 90:
                                - flag <[builder_obj]> <[passed_schematic]>_cubic[<[y].add[1]>]:<[square_plane].set[<[square_plane].get[<[x].add[1]>].unescaped.as_list.set[<[current_material].with[direction=NORTH]>].at[<[z].add[1]>].escaped>].at[<[x].add[1]>].escaped>
                            - if <[rotation]> == 180:
                                - flag <[builder_obj]> <[passed_schematic]>_cubic[<[y].add[1]>]:<[square_plane].set[<[square_plane].get[<[x].add[1]>].unescaped.as_list.set[<[current_material].with[direction=WEST]>].at[<[z].add[1]>].escaped>].at[<[x].add[1]>].escaped>
                            - if <[rotation]> == 270:
                                - flag <[builder_obj]> <[passed_schematic]>_cubic[<[y].add[1]>]:<[square_plane].set[<[square_plane].get[<[x].add[1]>].unescaped.as_list.set[<[current_material].with[direction=SOTUH]>].at[<[z].add[1]>].escaped>].at[<[x].add[1]>].escaped>
                        - case SOUTH:
                            - if <[rotation]> == 90:
                                - flag <[builder_obj]> <[passed_schematic]>_cubic[<[y].add[1]>]:<[square_plane].set[<[square_plane].get[<[x].add[1]>].unescaped.as_list.set[<[current_material].with[direction=EAST]>].at[<[z].add[1]>].escaped>].at[<[x].add[1]>].escaped>
                            - if <[rotation]> == 180:
                                - flag <[builder_obj]> <[passed_schematic]>_cubic[<[y].add[1]>]:<[square_plane].set[<[square_plane].get[<[x].add[1]>].unescaped.as_list.set[<[current_material].with[direction=NORTH]>].at[<[z].add[1]>].escaped>].at[<[x].add[1]>].escaped>
                            - if <[rotation]> == 270:
                                - flag <[builder_obj]> <[passed_schematic]>_cubic[<[y].add[1]>]:<[square_plane].set[<[square_plane].get[<[x].add[1]>].unescaped.as_list.set[<[current_material].with[direction=WEST]>].at[<[z].add[1]>].escaped>].at[<[x].add[1]>].escaped>
                        - case WEST:
                            - if <[rotation]> == 90:
                                - flag <[builder_obj]> <[passed_schematic]>_cubic[<[y].add[1]>]:<[square_plane].set[<[square_plane].get[<[x].add[1]>].unescaped.as_list.set[<[current_material].with[direction=SOUTH]>].at[<[z].add[1]>].escaped>].at[<[x].add[1]>].escaped>
                            - if <[rotation]> == 180:
                                - flag <[builder_obj]> <[passed_schematic]>_cubic[<[y].add[1]>]:<[square_plane].set[<[square_plane].get[<[x].add[1]>].unescaped.as_list.set[<[current_material].with[direction=EAST]>].at[<[z].add[1]>].escaped>].at[<[x].add[1]>].escaped>
                            - if <[rotation]> == 270:
                                - flag <[builder_obj]> <[passed_schematic]>_cubic[<[y].add[1]>]:<[square_plane].set[<[square_plane].get[<[x].add[1]>].unescaped.as_list.set[<[current_material].with[direction=NORTH]>].at[<[z].add[1]>].escaped>].at[<[x].add[1]>].escaped>
                - define z:<[z].add[1]>
            - define x:<[x].add[1]>
            - define z:0
        - define y:<[y].add[1]>
        - define x:0
task_build:
    type: task
    debug: false
    definitions: builder_obj|passed_schematic|origin|material_mask|material_sound
    script:
    - define x:0
    - define y:0
    - define z:0
    # get material value at x y z <[builder_obj].flag[<[schematic]>_cubic].get[<[y].add[1]>].unescaped.as_list.get[<[x].add[1]>].unescaped.as_list.get[<[z].add[1]>]>
    # set material value at x y z - flag <[builder_obj]> <[schematic]>_cubic[<[y].add[1]>]:<[builder_obj].flag[[schematic]_cubic].get[<[y].add[1]>].as_list.unescaped.set[<[schematic]_cubic.get[<[y].add[1]>].unescaped.as_list.get[<[x].add[1]>].unescaped.as_list.set[<material[air]>].at[<[z].add[1]>]>].at[<[x].add[1]>]>
    - while <[y]> < <schematic[<[passed_schematic]>].height>:
        - while <[x]> < <schematic[<[passed_schematic]>].width>:
            - wait 1t
            - while <[z]> < <schematic[<[passed_schematic]>].length>:
                #if the material in the schematic matrix matches the mask and the space is empty
                - if <[builder_obj].flag[<[passed_schematic]>_cubic].get[<[y].add[1]>].unescaped.as_list.get[<[x].add[1]>].unescaped.as_list.get[<[z].add[1]>].as_material.name> == <[material_mask].name> && <[origin].add[<[x]>,<[y]>,<[z]>].material.name> == air:
                    - define current_material:<[builder_obj].flag[<[passed_schematic]>_cubic].get[<[y].add[1]>].unescaped.as_list.get[<[x].add[1]>].unescaped.as_list.get[<[z].add[1]>]>
                    - if <[builder_obj].inventory.contains.material[<[current_material]>]>:
                        - ~walk <[builder_obj]> <[origin].add[<[x]>,<[y]>,<[z]>]> auto_range radius:1
                        - wait 1t
                        #walk to the location and place the block
                        - take <[current_material].name> from:<[builder_obj].inventory>
                        - modifyblock <[origin].add[<[x]>,<[y]>,<[z]>]> <[current_material]>
                        - animate <[builder_obj]> animation:ARM_SWING
                        - playsound <[origin].add[<[x]>,<[y]>,<[z]>]> sound:<[material_sound]>
                        #set the material in the schematic matrix to air
                        - flag <[builder_obj]> <[passed_schematic]>_cubic[<[y].add[1]>]:<[builder_obj].flag[<[passed_schematic]>_cubic].get[<[y].add[1]>].unescaped.as_list.set[<[builder_obj].flag[<[passed_schematic]>_cubic].get[<[y].add[1]>].unescaped.as_list.get[<[x].add[1]>].unescaped.as_list.set[<material[air]>].at[<[z].add[1]>].escaped>].at[<[x].add[1]>].escaped>
                        #place cooldown
                        - wait 10t
                        #check adjacent blocks in the schematic matrix for the same material
                        - ~run task_check_adjacent def:<[builder_obj]>|<[passed_schematic]>|<[origin]>|<[current_material]>|<[material_sound]>|<[x]>|<[y]>|<[z]>
                - define z:<[z].add[1]>
            - define x:<[x].add[1]>
            - define z:0
        - define y:<[y].add[1]>
        - define x:0
task_check_adjacent:
    type: task
    definitions: builder_obj|passed_schematic|origin|current_material|material_sound|x|y|z
    debug: fasle
    script:
    #adjacent blocks if they match the material of the last placed block
    #only the next x y and z are checked, all previous ones have already been checked by the build task
    #fix <> in .get[] tag
    - if <[x].add[2]> <= <schematic[<[passed_schematic]>].width>:
        #check next x for current material and check if the space is empty
        - if <[builder_obj].flag[<[passed_schematic]>_cubic].get[<[y].add[1]>].unescaped.as_list.get[<[x].add[2]>].unescaped.as_list.get[<[z].add[1]>].as_material.name> == <[current_material].name> && <[origin].add[<[x]>,<[y]>,<[z]>].material.name> == air:
            - ~walk <[builder_obj]> <[origin].add[<[x]>,<[y]>,<[z]>]> auto_range radius:1
            #replace the block and add effects
            - modifyblock <[origin].add[<[x].add[1]>,<[y]>,<[z]>]> <[current_material]>
            - animate <[builder_obj]> animation:ARM_SWING
            - playsound <[origin].add[<[x]>,<[y]>,<[z]>]> sound:<[material_sound]>
            #set the block to air in the schematic matrix
            - flag <[builder_obj]> <[passed_schematic]>_cubic[<[y].add[1]>]:<[builder_obj].flag[<[passed_schematic]>_cubic].get[<[y].add[1]>].unescaped.as_list.set[<[builder_obj].flag[<[passed_schematic]>_cubic].get[<[y].add[1]>].unescaped.as_list.get[<[x].add[1]>].unescaped.as_list.set[<material[air]>].at[<[z].add[1]>].escaped>].at[<[x].add[1]>].escaped>
            #break cooldown
            - wait 10t
            - ~run task_check_adjacent def:<[builder_obj]>|<[passed_schematic]>|<[origin]>|<[current_material]>|<[material_sound]>|<[x].add[1]>|<[y]>|<[z]>
    #check next z for current material and check if the space is empty
    - if <[z].add[2]> <= <schematic[<[passed_schematic]>].length>:
        - if <[builder_obj].flag[<[passed_schematic]>_cubic].get[<[y].add[1]>].unescaped.as_list.get[<[x].add[1]>].unescaped.as_list.get[<[z].add[2]>].as_material.name> == <[current_material].name> && <[origin].add[<[x]>,<[y]>,<[z]>].material.name> == air:
            - ~walk <[builder_obj]> <[origin].add[<[x]>,<[y]>,<[z]>]> auto_range
            #replace the block and add effects
            - modifyblock <[origin].add[<[x]>,<[y]>,<[z].add[1]>]> <[current_material]>
            - animate <[builder_obj]> animation:ARM_SWING
            - playsound <[origin].add[<[x]>,<[y]>,<[z]>]> sound:<[material_sound]>
            #set the block to air in the schematic matrix
            - flag <[builder_obj]> <[passed_schematic]>_cubic[<[y].add[1]>]:<[builder_obj].flag[<[passed_schematic]>_cubic].get[<[y].add[1]>].unescaped.as_list.set[<[builder_obj].flag[<[passed_schematic]>_cubic].get[<[y].add[1]>].unescaped.as_list.get[<[x].add[1]>].unescaped.as_list.set[<material[air]>].at[<[z].add[1]>].escaped>].at[<[x].add[1]>].escaped>
            #break cooldown
            - wait 10t
            - ~run task_check_adjacent def:<[builder_obj]>|<[passed_schematic]>|<[origin]>|<[current_material]>|<[material_sound]>|<[x]>|<[y]>|<[z].add[1]>
    #check next y for current material and check if the space is empty
    - if <[y].add[2]> <= <schematic[<[passed_schematic]>].length>:
        - if <[builder_obj].flag[<[passed_schematic]>_cubic].get[<[y].add[2]>].unescaped.as_list.get[<[x].add[1]>].unescaped.as_list.get[<[z].add[1]>].as_material.name> == <[current_material].name> && <[origin].add[<[x]>,<[y]>,<[z]>].material.name> == air:
            - ~walk <[builder_obj]> <[origin].add[<[x]>,<[y]>,<[z]>]> auto_range
            #replace the block and add effects
            - modifyblock <[origin].add[<[x]>,<[y].add[1]>,<[z]>]> <[current_material]>
            - animate <[builder_obj]> animation:ARM_SWING
            - playsound <[origin].add[<[x]>,<[y]>,<[z]>]> sound:<[material_sound]>
            #set the block to air in the schematic matrix
            - flag <[builder_obj]> <[passed_schematic]>_cubic[<[y].add[2]>]:<[builder_obj].flag[<[passed_schematic]>_cubic].get[<[y].add[2]>].unescaped.as_list.set[<[builder_obj].flag[<[passed_schematic]>_cubic].get[<[y].add[2]>].unescaped.as_list.get[<[x].add[1]>].unescaped.as_list.set[<material[air]>].at[<[z].add[1]>].escaped>].at[<[x].add[1]>].escaped>
            #break cooldown
            - wait 10t
            - ~run task_check_adjacent def:<[builder_obj]>|<[passed_schematic]>|<[origin]>|<[current_material]>|<[material_sound]>|<[x]>|<[y].add[1]>|<[z]>
#commands
task_clear_area:
    type: task
    debug: false
    definitions: builder_obj|current_schematic|origin
    script:
    #clear the area for a schematic, top to bottom
    - define x:0
    - define y:<schematic[<[current_schematic]>].height.sub[1]>
    - define z:0
    - while <[y]> >= 0:
        - while <[x]> < <schematic[<[current_schematic]>].width>:
            - wait 1t
            - while <[z]> < <schematic[<[current_schematic]>].length>:
                #check if there is something to remove thats not bedrock
                - if <location[<[origin]>].add[<[x]>,<[y]>,<[z]>].material> != <material[air]> && <location[<[origin]>].add[<[x]>,<[y]>,<[z]>].material> != <material[bedrock]>:
                    #move to the block and break it, gain the item if its breakable with an iron pickaxe
                    - ~walk <npc[<[builder_obj]>]> <location[<[origin]>].add[<[x]>,<[y]>,<[z]>]> auto_range
                    - give <location[<[origin]>].add[<[x]>,<[y]>,<[z]>].drops[iron_pickaxe]> to:<npc[<[builder_obj]>].inventory>
                    - modifyblock <location[<[origin]>].add[<[x]>,<[y]>,<[z]>]> <material[air]>
                    - animate <[builder_obj]> animation:ARM_SWING
                    #break cooldown
                    - wait 10t
                - define z:<[z].add[1]>
            - define x:<[x].add[1]>
            - define z:0
        - define y:<[y].sub[1]>
        - define x:0
reset_command: