redscript-mc 1.2.9 → 1.2.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (219) hide show
  1. package/README.md +35 -33
  2. package/README.zh.md +35 -33
  3. package/demo.gif +0 -0
  4. package/dist/__tests__/mc-integration.test.js +85 -0
  5. package/dist/ast/types.d.ts +84 -2
  6. package/dist/index.d.ts +1 -1
  7. package/dist/index.js +1 -1
  8. package/dist/lexer/index.d.ts +1 -1
  9. package/dist/lexer/index.js +2 -0
  10. package/dist/lowering/index.d.ts +3 -0
  11. package/dist/lowering/index.js +119 -11
  12. package/dist/optimizer/dce.js +6 -0
  13. package/dist/parser/index.d.ts +4 -0
  14. package/dist/parser/index.js +171 -18
  15. package/package.json +1 -1
  16. package/src/__tests__/fixtures/array-test.mcrs +30 -0
  17. package/src/__tests__/fixtures/break-continue-test.mcrs +46 -0
  18. package/src/__tests__/fixtures/enum-test.mcrs +37 -0
  19. package/src/__tests__/fixtures/foreach-at-test.mcrs +33 -0
  20. package/src/__tests__/fixtures/match-range-test.mcrs +45 -0
  21. package/src/__tests__/fixtures/struct-test.mcrs +34 -0
  22. package/src/__tests__/mc-integration.test.ts +97 -0
  23. package/src/ast/types.ts +24 -1
  24. package/src/index.ts +1 -1
  25. package/src/lexer/index.ts +3 -1
  26. package/src/lowering/index.ts +123 -11
  27. package/src/optimizer/dce.ts +6 -0
  28. package/src/parser/index.ts +159 -18
  29. package/test-datapacks/README.md +67 -0
  30. package/test-datapacks/test_control_flow/data/minecraft/tags/function/load.json +5 -0
  31. package/test-datapacks/test_control_flow/data/test_control_flow/function/__load.mcfunction +41 -0
  32. package/test-datapacks/test_control_flow/data/test_control_flow/function/run_control_flow_tests.mcfunction +21 -0
  33. package/test-datapacks/test_control_flow/data/test_control_flow/function/test_break/else_7.mcfunction +3 -0
  34. package/test-datapacks/test_control_flow/data/test_control_flow/function/test_break/else_8.mcfunction +3 -0
  35. package/test-datapacks/test_control_flow/data/test_control_flow/function/test_break/for_body_1.mcfunction +5 -0
  36. package/test-datapacks/test_control_flow/data/test_control_flow/function/test_break/for_check_0.mcfunction +5 -0
  37. package/test-datapacks/test_control_flow/data/test_control_flow/function/test_break/for_continue_2.mcfunction +5 -0
  38. package/test-datapacks/test_control_flow/data/test_control_flow/function/test_break/for_exit_2.mcfunction +5 -0
  39. package/test-datapacks/test_control_flow/data/test_control_flow/function/test_break/for_exit_3.mcfunction +5 -0
  40. package/test-datapacks/test_control_flow/data/test_control_flow/function/test_break/merge_5.mcfunction +5 -0
  41. package/test-datapacks/test_control_flow/data/test_control_flow/function/test_break/merge_6.mcfunction +2 -0
  42. package/test-datapacks/test_control_flow/data/test_control_flow/function/test_break/merge_8.mcfunction +1 -0
  43. package/test-datapacks/test_control_flow/data/test_control_flow/function/test_break/merge_9.mcfunction +1 -0
  44. package/test-datapacks/test_control_flow/data/test_control_flow/function/test_break/then_3.mcfunction +3 -0
  45. package/test-datapacks/test_control_flow/data/test_control_flow/function/test_break/then_4.mcfunction +3 -0
  46. package/test-datapacks/test_control_flow/data/test_control_flow/function/test_break/then_6.mcfunction +3 -0
  47. package/test-datapacks/test_control_flow/data/test_control_flow/function/test_break/then_7.mcfunction +3 -0
  48. package/test-datapacks/test_control_flow/data/test_control_flow/function/test_break.mcfunction +4 -0
  49. package/test-datapacks/test_control_flow/data/test_control_flow/function/test_complex_conditions/else_1.mcfunction +3 -0
  50. package/test-datapacks/test_control_flow/data/test_control_flow/function/test_complex_conditions/else_10.mcfunction +3 -0
  51. package/test-datapacks/test_control_flow/data/test_control_flow/function/test_complex_conditions/else_4.mcfunction +3 -0
  52. package/test-datapacks/test_control_flow/data/test_control_flow/function/test_complex_conditions/else_7.mcfunction +3 -0
  53. package/test-datapacks/test_control_flow/data/test_control_flow/function/test_complex_conditions/merge_11.mcfunction +1 -0
  54. package/test-datapacks/test_control_flow/data/test_control_flow/function/test_complex_conditions/merge_2.mcfunction +9 -0
  55. package/test-datapacks/test_control_flow/data/test_control_flow/function/test_complex_conditions/merge_5.mcfunction +7 -0
  56. package/test-datapacks/test_control_flow/data/test_control_flow/function/test_complex_conditions/merge_8.mcfunction +13 -0
  57. package/test-datapacks/test_control_flow/data/test_control_flow/function/test_complex_conditions/then_0.mcfunction +3 -0
  58. package/test-datapacks/test_control_flow/data/test_control_flow/function/test_complex_conditions/then_3.mcfunction +3 -0
  59. package/test-datapacks/test_control_flow/data/test_control_flow/function/test_complex_conditions/then_6.mcfunction +3 -0
  60. package/test-datapacks/test_control_flow/data/test_control_flow/function/test_complex_conditions/then_9.mcfunction +3 -0
  61. package/test-datapacks/test_control_flow/data/test_control_flow/function/test_complex_conditions.mcfunction +12 -0
  62. package/test-datapacks/test_control_flow/data/test_control_flow/function/test_continue/else_7.mcfunction +3 -0
  63. package/test-datapacks/test_control_flow/data/test_control_flow/function/test_continue/else_8.mcfunction +3 -0
  64. package/test-datapacks/test_control_flow/data/test_control_flow/function/test_continue/for_body_1.mcfunction +7 -0
  65. package/test-datapacks/test_control_flow/data/test_control_flow/function/test_continue/for_check_0.mcfunction +5 -0
  66. package/test-datapacks/test_control_flow/data/test_control_flow/function/test_continue/for_continue_2.mcfunction +5 -0
  67. package/test-datapacks/test_control_flow/data/test_control_flow/function/test_continue/for_exit_2.mcfunction +5 -0
  68. package/test-datapacks/test_control_flow/data/test_control_flow/function/test_continue/for_exit_3.mcfunction +5 -0
  69. package/test-datapacks/test_control_flow/data/test_control_flow/function/test_continue/merge_5.mcfunction +8 -0
  70. package/test-datapacks/test_control_flow/data/test_control_flow/function/test_continue/merge_6.mcfunction +5 -0
  71. package/test-datapacks/test_control_flow/data/test_control_flow/function/test_continue/merge_8.mcfunction +1 -0
  72. package/test-datapacks/test_control_flow/data/test_control_flow/function/test_continue/merge_9.mcfunction +1 -0
  73. package/test-datapacks/test_control_flow/data/test_control_flow/function/test_continue/then_3.mcfunction +2 -0
  74. package/test-datapacks/test_control_flow/data/test_control_flow/function/test_continue/then_4.mcfunction +2 -0
  75. package/test-datapacks/test_control_flow/data/test_control_flow/function/test_continue/then_6.mcfunction +3 -0
  76. package/test-datapacks/test_control_flow/data/test_control_flow/function/test_continue/then_7.mcfunction +3 -0
  77. package/test-datapacks/test_control_flow/data/test_control_flow/function/test_continue.mcfunction +4 -0
  78. package/test-datapacks/test_control_flow/data/test_control_flow/function/test_for_loop/else_13.mcfunction +3 -0
  79. package/test-datapacks/test_control_flow/data/test_control_flow/function/test_for_loop/else_16.mcfunction +3 -0
  80. package/test-datapacks/test_control_flow/data/test_control_flow/function/test_for_loop/else_4.mcfunction +3 -0
  81. package/test-datapacks/test_control_flow/data/test_control_flow/function/test_for_loop/else_5.mcfunction +3 -0
  82. package/test-datapacks/test_control_flow/data/test_control_flow/function/test_for_loop/for_body_1.mcfunction +5 -0
  83. package/test-datapacks/test_control_flow/data/test_control_flow/function/test_for_loop/for_body_10.mcfunction +8 -0
  84. package/test-datapacks/test_control_flow/data/test_control_flow/function/test_for_loop/for_body_12.mcfunction +5 -0
  85. package/test-datapacks/test_control_flow/data/test_control_flow/function/test_for_loop/for_body_7.mcfunction +3 -0
  86. package/test-datapacks/test_control_flow/data/test_control_flow/function/test_for_loop/for_body_8.mcfunction +3 -0
  87. package/test-datapacks/test_control_flow/data/test_control_flow/function/test_for_loop/for_check_0.mcfunction +5 -0
  88. package/test-datapacks/test_control_flow/data/test_control_flow/function/test_for_loop/for_check_11.mcfunction +5 -0
  89. package/test-datapacks/test_control_flow/data/test_control_flow/function/test_for_loop/for_check_6.mcfunction +5 -0
  90. package/test-datapacks/test_control_flow/data/test_control_flow/function/test_for_loop/for_check_7.mcfunction +5 -0
  91. package/test-datapacks/test_control_flow/data/test_control_flow/function/test_for_loop/for_check_9.mcfunction +5 -0
  92. package/test-datapacks/test_control_flow/data/test_control_flow/function/test_for_loop/for_continue_13.mcfunction +5 -0
  93. package/test-datapacks/test_control_flow/data/test_control_flow/function/test_for_loop/for_continue_2.mcfunction +5 -0
  94. package/test-datapacks/test_control_flow/data/test_control_flow/function/test_for_loop/for_continue_9.mcfunction +5 -0
  95. package/test-datapacks/test_control_flow/data/test_control_flow/function/test_for_loop/for_exit_10.mcfunction +5 -0
  96. package/test-datapacks/test_control_flow/data/test_control_flow/function/test_for_loop/for_exit_11.mcfunction +5 -0
  97. package/test-datapacks/test_control_flow/data/test_control_flow/function/test_for_loop/for_exit_14.mcfunction +2 -0
  98. package/test-datapacks/test_control_flow/data/test_control_flow/function/test_for_loop/for_exit_2.mcfunction +5 -0
  99. package/test-datapacks/test_control_flow/data/test_control_flow/function/test_for_loop/for_exit_3.mcfunction +5 -0
  100. package/test-datapacks/test_control_flow/data/test_control_flow/function/test_for_loop/for_exit_8.mcfunction +5 -0
  101. package/test-datapacks/test_control_flow/data/test_control_flow/function/test_for_loop/merge_14.mcfunction +1 -0
  102. package/test-datapacks/test_control_flow/data/test_control_flow/function/test_for_loop/merge_17.mcfunction +1 -0
  103. package/test-datapacks/test_control_flow/data/test_control_flow/function/test_for_loop/merge_5.mcfunction +4 -0
  104. package/test-datapacks/test_control_flow/data/test_control_flow/function/test_for_loop/merge_6.mcfunction +4 -0
  105. package/test-datapacks/test_control_flow/data/test_control_flow/function/test_for_loop/then_12.mcfunction +3 -0
  106. package/test-datapacks/test_control_flow/data/test_control_flow/function/test_for_loop/then_15.mcfunction +3 -0
  107. package/test-datapacks/test_control_flow/data/test_control_flow/function/test_for_loop/then_3.mcfunction +3 -0
  108. package/test-datapacks/test_control_flow/data/test_control_flow/function/test_for_loop/then_4.mcfunction +3 -0
  109. package/test-datapacks/test_control_flow/data/test_control_flow/function/test_for_loop.mcfunction +4 -0
  110. package/test-datapacks/test_control_flow/data/test_control_flow/function/test_foreach_at/foreach_0.mcfunction +2 -0
  111. package/test-datapacks/test_control_flow/data/test_control_flow/function/test_foreach_at.mcfunction +5 -0
  112. package/test-datapacks/test_control_flow/data/test_control_flow/function/test_foreach_selector/else_1.mcfunction +3 -0
  113. package/test-datapacks/test_control_flow/data/test_control_flow/function/test_foreach_selector/foreach_0.mcfunction +4 -0
  114. package/test-datapacks/test_control_flow/data/test_control_flow/function/test_foreach_selector/merge_2.mcfunction +2 -0
  115. package/test-datapacks/test_control_flow/data/test_control_flow/function/test_foreach_selector/then_0.mcfunction +3 -0
  116. package/test-datapacks/test_control_flow/data/test_control_flow/function/test_foreach_selector.mcfunction +11 -0
  117. package/test-datapacks/test_control_flow/data/test_control_flow/function/test_if_else/else_1.mcfunction +3 -0
  118. package/test-datapacks/test_control_flow/data/test_control_flow/function/test_if_else/else_13.mcfunction +5 -0
  119. package/test-datapacks/test_control_flow/data/test_control_flow/function/test_if_else/else_16.mcfunction +3 -0
  120. package/test-datapacks/test_control_flow/data/test_control_flow/function/test_if_else/else_4.mcfunction +3 -0
  121. package/test-datapacks/test_control_flow/data/test_control_flow/function/test_if_else/merge_11.mcfunction +2 -0
  122. package/test-datapacks/test_control_flow/data/test_control_flow/function/test_if_else/merge_14.mcfunction +1 -0
  123. package/test-datapacks/test_control_flow/data/test_control_flow/function/test_if_else/merge_17.mcfunction +2 -0
  124. package/test-datapacks/test_control_flow/data/test_control_flow/function/test_if_else/merge_2.mcfunction +5 -0
  125. package/test-datapacks/test_control_flow/data/test_control_flow/function/test_if_else/merge_5.mcfunction +5 -0
  126. package/test-datapacks/test_control_flow/data/test_control_flow/function/test_if_else/merge_8.mcfunction +6 -0
  127. package/test-datapacks/test_control_flow/data/test_control_flow/function/test_if_else/then_0.mcfunction +3 -0
  128. package/test-datapacks/test_control_flow/data/test_control_flow/function/test_if_else/then_12.mcfunction +3 -0
  129. package/test-datapacks/test_control_flow/data/test_control_flow/function/test_if_else/then_15.mcfunction +3 -0
  130. package/test-datapacks/test_control_flow/data/test_control_flow/function/test_if_else/then_3.mcfunction +3 -0
  131. package/test-datapacks/test_control_flow/data/test_control_flow/function/test_if_else/then_6.mcfunction +5 -0
  132. package/test-datapacks/test_control_flow/data/test_control_flow/function/test_if_else/then_9.mcfunction +3 -0
  133. package/test-datapacks/test_control_flow/data/test_control_flow/function/test_if_else.mcfunction +6 -0
  134. package/test-datapacks/test_control_flow/data/test_control_flow/function/test_match/match_0.mcfunction +3 -0
  135. package/test-datapacks/test_control_flow/data/test_control_flow/function/test_match/match_1.mcfunction +3 -0
  136. package/test-datapacks/test_control_flow/data/test_control_flow/function/test_match/match_2.mcfunction +3 -0
  137. package/test-datapacks/test_control_flow/data/test_control_flow/function/test_match/match_3.mcfunction +2 -0
  138. package/test-datapacks/test_control_flow/data/test_control_flow/function/test_match/match_4.mcfunction +3 -0
  139. package/test-datapacks/test_control_flow/data/test_control_flow/function/test_match/match_5.mcfunction +3 -0
  140. package/test-datapacks/test_control_flow/data/test_control_flow/function/test_match/match_6.mcfunction +3 -0
  141. package/test-datapacks/test_control_flow/data/test_control_flow/function/test_match/match_7.mcfunction +3 -0
  142. package/test-datapacks/test_control_flow/data/test_control_flow/function/test_match/match_8.mcfunction +3 -0
  143. package/test-datapacks/test_control_flow/data/test_control_flow/function/test_match/match_9.mcfunction +2 -0
  144. package/test-datapacks/test_control_flow/data/test_control_flow/function/test_match.mcfunction +15 -0
  145. package/test-datapacks/test_control_flow/data/test_control_flow/function/test_while_loop/else_13.mcfunction +3 -0
  146. package/test-datapacks/test_control_flow/data/test_control_flow/function/test_while_loop/else_4.mcfunction +3 -0
  147. package/test-datapacks/test_control_flow/data/test_control_flow/function/test_while_loop/loop_body_1.mcfunction +5 -0
  148. package/test-datapacks/test_control_flow/data/test_control_flow/function/test_while_loop/loop_body_7.mcfunction +8 -0
  149. package/test-datapacks/test_control_flow/data/test_control_flow/function/test_while_loop/loop_check_0.mcfunction +5 -0
  150. package/test-datapacks/test_control_flow/data/test_control_flow/function/test_while_loop/loop_check_6.mcfunction +4 -0
  151. package/test-datapacks/test_control_flow/data/test_control_flow/function/test_while_loop/loop_exit_2.mcfunction +5 -0
  152. package/test-datapacks/test_control_flow/data/test_control_flow/function/test_while_loop/loop_exit_8.mcfunction +5 -0
  153. package/test-datapacks/test_control_flow/data/test_control_flow/function/test_while_loop/merge_11.mcfunction +2 -0
  154. package/test-datapacks/test_control_flow/data/test_control_flow/function/test_while_loop/merge_14.mcfunction +1 -0
  155. package/test-datapacks/test_control_flow/data/test_control_flow/function/test_while_loop/merge_5.mcfunction +3 -0
  156. package/test-datapacks/test_control_flow/data/test_control_flow/function/test_while_loop/then_12.mcfunction +3 -0
  157. package/test-datapacks/test_control_flow/data/test_control_flow/function/test_while_loop/then_3.mcfunction +3 -0
  158. package/test-datapacks/test_control_flow/data/test_control_flow/function/test_while_loop/then_9.mcfunction +2 -0
  159. package/test-datapacks/test_control_flow/data/test_control_flow/function/test_while_loop.mcfunction +3 -0
  160. package/test-datapacks/test_control_flow/pack.mcmeta +6 -0
  161. package/test-datapacks/test_control_flow.mcrs +242 -0
  162. package/test-datapacks/test_decorators/data/minecraft/tags/function/load.json +5 -0
  163. package/test-datapacks/test_decorators/data/minecraft/tags/function/tick.json +5 -0
  164. package/test-datapacks/test_decorators/data/test_decorators/function/__load.mcfunction +20 -0
  165. package/test-datapacks/test_decorators/data/test_decorators/function/__tick.mcfunction +3 -0
  166. package/test-datapacks/test_decorators/data/test_decorators/function/every_second/merge_2.mcfunction +9 -0
  167. package/test-datapacks/test_decorators/data/test_decorators/function/every_second/merge_5.mcfunction +1 -0
  168. package/test-datapacks/test_decorators/data/test_decorators/function/every_second/then_0.mcfunction +1 -0
  169. package/test-datapacks/test_decorators/data/test_decorators/function/every_second/then_3.mcfunction +4 -0
  170. package/test-datapacks/test_decorators/data/test_decorators/function/every_second/tick_body.mcfunction +6 -0
  171. package/test-datapacks/test_decorators/data/test_decorators/function/every_second/tick_skip.mcfunction +1 -0
  172. package/test-datapacks/test_decorators/data/test_decorators/function/every_second.mcfunction +5 -0
  173. package/test-datapacks/test_decorators/data/test_decorators/function/on_load.mcfunction +2 -0
  174. package/test-datapacks/test_decorators/data/test_decorators/function/on_test_trigger.mcfunction +2 -0
  175. package/test-datapacks/test_decorators/data/test_decorators/function/on_tick/merge_2.mcfunction +10 -0
  176. package/test-datapacks/test_decorators/data/test_decorators/function/on_tick/merge_5.mcfunction +5 -0
  177. package/test-datapacks/test_decorators/data/test_decorators/function/on_tick/merge_8.mcfunction +1 -0
  178. package/test-datapacks/test_decorators/data/test_decorators/function/on_tick/then_0.mcfunction +1 -0
  179. package/test-datapacks/test_decorators/data/test_decorators/function/on_tick/then_3.mcfunction +3 -0
  180. package/test-datapacks/test_decorators/data/test_decorators/function/on_tick/then_6.mcfunction +4 -0
  181. package/test-datapacks/test_decorators/data/test_decorators/function/on_tick.mcfunction +5 -0
  182. package/test-datapacks/test_decorators/data/test_decorators/function/run_decorator_tests.mcfunction +7 -0
  183. package/test-datapacks/test_decorators/data/test_decorators/function/setup_trigger_test.mcfunction +4 -0
  184. package/test-datapacks/test_decorators/data/test_decorators/function/start_slow_tick_test.mcfunction +4 -0
  185. package/test-datapacks/test_decorators/data/test_decorators/function/start_tick_test.mcfunction +4 -0
  186. package/test-datapacks/test_decorators/data/test_decorators/function/stop_tick_test.mcfunction +3 -0
  187. package/test-datapacks/test_decorators/pack.mcmeta +6 -0
  188. package/test-datapacks/test_decorators.mcrs +81 -0
  189. package/test-datapacks/test_events/data/minecraft/tags/function/load.json +5 -0
  190. package/test-datapacks/test_events/data/test_events/advancements/on_death_on_player_death.json +10 -0
  191. package/test-datapacks/test_events/data/test_events/function/__load.mcfunction +3 -0
  192. package/test-datapacks/test_events/data/test_events/function/on_player_death.mcfunction +3 -0
  193. package/test-datapacks/test_events/data/test_events/function/run_event_tests.mcfunction +5 -0
  194. package/test-datapacks/test_events/data/test_events/function/setup_events.mcfunction +3 -0
  195. package/test-datapacks/test_events/data/test_events/function/spawn_test_entity.mcfunction +3 -0
  196. package/test-datapacks/test_events/data/test_events/function/test_advancement_event.mcfunction +4 -0
  197. package/test-datapacks/test_events/pack.mcmeta +6 -0
  198. package/test-datapacks/test_events.mcrs +37 -0
  199. package/test-datapacks/test_fstrings/data/minecraft/tags/function/load.json +5 -0
  200. package/test-datapacks/test_fstrings/data/test_fstrings/function/__load.mcfunction +10 -0
  201. package/test-datapacks/test_fstrings/data/test_fstrings/function/run_fstring_tests.mcfunction +15 -0
  202. package/test-datapacks/test_fstrings/data/test_fstrings/function/test_actionbar_fstring.mcfunction +4 -0
  203. package/test-datapacks/test_fstrings/data/test_fstrings/function/test_announce.mcfunction +3 -0
  204. package/test-datapacks/test_fstrings/data/test_fstrings/function/test_multi_var_fstring.mcfunction +9 -0
  205. package/test-datapacks/test_fstrings/data/test_fstrings/function/test_say_fstring.mcfunction +4 -0
  206. package/test-datapacks/test_fstrings/data/test_fstrings/function/test_tell.mcfunction +3 -0
  207. package/test-datapacks/test_fstrings/data/test_fstrings/function/test_title_fstring.mcfunction +4 -0
  208. package/test-datapacks/test_fstrings/pack.mcmeta +6 -0
  209. package/test-datapacks/test_fstrings.mcrs +58 -0
  210. package/test-datapacks/test_timers/data/minecraft/tags/function/load.json +5 -0
  211. package/test-datapacks/test_timers/data/test_timers/function/__interval_0.mcfunction +3 -0
  212. package/test-datapacks/test_timers/data/test_timers/function/__interval_body_0.mcfunction +5 -0
  213. package/test-datapacks/test_timers/data/test_timers/function/__load.mcfunction +5 -0
  214. package/test-datapacks/test_timers/data/test_timers/function/__timeout_0.mcfunction +2 -0
  215. package/test-datapacks/test_timers/data/test_timers/function/run_timer_tests.mcfunction +5 -0
  216. package/test-datapacks/test_timers/data/test_timers/function/test_set_interval.mcfunction +5 -0
  217. package/test-datapacks/test_timers/data/test_timers/function/test_set_timeout.mcfunction +3 -0
  218. package/test-datapacks/test_timers/pack.mcmeta +6 -0
  219. package/test-datapacks/test_timers.mcrs +35 -0
package/README.md CHANGED
@@ -20,55 +20,56 @@ Write clean game logic. RedScript handles the scoreboard spaghetti.
20
20
 
21
21
  ### 🚀 [Try it online — no install needed!](https://redscript-ide.pages.dev)
22
22
 
23
+ <img src="./demo.gif" alt="RedScript Demo" width="400" />
24
+
25
+ *↑ Particles spawning at player position every tick — 100% vanilla, no mods! Just 30 lines of RedScript with full control flow: `if`, `foreach`, `@tick`, f-strings, and more.*
26
+
23
27
  </div>
24
28
 
25
29
  ---
26
30
 
27
31
  ### What is RedScript?
28
32
 
29
- You want to make a Minecraft mini-game. You need a countdown timer, kill counter, respawn logic, and a scoreboard display. In vanilla MC, that's 40+ `.mcfunction` files, hundreds of `execute if score` commands, and a weekend of debugging.
33
+ RedScript is a typed scripting language that compiles to vanilla Minecraft datapacks. Write clean code with variables, functions, loops, and events RedScript handles the scoreboard commands and `.mcfunction` files for you.
30
34
 
31
- With RedScript, it's this:
35
+ **The demo above?** Just 30 lines:
32
36
 
33
37
  ```rs
34
- // pvp_game.mcrs
35
- import "stdlib/player.mcrs"
36
-
37
- const GAME_TIME: int = 300;
38
-
39
- @tick(rate=20)
40
- fn every_second() {
41
- let time: int = scoreboard_get(#game, #timer);
42
-
43
- if (time <= 0) {
44
- end_game();
45
- return;
38
+ let counter: int = 0;
39
+ let running: bool = false;
40
+
41
+ @tick fn demo_tick() {
42
+ if (!running) { return; }
43
+ counter = counter + 1;
44
+
45
+ foreach (p in @a) at @s {
46
+ particle("minecraft:end_rod", ~0, ~1, ~0, 0.5, 0.5, 0.5, 0.1, 5);
47
+ }
48
+
49
+ if (counter % 20 == 0) {
50
+ say(f"Running for {counter} ticks");
46
51
  }
47
-
48
- scoreboard_set(#game, #timer, time - 1);
49
- actionbar(@a, "⏱ ${time}s remaining");
50
- }
51
-
52
- fn start_game() {
53
- scoreboard_set(#game, #timer, GAME_TIME);
54
- scoreboard_set(#game, #running, 1);
55
- title(@a, "Fight!", "Game started");
56
- tp(@a, (0, 64, 0));
57
52
  }
58
53
 
59
- fn end_game() {
60
- scoreboard_set(#game, #running, 0);
61
- title(@a, "Game Over!");
62
- announce("Thanks for playing!");
54
+ @keep fn start() {
55
+ running = true;
56
+ counter = 0;
57
+ say(f"Demo started!");
63
58
  }
64
59
 
65
- @on_death
66
- fn on_kill() {
67
- scoreboard_add(@s, #kills, 1);
60
+ @keep fn stop() {
61
+ running = false;
62
+ say(f"Demo stopped at {counter} ticks.");
68
63
  }
69
64
  ```
70
65
 
71
- One file. Compiles to a ready-to-use datapack in seconds.
66
+ **What you get:**
67
+ - ✅ `let` / `const` variables (no more `scoreboard players set`)
68
+ - ✅ `if` / `else` / `for` / `foreach` control flow
69
+ - ✅ `@tick` / `@load` / `@on(Event)` decorators
70
+ - ✅ `foreach (p in @a) at @s` — iterate entities with execute context
71
+ - ✅ f-strings like `f"Score: {points}"` for dynamic output
72
+ - ✅ One file → ready-to-use datapack
72
73
 
73
74
  ---
74
75
 
@@ -199,7 +200,8 @@ if (hp <= 0) {
199
200
  }
200
201
 
201
202
  for (let i: int = 0; i < 10; i = i + 1) {
202
- summon("minecraft:zombie", (i, 64, 0));
203
+ say(f"Spawning wave {i}");
204
+ summon("minecraft:zombie", ~0, ~0, ~0);
203
205
  }
204
206
 
205
207
  foreach (player in @a) {
package/README.zh.md CHANGED
@@ -20,55 +20,56 @@
20
20
 
21
21
  ### 🚀 [在线试用 — 无需安装!](https://redscript-ide.pages.dev)
22
22
 
23
+ <img src="./demo.gif" alt="RedScript Demo" width="400" />
24
+
25
+ *↑ 每 tick 在玩家位置生成粒子 — 纯原版,无需 MOD!仅 30 行 RedScript,包含完整控制流:`if`、`foreach`、`@tick`、f-strings 等。*
26
+
23
27
  </div>
24
28
 
25
29
  ---
26
30
 
27
31
  ### RedScript 是什么?
28
32
 
29
- 你想做一个 Minecraft 小游戏——倒计时、击杀计数、复活逻辑、记分板显示。用原版 MC 的话,这意味着 40+ 个 `.mcfunction` 文件、几百条 `execute if score` 命令,还要花一个周末调试。
33
+ RedScript 是一门编译到原版 Minecraft 数据包的脚本语言。用变量、函数、循环、事件写代码,RedScript 帮你生成记分板命令和 `.mcfunction` 文件。
30
34
 
31
- RedScript,就是这样:
35
+ **上面的演示?** 只有 30 行:
32
36
 
33
37
  ```rs
34
- // pvp_game.mcrs
35
- import "stdlib/player.mcrs"
36
-
37
- const GAME_TIME: int = 300;
38
-
39
- @tick(rate=20)
40
- fn every_second() {
41
- let time: int = scoreboard_get(#game, #timer);
42
-
43
- if (time <= 0) {
44
- end_game();
45
- return;
38
+ let counter: int = 0;
39
+ let running: bool = false;
40
+
41
+ @tick fn demo_tick() {
42
+ if (!running) { return; }
43
+ counter = counter + 1;
44
+
45
+ foreach (p in @a) at @s {
46
+ particle("minecraft:end_rod", ~0, ~1, ~0, 0.5, 0.5, 0.5, 0.1, 5);
47
+ }
48
+
49
+ if (counter % 20 == 0) {
50
+ say(f"已运行 {counter} ticks");
46
51
  }
47
-
48
- scoreboard_set(#game, #timer, time - 1);
49
- actionbar(@a, "⏱ 剩余 ${time} 秒");
50
- }
51
-
52
- fn start_game() {
53
- scoreboard_set(#game, #timer, GAME_TIME);
54
- scoreboard_set(#game, #running, 1);
55
- title(@a, "开始战斗!", "游戏已开始");
56
- tp(@a, (0, 64, 0));
57
52
  }
58
53
 
59
- fn end_game() {
60
- scoreboard_set(#game, #running, 0);
61
- title(@a, "游戏结束!");
62
- announce("感谢游玩!");
54
+ @keep fn start() {
55
+ running = true;
56
+ counter = 0;
57
+ say(f"Demo 已启动!");
63
58
  }
64
59
 
65
- @on_death
66
- fn on_kill() {
67
- scoreboard_add(@s, #kills, 1);
60
+ @keep fn stop() {
61
+ running = false;
62
+ say(f"Demo 已停止,共运行 {counter} ticks。");
68
63
  }
69
64
  ```
70
65
 
71
- 一个文件,几秒钟编译出可以直接用的 datapack。
66
+ **你得到:**
67
+ - ✅ `let` / `const` 变量(告别 `scoreboard players set`)
68
+ - ✅ `if` / `else` / `for` / `foreach` 完整控制流
69
+ - ✅ `@tick` / `@load` / `@on(Event)` 装饰器
70
+ - ✅ `foreach (p in @a) at @s` — 遍历实体并设置执行上下文
71
+ - ✅ f-strings 如 `f"分数: {points}"` 动态输出
72
+ - ✅ 一个文件 → 可直接使用的 datapack
72
73
 
73
74
  ---
74
75
 
@@ -199,7 +200,8 @@ if (hp <= 0) {
199
200
  }
200
201
 
201
202
  for (let i: int = 0; i < 10; i = i + 1) {
202
- summon("minecraft:zombie", (i, 64, 0));
203
+ say(f"生成第 {i} 波");
204
+ summon("minecraft:zombie", ~0, ~0, ~0);
203
205
  }
204
206
 
205
207
  foreach (player in @a) {
package/demo.gif ADDED
Binary file
@@ -731,4 +731,89 @@ describe('MC Integration - New Features', () => {
731
731
  expect(tickResult.ok).toBe(true);
732
732
  });
733
733
  });
734
+ describe('MC Integration - Extended Coverage', () => {
735
+ test('struct-test.mcrs: struct instantiation and field access', async () => {
736
+ if (!serverOnline)
737
+ return;
738
+ writeFixtureFile('struct-test.mcrs', 'struct_test');
739
+ await mc.reload();
740
+ await mc.command('/function struct_test:__load').catch(() => { });
741
+ await mc.command('/function struct_test:test_struct');
742
+ await mc.ticks(5);
743
+ expect(await mc.scoreboard('#struct_x', 'rs')).toBe(10);
744
+ expect(await mc.scoreboard('#struct_y', 'rs')).toBe(64);
745
+ expect(await mc.scoreboard('#struct_z', 'rs')).toBe(-5);
746
+ expect(await mc.scoreboard('#struct_x2', 'rs')).toBe(15); // 10+5
747
+ expect(await mc.scoreboard('#struct_z2', 'rs')).toBe(-10); // -5*2
748
+ expect(await mc.scoreboard('#struct_alive', 'rs')).toBe(1);
749
+ expect(await mc.scoreboard('#struct_score', 'rs')).toBe(100);
750
+ });
751
+ test('enum-test.mcrs: enum values and match', async () => {
752
+ if (!serverOnline)
753
+ return;
754
+ writeFixtureFile('enum-test.mcrs', 'enum_test');
755
+ await mc.reload();
756
+ await mc.command('/function enum_test:__load').catch(() => { });
757
+ await mc.command('/function enum_test:test_enum');
758
+ await mc.ticks(5);
759
+ expect(await mc.scoreboard('#enum_phase', 'rs')).toBe(2); // Playing=2
760
+ expect(await mc.scoreboard('#enum_match', 'rs')).toBe(2); // matched Playing
761
+ expect(await mc.scoreboard('#enum_rank', 'rs')).toBe(10); // Diamond=10
762
+ expect(await mc.scoreboard('#enum_high', 'rs')).toBe(1); // Diamond > Gold
763
+ });
764
+ test('array-test.mcrs: array operations', async () => {
765
+ if (!serverOnline)
766
+ return;
767
+ writeFixtureFile('array-test.mcrs', 'array_test');
768
+ await mc.reload();
769
+ await mc.command('/function array_test:__load').catch(() => { });
770
+ await mc.command('/function array_test:test_array');
771
+ await mc.ticks(5);
772
+ expect(await mc.scoreboard('#arr_0', 'rs')).toBe(10);
773
+ expect(await mc.scoreboard('#arr_2', 'rs')).toBe(30);
774
+ expect(await mc.scoreboard('#arr_4', 'rs')).toBe(50);
775
+ expect(await mc.scoreboard('#arr_len', 'rs')).toBe(5);
776
+ expect(await mc.scoreboard('#arr_sum', 'rs')).toBe(150); // 10+20+30+40+50
777
+ expect(await mc.scoreboard('#arr_push', 'rs')).toBe(4); // [1,2,3,4].len
778
+ expect(await mc.scoreboard('#arr_pop', 'rs')).toBe(4); // popped value
779
+ });
780
+ test('break-continue-test.mcrs: break and continue statements', async () => {
781
+ if (!serverOnline)
782
+ return;
783
+ writeFixtureFile('break-continue-test.mcrs', 'break_continue_test');
784
+ await mc.reload();
785
+ await mc.command('/function break_continue_test:__load').catch(() => { });
786
+ await mc.command('/function break_continue_test:test_break_continue');
787
+ await mc.ticks(10);
788
+ expect(await mc.scoreboard('#break_at', 'rs')).toBe(5);
789
+ expect(await mc.scoreboard('#sum_evens', 'rs')).toBe(20); // 0+2+4+6+8
790
+ expect(await mc.scoreboard('#while_break', 'rs')).toBe(7);
791
+ expect(await mc.scoreboard('#nested_break', 'rs')).toBe(3); // outer completes 3 times
792
+ });
793
+ test('match-range-test.mcrs: match with range patterns', async () => {
794
+ if (!serverOnline)
795
+ return;
796
+ writeFixtureFile('match-range-test.mcrs', 'match_range_test');
797
+ await mc.reload();
798
+ await mc.command('/function match_range_test:__load').catch(() => { });
799
+ await mc.command('/function match_range_test:test_match_range');
800
+ await mc.ticks(5);
801
+ expect(await mc.scoreboard('#grade', 'rs')).toBe(4); // score=85 → B
802
+ expect(await mc.scoreboard('#boundary_59', 'rs')).toBe(1); // 59 matches 0..59
803
+ expect(await mc.scoreboard('#boundary_60', 'rs')).toBe(2); // 60 matches 60..100
804
+ expect(await mc.scoreboard('#neg_range', 'rs')).toBe(1); // -5 matches ..0
805
+ });
806
+ test('foreach-at-test.mcrs: foreach with at @s context', async () => {
807
+ if (!serverOnline)
808
+ return;
809
+ writeFixtureFile('foreach-at-test.mcrs', 'foreach_at_test');
810
+ await mc.reload();
811
+ await mc.fullReset({ clearArea: false, killEntities: true, resetScoreboards: false });
812
+ await mc.command('/function foreach_at_test:setup').catch(() => { });
813
+ await mc.command('/function foreach_at_test:test_foreach_at');
814
+ await mc.ticks(10);
815
+ expect(await mc.scoreboard('#foreach_count', 'rs')).toBe(3);
816
+ expect(await mc.scoreboard('#foreach_at_count', 'rs')).toBe(3);
817
+ });
818
+ });
734
819
  //# sourceMappingURL=mc-integration.test.js.map
@@ -247,6 +247,45 @@ export type ExecuteSubcommand = {
247
247
  } | {
248
248
  kind: 'at';
249
249
  selector: EntitySelector;
250
+ } | {
251
+ kind: 'positioned';
252
+ x: string;
253
+ y: string;
254
+ z: string;
255
+ } | {
256
+ kind: 'positioned_as';
257
+ selector: EntitySelector;
258
+ } | {
259
+ kind: 'rotated';
260
+ yaw: string;
261
+ pitch: string;
262
+ } | {
263
+ kind: 'rotated_as';
264
+ selector: EntitySelector;
265
+ } | {
266
+ kind: 'facing';
267
+ x: string;
268
+ y: string;
269
+ z: string;
270
+ } | {
271
+ kind: 'facing_entity';
272
+ selector: EntitySelector;
273
+ anchor: 'eyes' | 'feet';
274
+ } | {
275
+ kind: 'anchored';
276
+ anchor: 'eyes' | 'feet';
277
+ } | {
278
+ kind: 'align';
279
+ axes: string;
280
+ } | {
281
+ kind: 'in';
282
+ dimension: string;
283
+ } | {
284
+ kind: 'on';
285
+ relation: string;
286
+ } | {
287
+ kind: 'summon';
288
+ entity: string;
250
289
  } | {
251
290
  kind: 'if_entity';
252
291
  selector?: EntitySelector;
@@ -258,8 +297,45 @@ export type ExecuteSubcommand = {
258
297
  varName?: string;
259
298
  filters?: SelectorFilter;
260
299
  } | {
261
- kind: 'in';
262
- dimension: string;
300
+ kind: 'if_block';
301
+ pos: [string, string, string];
302
+ block: string;
303
+ } | {
304
+ kind: 'unless_block';
305
+ pos: [string, string, string];
306
+ block: string;
307
+ } | {
308
+ kind: 'if_score';
309
+ target: string;
310
+ targetObj: string;
311
+ op: string;
312
+ source: string;
313
+ sourceObj: string;
314
+ } | {
315
+ kind: 'unless_score';
316
+ target: string;
317
+ targetObj: string;
318
+ op: string;
319
+ source: string;
320
+ sourceObj: string;
321
+ } | {
322
+ kind: 'if_score_range';
323
+ target: string;
324
+ targetObj: string;
325
+ range: string;
326
+ } | {
327
+ kind: 'unless_score_range';
328
+ target: string;
329
+ targetObj: string;
330
+ range: string;
331
+ } | {
332
+ kind: 'store_result';
333
+ target: string;
334
+ targetObj: string;
335
+ } | {
336
+ kind: 'store_success';
337
+ target: string;
338
+ targetObj: string;
263
339
  };
264
340
  export type Stmt = {
265
341
  kind: 'let';
@@ -275,6 +351,12 @@ export type Stmt = {
275
351
  kind: 'return';
276
352
  value?: Expr;
277
353
  span?: Span;
354
+ } | {
355
+ kind: 'break';
356
+ span?: Span;
357
+ } | {
358
+ kind: 'continue';
359
+ span?: Span;
278
360
  } | {
279
361
  kind: 'if';
280
362
  cond: Expr;
package/dist/index.d.ts CHANGED
@@ -3,7 +3,7 @@
3
3
  *
4
4
  * Main entry point for programmatic usage.
5
5
  */
6
- export declare const version = "1.2.9";
6
+ export declare const version = "1.2.11";
7
7
  import type { Warning } from './lowering';
8
8
  import { DatapackFile } from './codegen/mcfunction';
9
9
  import type { IRModule } from './ir/types';
package/dist/index.js CHANGED
@@ -9,7 +9,7 @@ exports.MCCommandValidator = exports.generateDatapack = exports.optimize = expor
9
9
  exports.compile = compile;
10
10
  exports.check = check;
11
11
  // eslint-disable-next-line @typescript-eslint/no-var-requires
12
- exports.version = '1.2.9';
12
+ exports.version = '1.2.11';
13
13
  const lexer_1 = require("./lexer");
14
14
  const parser_1 = require("./parser");
15
15
  const typechecker_1 = require("./typechecker");
@@ -5,7 +5,7 @@
5
5
  * Handles special cases like entity selectors vs decorators,
6
6
  * range literals, and raw commands.
7
7
  */
8
- export type TokenKind = 'fn' | 'let' | 'const' | 'if' | 'else' | 'while' | 'for' | 'foreach' | 'match' | 'return' | 'as' | 'at' | 'in' | 'is' | 'struct' | 'impl' | 'enum' | 'trigger' | 'namespace' | 'execute' | 'run' | 'unless' | 'int' | 'bool' | 'float' | 'string' | 'void' | 'BlockPos' | 'true' | 'false' | 'selector' | 'decorator' | 'int_lit' | 'float_lit' | 'byte_lit' | 'short_lit' | 'long_lit' | 'double_lit' | 'string_lit' | 'f_string' | 'range_lit' | 'rel_coord' | 'local_coord' | '+' | '-' | '*' | '/' | '%' | '~' | '^' | '==' | '!=' | '<' | '<=' | '>' | '>=' | '&&' | '||' | '!' | '=' | '+=' | '-=' | '*=' | '/=' | '%=' | '{' | '}' | '(' | ')' | '[' | ']' | ',' | ';' | ':' | '::' | '->' | '=>' | '.' | 'ident' | 'mc_name' | 'raw_cmd' | 'eof';
8
+ export type TokenKind = 'fn' | 'let' | 'const' | 'if' | 'else' | 'while' | 'for' | 'foreach' | 'match' | 'return' | 'break' | 'continue' | 'as' | 'at' | 'in' | 'is' | 'struct' | 'impl' | 'enum' | 'trigger' | 'namespace' | 'execute' | 'run' | 'unless' | 'int' | 'bool' | 'float' | 'string' | 'void' | 'BlockPos' | 'true' | 'false' | 'selector' | 'decorator' | 'int_lit' | 'float_lit' | 'byte_lit' | 'short_lit' | 'long_lit' | 'double_lit' | 'string_lit' | 'f_string' | 'range_lit' | 'rel_coord' | 'local_coord' | '+' | '-' | '*' | '/' | '%' | '~' | '^' | '==' | '!=' | '<' | '<=' | '>' | '>=' | '&&' | '||' | '!' | '=' | '+=' | '-=' | '*=' | '/=' | '%=' | '{' | '}' | '(' | ')' | '[' | ']' | ',' | ';' | ':' | '::' | '->' | '=>' | '.' | 'ident' | 'mc_name' | 'raw_cmd' | 'eof';
9
9
  export interface Token {
10
10
  kind: TokenKind;
11
11
  value: string;
@@ -23,6 +23,8 @@ const KEYWORDS = {
23
23
  foreach: 'foreach',
24
24
  match: 'match',
25
25
  return: 'return',
26
+ break: 'break',
27
+ continue: 'continue',
26
28
  as: 'as',
27
29
  at: 'at',
28
30
  in: 'in',
@@ -45,6 +45,7 @@ export declare class Lowering {
45
45
  private varTypes;
46
46
  private floatVars;
47
47
  private worldObjCounter;
48
+ private loopStack;
48
49
  constructor(namespace: string, sourceRanges?: SourceRange[]);
49
50
  lower(program: Program): IRModule;
50
51
  private lowerFn;
@@ -54,6 +55,8 @@ export declare class Lowering {
54
55
  private lowerStmt;
55
56
  private lowerLetStmt;
56
57
  private lowerReturnStmt;
58
+ private lowerBreakStmt;
59
+ private lowerContinueStmt;
57
60
  private lowerIfStmt;
58
61
  private lowerIsCheckIfStmt;
59
62
  private lowerWhileStmt;