@lzimul/minecraft-mcp 1.0.4 → 1.0.6
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/LICENSE +21 -21
- package/README.md +297 -219
- package/build/app/server.js +6 -1
- package/build/app/tool-events.js +72 -0
- package/build/app/websocket.js +116 -0
- package/build/config/server-info.js +4 -4
- package/build/config/storage.js +2 -1
- package/build/config/websocket.js +48 -0
- package/build/config/world-limits.js +2 -0
- package/build/enums/move-direction.enum.js +9 -0
- package/build/index.js +19 -1
- package/build/interfaces/websocket.interface.js +1 -0
- package/build/resources/dimension-resources.js +2 -2
- package/build/tools/entity-tools.js +318 -5
- package/build/tools/world-tools.js +388 -1
- package/build/utils/logger.js +1 -1
- package/build/world/block-spec.js +3 -1
- package/build/world/entity-inventory.js +21 -4
- package/build/world/simulated-dimension.js +135 -9
- package/build/world/stores/file-world-store.js +47 -39
- package/build/world/stores/memory-world-store.js +5 -0
- package/build/world/stores/serialized-entity.js +4 -3
- package/build/world/stores/serialized-snapshot.js +35 -0
- package/lib/app/server.d.ts +5 -1
- package/lib/app/server.d.ts.map +1 -1
- package/lib/app/tool-events.d.ts +5 -0
- package/lib/app/tool-events.d.ts.map +1 -0
- package/lib/app/websocket.d.ts +10 -0
- package/lib/app/websocket.d.ts.map +1 -0
- package/lib/config/dimensions.d.ts.map +1 -1
- package/lib/config/server-info.d.ts.map +1 -1
- package/lib/config/storage.d.ts.map +1 -1
- package/lib/config/websocket.d.ts +8 -0
- package/lib/config/websocket.d.ts.map +1 -0
- package/lib/config/world-limits.d.ts +2 -0
- package/lib/config/world-limits.d.ts.map +1 -1
- package/lib/data/entities.d.ts.map +1 -1
- package/lib/enums/bounding-box.enum.d.ts.map +1 -1
- package/lib/enums/dimension-type.enum.d.ts.map +1 -1
- package/lib/enums/entity-kind.enum.d.ts.map +1 -1
- package/lib/enums/icon-theme.enum.d.ts.map +1 -1
- package/lib/enums/inventory-section.enum.d.ts.map +1 -1
- package/lib/enums/move-direction.enum.d.ts +9 -0
- package/lib/enums/move-direction.enum.d.ts.map +1 -0
- package/lib/index.d.ts +1 -1
- package/lib/index.d.ts.map +1 -1
- package/lib/interfaces/block.interface.d.ts.map +1 -1
- package/lib/interfaces/data-entry.interface.d.ts.map +1 -1
- package/lib/interfaces/dimension.interface.d.ts.map +1 -1
- package/lib/interfaces/entity-inventory.interface.d.ts.map +1 -1
- package/lib/interfaces/entity-type.interface.d.ts.map +1 -1
- package/lib/interfaces/entity.interface.d.ts.map +1 -1
- package/lib/interfaces/item.interface.d.ts.map +1 -1
- package/lib/interfaces/placed-block.interface.d.ts.map +1 -1
- package/lib/interfaces/websocket.interface.d.ts +47 -0
- package/lib/interfaces/websocket.interface.d.ts.map +1 -0
- package/lib/interfaces/world-store.interface.d.ts +1 -0
- package/lib/interfaces/world-store.interface.d.ts.map +1 -1
- package/lib/resources/block-resources.d.ts.map +1 -1
- package/lib/resources/data-resources.d.ts.map +1 -1
- package/lib/resources/dimension-resources.d.ts +3 -0
- package/lib/resources/dimension-resources.d.ts.map +1 -1
- package/lib/resources/entity-resources.d.ts.map +1 -1
- package/lib/resources/index.d.ts.map +1 -1
- package/lib/resources/item-resources.d.ts.map +1 -1
- package/lib/schemas/block-schema.d.ts.map +1 -1
- package/lib/schemas/coordinate-schema.d.ts.map +1 -1
- package/lib/schemas/dimension-schema.d.ts.map +1 -1
- package/lib/schemas/entity-schema.d.ts.map +1 -1
- package/lib/schemas/item-schema.d.ts.map +1 -1
- package/lib/tools/block-tools.d.ts.map +1 -1
- package/lib/tools/entity-tools.d.ts.map +1 -1
- package/lib/tools/index.d.ts.map +1 -1
- package/lib/tools/item-tools.d.ts.map +1 -1
- package/lib/tools/result.d.ts.map +1 -1
- package/lib/tools/world-tools.d.ts.map +1 -1
- package/lib/utils/logger.d.ts.map +1 -1
- package/lib/world/block-spec.d.ts.map +1 -1
- package/lib/world/block-states.d.ts.map +1 -1
- package/lib/world/entity-inventory.d.ts.map +1 -1
- package/lib/world/item-spec.d.ts.map +1 -1
- package/lib/world/simulated-dimension.d.ts +25 -0
- package/lib/world/simulated-dimension.d.ts.map +1 -1
- package/lib/world/stores/file-world-store.d.ts +2 -2
- package/lib/world/stores/file-world-store.d.ts.map +1 -1
- package/lib/world/stores/index.d.ts.map +1 -1
- package/lib/world/stores/memory-world-store.d.ts +1 -0
- package/lib/world/stores/memory-world-store.d.ts.map +1 -1
- package/lib/world/stores/serialized-block.d.ts.map +1 -1
- package/lib/world/stores/serialized-entity.d.ts.map +1 -1
- package/lib/world/stores/serialized-snapshot.d.ts +6 -0
- package/lib/world/stores/serialized-snapshot.d.ts.map +1 -0
- package/lib/world/world.d.ts.map +1 -1
- package/package.json +116 -113
package/build/app/server.js
CHANGED
|
@@ -2,8 +2,13 @@ import { McpServer } from '@modelcontextprotocol/server';
|
|
|
2
2
|
import { SERVER_INFO } from '../config/server-info.js';
|
|
3
3
|
import { registerResources } from '../resources/index.js';
|
|
4
4
|
import { registerTools } from '../tools/index.js';
|
|
5
|
-
|
|
5
|
+
import { instrumentToolCalls } from './tool-events.js';
|
|
6
|
+
export function createServer(world, options) {
|
|
6
7
|
const server = new McpServer(SERVER_INFO);
|
|
8
|
+
const onToolCall = options?.onToolCall;
|
|
9
|
+
if (onToolCall) {
|
|
10
|
+
instrumentToolCalls(server, onToolCall);
|
|
11
|
+
}
|
|
7
12
|
registerTools(server, world);
|
|
8
13
|
registerResources(server, world);
|
|
9
14
|
return server;
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { toErrorMessage } from '../utils/error-message.js';
|
|
2
|
+
import { logger } from '../utils/logger.js';
|
|
3
|
+
function readIsError(result) {
|
|
4
|
+
if (typeof result !== 'object' || result === null) {
|
|
5
|
+
return false;
|
|
6
|
+
}
|
|
7
|
+
return result.isError === true;
|
|
8
|
+
}
|
|
9
|
+
function extractErrorMessage(result) {
|
|
10
|
+
if (typeof result !== 'object' || result === null) {
|
|
11
|
+
return 'Tool call failed';
|
|
12
|
+
}
|
|
13
|
+
const content = result.content;
|
|
14
|
+
if (Array.isArray(content)) {
|
|
15
|
+
const first = content.find((entry) => typeof entry === 'object' &&
|
|
16
|
+
entry !== null &&
|
|
17
|
+
entry.type === 'text' &&
|
|
18
|
+
typeof entry.text === 'string');
|
|
19
|
+
if (first) {
|
|
20
|
+
return first.text;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
return 'Tool call failed';
|
|
24
|
+
}
|
|
25
|
+
function safeNotify(listener, event) {
|
|
26
|
+
try {
|
|
27
|
+
listener(event);
|
|
28
|
+
}
|
|
29
|
+
catch (error) {
|
|
30
|
+
logger.warn(`Tool-call listener failed: ${toErrorMessage(error)}`);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
export function instrumentToolCalls(server, listener) {
|
|
34
|
+
const host = server;
|
|
35
|
+
const original = host.registerTool.bind(server);
|
|
36
|
+
host.registerTool = (name, config, cb) => {
|
|
37
|
+
const wrapped = async (args, extra) => {
|
|
38
|
+
const startedAt = Date.now();
|
|
39
|
+
try {
|
|
40
|
+
const result = await cb(args, extra);
|
|
41
|
+
const durationMs = Date.now() - startedAt;
|
|
42
|
+
const isError = readIsError(result);
|
|
43
|
+
safeNotify(listener, {
|
|
44
|
+
type: 'tool-call',
|
|
45
|
+
tool: name,
|
|
46
|
+
arguments: args,
|
|
47
|
+
result,
|
|
48
|
+
isError,
|
|
49
|
+
error: isError ? extractErrorMessage(result) : null,
|
|
50
|
+
startedAt,
|
|
51
|
+
durationMs
|
|
52
|
+
});
|
|
53
|
+
return result;
|
|
54
|
+
}
|
|
55
|
+
catch (error) {
|
|
56
|
+
const durationMs = Date.now() - startedAt;
|
|
57
|
+
safeNotify(listener, {
|
|
58
|
+
type: 'tool-call',
|
|
59
|
+
tool: name,
|
|
60
|
+
arguments: args,
|
|
61
|
+
result: null,
|
|
62
|
+
isError: true,
|
|
63
|
+
error: toErrorMessage(error),
|
|
64
|
+
startedAt,
|
|
65
|
+
durationMs
|
|
66
|
+
});
|
|
67
|
+
throw error;
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
return original(name, config, wrapped);
|
|
71
|
+
};
|
|
72
|
+
}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import { WebSocket, WebSocketServer } from 'ws';
|
|
2
|
+
import { toErrorMessage } from '../utils/error-message.js';
|
|
3
|
+
import { logger } from '../utils/logger.js';
|
|
4
|
+
import { dimensionState } from '../resources/dimension-resources.js';
|
|
5
|
+
import { World } from '../world/world.js';
|
|
6
|
+
function buildWorldSnapshot(world) {
|
|
7
|
+
return {
|
|
8
|
+
type: 'world-snapshot',
|
|
9
|
+
timestamp: Date.now(),
|
|
10
|
+
dimensions: World.listDimensions().map(dimension => dimensionState(world, dimension))
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
function sendText(socket, text) {
|
|
14
|
+
if (socket.readyState !== WebSocket.OPEN) {
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
17
|
+
try {
|
|
18
|
+
socket.send(text);
|
|
19
|
+
}
|
|
20
|
+
catch (error) {
|
|
21
|
+
logger.warn(`WebSocket send failed: ${toErrorMessage(error)}`);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
function sendObject(socket, payload) {
|
|
25
|
+
try {
|
|
26
|
+
sendText(socket, JSON.stringify(payload));
|
|
27
|
+
}
|
|
28
|
+
catch (error) {
|
|
29
|
+
logger.warn(`WebSocket serialize failed: ${toErrorMessage(error)}`);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
function isClientMessage(value) {
|
|
33
|
+
if (typeof value !== 'object' || value === null) {
|
|
34
|
+
return false;
|
|
35
|
+
}
|
|
36
|
+
const type = value.type;
|
|
37
|
+
return type === 'world-request' || type === 'world';
|
|
38
|
+
}
|
|
39
|
+
function handleClientMessage(world, socket, data) {
|
|
40
|
+
const text = data.toString().trim();
|
|
41
|
+
if (text.length === 0) {
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
let request;
|
|
45
|
+
try {
|
|
46
|
+
request = JSON.parse(text);
|
|
47
|
+
}
|
|
48
|
+
catch {
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
if (isClientMessage(request)) {
|
|
52
|
+
sendObject(socket, buildWorldSnapshot(world));
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
export function startWebSocketService(world, config) {
|
|
56
|
+
const clients = new Set();
|
|
57
|
+
const wss = new WebSocketServer({
|
|
58
|
+
host: config.host,
|
|
59
|
+
port: config.port,
|
|
60
|
+
path: config.path
|
|
61
|
+
});
|
|
62
|
+
wss.on('error', error => {
|
|
63
|
+
logger.error(`WebSocket service error: ${toErrorMessage(error)}`);
|
|
64
|
+
});
|
|
65
|
+
wss.on('connection', socket => {
|
|
66
|
+
clients.add(socket);
|
|
67
|
+
logger.info(`WebSocket client connected (${clients.size} client(s))`);
|
|
68
|
+
sendObject(socket, buildWorldSnapshot(world));
|
|
69
|
+
socket.on('message', data => {
|
|
70
|
+
handleClientMessage(world, socket, data);
|
|
71
|
+
});
|
|
72
|
+
socket.on('close', () => {
|
|
73
|
+
clients.delete(socket);
|
|
74
|
+
logger.info(`WebSocket client disconnected (${clients.size} client(s))`);
|
|
75
|
+
});
|
|
76
|
+
socket.on('error', error => {
|
|
77
|
+
logger.warn(`WebSocket client error: ${toErrorMessage(error)}`);
|
|
78
|
+
clients.delete(socket);
|
|
79
|
+
});
|
|
80
|
+
});
|
|
81
|
+
function broadcast(event) {
|
|
82
|
+
if (clients.size === 0) {
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
let text;
|
|
86
|
+
try {
|
|
87
|
+
text = JSON.stringify(event);
|
|
88
|
+
}
|
|
89
|
+
catch (error) {
|
|
90
|
+
logger.warn(`WebSocket tool-call serialize failed: ${toErrorMessage(error)}`);
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
for (const socket of clients) {
|
|
94
|
+
sendText(socket, text);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
function clientCount() {
|
|
98
|
+
return clients.size;
|
|
99
|
+
}
|
|
100
|
+
async function close() {
|
|
101
|
+
for (const socket of clients) {
|
|
102
|
+
try {
|
|
103
|
+
socket.close(1001, 'Server shutting down');
|
|
104
|
+
}
|
|
105
|
+
catch {
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
clients.clear();
|
|
109
|
+
await new Promise(resolve => {
|
|
110
|
+
wss.close(() => {
|
|
111
|
+
resolve();
|
|
112
|
+
});
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
return { broadcast, clientCount, close };
|
|
116
|
+
}
|
|
@@ -4,11 +4,11 @@ import { MINECRAFT_ITEM_COUNT } from '../data/items.js';
|
|
|
4
4
|
import { MINECRAFT_DATA_VERSION } from '../data/version.js';
|
|
5
5
|
import { EIconTheme } from '../enums/icon-theme.enum.js';
|
|
6
6
|
export const SERVER_INFO = {
|
|
7
|
-
name: 'lzimul',
|
|
7
|
+
name: '@lzimul/minecraft-mcp',
|
|
8
8
|
title: 'lZiMUl Minecraft MCP',
|
|
9
|
-
description: `Minecraft Model Context Protocol server (Java Edition ${MINECRAFT_DATA_VERSION}): exposes all ${MINECRAFT_BLOCK_COUNT} blocks, ${MINECRAFT_ITEM_COUNT} items and ${MINECRAFT_ENTITY_COUNT} entity types with their properties as resources, plus tools to read and
|
|
10
|
-
version: '1.0.
|
|
11
|
-
websiteUrl: 'https://
|
|
9
|
+
description: `Minecraft Model Context Protocol server (Java Edition ${MINECRAFT_DATA_VERSION}): exposes all ${MINECRAFT_BLOCK_COUNT} blocks, ${MINECRAFT_ITEM_COUNT} items and ${MINECRAFT_ENTITY_COUNT} entity types with their properties as resources, plus tools to read, place, query and fill blocks, inspect dimensions, create, move and delete entities and players, set entity positions, and manage their hotbar and backpack inventories.`,
|
|
10
|
+
version: '1.0.6',
|
|
11
|
+
websiteUrl: 'https://projects.lzimul.com/minecraft-mcp',
|
|
12
12
|
icons: [
|
|
13
13
|
{
|
|
14
14
|
src: 'https://i1.hdslb.com/bfs/face/79fbb5635ff6e50fe2699c518af82162523e5f08.jpg',
|
package/build/config/storage.js
CHANGED
|
@@ -4,9 +4,10 @@ function storageKind() {
|
|
|
4
4
|
? 'memory'
|
|
5
5
|
: 'file';
|
|
6
6
|
}
|
|
7
|
+
const DEFAULT_WORLD_DIRECTORY = './app/dimensions';
|
|
7
8
|
function storageDirectory() {
|
|
8
9
|
const configured = process.env.MCP_WORLD_DIR?.trim();
|
|
9
|
-
return path.resolve(configured && configured.length > 0 ? configured :
|
|
10
|
+
return path.resolve(configured && configured.length > 0 ? configured : DEFAULT_WORLD_DIRECTORY);
|
|
10
11
|
}
|
|
11
12
|
export const WORLD_STORAGE = {
|
|
12
13
|
kind: storageKind(),
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
function envString(name) {
|
|
2
|
+
const raw = process.env[name];
|
|
3
|
+
if (typeof raw !== 'string') {
|
|
4
|
+
return null;
|
|
5
|
+
}
|
|
6
|
+
const trimmed = raw.trim();
|
|
7
|
+
return trimmed.length > 0 ? trimmed : null;
|
|
8
|
+
}
|
|
9
|
+
function envFlag(name, fallback) {
|
|
10
|
+
const raw = envString(name);
|
|
11
|
+
if (raw === null) {
|
|
12
|
+
return fallback;
|
|
13
|
+
}
|
|
14
|
+
const normalized = raw.toLowerCase();
|
|
15
|
+
if (['false', '0', 'no', 'off'].includes(normalized)) {
|
|
16
|
+
return false;
|
|
17
|
+
}
|
|
18
|
+
if (['true', '1', 'yes', 'on'].includes(normalized)) {
|
|
19
|
+
return true;
|
|
20
|
+
}
|
|
21
|
+
return fallback;
|
|
22
|
+
}
|
|
23
|
+
function envPort(name, fallback) {
|
|
24
|
+
const raw = envString(name);
|
|
25
|
+
if (raw === null) {
|
|
26
|
+
return fallback;
|
|
27
|
+
}
|
|
28
|
+
const parsed = Number.parseInt(raw, 10);
|
|
29
|
+
return Number.isInteger(parsed) && parsed > 0 && parsed <= 65535
|
|
30
|
+
? parsed
|
|
31
|
+
: fallback;
|
|
32
|
+
}
|
|
33
|
+
function envHost(name, fallback) {
|
|
34
|
+
return envString(name) ?? fallback;
|
|
35
|
+
}
|
|
36
|
+
function envPath(name, fallback) {
|
|
37
|
+
const raw = envString(name);
|
|
38
|
+
if (raw === null) {
|
|
39
|
+
return fallback;
|
|
40
|
+
}
|
|
41
|
+
return raw.startsWith('/') ? raw : `/${raw}`;
|
|
42
|
+
}
|
|
43
|
+
export const WEBSOCKET_CONFIG = {
|
|
44
|
+
enabled: envFlag('MCP_WS_ENABLED', true),
|
|
45
|
+
host: envHost('MCP_WS_HOST', '127.0.0.1'),
|
|
46
|
+
port: envPort('MCP_WS_PORT', 8765),
|
|
47
|
+
path: envPath('MCP_WS_PATH', '/')
|
|
48
|
+
};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export var EMoveDirection;
|
|
2
|
+
(function (EMoveDirection) {
|
|
3
|
+
EMoveDirection["Forward"] = "forward";
|
|
4
|
+
EMoveDirection["Back"] = "back";
|
|
5
|
+
EMoveDirection["Left"] = "left";
|
|
6
|
+
EMoveDirection["Right"] = "right";
|
|
7
|
+
EMoveDirection["Up"] = "up";
|
|
8
|
+
EMoveDirection["Down"] = "down";
|
|
9
|
+
})(EMoveDirection || (EMoveDirection = {}));
|
package/build/index.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { serveStdio } from '@modelcontextprotocol/server/stdio';
|
|
3
3
|
import { createServer } from './app/server.js';
|
|
4
|
+
import { startWebSocketService } from './app/websocket.js';
|
|
5
|
+
import { WEBSOCKET_CONFIG } from './config/websocket.js';
|
|
4
6
|
import { WORLD_STORAGE } from './config/storage.js';
|
|
5
7
|
import { toErrorMessage } from './utils/error-message.js';
|
|
6
8
|
import { logger } from './utils/logger.js';
|
|
@@ -8,7 +10,14 @@ import { createWorldStore } from './world/stores/index.js';
|
|
|
8
10
|
import { World } from './world/world.js';
|
|
9
11
|
async function main() {
|
|
10
12
|
const world = await World.load(createWorldStore(), WORLD_STORAGE.writeDelayMs);
|
|
11
|
-
|
|
13
|
+
let wsService = null;
|
|
14
|
+
if (WEBSOCKET_CONFIG.enabled) {
|
|
15
|
+
wsService = startWebSocketService(world, WEBSOCKET_CONFIG);
|
|
16
|
+
logger.info(`WebSocket service listening on ws://${WEBSOCKET_CONFIG.host}:${WEBSOCKET_CONFIG.port}${WEBSOCKET_CONFIG.path}`);
|
|
17
|
+
}
|
|
18
|
+
const handle = serveStdio(() => createServer(world, wsService ? { onToolCall: wsService.broadcast } : {}), {
|
|
19
|
+
legacy: 'reject'
|
|
20
|
+
});
|
|
12
21
|
let shuttingDown = false;
|
|
13
22
|
const shutdown = async (exitCode) => {
|
|
14
23
|
if (shuttingDown) {
|
|
@@ -30,6 +39,15 @@ async function main() {
|
|
|
30
39
|
logger.error(`Failed to close the MCP transport: ${toErrorMessage(error)}`);
|
|
31
40
|
code = 1;
|
|
32
41
|
}
|
|
42
|
+
if (wsService) {
|
|
43
|
+
try {
|
|
44
|
+
await wsService.close();
|
|
45
|
+
}
|
|
46
|
+
catch (error) {
|
|
47
|
+
logger.error(`Failed to close the WebSocket service: ${toErrorMessage(error)}`);
|
|
48
|
+
code = 1;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
33
51
|
process.exit(code);
|
|
34
52
|
};
|
|
35
53
|
process.once('SIGINT', () => {
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { toBlockInfo } from '../schemas/block-schema.js';
|
|
2
2
|
import { toEntityInfo } from '../schemas/entity-schema.js';
|
|
3
|
-
import { errorResource } from './error-content.js';
|
|
4
3
|
import { World } from '../world/world.js';
|
|
4
|
+
import { errorResource } from './error-content.js';
|
|
5
5
|
function dimensionSummary(world, dimension) {
|
|
6
6
|
const simulated = world.getDimension(dimension.type);
|
|
7
7
|
return {
|
|
@@ -17,7 +17,7 @@ function dimensionSummary(world, dimension) {
|
|
|
17
17
|
uri: `lzimul://minecraft/dimensions/${dimension.type}`
|
|
18
18
|
};
|
|
19
19
|
}
|
|
20
|
-
function dimensionState(world, dimension) {
|
|
20
|
+
export function dimensionState(world, dimension) {
|
|
21
21
|
const simulated = world.getDimension(dimension.type);
|
|
22
22
|
return {
|
|
23
23
|
key: dimension.key,
|