https://github.com/yuhangle/world-inspector
https://github.com/yuhangle/world-inspector
Last synced: about 1 month ago
JSON representation
- Host: GitHub
- URL: https://github.com/yuhangle/world-inspector
- Owner: yuhangle
- License: mit
- Created: 2026-05-26T12:41:04.000Z (about 2 months ago)
- Default Branch: main
- Last Pushed: 2026-05-26T13:41:10.000Z (about 2 months ago)
- Last Synced: 2026-05-26T14:35:39.061Z (about 2 months ago)
- Language: Rust
- Size: 17.6 KB
- Stars: 0
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# World Inspector
读取和检视 Minecraft 基岩版存档数据 — 方块、玩家、实体、区块 — 直接从 LevelDB 中读取。支持跨存档导入/导出。
## 编译
```bash
# CLI 工具 + 静态库
cargo build --release
# 仅静态库
cargo build --release --lib
```
产物:
- `target/release/world-inspector` — CLI 工具
- `target/release/libworld_inspector.a` — C FFI 静态库
## CLI 用法
```
world-inspector <世界路径> 存档概要
world-inspector <世界路径> [dimension] 查询方块
world-inspector <世界路径> --players 列出玩家
world-inspector <世界路径> --actors 列出实体
world-inspector <世界路径> --player 查看玩家数据
world-inspector <世界路径> --player --dump 完整 NBT 转储
world-inspector <世界路径> --player --json JSON 输出背包
实体管理:
world-inspector <世界路径> --wipe-actors 擦除非玩家实体
world-inspector <世界路径> --wipe-actors --include-players 擦除全部实体(含玩家数据)
world-inspector <世界路径> --export-actors 导出实体到 JSON(含玩家)
world-inspector <世界路径> --export-actors --no-players 导出仅非玩家实体
world-inspector <世界路径> --import-actors 从 JSON 导入实体(覆盖)
world-inspector <世界路径> --import-actors --skip-existing 导入实体(跳过已存在)
区块管理:
world-inspector <世界路径> --export-chunks 导出单区块
world-inspector <世界路径> --export-chunks 导出区块范围
world-inspector <世界路径> --import-chunks 从 JSON 导入区块(覆盖)
world-inspector <世界路径> --import-chunks --skip-existing 导入区块(跳过已存在)
```
### 示例
```bash
# 存档概要
world-inspector /bedrock_server/worlds/Bedrock\ level
# 查询方块 (-3, -60, -3) 主世界
world-inspector /bedrock_server/worlds/Bedrock\ level -3 -60 -3
# 查看下界方块
world-inspector /bedrock_server/worlds/Bedrock\ level 0 100 0 nether
# 列出所有玩家
world-inspector /bedrock_server/worlds/Bedrock\ level --players
# 查看玩家背包 (JSON)
world-inspector /bedrock_server/worlds/Bedrock\ level --player player_ --json
# 完整数据转储
world-inspector /bedrock_server/worlds/Bedrock\ level --player player_ --dump
# 导出所有实体 + 玩家数据
world-inspector /world --export-actors entities.json
# 仅导出非玩家实体(不含玩家数据)
world-inspector /world --export-actors entities.json --no-players
# 导入实体到目标存档(覆盖模式)
world-inspector /target-world --import-actors entities.json
# 擦除非玩家实体
world-inspector /world --wipe-actors
# 擦除全部实体(含玩家数据)
world-inspector /world --wipe-actors --include-players
# 导出区块(方块坐标 0, 64 所在的单区块)
world-inspector /world --export-chunks chunks.json 0 64
# 导出区块范围(矩形区域内的所有区块)
world-inspector /world --export-chunks chunks.json -100 64 200 128
# 导入区块到目标存档
world-inspector /target-world --import-chunks chunks.json
```
## 跨存档数据迁移
通过组合使用导出/导入命令,可以在存档之间迁移数据:
```bash
# 1. 从源存档导出实体 + 玩家数据
./wi /source --export-actors entities.json
# 2. 从源存档导出区块(覆盖目标存档需要替换的区域)
./wi /source --export-chunks chunks.json -100 64 200 128
# 3. 清空目标存档(按需选做)
./wi /target --wipe-actors --include-players
# 4. 导入实体到目标存档
./wi /target --import-actors entities.json
# 5. 导入区块到目标存档
./wi /target --import-chunks chunks.json
```
实体和区块分开管理,可按需选择性迁移。
### 导出文件格式
所有导出的 JSON 文件通用结构:
```json
{
"total": 100,
"entries": [
{
"key_hex": "6163746f72707265666978...",
"value_base64": "eJzEyz...",
"identifier": "minecraft:zombie"
}
],
"chunks": ["0,4", "1,4"]
}
```
- `total` — 条目总数
- `entries` — 键值对列表(key 为 hex 编码,value 为 base64 编码)
- `identifier` — 实体类型(仅实体导出时存在)
- `chunks` — 已导出区块列表(仅区块导出时存在)
## 玩家 key
LevelDB 中的玩家 key 有三种格式:
| 格式 | 说明 |
|---|---|
| `~local_player` | 单人模式本地玩家 |
| `player_` | 玩家身份数据(含 ServerId 指向 player_server_) |
| `player_server_` | 玩家完整游戏数据(背包、位置、生命等) |
CLI 自动跟随 `ServerId` 链接显示关联数据。
## 注
- 只读命令以 `read_only` 模式打开 LevelDB,不修改数据
- 写命令(wipe/import)以读写模式独立打开 DB,不影响只读功能
- delete 操作写入 LevelDB 删除标记(tombstone),BDS 启动时自动识别
- 导出的 JSON 文件支持 `--skip-existing` 可重入安全地增量导入
## C FFI 接口
将 `world_inspector` 链接为静态库后,C/C++ 可调用以下函数。
### 基础接口
```c
#include "world_inspector.h"
// 打开/关闭世界
WiWorld* wi_open(const char* world_path);
void wi_close(WiWorld* world);
// 查询背包(结构化 C struct 返回)
typedef struct { int32_t slot; char* name; int32_t count; int32_t damage; char* tag_json; } WiItem;
typedef struct { WiItem* items; int32_t count; } WiItemArray;
typedef struct { WiItemArray inventory; WiItemArray armor; WiItem* offhand; } WiInventoryResult;
WiInventoryResult* wi_get_inventory(WiWorld* world, const char* player_key);
void wi_free_inventory(WiInventoryResult* result);
// 一键 JSON 查询(每次调用独立打开/关闭数据库)
char* wi_get_inventory_json(const char* world_path, const char* player_key);
void wi_free_string(char* s);
// 列出玩家
char** wi_list_player_keys(WiWorld* world, int32_t* out_count);
void wi_free_string_array(char** arr, int32_t count);
```
### 预编码背包接口
返回预序列化为二进制 NBT 的物品数据(LE 格式,无头),可直接用于需要预编码物品的 UI 系统,保留物品的全部 NBT 属性。
```c
typedef struct {
int32_t slot;
char* type_id; // "minecraft:diamond_sword"
int32_t count;
int32_t damage;
uint8_t* nbt_bytes; // tag 子化合物的二进制 NBT(LE 无头格式)
int32_t nbt_len;
} WiEncodedItem;
typedef struct {
WiEncodedItem* items;
int32_t count;
} WiEncodedInventory;
WiEncodedInventory* wi_get_encoded_inventory(const char* world_path, const char* player_key);
void wi_free_encoded_inventory(WiEncodedInventory* inv);
```
### C++ 示例
```cpp
#include "world_inspector.h"
#include
#include
#include
struct InventorySlot {
int slot;
std::string type_id;
int count;
int damage;
std::vector nbt;
};
std::vector load_offline_inventory(const char* world_path, const char* player_uuid) {
std::vector slots;
WiEncodedInventory* inv = wi_get_encoded_inventory(world_path, player_uuid);
if (!inv) return slots;
for (int i = 0; i < inv->count; i++) {
auto& item = inv->items[i];
slots.push_back(InventorySlot{
item.slot,
item.type_id,
item.count,
item.damage,
{item.nbt_bytes, item.nbt_bytes + item.nbt_len}
});
}
wi_free_encoded_inventory(inv);
return slots;
}
```
## Rust 库接口
```rust
use world_inspector::WorldHandle;
let mut handle = WorldHandle::open("worlds/Bedrock level")?;
// 查询玩家背包(结构化数据)
let inv = handle.get_player_inventory("player_")?;
for item in &inv.inventory {
println!("Slot {}: {} x{}", item.slot, item.name, item.count);
}
// 查询预编码物品(二进制 NBT)
let encoded = handle.get_player_encoded_items("player_")?;
for item in &encoded {
println!("Slot {}: {} nbt_len={}", item.slot, item.name, item.nbt_bytes.len());
}
// 列出所有玩家 key
let keys = handle.list_player_keys();
```
## 架构
```
LevelDB (NBT binary)
│
├─ CLI: 方块查询、实体管理、区块操作
│
├─ wi_get_inventory_json() → JSON string(调试/外部接口)
│
├─ wi_get_inventory() → WiInventoryResult(结构化 C struct)
│
└─ wi_get_encoded_inventory() → WiEncodedItem[](预编码 binary NBT)
│
▼
预编码物品可直接供 UI 系统使用
```