Skip to content

Commit 8f6db95

Browse files
authored
localRoot must point directly to js files, not pack root. Warn user if no sources found at set location. (#20)
1 parent c4abc73 commit 8f6db95

File tree

6 files changed

+70
-41
lines changed

6 files changed

+70
-41
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,3 +23,7 @@
2323
## Version 0.4.0 (August 2022)
2424

2525
- Add support for source maps that contain absolute paths.
26+
27+
## Version 0.5.0 (September 2022)
28+
29+
- Changes to the source path location in Minecraft require that localRoot points to a directory with sources, not the pack root. Update your launch.json 'localRoot'.

package.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"name": "minecraft-debugger",
33
"displayName": "Minecraft Bedrock Edition Debugger",
44
"description": "Debug your JavaScript code running as part of the GameTest Framework experimental feature in Minecraft Bedrock Edition.",
5-
"version": "0.4.1",
5+
"version": "0.5.0",
66
"publisher": "mojang-studios",
77
"author": {
88
"name": "Mojang Studios"
@@ -61,8 +61,8 @@
6161
},
6262
"localRoot": {
6363
"type": "string",
64-
"description": "The local root of the Minecraft Add-On.",
65-
"default": "${workspaceFolder}/"
64+
"description": "The local root of the Minecraft Add-On scripts folder.",
65+
"default": "${workspaceFolder}/scripts/"
6666
},
6767
"sourceMapRoot": {
6868
"type": "string",

src/ConfigProvider.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ export class ConfigProvider implements vscode.DebugConfigurationProvider {
2121
config.name = 'Attach to Minecraft';
2222
}
2323
if (!config.localRoot) {
24-
config.localRoot = "${workspaceFolder}/";
24+
config.localRoot = "${workspaceFolder}/scripts/";
2525
}
2626
if (!config.port) {
2727
config.inputPort = "${command:PromptForPort}"; // prompt user for port

src/Session.ts

Lines changed: 59 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import { MessageStreamParser } from './MessageStreamParser';
99
import { SourceMaps } from './SourceMaps';
1010
import { FileSystemWatcher, window, workspace } from 'vscode';
1111
import * as path from 'path';
12+
import * as fs from 'fs';
1213

1314
interface PendingResponse {
1415
resolve: Function;
@@ -42,6 +43,9 @@ export class Session extends DebugSession {
4243
private _sourceMaps: SourceMaps = new SourceMaps("");
4344
private _fileWatcher?: FileSystemWatcher;
4445
private _activeThreadId: number = 0; // the one being debugged
46+
private _localRoot: string = "";
47+
private _sourceMapRoot?: string;
48+
private _generatedSourceRoot?: string;
4549

4650
public constructor() {
4751
super();
@@ -81,6 +85,10 @@ export class Session extends DebugSession {
8185
return;
8286
}
8387

88+
this._localRoot = args.localRoot ? path.normalize(args.localRoot) : "";
89+
this._sourceMapRoot = args.sourceMapRoot ? path.normalize(args.sourceMapRoot) : undefined;
90+
this._generatedSourceRoot = args.generatedSourceRoot ? path.normalize(args.generatedSourceRoot) : undefined;
91+
8492
// Listen or connect (default), depending on mode.
8593
// Attach makes more sense to use connect, but some MC platforms require using listen.
8694
try {
@@ -96,13 +104,7 @@ export class Session extends DebugSession {
96104
return;
97105
}
98106

99-
// init source maps
100-
this._sourceMaps = new SourceMaps(args.localRoot, args.sourceMapRoot, args.generatedSourceRoot);
101-
102-
// watch for source map changes
103-
this.createSourceMapFileWatcher(args.sourceMapRoot);
104-
105-
// tell VSCode that attach is complete
107+
// tell VSCode that attach has been received
106108
this.sendResponse(response);
107109
}
108110

@@ -357,9 +359,22 @@ export class Session extends DebugSession {
357359
// connect socket to stream parser
358360
socket.pipe(socketStreamParser as any);
359361

362+
//
363+
// Now wait for the debugee protocol event which will call onConnectionComplete if accepted.
364+
//
365+
}
366+
367+
private onConnectionComplete() {
368+
// success
360369
this.showNotification("Success! Debugger is now connected.", LogLevel.Log);
361370

362-
// Now that a connection is established, send this event to
371+
// init source maps
372+
this._sourceMaps = new SourceMaps(this._localRoot, this._sourceMapRoot, this._generatedSourceRoot);
373+
374+
// watch for source map changes
375+
this.createSourceMapFileWatcher(this._sourceMapRoot);
376+
377+
// Now that a connection is established, and capabilities have been delivered, send this event to
363378
// tell VSCode to ask Minecraft/debugee for config data (breakpoints etc).
364379
// When config is complete VSCode calls 'configurationDoneRequest' and the DA
365380
// sends a 'resume' message to the debugee, which had paused following the attach.
@@ -498,18 +513,42 @@ export class Session extends DebugSession {
498513

499514
// ------------------------------------------------------------------------
500515

501-
private handleProtocolEvent(eventMessage: any) {
502-
let mcVer = eventMessage.version;
503-
let extVer = Session.DEBUGGER_PROTOCOL_VERSION;
504-
if (mcVer < extVer) {
505-
// Minecraft protocol is behind the extension
506-
let errorMessage = `Minecraft's debugger protocol [${mcVer}] is not compatible with this extension's protocol [${extVer}], please update Minecraft.`;
507-
this.showNotification(errorMessage, LogLevel.Error);
508-
}
509-
else if (mcVer > extVer) {
510-
// Extension protocol is behind Minecraft
511-
let errorMessage = `This extension's protocol [${extVer}] is not compatible with Minecraft's debugger protocol [${mcVer}], please update the extension.`;
512-
this.showNotification(errorMessage, LogLevel.Error);
516+
private handleProtocolEvent(protocolCapabilities: any) {
517+
//
518+
// handle protocol capabilities here...
519+
// can fail connection on errors
520+
//
521+
522+
// MC isn't using pack root, check that localRoot is pointing to js files
523+
if (protocolCapabilities.disablePackRoot) {
524+
this.handleCapabilityDisablePackRoot(); // warn but don't fail connection
525+
}
526+
527+
// success
528+
this.onConnectionComplete();
529+
}
530+
531+
// MC source files are rooted to scripts/ folder, not the pack root.
532+
// check that the localRoot property of launch.json contains source files.
533+
// message to user if no source files are found.
534+
private handleCapabilityDisablePackRoot() {
535+
let sourcePath = this._sourceMapRoot ? this._sourceMapRoot : this._localRoot;
536+
let foundSourceFiles = false;
537+
try {
538+
let fileNames = fs.readdirSync(sourcePath);
539+
for (let fn of fileNames) {
540+
let ext = path.extname(fn);
541+
if (ext == ".js" || ext == ".ts") {
542+
foundSourceFiles = true;
543+
break;
544+
}
545+
}
546+
}
547+
catch (e) {
548+
}
549+
550+
if (!foundSourceFiles) {
551+
this.showNotification("Failed to find source files. Check that launch.json 'localRoot' contains scripts or if using source maps that 'sourceMapRoot' is correct.", LogLevel.Warn);
513552
}
514553
}
515554

src/SourceMaps.ts

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@
22
// Copyright (C) Microsoft Corporation. All rights reserved.
33

44
import { BasicSourceMapConsumer, MappedPosition, NullablePosition, SourceMapConsumer } from 'source-map';
5+
import { normalizePath, normalizePathForRemote } from './Utils';
56
import * as fs from 'fs';
67
import * as path from 'path';
7-
import { normalizePath, normalizePathForRemote, removeRemotePathPrefix, addRemotePathPrefix } from './Utils';
88

99
interface MapInfo {
1010
mapAbsoluteDirectory: string // full path to parent folder of map file, needed when combining with relative paths within map
@@ -169,8 +169,7 @@ export class SourceMaps {
169169
}
170170

171171
// given absolute path to generated source, convert to a remote relative path the debugger understands
172-
let generatedRemoteRelativePath = addRemotePathPrefix(mapInfo.generatedSourceRelativePath);
173-
return normalizePathForRemote(generatedRemoteRelativePath);
172+
return normalizePathForRemote(mapInfo.generatedSourceRelativePath);
174173
}
175174

176175
public async getGeneratedPositionFor(originalPosition: MappedPosition): Promise<NullablePosition> {
@@ -212,7 +211,7 @@ export class SourceMaps {
212211
return originalLocalRelativePosition;
213212
}
214213

215-
let mapInfo = await this._sourceMapCache.getMapFromGeneratedSource(removeRemotePathPrefix(generatedPosition.source));
214+
let mapInfo = await this._sourceMapCache.getMapFromGeneratedSource(generatedPosition.source);
216215
if (mapInfo) {
217216
let originalPos = mapInfo.sourceMap.originalPositionFor({
218217
column: generatedPosition.column,

src/Utils.ts

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -34,16 +34,3 @@ export function normalizePathForRemote(filePath: string) {
3434
// remote debugger expects forward slashes on all platforms
3535
return filePath.replace(/\\/g,"/");
3636
}
37-
38-
// TODO: remove this after fixing internal root path of MC scripts
39-
export function removeRemotePathPrefix(filePath: string) {
40-
// remove the required "/scripts/" prefix from the generated sources when coming back from debugger
41-
return filePath.split('/').slice(1).join('/');
42-
}
43-
44-
// TODO: remove this
45-
export function addRemotePathPrefix(filePath: string) {
46-
const REMOTE_SOURCE_PATH_PREFIX = "scripts";
47-
// required to prepend "/scripts/" to generated sources for remote debugger
48-
return path.join(REMOTE_SOURCE_PATH_PREFIX, filePath);
49-
}

0 commit comments

Comments
 (0)