redscript-mc 3.0.1 → 3.0.2

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 (225) hide show
  1. package/.github/workflows/ci.yml +1 -0
  2. package/README.md +119 -313
  3. package/README.zh.md +118 -314
  4. package/ROADMAP.md +5 -5
  5. package/dist/data/impl_test/function/counter/get.mcfunction +5 -0
  6. package/dist/data/impl_test/function/counter/inc.mcfunction +7 -0
  7. package/dist/data/impl_test/function/counter/new.mcfunction +4 -0
  8. package/dist/data/impl_test/function/load.mcfunction +1 -0
  9. package/dist/data/impl_test/function/test_impl.mcfunction +10 -0
  10. package/dist/data/minecraft/tags/function/load.json +5 -0
  11. package/dist/data/playground/function/load.mcfunction +1 -0
  12. package/dist/data/playground/function/start.mcfunction +4 -0
  13. package/dist/data/playground/function/start__say_macro_t1.mcfunction +1 -0
  14. package/dist/data/playground/function/stop.mcfunction +5 -0
  15. package/dist/data/playground/function/stop__say_macro_t0.mcfunction +1 -0
  16. package/dist/data/stdlib_queue8_test/function/__queue_append_apply.mcfunction +4 -0
  17. package/dist/data/stdlib_queue8_test/function/__queue_peek_apply.mcfunction +4 -0
  18. package/dist/data/stdlib_queue8_test/function/__queue_size_raw_apply.mcfunction +4 -0
  19. package/dist/data/stdlib_queue8_test/function/load.mcfunction +1 -0
  20. package/dist/data/stdlib_queue8_test/function/queue_clear.mcfunction +6 -0
  21. package/dist/data/stdlib_queue8_test/function/queue_empty__merge_1.mcfunction +5 -0
  22. package/dist/data/stdlib_queue8_test/function/queue_empty__then_0.mcfunction +5 -0
  23. package/dist/data/stdlib_queue8_test/function/queue_peek__merge_1.mcfunction +13 -0
  24. package/dist/data/stdlib_queue8_test/function/queue_peek__then_0.mcfunction +5 -0
  25. package/dist/data/stdlib_queue8_test/function/queue_pop__merge_1.mcfunction +15 -0
  26. package/dist/data/stdlib_queue8_test/function/queue_pop__then_0.mcfunction +5 -0
  27. package/dist/data/stdlib_queue8_test/function/queue_push__const_11.mcfunction +6 -0
  28. package/dist/data/stdlib_queue8_test/function/queue_push__const_22.mcfunction +6 -0
  29. package/dist/data/stdlib_queue8_test/function/queue_size.mcfunction +13 -0
  30. package/dist/data/stdlib_queue8_test/function/test_queue_push_and_size.mcfunction +13 -0
  31. package/dist/data/test/function/load.mcfunction +1 -0
  32. package/dist/data/test/function/say_at.mcfunction +6 -0
  33. package/dist/data/test/function/test.mcfunction +4 -0
  34. package/dist/pack.mcmeta +6 -0
  35. package/dist/package.json +1 -1
  36. package/dist/src/__tests__/formatter-extra.test.d.ts +7 -0
  37. package/dist/src/__tests__/formatter-extra.test.js +123 -0
  38. package/dist/src/__tests__/global-vars.test.d.ts +13 -0
  39. package/dist/src/__tests__/global-vars.test.js +156 -0
  40. package/dist/src/__tests__/lint/new-rules.test.d.ts +9 -0
  41. package/dist/src/__tests__/lint/new-rules.test.js +402 -0
  42. package/dist/src/__tests__/lsp-rename.test.d.ts +8 -0
  43. package/dist/src/__tests__/lsp-rename.test.js +157 -0
  44. package/dist/src/__tests__/mc-integration/say-fstring.test.d.ts +11 -0
  45. package/dist/src/__tests__/mc-integration/say-fstring.test.js +220 -0
  46. package/dist/src/__tests__/mc-integration/stdlib-coverage-2.test.js +1 -1
  47. package/dist/src/__tests__/mc-integration/stdlib-coverage-3.test.js +1 -1
  48. package/dist/src/__tests__/mc-integration/stdlib-coverage-4.test.js +1 -1
  49. package/dist/src/__tests__/mc-integration/stdlib-coverage-5.test.js +1 -1
  50. package/dist/src/__tests__/mc-integration/stdlib-coverage-6.test.js +1 -1
  51. package/dist/src/__tests__/mc-integration/stdlib-coverage-7.test.js +1 -1
  52. package/dist/src/__tests__/mc-integration/stdlib-coverage-8.test.js +1 -1
  53. package/dist/src/__tests__/mc-syntax.test.js +4 -1
  54. package/dist/src/__tests__/monomorphize-coverage.test.d.ts +9 -0
  55. package/dist/src/__tests__/monomorphize-coverage.test.js +204 -0
  56. package/dist/src/__tests__/optimizer-cse.test.d.ts +7 -0
  57. package/dist/src/__tests__/optimizer-cse.test.js +226 -0
  58. package/dist/src/__tests__/parser.test.js +4 -13
  59. package/dist/src/__tests__/repl-server-extra.test.js +6 -7
  60. package/dist/src/__tests__/repl-server.test.js +5 -7
  61. package/dist/src/__tests__/stdlib/queue.test.js +6 -6
  62. package/dist/src/cli.js +0 -0
  63. package/dist/src/lexer/index.js +2 -1
  64. package/dist/src/lint/index.d.ts +12 -5
  65. package/dist/src/lint/index.js +730 -5
  66. package/dist/src/lsp/main.js +0 -0
  67. package/dist/src/mc-test/client.d.ts +21 -0
  68. package/dist/src/mc-test/client.js +34 -0
  69. package/dist/src/mir/lower.js +108 -6
  70. package/dist/src/optimizer/interprocedural.js +37 -2
  71. package/dist/src/parser/decl-parser.d.ts +19 -0
  72. package/dist/src/parser/decl-parser.js +323 -0
  73. package/dist/src/parser/expr-parser.d.ts +46 -0
  74. package/dist/src/parser/expr-parser.js +759 -0
  75. package/dist/src/parser/index.d.ts +8 -129
  76. package/dist/src/parser/index.js +13 -2262
  77. package/dist/src/parser/stmt-parser.d.ts +28 -0
  78. package/dist/src/parser/stmt-parser.js +577 -0
  79. package/dist/src/parser/type-parser.d.ts +20 -0
  80. package/dist/src/parser/type-parser.js +257 -0
  81. package/dist/src/parser/utils.d.ts +34 -0
  82. package/dist/src/parser/utils.js +141 -0
  83. package/docs/dev/README-mc-integration-tests.md +141 -0
  84. package/docs/lint-rules.md +162 -0
  85. package/docs/stdlib/bigint.md +2 -0
  86. package/editors/vscode/README.md +63 -41
  87. package/editors/vscode/out/extension.js +1881 -1776
  88. package/editors/vscode/out/lsp-server.js +4257 -3651
  89. package/editors/vscode/package-lock.json +3 -3
  90. package/editors/vscode/package.json +1 -1
  91. package/examples/loops-demo.mcrs +87 -0
  92. package/package.json +1 -1
  93. package/redscript-docs/docs/en/stdlib/advanced.md +629 -0
  94. package/redscript-docs/docs/en/stdlib/bigint.md +316 -0
  95. package/redscript-docs/docs/en/stdlib/bits.md +292 -0
  96. package/redscript-docs/docs/en/stdlib/bossbar.md +177 -0
  97. package/redscript-docs/docs/en/stdlib/calculus.md +289 -0
  98. package/redscript-docs/docs/en/stdlib/color.md +353 -0
  99. package/redscript-docs/docs/en/stdlib/combat.md +88 -0
  100. package/redscript-docs/docs/en/stdlib/cooldown.md +82 -0
  101. package/redscript-docs/docs/en/stdlib/dialog.md +155 -0
  102. package/redscript-docs/docs/en/stdlib/easing.md +558 -0
  103. package/redscript-docs/docs/en/stdlib/ecs.md +475 -0
  104. package/redscript-docs/docs/en/stdlib/effects.md +324 -0
  105. package/redscript-docs/docs/en/stdlib/events.md +3 -0
  106. package/redscript-docs/docs/en/stdlib/expr.md +45 -0
  107. package/redscript-docs/docs/en/stdlib/fft.md +141 -0
  108. package/redscript-docs/docs/en/stdlib/geometry.md +430 -0
  109. package/redscript-docs/docs/en/stdlib/graph.md +259 -0
  110. package/redscript-docs/docs/en/stdlib/heap.md +185 -0
  111. package/redscript-docs/docs/en/stdlib/interactions.md +179 -0
  112. package/redscript-docs/docs/en/stdlib/inventory.md +97 -0
  113. package/redscript-docs/docs/en/stdlib/linalg.md +557 -0
  114. package/redscript-docs/docs/en/stdlib/list.md +559 -0
  115. package/redscript-docs/docs/en/stdlib/map.md +140 -0
  116. package/redscript-docs/docs/en/stdlib/math.md +193 -0
  117. package/redscript-docs/docs/en/stdlib/math_hp.md +149 -0
  118. package/redscript-docs/docs/en/stdlib/matrix.md +403 -0
  119. package/redscript-docs/docs/en/stdlib/mobs.md +965 -0
  120. package/redscript-docs/docs/en/stdlib/noise.md +244 -0
  121. package/redscript-docs/docs/en/stdlib/ode.md +253 -0
  122. package/redscript-docs/docs/en/stdlib/parabola.md +342 -0
  123. package/redscript-docs/docs/en/stdlib/particles.md +311 -0
  124. package/redscript-docs/docs/en/stdlib/pathfind.md +255 -0
  125. package/redscript-docs/docs/en/stdlib/physics.md +493 -0
  126. package/redscript-docs/docs/en/stdlib/player.md +78 -0
  127. package/redscript-docs/docs/en/stdlib/quaternion.md +673 -0
  128. package/redscript-docs/docs/en/stdlib/queue.md +134 -0
  129. package/redscript-docs/docs/en/stdlib/random.md +223 -0
  130. package/redscript-docs/docs/en/stdlib/result.md +143 -0
  131. package/redscript-docs/docs/en/stdlib/scheduler.md +183 -0
  132. package/redscript-docs/docs/en/stdlib/set_int.md +190 -0
  133. package/redscript-docs/docs/en/stdlib/sets.md +101 -0
  134. package/redscript-docs/docs/en/stdlib/signal.md +400 -0
  135. package/redscript-docs/docs/en/stdlib/sort.md +104 -0
  136. package/redscript-docs/docs/en/stdlib/spawn.md +147 -0
  137. package/redscript-docs/docs/en/stdlib/state.md +142 -0
  138. package/redscript-docs/docs/en/stdlib/strings.md +154 -0
  139. package/redscript-docs/docs/en/stdlib/tags.md +3451 -0
  140. package/redscript-docs/docs/en/stdlib/teams.md +153 -0
  141. package/redscript-docs/docs/en/stdlib/timer.md +246 -0
  142. package/redscript-docs/docs/en/stdlib/vec.md +158 -0
  143. package/redscript-docs/docs/en/stdlib/world.md +298 -0
  144. package/redscript-docs/docs/zh/stdlib/advanced.md +615 -0
  145. package/redscript-docs/docs/zh/stdlib/bigint.md +316 -0
  146. package/redscript-docs/docs/zh/stdlib/bits.md +292 -0
  147. package/redscript-docs/docs/zh/stdlib/bossbar.md +170 -0
  148. package/redscript-docs/docs/zh/stdlib/calculus.md +287 -0
  149. package/redscript-docs/docs/zh/stdlib/color.md +353 -0
  150. package/redscript-docs/docs/zh/stdlib/combat.md +88 -0
  151. package/redscript-docs/docs/zh/stdlib/cooldown.md +84 -0
  152. package/redscript-docs/docs/zh/stdlib/dialog.md +152 -0
  153. package/redscript-docs/docs/zh/stdlib/easing.md +558 -0
  154. package/redscript-docs/docs/zh/stdlib/ecs.md +472 -0
  155. package/redscript-docs/docs/zh/stdlib/effects.md +324 -0
  156. package/redscript-docs/docs/zh/stdlib/events.md +3 -0
  157. package/redscript-docs/docs/zh/stdlib/expr.md +37 -0
  158. package/redscript-docs/docs/zh/stdlib/fft.md +128 -0
  159. package/redscript-docs/docs/zh/stdlib/geometry.md +430 -0
  160. package/redscript-docs/docs/zh/stdlib/graph.md +259 -0
  161. package/redscript-docs/docs/zh/stdlib/heap.md +185 -0
  162. package/redscript-docs/docs/zh/stdlib/interactions.md +160 -0
  163. package/redscript-docs/docs/zh/stdlib/inventory.md +94 -0
  164. package/redscript-docs/docs/zh/stdlib/linalg.md +543 -0
  165. package/redscript-docs/docs/zh/stdlib/list.md +561 -0
  166. package/redscript-docs/docs/zh/stdlib/map.md +132 -0
  167. package/redscript-docs/docs/zh/stdlib/math.md +193 -0
  168. package/redscript-docs/docs/zh/stdlib/math_hp.md +143 -0
  169. package/redscript-docs/docs/zh/stdlib/matrix.md +396 -0
  170. package/redscript-docs/docs/zh/stdlib/mobs.md +965 -0
  171. package/redscript-docs/docs/zh/stdlib/noise.md +244 -0
  172. package/redscript-docs/docs/zh/stdlib/ode.md +243 -0
  173. package/redscript-docs/docs/zh/stdlib/parabola.md +337 -0
  174. package/redscript-docs/docs/zh/stdlib/particles.md +307 -0
  175. package/redscript-docs/docs/zh/stdlib/pathfind.md +255 -0
  176. package/redscript-docs/docs/zh/stdlib/physics.md +493 -0
  177. package/redscript-docs/docs/zh/stdlib/player.md +78 -0
  178. package/redscript-docs/docs/zh/stdlib/quaternion.md +669 -0
  179. package/redscript-docs/docs/zh/stdlib/queue.md +124 -0
  180. package/redscript-docs/docs/zh/stdlib/random.md +222 -0
  181. package/redscript-docs/docs/zh/stdlib/result.md +147 -0
  182. package/redscript-docs/docs/zh/stdlib/scheduler.md +173 -0
  183. package/redscript-docs/docs/zh/stdlib/set_int.md +180 -0
  184. package/redscript-docs/docs/zh/stdlib/sets.md +107 -0
  185. package/redscript-docs/docs/zh/stdlib/signal.md +373 -0
  186. package/redscript-docs/docs/zh/stdlib/sort.md +104 -0
  187. package/redscript-docs/docs/zh/stdlib/spawn.md +142 -0
  188. package/redscript-docs/docs/zh/stdlib/state.md +134 -0
  189. package/redscript-docs/docs/zh/stdlib/strings.md +107 -0
  190. package/redscript-docs/docs/zh/stdlib/tags.md +3451 -0
  191. package/redscript-docs/docs/zh/stdlib/teams.md +150 -0
  192. package/redscript-docs/docs/zh/stdlib/timer.md +254 -0
  193. package/redscript-docs/docs/zh/stdlib/vec.md +158 -0
  194. package/redscript-docs/docs/zh/stdlib/world.md +289 -0
  195. package/src/__tests__/formatter-extra.test.ts +139 -0
  196. package/src/__tests__/global-vars.test.ts +171 -0
  197. package/src/__tests__/lint/new-rules.test.ts +437 -0
  198. package/src/__tests__/lsp-rename.test.ts +171 -0
  199. package/src/__tests__/mc-integration/say-fstring.test.ts +211 -0
  200. package/src/__tests__/mc-integration/stdlib-coverage-2.test.ts +1 -1
  201. package/src/__tests__/mc-integration/stdlib-coverage-3.test.ts +1 -1
  202. package/src/__tests__/mc-integration/stdlib-coverage-4.test.ts +1 -1
  203. package/src/__tests__/mc-integration/stdlib-coverage-5.test.ts +1 -1
  204. package/src/__tests__/mc-integration/stdlib-coverage-6.test.ts +1 -1
  205. package/src/__tests__/mc-integration/stdlib-coverage-7.test.ts +1 -1
  206. package/src/__tests__/mc-integration/stdlib-coverage-8.test.ts +1 -1
  207. package/src/__tests__/mc-syntax.test.ts +3 -0
  208. package/src/__tests__/monomorphize-coverage.test.ts +220 -0
  209. package/src/__tests__/optimizer-cse.test.ts +250 -0
  210. package/src/__tests__/parser.test.ts +4 -13
  211. package/src/__tests__/repl-server-extra.test.ts +6 -6
  212. package/src/__tests__/repl-server.test.ts +5 -6
  213. package/src/__tests__/stdlib/queue.test.ts +6 -6
  214. package/src/lexer/index.ts +2 -1
  215. package/src/lint/index.ts +713 -5
  216. package/src/mc-test/client.ts +40 -0
  217. package/src/mir/lower.ts +111 -2
  218. package/src/optimizer/interprocedural.ts +40 -2
  219. package/src/parser/decl-parser.ts +349 -0
  220. package/src/parser/expr-parser.ts +838 -0
  221. package/src/parser/index.ts +17 -2558
  222. package/src/parser/stmt-parser.ts +585 -0
  223. package/src/parser/type-parser.ts +276 -0
  224. package/src/parser/utils.ts +173 -0
  225. package/src/stdlib/queue.mcrs +19 -6
@@ -0,0 +1,289 @@
1
+ # World
2
+
3
+ > 本文档由 `src/stdlib/world.mcrs` 自动生成,请勿手动编辑。
4
+
5
+ ## API 列表
6
+
7
+ - [set_day](#set-day)
8
+ - [set_night](#set-night)
9
+ - [set_noon](#set-noon)
10
+ - [set_midnight](#set-midnight)
11
+ - [weather_clear](#weather-clear)
12
+ - [weather_rain](#weather-rain)
13
+ - [weather_thunder](#weather-thunder)
14
+ - [enable_keep_inventory](#enable-keep-inventory)
15
+ - [disable_keep_inventory](#disable-keep-inventory)
16
+ - [disable_mob_griefing](#disable-mob-griefing)
17
+ - [disable_fire_spread](#disable-fire-spread)
18
+ - [set_peaceful](#set-peaceful)
19
+ - [set_easy](#set-easy)
20
+ - [set_normal](#set-normal)
21
+ - [set_hard](#set-hard)
22
+ - [barrier_wall](#barrier-wall)
23
+ - [clear_area](#clear-area)
24
+ - [glass_box](#glass-box)
25
+ - [sun_altitude](#sun-altitude)
26
+ - [sun_azimuth](#sun-azimuth)
27
+
28
+ ---
29
+
30
+ ## `set_day`
31
+
32
+ 将世界时间设置为白天(tick 1000)
33
+
34
+ ```redscript
35
+ fn set_day()
36
+ ```
37
+
38
+ ---
39
+
40
+ ## `set_night`
41
+
42
+ 将世界时间设置为夜晚(tick 13000)
43
+
44
+ ```redscript
45
+ fn set_night()
46
+ ```
47
+
48
+ ---
49
+
50
+ ## `set_noon`
51
+
52
+ 将世界时间设置为正午(tick 6000)
53
+
54
+ ```redscript
55
+ fn set_noon()
56
+ ```
57
+
58
+ ---
59
+
60
+ ## `set_midnight`
61
+
62
+ 将世界时间设置为午夜(tick 18000)
63
+
64
+ ```redscript
65
+ fn set_midnight()
66
+ ```
67
+
68
+ ---
69
+
70
+ ## `weather_clear`
71
+
72
+ 将天气设置为晴天
73
+
74
+ ```redscript
75
+ fn weather_clear()
76
+ ```
77
+
78
+ ---
79
+
80
+ ## `weather_rain`
81
+
82
+ 将天气设置为下雨
83
+
84
+ ```redscript
85
+ fn weather_rain()
86
+ ```
87
+
88
+ ---
89
+
90
+ ## `weather_thunder`
91
+
92
+ 将天气设置为雷暴
93
+
94
+ ```redscript
95
+ fn weather_thunder()
96
+ ```
97
+
98
+ ---
99
+
100
+ ## `enable_keep_inventory`
101
+
102
+ 启用 `keepInventory` 游戏规则
103
+
104
+ ```redscript
105
+ fn enable_keep_inventory()
106
+ ```
107
+
108
+ ---
109
+
110
+ ## `disable_keep_inventory`
111
+
112
+ 关闭 `keepInventory` 游戏规则
113
+
114
+ ```redscript
115
+ fn disable_keep_inventory()
116
+ ```
117
+
118
+ ---
119
+
120
+ ## `disable_mob_griefing`
121
+
122
+ 将 `mobGriefing` 设为 false,禁止生物破坏方块
123
+
124
+ ```redscript
125
+ fn disable_mob_griefing()
126
+ ```
127
+
128
+ ---
129
+
130
+ ## `disable_fire_spread`
131
+
132
+ 将 `doFireTick` 设为 false,禁止火焰蔓延
133
+
134
+ ```redscript
135
+ fn disable_fire_spread()
136
+ ```
137
+
138
+ ---
139
+
140
+ ## `set_peaceful`
141
+
142
+ 将难度设置为和平
143
+
144
+ ```redscript
145
+ fn set_peaceful()
146
+ ```
147
+
148
+ ---
149
+
150
+ ## `set_easy`
151
+
152
+ 将难度设置为简单
153
+
154
+ ```redscript
155
+ fn set_easy()
156
+ ```
157
+
158
+ ---
159
+
160
+ ## `set_normal`
161
+
162
+ 将难度设置为普通
163
+
164
+ ```redscript
165
+ fn set_normal()
166
+ ```
167
+
168
+ ---
169
+
170
+ ## `set_hard`
171
+
172
+ 将难度设置为困难
173
+
174
+ ```redscript
175
+ fn set_hard()
176
+ ```
177
+
178
+ ---
179
+
180
+ ## `barrier_wall`
181
+
182
+ 用屏障方块填充一个长方体区域
183
+
184
+ ```redscript
185
+ fn barrier_wall(x1: int, y1: int, z1: int, x2: int, y2: int, z2: int)
186
+ ```
187
+
188
+ **参数**
189
+
190
+ | 参数 | 说明 |
191
+ |------|------|
192
+ | `x1` | 第一个角点 X 坐标 |
193
+ | `y1` | 第一个角点 Y 坐标 |
194
+ | `z1` | 第一个角点 Z 坐标 |
195
+ | `x2` | 对角点 X 坐标 |
196
+ | `y2` | 对角点 Y 坐标 |
197
+ | `z2` | 对角点 Z 坐标 |
198
+
199
+ ---
200
+
201
+ ## `clear_area`
202
+
203
+ 用空气填充一个长方体区域,以清空该区域
204
+
205
+ ```redscript
206
+ fn clear_area(x1: int, y1: int, z1: int, x2: int, y2: int, z2: int)
207
+ ```
208
+
209
+ **参数**
210
+
211
+ | 参数 | 说明 |
212
+ |------|------|
213
+ | `x1` | 第一个角点 X 坐标 |
214
+ | `y1` | 第一个角点 Y 坐标 |
215
+ | `z1` | 第一个角点 Z 坐标 |
216
+ | `x2` | 对角点 X 坐标 |
217
+ | `y2` | 对角点 Y 坐标 |
218
+ | `z2` | 对角点 Z 坐标 |
219
+
220
+ ---
221
+
222
+ ## `glass_box`
223
+
224
+ 构建一个中空玻璃盒,先填满外壳再挖空内部
225
+
226
+ ```redscript
227
+ fn glass_box(x1: int, y1: int, z1: int, x2: int, y2: int, z2: int)
228
+ ```
229
+
230
+ **参数**
231
+
232
+ | 参数 | 说明 |
233
+ |------|------|
234
+ | `x1` | 第一个角点 X 坐标 |
235
+ | `y1` | 第一个角点 Y 坐标 |
236
+ | `z1` | 第一个角点 Z 坐标 |
237
+ | `x2` | 对角点 X 坐标 |
238
+ | `y2` | 对角点 Y 坐标 |
239
+ | `z2` | 对角点 Z 坐标 |
240
+
241
+ ---
242
+
243
+ ## `sun_altitude`
244
+
245
+ 根据世界时间计算太阳高度角,结果为角度 ×10000 定点数
246
+
247
+ ```redscript
248
+ fn sun_altitude(ticks: int): int
249
+ ```
250
+
251
+ **参数**
252
+
253
+ | 参数 | 说明 |
254
+ |------|------|
255
+ | `ticks` | Minecraft 世界时间(游戏刻) |
256
+
257
+ **返回:** 太阳高度角,单位为角度 ×10000
258
+
259
+ **示例**
260
+
261
+ ```redscript
262
+ let alt = sun_altitude(6000) // 900000
263
+ ```
264
+
265
+ ---
266
+
267
+ ## `sun_azimuth`
268
+
269
+ 根据世界时间计算太阳方位角,结果为角度 ×10000 定点数
270
+
271
+ ```redscript
272
+ fn sun_azimuth(ticks: int): int
273
+ ```
274
+
275
+ **参数**
276
+
277
+ | 参数 | 说明 |
278
+ |------|------|
279
+ | `ticks` | Minecraft 世界时间(游戏刻) |
280
+
281
+ **返回:** 方位角,范围为 `[0, 3600000)`
282
+
283
+ **示例**
284
+
285
+ ```redscript
286
+ let az = sun_azimuth(6000) // 900000
287
+ ```
288
+
289
+ ---
@@ -0,0 +1,139 @@
1
+ /**
2
+ * Additional coverage for src/formatter/index.ts
3
+ *
4
+ * Targets uncovered branches: string handling, long line wrapping,
5
+ * comment preservation, CRLF normalization, multiple blank line collapsing.
6
+ */
7
+
8
+ import { format } from '../formatter'
9
+
10
+ describe('formatter — string literal preservation', () => {
11
+ it('does not reindent content inside string literals', () => {
12
+ const input = 'fn test(): void {\nlet s: string = "{ not a block }";\n}'
13
+ const result = format(input)
14
+ expect(result).toContain('"{ not a block }"')
15
+ })
16
+
17
+ it('handles multiline strings spanning multiple lines', () => {
18
+ // A string that contains a newline escape
19
+ const input = 'fn test(): void {\nlet s: string = "line1\\nline2";\n}'
20
+ const result = format(input)
21
+ expect(result).toContain('"line1\\nline2"')
22
+ })
23
+
24
+ it('handles escaped quotes inside strings', () => {
25
+ const input = 'fn test(): void {\nlet s: string = "say \\"hello\\"";\n}'
26
+ const result = format(input)
27
+ expect(result).toContain('"say \\"hello\\""')
28
+ })
29
+
30
+ it('handles string with braces that should not affect indentation', () => {
31
+ const input = 'fn test(): void {\nlet s: string = "{{{}}} more";\nlet x: int = 1;\n}'
32
+ const result = format(input)
33
+ // x should be indented at 1 level (inside fn), not affected by string braces
34
+ expect(result).toMatch(/^ {2}let x: int = 1;$/m)
35
+ })
36
+ })
37
+
38
+ describe('formatter — comment handling', () => {
39
+ it('preserves inline comments', () => {
40
+ const input = 'fn test(): void {\nlet x: int = 1; // important\n}'
41
+ const result = format(input)
42
+ expect(result).toContain('// important')
43
+ })
44
+
45
+ it('does not treat braces in comments as code', () => {
46
+ const input = 'fn test(): void {\n// { this is a comment\nlet x: int = 1;\n}'
47
+ const result = format(input)
48
+ expect(result).toMatch(/^ {2}let x: int = 1;$/m)
49
+ })
50
+ })
51
+
52
+ describe('formatter — CRLF normalization', () => {
53
+ it('normalizes CRLF to LF', () => {
54
+ const input = 'fn test(): void {\r\nlet x: int = 1;\r\n}'
55
+ const result = format(input)
56
+ expect(result).not.toContain('\r')
57
+ expect(result).toBe('fn test(): void {\n let x: int = 1;\n}\n')
58
+ })
59
+ })
60
+
61
+ describe('formatter — blank line collapsing', () => {
62
+ it('collapses more than 2 consecutive blank lines', () => {
63
+ const input = 'fn a(): void {\n}\n\n\n\n\nfn b(): void {\n}'
64
+ const result = format(input)
65
+ // Should have at most 2 blank lines between functions
66
+ expect(result).not.toMatch(/\n\n\n\n/)
67
+ })
68
+
69
+ it('strips leading blank lines', () => {
70
+ const input = '\n\n\nfn test(): void {\n}'
71
+ const result = format(input)
72
+ expect(result).toMatch(/^fn test/)
73
+ })
74
+ })
75
+
76
+ describe('formatter — long line wrapping', () => {
77
+ it('wraps function calls longer than 80 characters', () => {
78
+ const inner = 'fn test(): void {\n some_function(argument_one, argument_two, argument_three, argument_four, argument_five);\n}'
79
+ const result = format(inner)
80
+ // Should be wrapped since the line is > 80 chars
81
+ const lines = result.split('\n')
82
+ // After wrapping, should produce more lines than original 3
83
+ expect(lines.length).toBeGreaterThan(3)
84
+ })
85
+
86
+ it('does not wrap short function calls', () => {
87
+ const input = 'fn test(): void {\n foo(a, b);\n}'
88
+ const result = format(input)
89
+ expect(result).toContain('foo(a, b)')
90
+ })
91
+
92
+ it('does not wrap lines with comments even if long', () => {
93
+ const longComment = 'fn test(): void {\n let x: int = 1; // this is a very long comment that makes the line exceed 80 characters easily\n}'
94
+ const result = format(longComment)
95
+ // Should keep comment line as-is (no wrapping)
96
+ expect(result).toContain('// this is a very long comment')
97
+ })
98
+ })
99
+
100
+ describe('formatter — brace collapsing', () => {
101
+ it('puts opening brace on same line as preceding statement', () => {
102
+ const input = 'if true\n{\nlet x: int = 1;\n}'
103
+ const result = format(input)
104
+ expect(result).toContain('if true {')
105
+ })
106
+
107
+ it('handles else brace normalization', () => {
108
+ const input = 'fn test(): void {\nif true {\nlet x: int = 1;\n}else{\nlet y: int = 2;\n}\n}'
109
+ const result = format(input)
110
+ expect(result).toContain('} else {')
111
+ })
112
+ })
113
+
114
+ describe('formatter — deeply nested code', () => {
115
+ it('indents 3 levels deep correctly', () => {
116
+ const input = 'fn test(): void {\nif true {\nif false {\nlet x: int = 1;\n}\n}\n}'
117
+ const result = format(input)
118
+ expect(result).toMatch(/^ {6}let x: int = 1;$/m)
119
+ })
120
+ })
121
+
122
+ describe('formatter — edge cases', () => {
123
+ it('handles single line code', () => {
124
+ const result = format('let x: int = 1;')
125
+ expect(result).toBe('let x: int = 1;\n')
126
+ })
127
+
128
+ it('handles code with only braces', () => {
129
+ const result = format('{}')
130
+ expect(result).toContain('{')
131
+ expect(result).toContain('}')
132
+ })
133
+
134
+ it('handles closing brace followed by opening brace', () => {
135
+ const input = 'fn a(): void {\n}\nfn b(): void {\n}'
136
+ const result = format(input)
137
+ expect(result).toContain('fn a(): void {\n}\nfn b(): void {\n}\n')
138
+ })
139
+ })
@@ -0,0 +1,171 @@
1
+ /**
2
+ * Integration tests for module-level global variables.
3
+ *
4
+ * Covers:
5
+ * - Global variable assignment and read (score_write / score_read)
6
+ * - Global variable increment in a loop
7
+ * - Global variable visible across functions
8
+ * - Global variable in f-string interpolation (no stray "~")
9
+ *
10
+ * These tests compile RedScript source and inspect the generated .mcfunction
11
+ * content to verify correct scoreboard-based code generation.
12
+ */
13
+
14
+ import { compile } from '../emit/compile'
15
+
16
+ // Helper: find a function's body by name
17
+ function getFunctionBody(
18
+ files: { path: string; content: string }[],
19
+ fnName: string,
20
+ ns = 'test'
21
+ ): string {
22
+ const target = `data/${ns}/function/${fnName}.mcfunction`
23
+ const f = files.find(f => f.path === target || f.path.endsWith(`/${fnName}.mcfunction`))
24
+ if (!f) {
25
+ const paths = files.map(f => f.path).join('\n')
26
+ throw new Error(`Function '${fnName}' not found in output. Files:\n${paths}`)
27
+ }
28
+ return f.content
29
+ }
30
+
31
+ // ──────────────────────────────────────────────────────────────
32
+ // Test 1: global variable assignment and read
33
+ // ──────────────────────────────────────────────────────────────
34
+ describe('Global variable: assignment and read', () => {
35
+ const src = `
36
+ let counter: int = 0;
37
+
38
+ @keep
39
+ fn set_counter() {
40
+ counter = 42;
41
+ }
42
+
43
+ @keep
44
+ fn get_counter() {
45
+ scoreboard_set("#result", "rs", counter);
46
+ }
47
+ `
48
+
49
+ it('set_counter uses scoreboard players set to write global', () => {
50
+ const { files } = compile(src, { namespace: 'test' })
51
+ const body = getFunctionBody(files, 'set_counter')
52
+ // Should write 42 to the scoreboard for the global variable
53
+ expect(body).toContain('scoreboard players set')
54
+ expect(body).toContain('42')
55
+ })
56
+
57
+ it('get_counter reads global via score_read (not hardcoded 0)', () => {
58
+ const { files } = compile(src, { namespace: 'test' })
59
+ const body = getFunctionBody(files, 'get_counter')
60
+ // Should contain a scoreboard read for the counter variable,
61
+ // not a hardcoded literal "0" assignment
62
+ expect(body).toContain('scoreboard players')
63
+ // The result should not be a constant "0" — it must read the scoreboard
64
+ // (hardcoded copy t = 0 was the old bug)
65
+ expect(body).not.toMatch(/scoreboard players set #result rs 0\s*$/)
66
+ })
67
+ })
68
+
69
+ // ──────────────────────────────────────────────────────────────
70
+ // Test 2: global variable increment in a loop
71
+ // ──────────────────────────────────────────────────────────────
72
+ describe('Global variable: increment in a loop', () => {
73
+ const src = `
74
+ let running: int = 0;
75
+
76
+ @keep
77
+ fn count_up() {
78
+ let i: int = 0;
79
+ while i < 5 {
80
+ running = running + 1;
81
+ i = i + 1;
82
+ }
83
+ }
84
+ `
85
+
86
+ it('count_up reads and writes running (not a no-op)', () => {
87
+ const { files } = compile(src, { namespace: 'test' })
88
+ const body = getFunctionBody(files, 'count_up')
89
+ // Should contain scoreboard operations (not an empty function)
90
+ expect(body.trim().length).toBeGreaterThan(0)
91
+ expect(body).toContain('scoreboard players')
92
+ })
93
+
94
+ it('DCE does not eliminate running = running + 1', () => {
95
+ const { files } = compile(src, { namespace: 'test' })
96
+ // The while loop generates sub-functions; check all files
97
+ const allContent = files.map(f => f.content).join('\n')
98
+ // There must be a scoreboard add or operation for running
99
+ const hasAdd = allContent.includes('scoreboard players add') ||
100
+ allContent.includes('scoreboard players operation')
101
+ expect(hasAdd).toBe(true)
102
+ })
103
+ })
104
+
105
+ // ──────────────────────────────────────────────────────────────
106
+ // Test 3: global variable visible across functions
107
+ // ──────────────────────────────────────────────────────────────
108
+ describe('Global variable: cross-function visibility', () => {
109
+ const src = `
110
+ let x: int = 0;
111
+
112
+ @keep
113
+ fn set_x() {
114
+ x = 42;
115
+ }
116
+
117
+ @keep
118
+ fn get_x() {
119
+ scoreboard_set("#out", "rs", x);
120
+ }
121
+ `
122
+
123
+ it('set_x writes to x (not just a local temp)', () => {
124
+ const { files } = compile(src, { namespace: 'test' })
125
+ const body = getFunctionBody(files, 'set_x')
126
+ expect(body).toContain('scoreboard players set')
127
+ expect(body).toContain('42')
128
+ // The write must target the persistent scoreboard name for x, not a temp
129
+ expect(body).toContain('x')
130
+ })
131
+
132
+ it('get_x reads x from scoreboard', () => {
133
+ const { files } = compile(src, { namespace: 'test' })
134
+ const body = getFunctionBody(files, 'get_x')
135
+ // Must contain a scoreboard get / operation to read x
136
+ expect(body).toContain('scoreboard players')
137
+ expect(body).toContain('x')
138
+ })
139
+ })
140
+
141
+ // ──────────────────────────────────────────────────────────────
142
+ // Test 4: global variable in f-string interpolation
143
+ // ──────────────────────────────────────────────────────────────
144
+ describe('Global variable: f-string interpolation', () => {
145
+ const src = `
146
+ let score_val: int = 0;
147
+
148
+ @keep
149
+ fn announce() {
150
+ say(f"Score: {score_val}");
151
+ }
152
+ `
153
+
154
+ it('announce does not contain stray ~ in tellraw', () => {
155
+ const { files } = compile(src, { namespace: 'test' })
156
+ const body = getFunctionBody(files, 'announce')
157
+ // The generated tellraw must not fall back to "~" (the old default bug)
158
+ expect(body).not.toContain('"text":"~"')
159
+ expect(body).not.toContain('"~"')
160
+ })
161
+
162
+ it('announce reads score_val from scoreboard (not hardcoded)', () => {
163
+ const { files } = compile(src, { namespace: 'test' })
164
+ const body = getFunctionBody(files, 'announce')
165
+ // f-string int interpolation uses macro pattern:
166
+ // execute store result storage ... run scoreboard players get score_val __test
167
+ expect(body).toContain('score_val')
168
+ // Must be a dynamic read, not a constant
169
+ expect(body).not.toMatch(/say Score: \d+/)
170
+ })
171
+ })