Skip to content

Commit

Permalink
Merge pull request #23 from nickpoorman/master
Browse files Browse the repository at this point in the history
Added falling damage
  • Loading branch information
deoxxa committed Jan 5, 2013
2 parents e1aa678 + 9b91fbd commit 92074f4
Show file tree
Hide file tree
Showing 7 changed files with 153 additions and 0 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/node_modules
/config.json
/map
/server.js
1 change: 1 addition & 0 deletions lib/game.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 = {};
Expand Down
4 changes: 4 additions & 0 deletions lib/player.js
Original file line number Diff line number Diff line change
Expand Up @@ -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; }
};
Expand Down
27 changes: 27 additions & 0 deletions plugins/player-abilities.js
Original file line number Diff line number Diff line change
@@ -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);
});
});
};
};
76 changes: 76 additions & 0 deletions plugins/player-fall.js
Original file line number Diff line number Diff line change
@@ -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));
};
32 changes: 32 additions & 0 deletions plugins/player-health.js
Original file line number Diff line number Diff line change
@@ -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;
});
};
12 changes: 12 additions & 0 deletions server.example.js
Original file line number Diff line number Diff line change
Expand Up @@ -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.

Expand Down

0 comments on commit 92074f4

Please sign in to comment.