Skip to content

Commit 1bf52d6

Browse files
committed
Merge pull request #32 from voxel/circleci
Add CircleCI. Closes GH-31
2 parents cfac592 + 791d1d8 commit 1bf52d6

File tree

7 files changed

+127
-93
lines changed

7 files changed

+127
-93
lines changed

.gitmodules

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
[submodule "app/wsmc"]
2+
path = app/wsmc
3+
url = https://github.com/deathcap/wsmc

app/package.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,5 +61,8 @@
6161
"scripts": {
6262
"start": "beefy app.js -- --debug"
6363
},
64-
"license": "MIT"
64+
"license": "MIT",
65+
"devDependencies": {
66+
"browserify": "^13.0.0"
67+
}
6568
}

app/wsmc

Submodule wsmc added at 9377604

circle.yml

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
machine:
2+
node:
3+
version: 4
4+
java:
5+
version: oraclejdk7
6+
checkout:
7+
post:
8+
# clone the wsmc submodule (see https://circleci.com/docs/configuration)
9+
- git submodule sync
10+
- git submodule update --init
11+
# package voxel-clientmc
12+
- npm install
13+
- (cd app && npm install)
14+
- ./app/node_modules/.bin/browserify app/app.js > app/wsmc/src/main/resources/www/bundle.js
15+
# build wsmc/Java with the bundled voxel-clientmc
16+
- (cd app/wsmc && mvn package)
17+
18+
test:
19+
post:
20+
- cp -r app/wsmc/target/wsmc*.jar $CIRCLE_ARTIFACTS/

clientmc.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ class ClientMC extends EventEmitter
114114
const hash = document.location.hash;
115115
if (hash.length < 2) {
116116
// try anonymous auth
117-
username = 'mcwebchatuserX';
117+
username = 'user1';
118118
} else {
119119
username = hash.substring(1); // remove #
120120
}
@@ -128,6 +128,7 @@ class ClientMC extends EventEmitter
128128

129129
// pass some useful data to the worker
130130
this.mfworkerStream.write({cmd: 'setVariables',
131+
username: username,
131132
translateBlockIDs: this.translateBlockIDs,
132133
reverseBlockIDs: this.reverseBlockIDs,
133134
defaultBlockID: this.defaultBlockID,

mf-worker.js

Lines changed: 96 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,13 @@ const Writable = require('stream').Writable;
88
const through = require('through');
99
const ndarray = require('ndarray');
1010
const vec3Object = require('vec3'); // note: object type used by mineflayer, NOT gl-vec3 which is just a typed array :(
11+
const isBuffer = require('is-buffer');
1112

1213
module.exports = function(self) {
1314
console.log('mf-worker initializing',self);
1415

1516
self.readStream = ParentStream().pipe(toBufferStream).pipe(through(function write(event) {
16-
if (Buffer.isBuffer(event)) {
17+
if (isBuffer(event)) {
1718
// buffer data passes through to readStream -> duplexStream for bot
1819
this.queue(event);
1920
} else {
@@ -39,56 +40,6 @@ module.exports = function(self) {
3940

4041
self.duplexStream = duplexer(self.writeStream, self.readStream);
4142

42-
self.bot = mineflayer.createBot({
43-
username: 'user1', // TODO
44-
stream: self.duplexStream,
45-
noPacketFramer: true
46-
});
47-
48-
console.log('mf-worker bot',self.bot);
49-
50-
self.bot.on('game', function() {
51-
console.log('mf-worker spawn position: '+JSON.stringify(self.bot.spawnPoint));
52-
self.postMessage({cmd: 'spawn', spawnPoint: self.bot.spawnPoint});
53-
});
54-
55-
self.bot.on('kicked', function(reason) {
56-
self.postMessage({cmd: 'kicked', reason: reason});
57-
});
58-
59-
self.bot.on('message', function(message) {
60-
//self.console.logNode(tellraw2dom(message.json)); // TODO: send back to parent
61-
console.log('mf-worker chat message', message);
62-
self.postMessage({cmd: 'chat', message: message});
63-
});
64-
65-
self.bot.on('error', function(err) {
66-
console.log('WebSocket error', err);
67-
self.postMessage({cmd: 'error', error: err});
68-
});
69-
70-
self.bot.on('close', function() {
71-
console.log('WebSocket closed');
72-
self.postMessage({cmd: 'close'});
73-
});
74-
75-
self.bot.on('chunkColumnLoad', function(point) {
76-
self.addColumn(point);
77-
});
78-
79-
let pos = [0,0,0];
80-
self.bot.on('blockUpdate', function(oldBlock, newBlock) {
81-
console.log('blockUpdate', oldBlock, newBlock);
82-
const position = newBlock.position;
83-
pos[0] = position.x;
84-
pos[1] = position.y;
85-
pos[2] = position.z;
86-
const val = self.translateBlockID((newBlock.type << 4) | newBlock.metadata);
87-
self.postMessage({cmd: 'setBlock', position: pos, value: val});
88-
//self.game.setBlock(pos, val);
89-
});
90-
// TODO: also handle mass block update (event? would like to optimize multi_block_change, but..)
91-
9243
// Translate packed MC block ID (lower 4 bits metadata, upper 12 block) to 16-bit voxel ID
9344
self.translateBlockID = function(mcPackedID) {
9445
let ourBlockID;
@@ -255,46 +206,6 @@ module.exports = function(self) {
255206
self.postMessage({cmd: 'chunks', chunks: chunkCache}); // TODO: transferrable
256207
};
257208

258-
self.bot.on('blockBreakProgressObserved', function(block, destroyStage) {
259-
self.postMessage({cmd: 'blockBreakProgressObserved', position:[block.position.x, block.position.y, block.position.z], destroyStage: destroyStage});
260-
});
261-
self.bot.on('blockBreakProgressEnd', function(block) {
262-
self.postMessage({cmd: 'blockBreakProgressEnd', position:[block.position.x, block.position.y, block.position.z]});
263-
});
264-
265-
266-
self.bot.on('move', function() { // TODO: also support entityMoved, other entities, players, mobs
267-
// player move
268-
self.postMessage({cmd: 'move', position:[self.bot.entity.position.x, self.bot.entity.position.y, self.bot.entity.position.z]});
269-
});
270-
271-
self.bot.on('soundEffectHeard', function(soundName, position, volume, pitch) {
272-
//console.log('soundEffectHeard',arguments);
273-
// TODO: event.x,y,z(location?), volume, pitch - 3D sound https://github.com/deathcap/voxel-sfx/issues/3 Positional audio? (voxel-audio)
274-
self.postMessage({cmd: 'sound', soundName:soundName});
275-
});
276-
277-
self.bot._client.on('held_item_slot', function(packet) { // TODO: this really should be emitted in mineflayer
278-
//packet.slot
279-
const slot = self.bot.quickBarSlot;
280-
console.log('held_item_slot',slot);
281-
self.postMessage({cmd: 'heldItemSlot', slot:slot});
282-
});
283-
284-
self.bot.on('setSlot:0', function(oldItem, newItem) { // slot 0 is player inventory
285-
console.log('setSlot',oldItem,newItem);
286-
if (!oldItem && !newItem) return; // TODO: why does mineflayer send this?
287-
self.postMessage({cmd: 'setSlot', oldItem:oldItem, newItem:newItem});
288-
});
289-
// TODO: window items packet? for setting multiple slots
290-
291-
self.bot._client.on('resource_pack_send', function(packet) { // TODO: mineflayer api
292-
self.postMessage({cmd: 'resourcePack', url:packet.url, hash:packet.hash});
293-
});
294-
295-
// if we exist (the webworker), socket is connected
296-
self.bot._client.emit('connect');
297-
298209

299210
// handlers called for main thread
300211
self.chat = function(event) {
@@ -305,6 +216,100 @@ module.exports = function(self) {
305216
for (let key in event) {
306217
self[key] = event[key];
307218
}
219+
220+
// Now that the main thread has gave us the necessary data (username, ...), initialize the bot
221+
222+
self.bot = mineflayer.createBot({
223+
username: self.username,
224+
stream: self.duplexStream,
225+
noPacketFramer: true
226+
});
227+
228+
console.log('mf-worker bot',self.bot);
229+
230+
self.bot.on('game', function() {
231+
console.log('mf-worker spawn position: '+JSON.stringify(self.bot.spawnPoint));
232+
self.postMessage({cmd: 'spawn', spawnPoint: self.bot.spawnPoint});
233+
});
234+
235+
self.bot.on('kicked', function(reason) {
236+
self.postMessage({cmd: 'kicked', reason: reason});
237+
});
238+
239+
self.bot.on('message', function(message) {
240+
//self.console.logNode(tellraw2dom(message.json)); // TODO: send back to parent
241+
console.log('mf-worker chat message', message);
242+
self.postMessage({cmd: 'chat', message: message});
243+
});
244+
245+
self.bot.on('error', function(err) {
246+
console.log('WebSocket error', err);
247+
self.postMessage({cmd: 'error', error: err});
248+
});
249+
250+
self.bot.on('close', function() {
251+
console.log('WebSocket closed');
252+
self.postMessage({cmd: 'close'});
253+
});
254+
255+
self.bot.on('chunkColumnLoad', function(point) {
256+
self.addColumn(point);
257+
});
258+
259+
let pos = [0,0,0];
260+
self.bot.on('blockUpdate', function(oldBlock, newBlock) {
261+
console.log('blockUpdate', oldBlock, newBlock);
262+
const position = newBlock.position;
263+
pos[0] = position.x;
264+
pos[1] = position.y;
265+
pos[2] = position.z;
266+
const val = self.translateBlockID((newBlock.type << 4) | newBlock.metadata);
267+
self.postMessage({cmd: 'setBlock', position: pos, value: val});
268+
//self.game.setBlock(pos, val);
269+
});
270+
// TODO: also handle mass block update (event? would like to optimize multi_block_change, but..)
271+
272+
self.bot.on('blockBreakProgressObserved', function(block, destroyStage) {
273+
self.postMessage({cmd: 'blockBreakProgressObserved', position:[block.position.x, block.position.y, block.position.z], destroyStage: destroyStage});
274+
});
275+
self.bot.on('blockBreakProgressEnd', function(block) {
276+
self.postMessage({cmd: 'blockBreakProgressEnd', position:[block.position.x, block.position.y, block.position.z]});
277+
});
278+
279+
280+
self.bot.on('move', function() { // TODO: also support entityMoved, other entities, players, mobs
281+
// player move
282+
self.postMessage({cmd: 'move', position:[self.bot.entity.position.x, self.bot.entity.position.y, self.bot.entity.position.z]});
283+
});
284+
285+
self.bot.on('soundEffectHeard', function(soundName, position, volume, pitch) {
286+
//console.log('soundEffectHeard',arguments);
287+
// TODO: event.x,y,z(location?), volume, pitch - 3D sound https://github.com/deathcap/voxel-sfx/issues/3 Positional audio? (voxel-audio)
288+
self.postMessage({cmd: 'sound', soundName:soundName});
289+
});
290+
291+
self.bot._client.on('held_item_slot', function(packet) { // TODO: this really should be emitted in mineflayer
292+
//packet.slot
293+
const slot = self.bot.quickBarSlot;
294+
console.log('held_item_slot',slot);
295+
self.postMessage({cmd: 'heldItemSlot', slot:slot});
296+
});
297+
298+
self.bot.on('setSlot:0', function(oldItem, newItem) { // slot 0 is player inventory
299+
console.log('setSlot',oldItem,newItem);
300+
if (!oldItem && !newItem) return; // TODO: why does mineflayer send this?
301+
self.postMessage({cmd: 'setSlot', oldItem:oldItem, newItem:newItem});
302+
});
303+
// TODO: window items packet? for setting multiple slots
304+
305+
self.bot._client.on('resource_pack_send', function(packet) { // TODO: mineflayer api
306+
self.postMessage({cmd: 'resourcePack', url:packet.url, hash:packet.hash});
307+
});
308+
309+
// if we exist (the webworker), socket is connected
310+
self.bot._client.emit('connect');
311+
312+
308313
};
309314

310315
// http://wiki.vg/Protocol#Player_Digging

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
"dependencies": {
1414
"duplexer": "^0.1.1",
1515
"ever": "0.0.3",
16+
"is-buffer": "^1.1.2",
1617
"itempile": "^1.0.2",
1718
"minecraft-data": "^0.19.1",
1819
"ndarray": "^1.0.14",

0 commit comments

Comments
 (0)