Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

Added falling damage #23

Merged
merged 3 commits into from

3 participants

@nickpoorman

There are three new plugins.

player-fall - When a user falls determines damage to be done and fires a damage event on the player.
player-abilities - Used to keep track of when the user is flying for player-fall.
player-health - Modifies the player health on damage events.

plugins/player-fall.js
((26 lines not shown))
+ // 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 that = this;

deoxxa will get angry at you for this :P so .bind(this) the function instead

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
plugins/player-abilities.js
((3 lines not shown))
+ 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.log('[Warning] Player client side game mode does not match server side!');

maybe change this to console.warn just so it prints to stderr

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@deoxxa
Owner

Looks good, merging.

@deoxxa deoxxa merged commit 92074f4 into deoxxa:master
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
This page is out of date. Refresh to see the latest.
View
1  .gitignore
@@ -1,3 +1,4 @@
/node_modules
/config.json
/map
+/server.js
View
1  lib/game.js
@@ -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
4 lib/player.js
@@ -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; }
};
View
2  lib/serialiser.js
@@ -142,7 +142,7 @@ Serialiser.prototype.write = function write(packet) {
}
case 0x08: {
- this.emit("data", S().uint8(packet.pid).int16be(packet.health).int16be(packet.health).floatbe(packet.saturation).result());
+ this.emit("data", S().uint8(packet.pid).int16be(packet.health).int16be(packet.food).floatbe(packet.saturation).result());
break;
}
View
27 plugins/player-abilities.js
@@ -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
76 plugins/player-fall.js
@@ -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
32 plugins/player-health.js
@@ -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
12 server.example.js
@@ -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.
Something went wrong with that request. Please try again.