Permalink
Browse files

Merge pull request #23 from nickpoorman/master

Added falling damage
  • Loading branch information...
2 parents e1aa678 + 9b91fbd commit 92074f469a76f8b5d3f773927a90fb29f91fe118 @deoxxa committed Jan 5, 2013
Showing with 153 additions and 0 deletions.
  1. +1 −0 .gitignore
  2. +1 −0 lib/game.js
  3. +4 −0 lib/player.js
  4. +27 −0 plugins/player-abilities.js
  5. +76 −0 plugins/player-fall.js
  6. +32 −0 plugins/player-health.js
  7. +12 −0 server.example.js
View
@@ -1,3 +1,4 @@
/node_modules
/config.json
/map
+/server.js
View
@@ -5,6 +5,7 @@ var Map = require("./map");
var Game = module.exports = function Game(config) {
events.EventEmitter.call(this);
+ this.setMaxListeners(0);
if (!config) {
config = {};
View
@@ -13,6 +13,10 @@ var Player = module.exports = function Player(game, options) {
this.stance = 0;
this.on_ground = 1;
+ this.health = 20;
+ this.food = 20;
+ this.saturation = 5;
+
if (typeof this.options.stance === "number") { this.stance = this.options.stance; }
if (typeof this.options.on_ground === "number") { this.on_ground = this.options.on_ground; }
};
@@ -0,0 +1,27 @@
+/**
+ Player abilities plugin.
+ This is used to keep track of player ability state between the client and the server.
+ Handles 0xCA in protocol.
+*/
+module.exports = function() {
+ return function(game) {
+ game.on("player:join", function(player) {
+ player.client.on("packet:ca", function(packet) {
+
+ var creativeMode = (packet.flags & 0x01);
+ var flying = (packet.flags & 0x02) >> 1;
+ var canFly = (packet.flags & 0x04) >> 2;
+ var invulnerable = (packet.flags & 0x08) >> 3;
+
+ if(player.mode != creativeMode) {
+ // something weird is happening here, lets log it
+ console.warn('[Warning] Player client side game mode does not match server side!');
+ }
+
+ player.flying = flying;
+ // trigger an event here to notify any plugins listening for flying status
+ player.emit("flying", flying);
+ });
+ });
+ };
+};
View
@@ -0,0 +1,76 @@
+/**
+ Fall plugin.
+ When a user falls apply the damage to their health.
+ This is by no means complete. Just having some fun playing with node and minecraft.
+ Also, this doesn't yet take into consideration velocity, and falling into water.
+
+ This might need to be loaded after player-abilities plugin.
+*/
+module.exports = function() {
+ return function(game) {
+ game.on("player:join", function(player) {
+ player.client.on("packet:0a", on_fall.bind(player, game));
+ player.client.on("packet:0b", on_fall.bind(player, game));
+ player.client.on("packet:0c", on_fall.bind(player, game));
+ player.client.on("packet:0d", on_fall.bind(player, game));
+ player.on("flying", handle_falling_pos.bind(player));
+ });
+ };
+};
+
+var set_falling_pos = function set_falling_pos(player) {
+ player.start_falling_pos = player.y;
+ }
+
+var handle_falling_pos = function handle_falling_pos(flying) {
+ // if the player stops flying
+ if(!flying) set_falling_pos(this);
+ }
+
+var on_fall = function on_fall(game, packet) {
+ // Need the block type to determine if the player is swimming.
+ // Maybe there is a better way to do this? ...swimming/flying should probably be kept track of in player.js with movement.js
+ var x = packet.x || this.x,
+ z = packet.z || this.z,
+ y = packet.y || this.y;
+
+ var block_x = x & 0x0f,
+ block_z = z & 0x0f,
+ block_y = y;
+
+ var WATER = 8;
+ var STATIONARY_WATER = 9;
+
+ game.map.get_abs_chunk(x, z, function(err, chunk) {
+ var blockType = chunk.get_block_type(block_x, block_z, block_y);
+ var swimming = blockType == STATIONARY_WATER || blockType == WATER;
+
+ // try to guess if they are flying to begin with
+ // if the block below them is air then they are probably flying
+ // this is untested - might need to find a way to do this with the protocol
+ if(typeof this.flying == "undefined") {
+ this.flying = chunk.get_block_type(block_x, block_z, block_y - 1) == 0;
+ }
+
+ // don't apply fall if they are swimming
+ if(!swimming) {
+ // when on_ground changes from true to false start keeping track of distance
+ if(this.on_ground && !packet["on_ground"]) {
+ set_falling_pos(this);
+ }
+ // Edge case:
+ // also when flying changes from true to false we need to set the height
+ // - this will get handled when the "flying",false event fires
+
+ // when it changes from false to true then calculate damage
+ if(!this.on_ground && packet["on_ground"]) {
+ var damage = Math.floor(this.start_falling_pos - packet.y - 3);
+ //trigger a damage event on the player
+ if(damage > 0) this.emit("damage", damage);
+
+ //TODO?: emit sound 0x3e
+ }
+ }
+
+ }.bind(this));
+ };
View
@@ -0,0 +1,32 @@
+module.exports = function() {
+ return function(game) {
+ game.on("player:join", function(player) {
+ player.on("damage", on_damage.bind(player));
+
+ // defaults
+ player.damaged = 0;
+ });
+
+ game.on("tick", update_health.bind(null, game));
+ };
+};
+
+var on_damage = function on_damage(damage) {
+ //set the damage to the player if they aren't on creative mode, so 0 or 2
+ if(this.mode != 1) {
+ this.damaged += damage;
+ }
+ };
+
+var update_health = function update_health(game) {
+ game.players.filter(function(e) {
+ return e.damaged > 0;
+ }).forEach(function(player) {
+ // modify the players health to match the damage done
+ player.health -= player.damaged;
+ // send out necessary packet to update the health
+ player.health < 0 ? player.kill() : player.setHealth(player.health, player.food, player.saturation);
+ // reset the damage done
+ player.damaged = 0;
+ });
+ };
View
@@ -150,6 +150,18 @@ game.use(SaveMapPlugin(__dirname + "/map"));
var AdminPlugin = require('./plugins/admin');
game.use(AdminPlugin());
+// This is used to keep track of player ability state between the client and the server
+var PlayerAbilitiesPlugin = require('./plugins/player-abilities');
+game.use(PlayerAbilitiesPlugin());
+
+// This plugin manages players health & hunger
+var PlayerHealthPlugin = require('./plugins/player-health');
+game.use(PlayerHealthPlugin());
+
+// This plugin controlls falling damage/death
+var PlayerFallPlugin = require('./plugins/player-fall');
+game.use(PlayerFallPlugin());
+
// The server object is basically a wrapper around `net.Server` that constructs
// `Client` objects as they connect.

0 comments on commit 92074f4

Please sign in to comment.