From 3ba46f0e97e24adc3dc479b46e85163e7c5553f2 Mon Sep 17 00:00:00 2001 From: DemiPixel Date: Sun, 22 Nov 2015 16:06:59 -0800 Subject: [PATCH] Adding behaviors --- src/lib/behavior.js | 7 ++- src/lib/plugins/animations.js | 12 ++-- src/lib/plugins/blocks.js | 9 ++- src/lib/plugins/chat.js | 17 ++++-- src/lib/plugins/daycycle.js | 7 ++- src/lib/plugins/digging.js | 18 +++--- src/lib/plugins/placeBlock.js | 7 ++- src/lib/plugins/pvp.js | 33 +++++++---- src/lib/plugins/respawn.js | 20 ++++--- src/lib/plugins/sound.js | 6 +- src/lib/plugins/updatePositions.js | 94 +++++++++++++++++------------- src/lib/plugins/world.js | 18 ++++-- 12 files changed, 159 insertions(+), 89 deletions(-) diff --git a/src/lib/behavior.js b/src/lib/behavior.js index 2ae13b4..b0f3ec2 100644 --- a/src/lib/behavior.js +++ b/src/lib/behavior.js @@ -1,20 +1,23 @@ module.exports = (obj) => { - return async (eventName, data, func, opt) => { + return async (eventName, data, func, cancelFunc) => { var hiddenCancelled = false; var cancelled = false; var cancelCount = 0; - var cancel = (hidden) => { // Hidden shouldn't be used often but it's not hard to implement so meh + var defaultCancel = true; + var cancel = (dC=true, hidden=false) => { // Hidden shouldn't be used often but it's not hard to implement so meh if (hidden) hiddenCancelled = true; else { cancelled = true; cancelCount++; } + defaultCancel = dC; } await obj.emit(eventName + '_cancel', data, cancel); await obj.emit(eventName, data, cancelled, cancelCount); if (!hiddenCancelled && !cancelled) await func(data); + else if (cancelFunc && defaultCancel) cancelFunc(data); await obj.emit(eventName + '_done', data, cancelled); } diff --git a/src/lib/plugins/animations.js b/src/lib/plugins/animations.js index 19f3a3f..db6818b 100644 --- a/src/lib/plugins/animations.js +++ b/src/lib/plugins/animations.js @@ -1,10 +1,14 @@ module.exports.player=function(player) { player._client.on("arm_animation", () => - player._writeOthersNearby("animation", { - entityId: player.id, - animation: 0 - })); + player.behavior('punch', {}, () => { + player._writeOthersNearby("animation", { + entityId: player.id, + animation: 0 + }); + }) + ); + player._client.on("entity_action", ({actionId} = {}) => { if(actionId == 3) { diff --git a/src/lib/plugins/blocks.js b/src/lib/plugins/blocks.js index 909673c..59e3603 100644 --- a/src/lib/plugins/blocks.js +++ b/src/lib/plugins/blocks.js @@ -13,10 +13,17 @@ module.exports.player=function(player,serv) }; player.sendBlock = (position, blockType, blockData) => // Call from player.setBlock unless you want "local" fake blocks - player._client.write("block_change",{ + player.behavior('sendBlock', { + position: position, + id: blockType, + damage: blockData + }, ({position, id, damage}) => { + player._client.write("block_change",{ location:position, type:blockType<<4 | blockData + }); }); + player.setBlock = (position,blockType,blockData) => serv.setBlock(player.world,position,blockType,blockData); diff --git a/src/lib/plugins/chat.js b/src/lib/plugins/chat.js index d5ea1c2..5e78e6f 100644 --- a/src/lib/plugins/chat.js +++ b/src/lib/plugins/chat.js @@ -11,12 +11,21 @@ module.exports.player=function(player,serv) { player._client.on('chat', ({message} = {}) => { if(message[0]=="/") { - var command = message.slice(1); - player.handleCommand(command); + player.behavior('command', { + message: message + }, ({message}) => { + var command = message.slice(1); + player.handleCommand(command); + }); } else { - serv.broadcast('<' + player.username + '>' + ' ' + message); - player.emit("chat",message); + player.behavior('chat', { + message: message, + broadcastMessage: '<' + player.username + '>' + ' ' + message, + broadcast: true + }, ({message, broadcast, broadcastMessage}) => { + if (broadcast) serv.broadcast(broadcastMessage); + }); } }); diff --git a/src/lib/plugins/daycycle.js b/src/lib/plugins/daycycle.js index 6048f86..6c9ffd5 100644 --- a/src/lib/plugins/daycycle.js +++ b/src/lib/plugins/daycycle.js @@ -14,7 +14,12 @@ module.exports.server=function(serv) { serv.on('tick', (delta,count) => { if (!serv.doDaylightCycle) return; if (count % 20 == 0) { - serv.setTime((serv.time + 20) % 24000); // Vanilla only does it every second + serv.behavior('changeTime', { + old: serv.time, + newTime: serv.time + 20 + }, ({newTime}) => { + serv.setTime((serv.time + 20) % 24000); // Vanilla only does it every second + }); } }) }; diff --git a/src/lib/plugins/digging.js b/src/lib/plugins/digging.js index 378e28e..9f4f674 100644 --- a/src/lib/plugins/digging.js +++ b/src/lib/plugins/digging.js @@ -2,6 +2,11 @@ var Vec3 = require("vec3").Vec3; module.exports.player=function(player,serv) { + + function cancelDig({position, block}) { + player.sendBlock(position, block.id, block.data); + } + player._client.on("block_dig",({location,status} = {}) => { var pos=new Vec3(location.x,location.y,location.z); player.world.getBlock(pos) @@ -19,31 +24,30 @@ module.exports.player=function(player,serv) block: block }, ({position}) => { return startDigging(position); - }); + }, cancelDig); else if(status==2) player.behavior('finishDig', { // Finish dig survival position: position, block: block }, ({position}) => { return completeDigging(position); - }); + }, cancelDig); else if(status==1) player.behavior('cancelDig', { // Cancel dig survival position: position, block: block }, ({position}) => { return cancelDigging(position); - }); + }, cancelDig); else if(status==0 && player.gameMode==1) player.behavior('dig', { // Start/finish dig creative position: position, block: block }, ({position}) => { return creativeDigging(position); - }); - } - )} - ) + }, cancelDig); + }, cancelDig) + }) .catch((err)=> setTimeout(() => {throw err;},0)) }); diff --git a/src/lib/plugins/placeBlock.js b/src/lib/plugins/placeBlock.js index ab7e6df..e3a6c8b 100644 --- a/src/lib/plugins/placeBlock.js +++ b/src/lib/plugins/placeBlock.js @@ -26,7 +26,8 @@ module.exports.player=function(player,serv) position: placedPosition, reference: referencePosition, playSound: true, - sound: 'dig.' + (materialToSound[blocks[heldItem.blockId].material] || 'stone') + sound: 'dig.' + (materialToSound[blocks[heldItem.blockId].material] || 'stone'), + world: player.world }, ({direction, heldItem, position, reference, playSound, sound}) => { if (playSound) { serv.playSound(sound, player.world, placedPosition.clone().add(new Vec3(0.5, 0.5, 0.5)), { @@ -46,6 +47,10 @@ module.exports.player=function(player,serv) location:position }); } + }, async () => { + var id = await player.world.getBlockType(placedPosition); + var damage = await player.world.getBlockData(placedPosition); + player.sendBlock(placedPosition, id, damage); }); }); }; diff --git a/src/lib/plugins/pvp.js b/src/lib/plugins/pvp.js index 18262e8..a9d9f51 100644 --- a/src/lib/plugins/pvp.js +++ b/src/lib/plugins/pvp.js @@ -17,22 +17,31 @@ module.exports.player=function(player,serv) var attackedEntity = serv.entities[entityId]; if(!attackedEntity || (attackedEntity.gameMode != 0 && attackedEntity.type == 'player')) return; - attackedEntity.updateHealth(attackedEntity.health - 1); - serv.playSound('game.player.hurt', player.world, attackedEntity.position.scaled(1/32)); + player.behavior('attack', { + attackedEntity: attackedEntity, + sound: 'game.player.hurt', + playSound: true, + damage: 1, + velocity: attackedEntity.position.minus(player.position).plus(new Vec3(0, 0.5, 0)).scaled(5), + maxVelocity: new Vec3(4, 4, 4), + animation: true + }, ({entity, sound, playSound, damage, velocity, maxVelocity, animation}) => { + attackedEntity.updateHealth(attackedEntity.health - dealDamage); + serv.playSound(sound, player.world, attackedEntity.position.scaled(1/32)); - var attackVelocity = attackedEntity.position.minus(player.position).plus(new Vec3(0, 0.5, 0)).scaled(5/32); - attackedEntity.sendVelocity(attackVelocity, new Vec3(4, 4, 4)); + attackedEntity.sendVelocity(velocity.scaled(1/32), maxVelocity); - if(attackedEntity.health<=0) - attackedEntity._writeOthers('entity_status',{ + if(attackedEntity.health<=0 && animation) + attackedEntity._writeOthers('entity_status',{ + entityId:attackedEntity.id, + entityStatus:3 + }); + else if (animation) + attackedEntity._writeOthers('animation',{ entityId:attackedEntity.id, - entityStatus:3 + animation:1 }); - else - attackedEntity._writeOthers('animation',{ - entityId:attackedEntity.id, - animation:1 - }); + }); } player._client.on("use_entity", ({mouse,target} = {}) => { diff --git a/src/lib/plugins/respawn.js b/src/lib/plugins/respawn.js index bacc817..a1bdc89 100644 --- a/src/lib/plugins/respawn.js +++ b/src/lib/plugins/respawn.js @@ -2,16 +2,18 @@ module.exports.player=function(player) { player._client.on("client_command", ({payload}) => { if(payload == 0) { - player._client.write("respawn",{ - dimension:0, - difficulty:0, - gamemode:player.gameMode, - levelType:'default' + player.behavior('requestRespawn', {}, () => { + player._client.write("respawn",{ + dimension:0, + difficulty:0, + gamemode:player.gameMode, + levelType:'default' + }); + player.sendPosition(); + player.updateHealth(20); + player.nearbyEntities=[]; + player.updateAndSpawn(); }); - player.sendPosition(); - player.updateHealth(20); - player.nearbyEntities=[]; - player.updateAndSpawn(); } }); }; \ No newline at end of file diff --git a/src/lib/plugins/sound.js b/src/lib/plugins/sound.js index fd4f281..672861b 100644 --- a/src/lib/plugins/sound.js +++ b/src/lib/plugins/sound.js @@ -40,11 +40,12 @@ module.exports.player=function(player,serv) { serv.playSound(sound, player.world, null, opt); }; - player._client.on('block_place', ({location}={}) => { + player._client.on('placeBlock_cancel', ({location}={}, cancel) => { if (player.crouching) return; var pos=new Vec3(location.x,location.y,location.z); player.world.getBlockType(pos).then((id) => { if (id != 25) return; + cancel(); if (!player.world.blockEntityData[pos.toString()]) player.world.blockEntityData[pos.toString()] = {}; var data = player.world.blockEntityData[pos.toString()]; if (typeof data.note == 'undefined') data.note = -1; @@ -54,11 +55,12 @@ module.exports.player=function(player,serv) { }).catch((err)=> setTimeout(() => {throw err;},0)); }); - player._client.on('block_dig', ({location,status} = {}) => { + player._client.on('dig_cancel', ({location,status} = {}, cancel) => { if (status != 0 || player.gameMode == 1) return; var pos=new Vec3(location.x,location.y,location.z); player.world.getBlockType(pos).then((id) => { if (id != 25) return; + cancel(); if (!player.world.blockEntityData[pos.toString()]) player.world.blockEntityData[pos.toString()] = {}; var data = player.world.blockEntityData[pos.toString()]; if (typeof data.note == 'undefined') data.note = 0; diff --git a/src/lib/plugins/updatePositions.js b/src/lib/plugins/updatePositions.js index 749f41d..dba6c20 100644 --- a/src/lib/plugins/updatePositions.js +++ b/src/lib/plugins/updatePositions.js @@ -17,21 +17,29 @@ module.exports.player=function(player) } function sendLook(yaw,pitch,onGround) { - var convYaw=conv(yaw); - var convPitch=conv(pitch); - if (convYaw == player.yaw && convPitch == player.pitch) return; - player._writeOthersNearby("entity_look", { - entityId: player.id, - yaw: convYaw, - pitch: convPitch, + player.behavior('look', { + yaw: yaw, + pitch: pitch, onGround: onGround - }); - player.yaw = convYaw; - player.pitch = convPitch; - player.onGround = onGround; - player._writeOthersNearby("entity_head_rotation", { - entityId: player.id, - headYaw: convYaw + }, ({yaw, pitch, onGround}) => { + var convYaw=conv(yaw); + var convPitch=conv(pitch); + if (convYaw == player.yaw && convPitch == player.pitch) return; + player._writeOthersNearby("entity_look", { + entityId: player.id, + yaw: convYaw, + pitch: convPitch, + onGround: onGround + }); + player.yaw = convYaw; + player.pitch = convPitch; + player.onGround = onGround; + player._writeOthersNearby("entity_head_rotation", { + entityId: player.id, + headYaw: convYaw + }); + }, () => { + player.sendPosition(); }); } @@ -44,33 +52,39 @@ module.exports.player=function(player) }); function sendRelativePositionChange(newPosition, onGround) { - if (player.position.distanceTo(new Vec3(0, 0, 0)) != 0) { - var diff = newPosition.minus(player.position); - if(diff.abs().x>127 || diff.abs().y>127 || diff.abs().z>127) - { - player._writeOthersNearby('entity_teleport', { - entityId:player.id, - x: newPosition.x, - y: newPosition.y, - z: newPosition.z, - yaw: player.yaw, - pitch: player.pitch, - onGround: onGround - }); + player.behavior('move', { + onGround: onGround, + position: newPosition + }, ({onGround, position}) => { + if (player.position.distanceTo(new Vec3(0, 0, 0)) != 0) { + var diff = newPosition.minus(player.position); + if(diff.abs().x>127 || diff.abs().y>127 || diff.abs().z>127) + { + player._writeOthersNearby('entity_teleport', { + entityId:player.id, + x: newPosition.x, + y: newPosition.y, + z: newPosition.z, + yaw: player.yaw, + pitch: player.pitch, + onGround: onGround + }); + } + else if (diff.distanceTo(new Vec3(0, 0, 0)) != 0) { + player._writeOthersNearby('rel_entity_move', { + entityId: player.id, + dX: diff.x, + dY: diff.y, + dZ: diff.z, + onGround: onGround + }); + } } - else if (diff.distanceTo(new Vec3(0, 0, 0)) != 0) { - player._writeOthersNearby('rel_entity_move', { - entityId: player.id, - dX: diff.x, - dY: diff.y, - dZ: diff.z, - onGround: onGround - }); - } - } - player.position = newPosition; - player.onGround = onGround; - player.emit("positionChanged"); + player.position = newPosition; + player.onGround = onGround; + }, () => { + player.sendPosition(); + }); } player.sendPosition = () => { diff --git a/src/lib/plugins/world.js b/src/lib/plugins/world.js index 9fab63d..1804d58 100644 --- a/src/lib/plugins/world.js +++ b/src/lib/plugins/world.js @@ -70,14 +70,20 @@ module.exports.player=function(player,serv) { player.sendChunk = (chunkX,chunkZ,column) => { - player._client.write('map_chunk', { + return player.behavior('sendChunk', { x: chunkX, z: chunkZ, - groundUp: true, - bitMap: 0xffff, - chunkData: column.dump() - }); - return Promise.resolve(); + chunk: column + }, ({x, z, chunk}) => { + player._client.write('map_chunk', { + x: x, + z: z, + groundUp: true, + bitMap: 0xffff, + chunkData: chunk.dump() + }); + return Promise.resolve(); + }) }; function spiral(arr)