Skip to content
Merged

pr #7

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1,047 changes: 373 additions & 674 deletions LICENSE

Large diffs are not rendered by default.

147 changes: 91 additions & 56 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,87 +1,122 @@
# Datapack Breakpoint
# Sniffer

English | [简体中文](README_zh.md)
## Overview

## Introduce
Sniffer is a debug adapter for Minecraft datapacks that allows you to debug your `.mcfunction` files directly from Visual Studio Code. It provides features like breakpoints, step execution, and variable inspection to make datapack development easier and more efficient.

This is a fabric mod for Minecraft 1.21, which allows you to set breakpoints in the game and "freeze" the game when
the breakpoint is reached.
## Features

## Usage
- Set breakpoints in `.mcfunction` files
- Connect to a running Minecraft instance
- Inspect game state during debugging
- Step through command execution
- Path mapping between Minecraft and local files

* Set a breakpoint
## Requirements

In datapack, you can insert `#breakpoint` into .mcfunction file to set a breakpoint. For example:
- Minecraft with Fabric Loader
- Visual Studio Code

```mcfunction
#test:test

say 1
say 2
#breakpoint
say 3
say 4
```

In this case, after the game executes `say 2`, the game will be "frozen" because it meets the breakpoint.
<!-- ## Installation

When the game is "frozen", you can still move around, do whatever you want, just like execute the command `tick freeze`.
So you can check the game state, or do some debugging.
### Minecraft Mod Installation

* Step
1. Install [Fabric Loader](https://fabricmc.net/use/) for your Minecraft version
2. Download the Sniffer mod JAR from the [releases page](https://github.com/mcbookshelf/sniffer/releases)
3. Place the JAR file in your Minecraft `mods` folder
4. Launch Minecraft with Fabric

When the game is "frozen", you can use the command `/breakpoint step` to execute the next command. In above example,
after the game meets the breakpoint, you can use `/breakpoint step` to execute `say 3`, and then use `/breakpoint step`
to execute `say 4`. When all commands are executed, the game will be unfrozen and continue running.
### VSCode Extension Installation

* Continue
1. Open Visual Studio Code
2. Go to the Extensions view (Ctrl+Shift+X)
3. Search for "Sniffer"
4. Click Install -->

When the game is "frozen", you can use the command `/breakpoint move` to unfreeze the game and continue running.
## Mod Configuration
The mod can be configured through the in-game configuration screen, accessible via Mod Menu.
You can also configure the mod in the `config/sniffer.json` file.
The following options are available:

* Get Macro Arguments
### Debug Server Settings
- **Server Port**: The port number for the debug server (default: 25599)
- **Server path**: The path to the debug server (default: `/dap`)

By using `/breakpoint get <key>`, you can get the value of the macro argument if the game is executing a macro function.
For example:
## Connecting to Minecraft

```mcfunction
#test:test_macro
1. Open your datapack project in VSCode
2. Create a `.vscode/launch.json` file with the following configuration:

say start
#breakpoint
$say $(msg)
say end
```json
{
"version": "0.2.0",
"configurations": [
{
"type": "sniffer",
"request": "attach",
"name": "Connect to Minecraft",
"address": "ws://localhost:25599/dap"
}
]
}
```

After executing `function test:test_macro {"msg":"test"}`, we passed the value `test` to the macro argument `msg` and
then the game will pause before `$say $(msg)`. At this time, you can use `/breakpoint get msg` to get the value `test`.
3. Start Minecraft with the Sniffer mod installed
4. In VSCode, press F5 or click the "Run and Debug" button
5. Select "Connect to Minecraft" from the dropdown menu

* Get Function Stack
You can now place breakpoints in your `.mcfunction` files and execute it from the game to step through the code.

By using `/breakpoint stack`, you can get the function stack of the current game. For example, if we have following two
functions:
## Usage in Minecraft

```mcfunction
#test:test1
The debugger can be controlled directly from Minecraft using the following commands:

say 1
function test:test2
say 2
- `/breakpoint continue`: Resume execution after hitting a breakpoint
- `/breakpoint step`: Execute the next command and pause
- `/breakpoint step_over`: Skip to the next command in the current function
- `/breakpoint step_out`: Continue execution until the current function returns

#test: test2
say A
#breakpoint
say B
```
All commands require operator permissions (level 2) to use.

When execution is paused at a breakpoint, the gametick will be freezed.



## Development

### Project Structure

When the game pauses at the breakpoint, you can use `/breakpoint stack` and the function stack will be printed in the
chat screen:
- `src/main`: Main mod code for Minecraft
- `src/client`: Client-side mod code
- `vscode`: VSCode extension source code

### Building the Project

To build the Minecraft mod:

```bash
./gradlew build
```
test:test2
test:test

To build the VSCode extension:

```bash
cd vscode
npm install
npm run build
```

* Run command in current context
## License

This project is licensed under the MPL-2.0 License - see the [LICENSE](LICENSE) file for details.

## Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

## Acknowledgements

By using `/breakpoint run <command>`, you can run any command in the current context, just like `execute ... run ...`.
- [Fabric](https://fabricmc.net/) - Mod loader for Minecraft
- [VSCode Debug Adapter](https://code.visualstudio.com/api/extension-guides/debugger-extension) - VSCode debugging API
- [Datapack Debugger](https://github.com/Alumopper/Datapack-Debugger/) by [Alumopper](https://github.com/Alumopper) - Original implementation of the debugger, without the DAP layer
83 changes: 0 additions & 83 deletions README_zh.md

This file was deleted.

22 changes: 19 additions & 3 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,17 @@ repositories {
// Loom adds the essential maven repositories to download Minecraft and libraries from automatically.
// See https://docs.gradle.org/current/userguide/declaring_repositories.html
// for more information about repositories.

// Added repositories for Cloth Config and ModMenu
maven { url "https://maven.shedaniel.me/" }
maven { url "https://maven.terraformersmc.com/releases/" }
}

loom {
splitEnvironmentSourceSets()

mods {
"datapack-debugger" {
"sniffer" {
sourceSet sourceSets.main
sourceSet sourceSets.client
}
Expand All @@ -31,13 +35,26 @@ loom {
}

dependencies {
implementation 'org.eclipse.lsp4j:org.eclipse.lsp4j:0.24.0'
implementation 'org.eclipse.lsp4j:org.eclipse.lsp4j.debug:0.24.0'
implementation 'jakarta.websocket:jakarta.websocket-api:2.2.0'
implementation 'org.glassfish.tyrus:tyrus-server:2.2.0'
implementation 'org.glassfish.tyrus:tyrus-container-grizzly-server:2.2.0'

// To change the versions see the gradle.properties file
minecraft "com.mojang:minecraft:${project.minecraft_version}"
mappings "net.fabricmc:yarn:${project.yarn_mappings}:v2"
modImplementation "net.fabricmc:fabric-loader:${project.loader_version}"

// Fabric API. This is technically optional, but you probably want it anyway.
modImplementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_version}"
modImplementation "net.fabricmc.fabric-api:fabric-key-binding-api-v1:${project.fabric_version}"

// Added Cloth Config and ModMenu
modApi("me.shedaniel.cloth:cloth-config-fabric:17.0.144") {
exclude(group: "net.fabricmc.fabric-api")
}
modImplementation("com.terraformersmc:modmenu:13.0.2")
}

processResources {
Expand All @@ -57,7 +74,6 @@ java {
// if it is present.
// If you remove this line, sources will not be generated.
withSourcesJar()

sourceCompatibility = JavaVersion.VERSION_21
targetCompatibility = JavaVersion.VERSION_21
}
Expand Down Expand Up @@ -87,5 +103,5 @@ publishing {
}

loom {
accessWidenerPath = file("src/main/resources/datapack-debugger.accesswidener")
accessWidenerPath = file("src/main/resources/sniffer.accesswidener")
}
14 changes: 7 additions & 7 deletions gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@ org.gradle.parallel=true

# Fabric Properties
# check these on https://fabricmc.net/develop
minecraft_version=1.21
yarn_mappings=1.21+build.9
loader_version=0.15.11
minecraft_version=1.21.4
yarn_mappings=1.21.4+build.8
loader_version=0.16.10

# Mod Properties
mod_version=1.1.2
maven_group=top.mcfpp.mod.debugger
archives_base_name=datapack-debugger
mod_version=0.1.0
maven_group=net.gunivers
archives_base_name=sniffer

# Dependencies
fabric_version=0.100.7+1.21
fabric_version=0.118.0+1.21.4
37 changes: 37 additions & 0 deletions src/client/java/net/gunivers/sniffer/DatapackBreakpointClient.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package net.gunivers.sniffer;

import net.fabricmc.api.ClientModInitializer;
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents;
import net.fabricmc.fabric.api.client.keybinding.v1.KeyBindingHelper;
import net.minecraft.client.option.KeyBinding;
import net.minecraft.client.util.InputUtil;
import org.lwjgl.glfw.GLFW;
import net.gunivers.sniffer.command.BreakPointCommand;;

/**
* @author Alumopper
* @author theogiraudet
*/
public class DatapackBreakpointClient implements ClientModInitializer {

private static KeyBinding stepInto;

@Override
public void onInitializeClient() {
stepInto = KeyBindingHelper.registerKeyBinding(new KeyBinding(
"sniffer.step", // The translation key of the keybinding's name
InputUtil.Type.KEYSYM, // The type of the keybinding, KEYSYM for keyboard, MOUSE for mouse.
GLFW.GLFW_KEY_F7, // The keycode of the key
"sniffer.name" // The translation key of the keybinding's category.
));

ClientTickEvents.END_CLIENT_TICK.register(client -> {
while(stepInto.wasPressed()) {
if(BreakPointCommand.debugMode) {
BreakPointCommand.step(1, client.player.getCommandSource(client.getServer().getWorld(client.player.getWorld().getRegistryKey())));
}
}
});
}

}
Loading
Loading