redscript-mc 1.2.28 → 1.2.29

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.
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "redscript-vscode",
3
- "version": "1.0.35",
3
+ "version": "1.0.37",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "redscript-vscode",
9
- "version": "1.0.35",
9
+ "version": "1.0.37",
10
10
  "license": "MIT",
11
11
  "dependencies": {
12
12
  "redscript": "file:../../"
@@ -23,7 +23,7 @@
23
23
  },
24
24
  "../..": {
25
25
  "name": "redscript-mc",
26
- "version": "1.2.27",
26
+ "version": "1.2.28",
27
27
  "license": "MIT",
28
28
  "bin": {
29
29
  "redscript": "dist/cli.js",
@@ -2,7 +2,7 @@
2
2
  "name": "redscript-vscode",
3
3
  "displayName": "RedScript for Minecraft",
4
4
  "description": "Syntax highlighting, error diagnostics, and language support for RedScript — a compiler targeting Minecraft Java Edition",
5
- "version": "1.0.35",
5
+ "version": "1.0.37",
6
6
  "publisher": "bkmashiro",
7
7
  "icon": "icon.png",
8
8
  "license": "MIT",
@@ -1009,6 +1009,24 @@ export function registerHoverProvider(context: vscode.ExtensionContext): void {
1009
1009
  provideHover(document, position) {
1010
1010
  const line = document.lineAt(position.line).text
1011
1011
 
1012
+ // ── #rs — special compiler token ────────────────────────
1013
+ const rsRange = document.getWordRangeAtPosition(position, /#rs\b/)
1014
+ if (rsRange) {
1015
+ const md = new vscode.MarkdownString('', true)
1016
+ md.isTrusted = true
1017
+ md.appendCodeblock('#rs', 'redscript')
1018
+ md.appendMarkdown('**RS Internal Scoreboard Objective** *(compiler token)*\n\n')
1019
+ md.appendMarkdown('Resolves to the current datapack\'s internal scoreboard objective at compile time.\n\n')
1020
+ md.appendMarkdown('Default: `__<namespace>` (e.g. `__mygame` for namespace `mygame`).\n\n')
1021
+ md.appendMarkdown('Use `#rs` in `scoreboard_get` / `scoreboard_set` when you need to read or write\n')
1022
+ md.appendMarkdown('the compiler\'s own variable slots — such as in stdlib implementations.\n\n')
1023
+ md.appendMarkdown('> ⚠️ Unlike other `#name` tokens, `#rs` does **not** compile to the literal string `rs`.\n')
1024
+ md.appendMarkdown('> It tracks the `--scoreboard` flag or the `__<namespace>` default.\n\n')
1025
+ md.appendMarkdown('**Example:**\n')
1026
+ md.appendCodeblock('scoreboard_set("timer_ticks", #rs, 0);\n// compiles to: scoreboard players set timer_ticks __mygame 0', 'redscript')
1027
+ return new vscode.Hover(md, rsRange)
1028
+ }
1029
+
1012
1030
  // ── #mc_name hover ──────────────────────────────────────
1013
1031
  const mcRange = document.getWordRangeAtPosition(position, /#[a-zA-Z_][a-zA-Z0-9_]*/)
1014
1032
  if (mcRange) {
@@ -307,9 +307,18 @@
307
307
  },
308
308
 
309
309
  "mc-name": {
310
- "comment": "#objective, #tag, #team — unquoted MC identifier literal",
311
- "name": "variable.other.mc-name.redscript",
312
- "match": "#[a-zA-Z_][a-zA-Z0-9_]*"
310
+ "comment": "#objective, #tag, #team — unquoted MC identifier literal. #rs is the special RS-internal scoreboard objective token.",
311
+ "patterns": [
312
+ {
313
+ "comment": "#rs — special compiler token: resolves to the current datapack's internal scoreboard objective (__<namespace>)",
314
+ "name": "support.constant.rs-objective.redscript",
315
+ "match": "#rs\\b"
316
+ },
317
+ {
318
+ "name": "variable.other.mc-name.redscript",
319
+ "match": "#[a-zA-Z_][a-zA-Z0-9_]*"
320
+ }
321
+ ]
313
322
  },
314
323
 
315
324
  "operators": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "redscript-mc",
3
- "version": "1.2.28",
3
+ "version": "1.2.29",
4
4
  "description": "A high-level programming language that compiles to Minecraft datapacks",
5
5
  "main": "dist/index.js",
6
6
  "bin": {
@@ -55,7 +55,7 @@ describe('CLI API', () => {
55
55
  const result = compile(source, { namespace: 'mygame', filePath: mainPath })
56
56
  const tickTimer = result.files.find(file => file.path.endsWith('/tick_timer.mcfunction'))
57
57
 
58
- expect(tickTimer?.content).toContain('scoreboard players set #rs mygame.timer_ticks 1')
58
+ expect(tickTimer?.content).toContain('scoreboard players set #rs __mygame.timer_ticks 1')
59
59
  })
60
60
 
61
61
  it('adds a call-site hash for stdlib internal scoreboard objectives', () => {
@@ -113,8 +113,8 @@ describe('CLI API', () => {
113
113
 
114
114
  expect(result.typeErrors).toEqual([])
115
115
  const newFn = result.files.find(file => file.path.endsWith('/Timer_new.mcfunction'))
116
- expect(newFn?.content).toContain('scoreboard players set timer_ticks timernew 0')
117
- expect(newFn?.content).toContain('scoreboard players set timer_active timernew 0')
116
+ expect(newFn?.content).toContain('scoreboard players set timer_ticks __timernew 0')
117
+ expect(newFn?.content).toContain('scoreboard players set timer_active __timernew 0')
118
118
  })
119
119
 
120
120
  it('Timer.start/pause/reset', () => {
@@ -142,9 +142,9 @@ describe('CLI API', () => {
142
142
  const pauseFn = result.files.find(file => file.path.endsWith('/Timer_pause.mcfunction'))
143
143
  const resetFn = result.files.find(file => file.path.endsWith('/Timer_reset.mcfunction'))
144
144
 
145
- expect(startFn?.content).toContain('scoreboard players set timer_active timerstate 1')
146
- expect(pauseFn?.content).toContain('scoreboard players set timer_active timerstate 0')
147
- expect(resetFn?.content).toContain('scoreboard players set timer_ticks timerstate 0')
145
+ expect(startFn?.content).toContain('scoreboard players set timer_active __timerstate 1')
146
+ expect(pauseFn?.content).toContain('scoreboard players set timer_active __timerstate 0')
147
+ expect(resetFn?.content).toContain('scoreboard players set timer_ticks __timerstate 0')
148
148
  })
149
149
 
150
150
  it('Timer.done returns bool', () => {
@@ -171,9 +171,9 @@ describe('CLI API', () => {
171
171
  expect(result.typeErrors).toEqual([])
172
172
  const doneFn = result.files.find(file => file.path.endsWith('/Timer_done.mcfunction'))
173
173
  const mainFn = result.files.find(file => file.path.endsWith('/main.mcfunction'))
174
- expect(doneFn?.content).toContain('scoreboard players get timer_ticks timerdone')
174
+ expect(doneFn?.content).toContain('scoreboard players get timer_ticks __timerdone')
175
175
  expect(doneFn?.content).toContain('return run scoreboard players get')
176
- expect(mainFn?.content).toContain('execute if score $main_finished timerdone matches 1..')
176
+ expect(mainFn?.content).toContain('execute if score $main_finished __timerdone matches 1..')
177
177
  })
178
178
 
179
179
  it('Timer.tick increments', () => {
@@ -201,10 +201,10 @@ describe('CLI API', () => {
201
201
  .map(file => file.content)
202
202
  .join('\n')
203
203
 
204
- expect(tickOutput).toContain('scoreboard players get timer_active timertick')
205
- expect(tickOutput).toContain('scoreboard players get timer_ticks timertick')
206
- expect(tickOutput).toContain(' += $const_1 timertick')
207
- expect(tickOutput).toContain('execute store result score timer_ticks timertick run scoreboard players get $_')
204
+ expect(tickOutput).toContain('scoreboard players get timer_active __timertick')
205
+ expect(tickOutput).toContain('scoreboard players get timer_ticks __timertick')
206
+ expect(tickOutput).toContain(' += $const_1 __timertick')
207
+ expect(tickOutput).toContain('execute store result score timer_ticks __timertick run scoreboard players get $_')
208
208
  })
209
209
  })
210
210
 
@@ -28,7 +28,7 @@ fn turret_tick() {
28
28
  const parent = getFileContent(result.files, 'data/test/function/turret_tick.mcfunction')
29
29
  const loopBody = getFileContent(result.files, 'data/test/function/turret_tick/foreach_0.mcfunction')
30
30
 
31
- const hoistedRead = 'execute store result score $_0 test run scoreboard players get config test.turret_range'
31
+ const hoistedRead = 'execute store result score $_0 __test run scoreboard players get config test.turret_range'
32
32
  const executeCall = 'execute as @e[tag=turret] run function test:turret_tick/foreach_0'
33
33
 
34
34
  expect(parent).toContain(hoistedRead)
@@ -54,7 +54,7 @@ fn read_twice() {
54
54
  const readMatches = fn.match(/scoreboard players get @s test\.coins/g) ?? []
55
55
 
56
56
  expect(readMatches).toHaveLength(1)
57
- expect(fn).toContain('scoreboard players operation $_1 test = $_0 test')
57
+ expect(fn).toContain('scoreboard players operation $_1 __test = $_0 __test')
58
58
  })
59
59
 
60
60
  test('reuses duplicate arithmetic sequences', () => {
@@ -71,10 +71,10 @@ fn math() {
71
71
 
72
72
  const result = compile(source, { namespace: 'test' })
73
73
  const fn = getFileContent(result.files, 'data/test/function/math.mcfunction')
74
- const addMatches = fn.match(/\+= \$const_2 test/g) ?? []
74
+ const addMatches = fn.match(/\+= \$const_2 __test/g) ?? []
75
75
 
76
76
  expect(addMatches).toHaveLength(1)
77
- expect(fn).toContain('scoreboard players operation $_1 test = $_0 test')
77
+ expect(fn).toContain('scoreboard players operation $_1 __test = $_0 __test')
78
78
  })
79
79
  })
80
80
 
package/src/compile.ts CHANGED
@@ -28,8 +28,9 @@ export interface CompileOptions {
28
28
  dce?: boolean
29
29
  mangle?: boolean
30
30
  /** Scoreboard objective used for all variable slots.
31
- * Defaults to 'rs'. Set to a unique value (e.g. 'mypack_rs') when loading
32
- * multiple RedScript datapacks simultaneously to avoid variable collisions. */
31
+ * Defaults to '__<namespace>' (e.g. '__mathshow') the double-underscore
32
+ * prefix signals compiler-internal and avoids occupying the user's namespace.
33
+ * Each datapack gets a unique objective automatically; no manual setup needed. */
33
34
  scoreboardObjective?: string
34
35
  /** Additional source files that should be treated as *library* code.
35
36
  * Functions in these files are DCE-eligible: they are only compiled into
@@ -269,7 +270,7 @@ export function compile(source: string, options: CompileOptions = {}): CompileRe
269
270
  // Configure scoreboard objective for this compilation.
270
271
  // Default: use the datapack namespace so each datapack gets its own objective
271
272
  // automatically, preventing variable collisions when multiple datapacks coexist.
272
- const scoreboardObj = options.scoreboardObjective ?? namespace
273
+ const scoreboardObj = options.scoreboardObjective ?? `__${namespace}`
273
274
  setScoreboardObjective(scoreboardObj)
274
275
 
275
276
  // Lowering
package/src/index.ts CHANGED
@@ -36,9 +36,10 @@ export interface CompileOptions {
36
36
  filePath?: string
37
37
  dce?: boolean
38
38
  mangle?: boolean
39
- /** Scoreboard objective used for all variable slots (default: 'rs').
40
- * Set a unique value per datapack to avoid collisions when multiple
41
- * RedScript datapacks are loaded simultaneously. */
39
+ /** Scoreboard objective used for all variable slots.
40
+ * Defaults to '__<namespace>' (e.g. '__mathshow') to avoid collisions when
41
+ * multiple RedScript datapacks are loaded simultaneously, without occupying
42
+ * the user's own namespace. Override only if you need a specific name. */
42
43
  scoreboardObjective?: string
43
44
  }
44
45
 
@@ -108,7 +109,7 @@ export function compile(source: string, options: CompileOptions = {}): CompileRe
108
109
  // Configure scoreboard objective for this compilation.
109
110
  // Default: use the datapack namespace so each datapack gets its own objective
110
111
  // automatically, preventing variable collisions when multiple datapacks coexist.
111
- const scoreboardObj = options.scoreboardObjective ?? namespace
112
+ const scoreboardObj = options.scoreboardObjective ?? `__${namespace}`
112
113
  setScoreboardObjective(scoreboardObj)
113
114
 
114
115
  // Lowering to IR