redscript-mc 1.0.0
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.
- package/.github/ISSUE_TEMPLATE/bug_report.md +40 -0
- package/.github/ISSUE_TEMPLATE/feature_request.md +31 -0
- package/.github/ISSUE_TEMPLATE/wrong_output.md +33 -0
- package/.github/PULL_REQUEST_TEMPLATE.md +34 -0
- package/.github/workflows/ci.yml +29 -0
- package/.github/workflows/publish-extension.yml +35 -0
- package/LICENSE +21 -0
- package/README.md +261 -0
- package/README.zh.md +261 -0
- package/dist/__tests__/cli.test.d.ts +1 -0
- package/dist/__tests__/cli.test.js +140 -0
- package/dist/__tests__/codegen.test.d.ts +1 -0
- package/dist/__tests__/codegen.test.js +121 -0
- package/dist/__tests__/diagnostics.test.d.ts +4 -0
- package/dist/__tests__/diagnostics.test.js +149 -0
- package/dist/__tests__/e2e.test.d.ts +6 -0
- package/dist/__tests__/e2e.test.js +1528 -0
- package/dist/__tests__/lexer.test.d.ts +1 -0
- package/dist/__tests__/lexer.test.js +316 -0
- package/dist/__tests__/lowering.test.d.ts +1 -0
- package/dist/__tests__/lowering.test.js +819 -0
- package/dist/__tests__/mc-integration.test.d.ts +12 -0
- package/dist/__tests__/mc-integration.test.js +395 -0
- package/dist/__tests__/mc-syntax.test.d.ts +1 -0
- package/dist/__tests__/mc-syntax.test.js +112 -0
- package/dist/__tests__/nbt.test.d.ts +1 -0
- package/dist/__tests__/nbt.test.js +82 -0
- package/dist/__tests__/optimizer-advanced.test.d.ts +1 -0
- package/dist/__tests__/optimizer-advanced.test.js +124 -0
- package/dist/__tests__/optimizer.test.d.ts +1 -0
- package/dist/__tests__/optimizer.test.js +118 -0
- package/dist/__tests__/parser.test.d.ts +1 -0
- package/dist/__tests__/parser.test.js +717 -0
- package/dist/__tests__/repl.test.d.ts +1 -0
- package/dist/__tests__/repl.test.js +27 -0
- package/dist/__tests__/runtime.test.d.ts +1 -0
- package/dist/__tests__/runtime.test.js +276 -0
- package/dist/__tests__/structure-optimizer.test.d.ts +1 -0
- package/dist/__tests__/structure-optimizer.test.js +33 -0
- package/dist/__tests__/typechecker.test.d.ts +1 -0
- package/dist/__tests__/typechecker.test.js +364 -0
- package/dist/ast/types.d.ts +357 -0
- package/dist/ast/types.js +9 -0
- package/dist/cli.d.ts +11 -0
- package/dist/cli.js +407 -0
- package/dist/codegen/cmdblock/index.d.ts +26 -0
- package/dist/codegen/cmdblock/index.js +45 -0
- package/dist/codegen/mcfunction/index.d.ts +34 -0
- package/dist/codegen/mcfunction/index.js +413 -0
- package/dist/codegen/structure/index.d.ts +18 -0
- package/dist/codegen/structure/index.js +249 -0
- package/dist/compile.d.ts +30 -0
- package/dist/compile.js +152 -0
- package/dist/data/arena/function/__load.mcfunction +6 -0
- package/dist/data/arena/function/__tick.mcfunction +2 -0
- package/dist/data/arena/function/announce_leaders/else_1.mcfunction +3 -0
- package/dist/data/arena/function/announce_leaders/foreach_0/merge_2.mcfunction +1 -0
- package/dist/data/arena/function/announce_leaders/foreach_0/then_0.mcfunction +3 -0
- package/dist/data/arena/function/announce_leaders/foreach_0.mcfunction +7 -0
- package/dist/data/arena/function/announce_leaders/foreach_1/merge_2.mcfunction +1 -0
- package/dist/data/arena/function/announce_leaders/foreach_1/then_0.mcfunction +4 -0
- package/dist/data/arena/function/announce_leaders/foreach_1.mcfunction +6 -0
- package/dist/data/arena/function/announce_leaders/merge_2.mcfunction +1 -0
- package/dist/data/arena/function/announce_leaders/then_0.mcfunction +4 -0
- package/dist/data/arena/function/announce_leaders.mcfunction +6 -0
- package/dist/data/arena/function/arena_tick/merge_2.mcfunction +1 -0
- package/dist/data/arena/function/arena_tick/then_0.mcfunction +4 -0
- package/dist/data/arena/function/arena_tick.mcfunction +11 -0
- package/dist/data/counter/function/__load.mcfunction +5 -0
- package/dist/data/counter/function/__tick.mcfunction +2 -0
- package/dist/data/counter/function/counter_tick/merge_2.mcfunction +1 -0
- package/dist/data/counter/function/counter_tick/then_0.mcfunction +3 -0
- package/dist/data/counter/function/counter_tick.mcfunction +11 -0
- package/dist/data/minecraft/tags/function/load.json +5 -0
- package/dist/data/minecraft/tags/function/tick.json +5 -0
- package/dist/data/quiz/function/__load.mcfunction +16 -0
- package/dist/data/quiz/function/__tick.mcfunction +6 -0
- package/dist/data/quiz/function/__trigger_quiz_a_dispatch.mcfunction +4 -0
- package/dist/data/quiz/function/__trigger_quiz_b_dispatch.mcfunction +4 -0
- package/dist/data/quiz/function/__trigger_quiz_c_dispatch.mcfunction +4 -0
- package/dist/data/quiz/function/__trigger_quiz_start_dispatch.mcfunction +4 -0
- package/dist/data/quiz/function/answer_a.mcfunction +4 -0
- package/dist/data/quiz/function/answer_b.mcfunction +4 -0
- package/dist/data/quiz/function/answer_c.mcfunction +4 -0
- package/dist/data/quiz/function/ask_question/else_1.mcfunction +5 -0
- package/dist/data/quiz/function/ask_question/else_4.mcfunction +5 -0
- package/dist/data/quiz/function/ask_question/else_7.mcfunction +4 -0
- package/dist/data/quiz/function/ask_question/merge_2.mcfunction +1 -0
- package/dist/data/quiz/function/ask_question/merge_5.mcfunction +2 -0
- package/dist/data/quiz/function/ask_question/merge_8.mcfunction +2 -0
- package/dist/data/quiz/function/ask_question/then_0.mcfunction +4 -0
- package/dist/data/quiz/function/ask_question/then_3.mcfunction +4 -0
- package/dist/data/quiz/function/ask_question/then_6.mcfunction +4 -0
- package/dist/data/quiz/function/ask_question.mcfunction +7 -0
- package/dist/data/quiz/function/finish_quiz.mcfunction +6 -0
- package/dist/data/quiz/function/handle_answer/else_1.mcfunction +5 -0
- package/dist/data/quiz/function/handle_answer/else_10.mcfunction +3 -0
- package/dist/data/quiz/function/handle_answer/else_16.mcfunction +3 -0
- package/dist/data/quiz/function/handle_answer/else_4.mcfunction +3 -0
- package/dist/data/quiz/function/handle_answer/else_7.mcfunction +5 -0
- package/dist/data/quiz/function/handle_answer/merge_11.mcfunction +2 -0
- package/dist/data/quiz/function/handle_answer/merge_14.mcfunction +2 -0
- package/dist/data/quiz/function/handle_answer/merge_17.mcfunction +2 -0
- package/dist/data/quiz/function/handle_answer/merge_2.mcfunction +8 -0
- package/dist/data/quiz/function/handle_answer/merge_5.mcfunction +2 -0
- package/dist/data/quiz/function/handle_answer/merge_8.mcfunction +2 -0
- package/dist/data/quiz/function/handle_answer/then_0.mcfunction +5 -0
- package/dist/data/quiz/function/handle_answer/then_12.mcfunction +5 -0
- package/dist/data/quiz/function/handle_answer/then_15.mcfunction +6 -0
- package/dist/data/quiz/function/handle_answer/then_3.mcfunction +6 -0
- package/dist/data/quiz/function/handle_answer/then_6.mcfunction +5 -0
- package/dist/data/quiz/function/handle_answer/then_9.mcfunction +6 -0
- package/dist/data/quiz/function/handle_answer.mcfunction +11 -0
- package/dist/data/quiz/function/start_quiz.mcfunction +5 -0
- package/dist/data/shop/function/__load.mcfunction +7 -0
- package/dist/data/shop/function/__tick.mcfunction +3 -0
- package/dist/data/shop/function/__trigger_shop_buy_dispatch.mcfunction +4 -0
- package/dist/data/shop/function/complete_purchase/else_1.mcfunction +5 -0
- package/dist/data/shop/function/complete_purchase/else_4.mcfunction +5 -0
- package/dist/data/shop/function/complete_purchase/else_7.mcfunction +3 -0
- package/dist/data/shop/function/complete_purchase/merge_2.mcfunction +2 -0
- package/dist/data/shop/function/complete_purchase/merge_5.mcfunction +2 -0
- package/dist/data/shop/function/complete_purchase/merge_8.mcfunction +2 -0
- package/dist/data/shop/function/complete_purchase/then_0.mcfunction +4 -0
- package/dist/data/shop/function/complete_purchase/then_3.mcfunction +4 -0
- package/dist/data/shop/function/complete_purchase/then_6.mcfunction +4 -0
- package/dist/data/shop/function/complete_purchase.mcfunction +7 -0
- package/dist/data/shop/function/handle_shop_trigger.mcfunction +3 -0
- package/dist/data/turret/function/__load.mcfunction +5 -0
- package/dist/data/turret/function/__tick.mcfunction +4 -0
- package/dist/data/turret/function/__trigger_deploy_turret_dispatch.mcfunction +4 -0
- package/dist/data/turret/function/deploy_turret.mcfunction +8 -0
- package/dist/data/turret/function/turret_tick/at_1.mcfunction +2 -0
- package/dist/data/turret/function/turret_tick/foreach_0.mcfunction +2 -0
- package/dist/data/turret/function/turret_tick/foreach_2.mcfunction +2 -0
- package/dist/data/turret/function/turret_tick/tick_body.mcfunction +3 -0
- package/dist/data/turret/function/turret_tick/tick_skip.mcfunction +1 -0
- package/dist/data/turret/function/turret_tick.mcfunction +5 -0
- package/dist/diagnostics/index.d.ts +44 -0
- package/dist/diagnostics/index.js +140 -0
- package/dist/index.d.ts +53 -0
- package/dist/index.js +126 -0
- package/dist/ir/builder.d.ts +32 -0
- package/dist/ir/builder.js +99 -0
- package/dist/ir/types.d.ts +117 -0
- package/dist/ir/types.js +15 -0
- package/dist/lexer/index.d.ts +36 -0
- package/dist/lexer/index.js +458 -0
- package/dist/lowering/index.d.ts +106 -0
- package/dist/lowering/index.js +2041 -0
- package/dist/mc-test/client.d.ts +128 -0
- package/dist/mc-test/client.js +174 -0
- package/dist/mc-test/runner.d.ts +28 -0
- package/dist/mc-test/runner.js +150 -0
- package/dist/mc-test/setup.d.ts +11 -0
- package/dist/mc-test/setup.js +98 -0
- package/dist/mc-validator/index.d.ts +17 -0
- package/dist/mc-validator/index.js +322 -0
- package/dist/nbt/index.d.ts +86 -0
- package/dist/nbt/index.js +250 -0
- package/dist/optimizer/commands.d.ts +36 -0
- package/dist/optimizer/commands.js +349 -0
- package/dist/optimizer/passes.d.ts +34 -0
- package/dist/optimizer/passes.js +227 -0
- package/dist/optimizer/structure.d.ts +8 -0
- package/dist/optimizer/structure.js +344 -0
- package/dist/pack.mcmeta +6 -0
- package/dist/parser/index.d.ts +76 -0
- package/dist/parser/index.js +1193 -0
- package/dist/repl.d.ts +16 -0
- package/dist/repl.js +165 -0
- package/dist/runtime/index.d.ts +101 -0
- package/dist/runtime/index.js +1288 -0
- package/dist/typechecker/index.d.ts +42 -0
- package/dist/typechecker/index.js +629 -0
- package/docs/COMPILATION_STATS.md +142 -0
- package/docs/IMPLEMENTATION_GUIDE.md +512 -0
- package/docs/LANGUAGE_REFERENCE.md +415 -0
- package/docs/MC_MAPPING.md +280 -0
- package/docs/STRUCTURE_TARGET.md +80 -0
- package/docs/mc-reference/commands.md +259 -0
- package/editors/vscode/.vscodeignore +10 -0
- package/editors/vscode/LICENSE +21 -0
- package/editors/vscode/README.md +78 -0
- package/editors/vscode/build.mjs +28 -0
- package/editors/vscode/icon.png +0 -0
- package/editors/vscode/mcfunction-language-configuration.json +28 -0
- package/editors/vscode/out/extension.js +7236 -0
- package/editors/vscode/package-lock.json +566 -0
- package/editors/vscode/package.json +137 -0
- package/editors/vscode/redscript-language-configuration.json +28 -0
- package/editors/vscode/snippets/redscript.json +114 -0
- package/editors/vscode/src/codeactions.ts +89 -0
- package/editors/vscode/src/completion.ts +130 -0
- package/editors/vscode/src/extension.ts +239 -0
- package/editors/vscode/src/hover.ts +1120 -0
- package/editors/vscode/src/symbols.ts +207 -0
- package/editors/vscode/syntaxes/mcfunction.tmLanguage.json +740 -0
- package/editors/vscode/syntaxes/redscript.tmLanguage.json +357 -0
- package/editors/vscode/tsconfig.json +13 -0
- package/jest.config.js +5 -0
- package/package.json +38 -0
- package/src/__tests__/cli.test.ts +130 -0
- package/src/__tests__/codegen.test.ts +128 -0
- package/src/__tests__/diagnostics.test.ts +195 -0
- package/src/__tests__/e2e.test.ts +1721 -0
- package/src/__tests__/fixtures/mc-commands-1.21.4.json +18734 -0
- package/src/__tests__/formatter.test.ts +46 -0
- package/src/__tests__/lexer.test.ts +356 -0
- package/src/__tests__/lowering.test.ts +962 -0
- package/src/__tests__/mc-integration.test.ts +409 -0
- package/src/__tests__/mc-syntax.test.ts +96 -0
- package/src/__tests__/nbt.test.ts +58 -0
- package/src/__tests__/optimizer-advanced.test.ts +144 -0
- package/src/__tests__/optimizer.test.ts +129 -0
- package/src/__tests__/parser.test.ts +800 -0
- package/src/__tests__/repl.test.ts +33 -0
- package/src/__tests__/runtime.test.ts +289 -0
- package/src/__tests__/structure-optimizer.test.ts +38 -0
- package/src/__tests__/typechecker.test.ts +395 -0
- package/src/ast/types.ts +248 -0
- package/src/cli.ts +445 -0
- package/src/codegen/cmdblock/index.ts +63 -0
- package/src/codegen/mcfunction/index.ts +471 -0
- package/src/codegen/structure/index.ts +305 -0
- package/src/compile.ts +188 -0
- package/src/diagnostics/index.ts +186 -0
- package/src/examples/README.md +77 -0
- package/src/examples/SHOWCASE_GAME.md +43 -0
- package/src/examples/arena.rs +44 -0
- package/src/examples/counter.rs +12 -0
- package/src/examples/pvp_arena.rs +131 -0
- package/src/examples/quiz.rs +90 -0
- package/src/examples/rpg.rs +13 -0
- package/src/examples/shop.rs +30 -0
- package/src/examples/showcase_game.rs +552 -0
- package/src/examples/stdlib_demo.rs +181 -0
- package/src/examples/turret.rs +27 -0
- package/src/examples/world_manager.rs +23 -0
- package/src/formatter/index.ts +22 -0
- package/src/index.ts +161 -0
- package/src/ir/builder.ts +114 -0
- package/src/ir/types.ts +119 -0
- package/src/lexer/index.ts +555 -0
- package/src/lowering/index.ts +2406 -0
- package/src/mc-test/client.ts +259 -0
- package/src/mc-test/runner.ts +140 -0
- package/src/mc-test/setup.ts +70 -0
- package/src/mc-validator/index.ts +367 -0
- package/src/nbt/index.ts +321 -0
- package/src/optimizer/commands.ts +416 -0
- package/src/optimizer/passes.ts +233 -0
- package/src/optimizer/structure.ts +441 -0
- package/src/parser/index.ts +1437 -0
- package/src/repl.ts +165 -0
- package/src/runtime/index.ts +1403 -0
- package/src/stdlib/README.md +156 -0
- package/src/stdlib/combat.rs +20 -0
- package/src/stdlib/cooldown.rs +45 -0
- package/src/stdlib/math.rs +49 -0
- package/src/stdlib/mobs.rs +99 -0
- package/src/stdlib/player.rs +29 -0
- package/src/stdlib/strings.rs +7 -0
- package/src/stdlib/timer.rs +51 -0
- package/src/templates/README.md +126 -0
- package/src/templates/combat.rs +96 -0
- package/src/templates/economy.rs +40 -0
- package/src/templates/mini-game-framework.rs +117 -0
- package/src/templates/quest.rs +78 -0
- package/src/test_programs/zombie_game.rs +25 -0
- package/src/typechecker/index.ts +737 -0
- package/tsconfig.json +16 -0
|
@@ -0,0 +1,415 @@
|
|
|
1
|
+
# RedScript Language Reference
|
|
2
|
+
|
|
3
|
+
This document describes the syntax RedScript accepts today.
|
|
4
|
+
|
|
5
|
+
## Program Structure
|
|
6
|
+
|
|
7
|
+
A source file may optionally declare a namespace, followed by any number of `struct` and `fn` declarations.
|
|
8
|
+
|
|
9
|
+
```rs
|
|
10
|
+
namespace turret;
|
|
11
|
+
|
|
12
|
+
struct TurretState { health: int }
|
|
13
|
+
|
|
14
|
+
fn main() {}
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
If no namespace is provided, the CLI derives one from the filename or uses the compile option you pass.
|
|
18
|
+
|
|
19
|
+
## Types
|
|
20
|
+
|
|
21
|
+
RedScript currently supports these primitive types:
|
|
22
|
+
|
|
23
|
+
| Type | Notes |
|
|
24
|
+
|:--|:--|
|
|
25
|
+
| `int` | Scoreboard-backed integer values |
|
|
26
|
+
| `bool` | Lowered as `0` or `1` |
|
|
27
|
+
| `float` | Fixed-point values scaled by `1000` |
|
|
28
|
+
| `string` | Used primarily in builtin calls |
|
|
29
|
+
| `void` | Function return type when no value is produced |
|
|
30
|
+
|
|
31
|
+
Composite types:
|
|
32
|
+
|
|
33
|
+
| Type form | Example |
|
|
34
|
+
|:--|:--|
|
|
35
|
+
| Struct | `TurretState` |
|
|
36
|
+
| Array | `int[]`, `string[]` |
|
|
37
|
+
|
|
38
|
+
### Variables
|
|
39
|
+
|
|
40
|
+
```rs
|
|
41
|
+
let hp: int = 20;
|
|
42
|
+
let enabled: bool = true;
|
|
43
|
+
let speed: float = 1.5;
|
|
44
|
+
let name: string = "turret";
|
|
45
|
+
let numbers: int[] = [1, 2, 3];
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
Type annotations are supported on `let` bindings and function parameters. Function return types use `->`.
|
|
49
|
+
|
|
50
|
+
## Functions
|
|
51
|
+
|
|
52
|
+
Functions use C-style syntax and may return values.
|
|
53
|
+
|
|
54
|
+
```rs
|
|
55
|
+
fn add(a: int, b: int) -> int {
|
|
56
|
+
return a + b;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
fn announce() {
|
|
60
|
+
say("Ready");
|
|
61
|
+
}
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
Rules:
|
|
65
|
+
|
|
66
|
+
- Parameters are positional.
|
|
67
|
+
- A missing return type defaults to `void`.
|
|
68
|
+
- `return;` is valid in `void` functions.
|
|
69
|
+
- Function calls are synchronous and compile to `function <namespace>:<name>`.
|
|
70
|
+
|
|
71
|
+
## Control Flow
|
|
72
|
+
|
|
73
|
+
### `if` / `else`
|
|
74
|
+
|
|
75
|
+
```rs
|
|
76
|
+
fn reward(kills: int) {
|
|
77
|
+
if (kills >= 10) {
|
|
78
|
+
give(@s, "minecraft:diamond", 1);
|
|
79
|
+
} else {
|
|
80
|
+
tell(@s, "Keep going.");
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
`else if` chains are expressed as nested `if` inside `else`.
|
|
86
|
+
|
|
87
|
+
### `while`
|
|
88
|
+
|
|
89
|
+
```rs
|
|
90
|
+
fn countdown() {
|
|
91
|
+
let n: int = 5;
|
|
92
|
+
while (n > 0) {
|
|
93
|
+
n -= 1;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### `for`
|
|
99
|
+
|
|
100
|
+
RedScript supports C-style `for` loops.
|
|
101
|
+
|
|
102
|
+
```rs
|
|
103
|
+
fn repeat() {
|
|
104
|
+
for (let i: int = 0; i < 5; i += 1) {
|
|
105
|
+
say("tick");
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
The initializer is optional, and compound assignment is supported in the step clause.
|
|
111
|
+
|
|
112
|
+
### `foreach`
|
|
113
|
+
|
|
114
|
+
`foreach` iterates over a selector by extracting the body into a helper function and running it with `execute as ... run function ...`.
|
|
115
|
+
|
|
116
|
+
```rs
|
|
117
|
+
fn notify_players() {
|
|
118
|
+
foreach (player in @a) {
|
|
119
|
+
title(player, "Fight!");
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
Inside the loop body, the bound variable refers to the current entity context.
|
|
125
|
+
|
|
126
|
+
## Structs
|
|
127
|
+
|
|
128
|
+
Structs group fields and are stored in Minecraft storage.
|
|
129
|
+
|
|
130
|
+
```rs
|
|
131
|
+
struct TurretState {
|
|
132
|
+
health: int,
|
|
133
|
+
level: int
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
fn create() {
|
|
137
|
+
let state: TurretState = { health: 40, level: 1 };
|
|
138
|
+
state.health = 50;
|
|
139
|
+
let hp = state.health;
|
|
140
|
+
}
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
Supported operations:
|
|
144
|
+
|
|
145
|
+
- Struct declaration
|
|
146
|
+
- Struct literals
|
|
147
|
+
- Field read
|
|
148
|
+
- Field assignment
|
|
149
|
+
- Compound assignment on fields such as `state.health += 5`
|
|
150
|
+
|
|
151
|
+
## Arrays
|
|
152
|
+
|
|
153
|
+
Arrays are currently backed by Minecraft storage.
|
|
154
|
+
|
|
155
|
+
```rs
|
|
156
|
+
fn sample() {
|
|
157
|
+
let nums: int[] = [1, 2, 3];
|
|
158
|
+
nums.push(4);
|
|
159
|
+
let first = nums[0];
|
|
160
|
+
}
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
Current support includes:
|
|
164
|
+
|
|
165
|
+
- Empty arrays: `[]`
|
|
166
|
+
- Array literals with initial values
|
|
167
|
+
- `push(...)`
|
|
168
|
+
- Index reads such as `arr[0]`
|
|
169
|
+
|
|
170
|
+
## Decorators
|
|
171
|
+
|
|
172
|
+
Decorators attach runtime behavior to functions.
|
|
173
|
+
|
|
174
|
+
### `@tick`
|
|
175
|
+
|
|
176
|
+
Runs every game tick through the generated `__tick.mcfunction`.
|
|
177
|
+
|
|
178
|
+
```rs
|
|
179
|
+
@tick
|
|
180
|
+
fn heartbeat() {
|
|
181
|
+
say("tick");
|
|
182
|
+
}
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
### `@tick(rate=N)`
|
|
186
|
+
|
|
187
|
+
Runs every `N` ticks using a generated scoreboard counter.
|
|
188
|
+
|
|
189
|
+
```rs
|
|
190
|
+
@tick(rate=20)
|
|
191
|
+
fn once_per_second() {
|
|
192
|
+
say("1 second");
|
|
193
|
+
}
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
### `@on_trigger("name")`
|
|
197
|
+
|
|
198
|
+
Generates trigger plumbing for `/trigger name`.
|
|
199
|
+
|
|
200
|
+
```rs
|
|
201
|
+
@on_trigger("shop_buy")
|
|
202
|
+
fn handle_shop() {
|
|
203
|
+
complete_purchase();
|
|
204
|
+
}
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
The compiler creates:
|
|
208
|
+
|
|
209
|
+
- a trigger objective in `__load.mcfunction`
|
|
210
|
+
- a dispatch function
|
|
211
|
+
- trigger checks inside `__tick.mcfunction`
|
|
212
|
+
|
|
213
|
+
## Execute Context
|
|
214
|
+
|
|
215
|
+
RedScript supports both shorthand context blocks and explicit `execute ... run { ... }`.
|
|
216
|
+
|
|
217
|
+
### `as`
|
|
218
|
+
|
|
219
|
+
```rs
|
|
220
|
+
as @a {
|
|
221
|
+
say("Hello from each player");
|
|
222
|
+
}
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
### `at`
|
|
226
|
+
|
|
227
|
+
```rs
|
|
228
|
+
at @s {
|
|
229
|
+
summon("zombie", "~", "~", "~");
|
|
230
|
+
}
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
### Combined `as` and `at`
|
|
234
|
+
|
|
235
|
+
```rs
|
|
236
|
+
as @a at @s {
|
|
237
|
+
particle("flame", "~", "~", "~");
|
|
238
|
+
}
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
### `execute ... run { ... }`
|
|
242
|
+
|
|
243
|
+
Supported subcommands today:
|
|
244
|
+
|
|
245
|
+
- `as <selector>`
|
|
246
|
+
- `at <selector>`
|
|
247
|
+
- `if entity <selector>`
|
|
248
|
+
- `unless entity <selector>`
|
|
249
|
+
- `in <dimension>`
|
|
250
|
+
|
|
251
|
+
Examples:
|
|
252
|
+
|
|
253
|
+
```rs
|
|
254
|
+
execute as @a run {
|
|
255
|
+
say("Hello");
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
execute as @a at @s run {
|
|
259
|
+
particle("flame", "~", "~", "~");
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
execute as @a if entity @s[tag=admin] run {
|
|
263
|
+
give(@s, "minecraft:diamond", 1);
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
execute as @a unless entity @s[tag=dead] run {
|
|
267
|
+
effect(@s, "regeneration", 5);
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
execute as @a at @s if entity @s[tag=vip] in overworld run {
|
|
271
|
+
title(@s, "VIP");
|
|
272
|
+
}
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
## Selectors
|
|
276
|
+
|
|
277
|
+
Entity selectors are first-class expressions and can be passed directly to builtins.
|
|
278
|
+
|
|
279
|
+
### Supported selector heads
|
|
280
|
+
|
|
281
|
+
| Selector | Meaning |
|
|
282
|
+
|:--|:--|
|
|
283
|
+
| `@a` | All players |
|
|
284
|
+
| `@e` | All entities |
|
|
285
|
+
| `@s` | Current executor |
|
|
286
|
+
| `@p` | Nearest player |
|
|
287
|
+
|
|
288
|
+
### Common filters
|
|
289
|
+
|
|
290
|
+
```rs
|
|
291
|
+
@e[type=zombie]
|
|
292
|
+
@e[type=zombie, distance=..8]
|
|
293
|
+
@e[type=armor_stand, tag=turret]
|
|
294
|
+
@a[scores={kills=10..}]
|
|
295
|
+
@p[distance=..5]
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
Supported filter categories in the current parser:
|
|
299
|
+
|
|
300
|
+
- `type`
|
|
301
|
+
- `distance` with ranges such as `..5`, `1..`, `1..10`
|
|
302
|
+
- `tag`
|
|
303
|
+
- score filters
|
|
304
|
+
- `limit`
|
|
305
|
+
- `sort`
|
|
306
|
+
- `nbt`
|
|
307
|
+
- `gamemode`
|
|
308
|
+
|
|
309
|
+
## Coordinates
|
|
310
|
+
|
|
311
|
+
Block positions are first-class values with the `BlockPos` type.
|
|
312
|
+
|
|
313
|
+
### Absolute coordinates
|
|
314
|
+
|
|
315
|
+
```rs
|
|
316
|
+
let spawn: BlockPos = (0, 64, 0);
|
|
317
|
+
setblock((4, 65, 4), "minecraft:gold_block");
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
### Relative coordinates
|
|
321
|
+
|
|
322
|
+
```rs
|
|
323
|
+
tp(@s, (~1, ~0, ~-1));
|
|
324
|
+
```
|
|
325
|
+
|
|
326
|
+
### Local coordinates
|
|
327
|
+
|
|
328
|
+
```rs
|
|
329
|
+
tp(@s, (^0, ^1, ^0));
|
|
330
|
+
```
|
|
331
|
+
|
|
332
|
+
### Mixed coordinates
|
|
333
|
+
|
|
334
|
+
```rs
|
|
335
|
+
setblock((~0, 64, ~0), "minecraft:stone");
|
|
336
|
+
```
|
|
337
|
+
|
|
338
|
+
Each component can be:
|
|
339
|
+
|
|
340
|
+
- an absolute integer like `64`
|
|
341
|
+
- a relative coordinate like `~` or `~-2`
|
|
342
|
+
- a local coordinate like `^` or `^3`
|
|
343
|
+
|
|
344
|
+
## Builtins
|
|
345
|
+
|
|
346
|
+
The compiler recognizes these builtins and lowers them directly to Minecraft commands or runtime helpers.
|
|
347
|
+
|
|
348
|
+
| Builtin | Returns | Notes |
|
|
349
|
+
|:--|:--|:--|
|
|
350
|
+
| `say(msg)` | `void` | Emits `say` |
|
|
351
|
+
| `tell(sel, msg)` | `void` | Emits `tellraw` with a plain text JSON component |
|
|
352
|
+
| `title(sel, msg)` | `void` | Emits `title <sel> title` |
|
|
353
|
+
| `give(sel, item, count?)` | `void` | Default count is `1` |
|
|
354
|
+
| `effect(sel, effect, duration?, amplifier?)` | `void` | Defaults: duration `30`, amplifier `0` |
|
|
355
|
+
| `summon(type, x?, y?, z?, nbt?)` | `void` | Defaults position to `~ ~ ~` |
|
|
356
|
+
| `particle(name, x?, y?, z?)` | `void` | Defaults position to `~ ~ ~` |
|
|
357
|
+
| `tp(sel, x?, y?, z?)` | `void` | Also accepts `tp(sel, pos)` with `BlockPos` |
|
|
358
|
+
| `setblock(x, y, z, block)` | `void` | Also accepts `setblock(pos, block)` with `BlockPos` |
|
|
359
|
+
| `fill(x1, y1, z1, x2, y2, z2, block)` | `void` | Also accepts `fill(from, to, block)` with `BlockPos` |
|
|
360
|
+
| `clone(x1, y1, z1, x2, y2, z2, dx, dy, dz)` | `void` | Also accepts `clone(from, to, dest)` with `BlockPos` |
|
|
361
|
+
| `kill(sel?)` | `void` | Defaults to `@s` |
|
|
362
|
+
| `scoreboard_get(target, objective)` | `int` | Reads a scoreboard score |
|
|
363
|
+
| `score(target, objective)` | `int` | Alias of `scoreboard_get` |
|
|
364
|
+
| `scoreboard_set(target, objective, value)` | `void` | Writes a scoreboard score |
|
|
365
|
+
| `data_get(kind, target, path, scale?)` | `int` | Reads NBT with `data get` |
|
|
366
|
+
| `random(min, max)` | `int` | Uses `scoreboard players random` for pre-1.20.3 compatibility |
|
|
367
|
+
| `random_native(min, max)` | `int` | Uses `/random value <min> <max>` (MC 1.20.3+) |
|
|
368
|
+
| `random_sequence(sequence, seed?)` | `void` | Uses `/random reset <sequence> <seed>`; default seed is `0` (MC 1.20.3+) |
|
|
369
|
+
| `spawn_object(x, y, z)` | world object handle | Spawns an invisible armor stand with generated tags |
|
|
370
|
+
| `raw(cmd)` | `void` | Emits a literal Minecraft command |
|
|
371
|
+
|
|
372
|
+
### Entity helper methods
|
|
373
|
+
|
|
374
|
+
These are written as member calls on selectors or spawned object handles:
|
|
375
|
+
|
|
376
|
+
| Method | Returns | Example |
|
|
377
|
+
|:--|:--|:--|
|
|
378
|
+
| `entity.tag(name)` | `void` | `@s.tag("boss");` |
|
|
379
|
+
| `entity.untag(name)` | `void` | `@s.untag("boss");` |
|
|
380
|
+
| `entity.has_tag(name)` | `bool` | `let boss: bool = @s.has_tag("boss");` |
|
|
381
|
+
|
|
382
|
+
## Operators
|
|
383
|
+
|
|
384
|
+
Arithmetic and comparison operators:
|
|
385
|
+
|
|
386
|
+
- `+`, `-`, `*`, `/`, `%`
|
|
387
|
+
- `==`, `!=`, `<`, `<=`, `>`, `>=`
|
|
388
|
+
- `&&`, `||`
|
|
389
|
+
- unary `-`, `!`
|
|
390
|
+
|
|
391
|
+
Assignment operators:
|
|
392
|
+
|
|
393
|
+
- `=`
|
|
394
|
+
- `+=`
|
|
395
|
+
- `-=`
|
|
396
|
+
- `*=`
|
|
397
|
+
- `/=`
|
|
398
|
+
- `%=`
|
|
399
|
+
|
|
400
|
+
## Raw Commands
|
|
401
|
+
|
|
402
|
+
Use `raw(...)` when you need an escape hatch for a command RedScript does not model directly.
|
|
403
|
+
|
|
404
|
+
```rs
|
|
405
|
+
fn admin() {
|
|
406
|
+
raw("gamemode creative @a");
|
|
407
|
+
}
|
|
408
|
+
```
|
|
409
|
+
|
|
410
|
+
## Notes on Numeric Semantics
|
|
411
|
+
|
|
412
|
+
- `int` values map directly to scoreboard integers.
|
|
413
|
+
- `bool` is lowered as integer `0` or `1`.
|
|
414
|
+
- `float` is stored as fixed-point `value * 1000`.
|
|
415
|
+
- String values are currently most useful as builtin arguments rather than general-purpose data values.
|
|
@@ -0,0 +1,280 @@
|
|
|
1
|
+
# RedScript to Minecraft Mapping
|
|
2
|
+
|
|
3
|
+
This document explains how the compiler maps RedScript constructs onto Minecraft commands and generated files.
|
|
4
|
+
|
|
5
|
+
## Pipeline Overview
|
|
6
|
+
|
|
7
|
+
The compiler pipeline is:
|
|
8
|
+
|
|
9
|
+
```text
|
|
10
|
+
Lexer -> Parser -> AST -> IR Lowering -> Optimizer -> CodeGen
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
The lowering stage converts RedScript syntax into a simple three-address IR. The optimizer rewrites that IR, and code generation emits datapack files or command block JSON.
|
|
14
|
+
|
|
15
|
+
## Variables
|
|
16
|
+
|
|
17
|
+
### Local scalar variables
|
|
18
|
+
|
|
19
|
+
Scalar locals such as `int`, `bool`, and fixed-point `float` values are stored as scoreboard entries on the `rs` objective.
|
|
20
|
+
|
|
21
|
+
Example RedScript:
|
|
22
|
+
|
|
23
|
+
```rs
|
|
24
|
+
fn sample() {
|
|
25
|
+
let x: int = 42;
|
|
26
|
+
}
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
Typical generated command pattern:
|
|
30
|
+
|
|
31
|
+
```mcfunction
|
|
32
|
+
scoreboard players set $x rs 42
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
The compiler uses fake-player names such as:
|
|
36
|
+
|
|
37
|
+
- `$x`
|
|
38
|
+
- `$t0`
|
|
39
|
+
- `$ret`
|
|
40
|
+
|
|
41
|
+
This keeps temporary values and user variables addressable through standard scoreboard operations.
|
|
42
|
+
|
|
43
|
+
### Booleans
|
|
44
|
+
|
|
45
|
+
Booleans are represented as:
|
|
46
|
+
|
|
47
|
+
- `0` for false
|
|
48
|
+
- `1` for true
|
|
49
|
+
|
|
50
|
+
Conditions are compiled into `execute if score ... matches 1..` style checks.
|
|
51
|
+
|
|
52
|
+
### Floats
|
|
53
|
+
|
|
54
|
+
`float` values are stored as fixed-point integers scaled by `1000`.
|
|
55
|
+
|
|
56
|
+
Example:
|
|
57
|
+
|
|
58
|
+
```rs
|
|
59
|
+
let speed: float = 1.5;
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
becomes an internal scoreboard value of `1500`.
|
|
63
|
+
|
|
64
|
+
Multiplication and division insert scaling correction steps during lowering so arithmetic remains approximately correct under the fixed-point scheme.
|
|
65
|
+
|
|
66
|
+
## Functions
|
|
67
|
+
|
|
68
|
+
Each RedScript function becomes one or more `.mcfunction` files in the generated namespace.
|
|
69
|
+
|
|
70
|
+
Example:
|
|
71
|
+
|
|
72
|
+
```rs
|
|
73
|
+
fn reward_player() {
|
|
74
|
+
give(@s, "minecraft:diamond", 1);
|
|
75
|
+
}
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
becomes a datapack function like:
|
|
79
|
+
|
|
80
|
+
```text
|
|
81
|
+
data/<namespace>/function/reward_player.mcfunction
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
Function calls map to Minecraft `function` commands:
|
|
85
|
+
|
|
86
|
+
```mcfunction
|
|
87
|
+
function <namespace>:reward_player
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
The compiler also generates runtime entrypoints such as:
|
|
91
|
+
|
|
92
|
+
- `__load.mcfunction`
|
|
93
|
+
- `__tick.mcfunction`
|
|
94
|
+
- trigger dispatch helpers like `__trigger_<name>_dispatch.mcfunction`
|
|
95
|
+
|
|
96
|
+
## Control Flow
|
|
97
|
+
|
|
98
|
+
RedScript control flow is lowered into basic blocks and conditional jumps, then emitted as `execute if score ... run function ...` patterns.
|
|
99
|
+
|
|
100
|
+
Examples:
|
|
101
|
+
|
|
102
|
+
- `if` creates conditional branches plus merge blocks.
|
|
103
|
+
- `while` and `for` create explicit loop check, body, and exit blocks.
|
|
104
|
+
- `foreach` extracts the loop body into a helper function and runs it with `execute as <selector> run function ...`.
|
|
105
|
+
|
|
106
|
+
## Selectors and Execution Context
|
|
107
|
+
|
|
108
|
+
Selectors such as `@a`, `@e[type=zombie]`, and `@s` are preserved directly in emitted commands.
|
|
109
|
+
|
|
110
|
+
Context blocks map as follows:
|
|
111
|
+
|
|
112
|
+
| RedScript | Minecraft form |
|
|
113
|
+
|:--|:--|
|
|
114
|
+
| `as @a { ... }` | `execute as @a run function ...` |
|
|
115
|
+
| `at @s { ... }` | `execute at @s run function ...` |
|
|
116
|
+
| `execute as @a if entity @s[tag=vip] run { ... }` | `execute as @a if entity @s[tag=vip] run function ...` |
|
|
117
|
+
|
|
118
|
+
The body is extracted into a helper `.mcfunction` so the generated `execute` command stays simple and composable.
|
|
119
|
+
|
|
120
|
+
## Builtins
|
|
121
|
+
|
|
122
|
+
Many RedScript builtins compile almost directly to one Minecraft command.
|
|
123
|
+
|
|
124
|
+
Examples:
|
|
125
|
+
|
|
126
|
+
| RedScript | Generated command pattern |
|
|
127
|
+
|:--|:--|
|
|
128
|
+
| `say("Hello")` | `say Hello` |
|
|
129
|
+
| `give(@s, "minecraft:bread", 1)` | `give @s minecraft:bread 1` |
|
|
130
|
+
| `kill(@e[type=zombie])` | `kill @e[type=zombie]` |
|
|
131
|
+
| `title(@a, "Fight!")` | `title @a title {"text":"Fight!"}` |
|
|
132
|
+
| `scoreboard_set(@s, "kills", 5)` | `scoreboard players set @s kills 5` |
|
|
133
|
+
|
|
134
|
+
Other builtins need special lowering:
|
|
135
|
+
|
|
136
|
+
- `scoreboard_get(...)` reads a scoreboard into a compiler-managed temp variable.
|
|
137
|
+
- `data_get(...)` uses `execute store result score ... run data get ...`.
|
|
138
|
+
- `random(...)` uses `scoreboard players random` for legacy compatibility.
|
|
139
|
+
- `random_native(...)` uses `/random value <min> <max>` on MC 1.20.3+.
|
|
140
|
+
- `random_sequence(...)` uses `/random reset <sequence> <seed>` on MC 1.20.3+.
|
|
141
|
+
- `spawn_object(...)` spawns an invisible armor stand and returns a selector handle.
|
|
142
|
+
|
|
143
|
+
## Structs
|
|
144
|
+
|
|
145
|
+
Structs are stored in Minecraft storage under `rs:heap`.
|
|
146
|
+
|
|
147
|
+
Example:
|
|
148
|
+
|
|
149
|
+
```rs
|
|
150
|
+
struct Point { x: int, y: int }
|
|
151
|
+
|
|
152
|
+
fn test() {
|
|
153
|
+
let p: Point = { x: 10, y: 20 };
|
|
154
|
+
p.x = 30;
|
|
155
|
+
}
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
Typical generated patterns:
|
|
159
|
+
|
|
160
|
+
```mcfunction
|
|
161
|
+
data modify storage rs:heap point_p.x set value 10
|
|
162
|
+
data modify storage rs:heap point_p.y set value 20
|
|
163
|
+
data modify storage rs:heap point_p.x set value 30
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
Field reads use `data get storage ...` together with `execute store result score ...`.
|
|
167
|
+
|
|
168
|
+
## Arrays
|
|
169
|
+
|
|
170
|
+
Arrays are represented with Minecraft storage and currently behave like NBT-backed collections.
|
|
171
|
+
|
|
172
|
+
Example:
|
|
173
|
+
|
|
174
|
+
```rs
|
|
175
|
+
let arr: int[] = [1, 2, 3];
|
|
176
|
+
arr.push(4);
|
|
177
|
+
let first = arr[0];
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
Typical generated patterns:
|
|
181
|
+
|
|
182
|
+
```mcfunction
|
|
183
|
+
data modify storage rs:heap arr set value []
|
|
184
|
+
data modify storage rs:heap arr append value 1
|
|
185
|
+
data modify storage rs:heap arr append value 2
|
|
186
|
+
data modify storage rs:heap arr append value 3
|
|
187
|
+
data modify storage rs:heap arr append value 4
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
This part of the storage model is still evolving, so larger collection features should be treated as early-stage compared with scalar scoreboard variables.
|
|
191
|
+
|
|
192
|
+
## World Objects
|
|
193
|
+
|
|
194
|
+
`spawn_object(...)` creates an invisible marker armor stand and uses tags plus scoreboards to model a world-backed object.
|
|
195
|
+
|
|
196
|
+
Example:
|
|
197
|
+
|
|
198
|
+
```rs
|
|
199
|
+
let turret = spawn_object(0, 64, 0);
|
|
200
|
+
turret.health = 100;
|
|
201
|
+
turret.tag("turret");
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
Typical generated behavior:
|
|
205
|
+
|
|
206
|
+
- summon an armor stand with tags like `__rs_obj_<n>`
|
|
207
|
+
- address it with a selector such as `@e[tag=__rs_obj_<n>,limit=1]`
|
|
208
|
+
- map field writes to scoreboard or storage operations
|
|
209
|
+
- map `tag(...)` and `untag(...)` to the vanilla `tag` command
|
|
210
|
+
|
|
211
|
+
## Tick and Trigger Decorators
|
|
212
|
+
|
|
213
|
+
### `@tick`
|
|
214
|
+
|
|
215
|
+
Tick handlers are registered through `data/minecraft/tags/function/tick.json` and invoked from `__tick.mcfunction`.
|
|
216
|
+
|
|
217
|
+
### `@tick(rate=N)`
|
|
218
|
+
|
|
219
|
+
Rate-limited tick handlers get an extra scoreboard counter. The compiler inserts logic equivalent to:
|
|
220
|
+
|
|
221
|
+
1. increment the counter every tick
|
|
222
|
+
2. check whether it has reached `N`
|
|
223
|
+
3. reset it when the body runs
|
|
224
|
+
|
|
225
|
+
### `@on_trigger("name")`
|
|
226
|
+
|
|
227
|
+
Trigger handlers generate:
|
|
228
|
+
|
|
229
|
+
- `scoreboard objectives add <name> trigger` in `__load.mcfunction`
|
|
230
|
+
- trigger checks in `__tick.mcfunction`
|
|
231
|
+
- a dispatch function that calls the user handler and clears the trigger score
|
|
232
|
+
|
|
233
|
+
## Command Block Target
|
|
234
|
+
|
|
235
|
+
In command block mode, the compiler emits a JSON description for command block placement instead of a datapack directory. This is meant for command-block-based setups while reusing the same frontend, lowering, and optimization pipeline.
|
|
236
|
+
|
|
237
|
+
## Optimizations
|
|
238
|
+
|
|
239
|
+
The optimizer currently includes three core passes.
|
|
240
|
+
|
|
241
|
+
### Constant folding
|
|
242
|
+
|
|
243
|
+
Compile-time constant expressions are evaluated early.
|
|
244
|
+
|
|
245
|
+
Example:
|
|
246
|
+
|
|
247
|
+
```rs
|
|
248
|
+
return 2 + 3;
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
is simplified to an IR constant equivalent to `5`.
|
|
252
|
+
|
|
253
|
+
### Copy propagation
|
|
254
|
+
|
|
255
|
+
Redundant temporaries are removed when values can be forwarded safely.
|
|
256
|
+
|
|
257
|
+
Example idea:
|
|
258
|
+
|
|
259
|
+
```rs
|
|
260
|
+
let x: int = 10;
|
|
261
|
+
let y: int = x;
|
|
262
|
+
return y;
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
can emit fewer scoreboard moves because `y` can reuse the known value of `x`.
|
|
266
|
+
|
|
267
|
+
### Dead code elimination
|
|
268
|
+
|
|
269
|
+
Assignments whose results are never read are removed before code generation. This reduces scoreboard churn and helps keep generated datapacks smaller and easier to inspect.
|
|
270
|
+
|
|
271
|
+
## Practical Consequences
|
|
272
|
+
|
|
273
|
+
The mapping strategy is intentionally pragmatic:
|
|
274
|
+
|
|
275
|
+
- scoreboard storage is fast and predictable for scalar logic
|
|
276
|
+
- storage-backed structs and arrays handle composite data
|
|
277
|
+
- helper functions keep `execute`-heavy control flow manageable
|
|
278
|
+
- optimization passes reduce unnecessary commands before codegen
|
|
279
|
+
|
|
280
|
+
That combination is what lets RedScript express higher-level gameplay logic while still compiling to vanilla Minecraft primitives.
|