-
Notifications
You must be signed in to change notification settings - Fork 11
/
Copy pathmineserver5.js
95 lines (88 loc) · 3.58 KB
/
mineserver5.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
const WebSocket = require('ws')
const uuid = require('uuid')
// Create a new websocket server on port 3000
console.log('Ready. On MineCraft chat, type /connect localhost:3000')
const wss = new WebSocket.Server({ port: 3000 })
// On Minecraft, when you type "/connect localhost:3000" it creates a connection
wss.on('connection', socket => {
console.log('Connected')
const sendQueue = [] // Queue of commands to be sent
const awaitedQueue = {} // Queue of responses awaited from Minecraft
// Send a command "cmd" to MineCraft
function send(cmd) {
const msg = {
"header": {
"version": 1,
"requestId": uuid.v4(), // Send unique ID each time
"messagePurpose": "commandRequest",
"messageType": "commandRequest"
},
"body": {
"version": 1,
"commandLine": cmd, // Define the command
"origin": {
"type": "player" // Message comes from player
}
}
}
sendQueue.push(msg) // Add the message to the queue
}
// Draw a pyramid of size "size" around the player.
function draw_pyramid(size) {
// y is the height of the pyramid. Start with y=0, and keep building up
for (let y = 0; y < size + 1; y++) {
// At the specified y, place blocks in a rectangle of size "side"
let side = size - y;
for (let x = -side; x < side + 1; x++) {
send(`setblock ~${x} ~${y} ~${-side} glowstone`)
send(`setblock ~${x} ~${y} ~${+side} glowstone`)
send(`setblock ~${-side} ~${y} ~${x} glowstone`)
send(`setblock ~${+side} ~${y} ~${x} glowstone`)
}
}
}
// Tell Minecraft to send all chat messages. Required once when Minecraft starts
socket.send(JSON.stringify({
"header": {
"version": 1, // Use version 1 message protocol
"requestId": uuid.v4(), // A unique ID for the request
"messageType": "commandRequest", // This is a request ...
"messagePurpose": "subscribe" // ... to subscribe to ...
},
"body": {
"eventName": "PlayerMessage" // ... all player messages.
},
}))
// When MineCraft sends a message (e.g. on player chat), act on it.
socket.on('message', packet => {
const msg = JSON.parse(packet)
// If this is a chat window
if (msg.body.eventName === 'PlayerMessage') {
// ... and it's like "pyramid 10" (or some number), draw a pyramid
const match = msg.body.properties.Message.match(/^pyramid (\d+)/i)
if (match)
draw_pyramid(+match[1])
}
// If we get a command response, act on it
if (msg.header.messagePurpose == 'commandResponse') {
// ... and it's for an awaited command
if (msg.header.requestId in awaitedQueue) {
// Print errors (if any)
if (msg.body.statusCode < 0)
console.log(awaitedQueue[msg.header.requestId].body.commandLine, msg.body.statusMessage)
// ... and delete it from the awaited queue
delete awaitedQueue[msg.header.requestId]
}
}
// Now, we've cleared all completed commands from the awaitedQueue.
// We can send new commands from the sendQueue -- up to a maximum of 100.
let count = Math.min(100 - Object.keys(awaitedQueue).length, sendQueue.length)
for (let i = 0; i < count; i++) {
// Each time, send the first command in sendQueue, and add it to the awaitedQueue
let command = sendQueue.shift()
socket.send(JSON.stringify(command))
awaitedQueue[command.header.requestId] = command
}
// Now we've sent as many commands as we can. Wait till the next message
})
})