Merge pull request #108 from demipixel/behaviors

Just like how caterpillars will turn into butterflies...
This commit is contained in:
Romain Beaumont 2015-11-20 23:44:29 +01:00
commit 4d267adb48
20 changed files with 249 additions and 186 deletions

16
src/lib/behavior.js Normal file
View file

@ -0,0 +1,16 @@
module.exports = (obj) => {
return (eventName, data, func, opt) => {
var hiddenCancelled = false;
var cancelled = false;
var cancel = (hidden) => { // Hidden shouldn't be used often but it's not hard to implement so meh
if (hidden) hiddenCancelled = true;
else cancelled = true;
}
obj.emit(eventName + '_cancel', data, cancel);
obj.emit(eventName, data, cancelled);
if (!hiddenCancelled && !cancelled) func(data);
obj.emit(eventName + '_done', data, cancelled);
}
}

14
src/lib/entity.js Normal file
View file

@ -0,0 +1,14 @@
var EventEmitter = require('events').EventEmitter;
var PrismarineEntity = require("prismarine-entity");
var util = require('util');
util.inherits(PrismarineEntity, EventEmitter);
class Entity extends PrismarineEntity
{
constructor(id) {
super(id);
EventEmitter.call(this);
}
}
module.exports = Entity;

View file

@ -1,13 +0,0 @@
var EventEmitter = require('events').EventEmitter;
class Player extends EventEmitter
{
constructor() {
super();
this._client=null;
this.entity=null;
}
}
module.exports = Player;

View file

@ -2,30 +2,21 @@ module.exports.player=function(player)
{ {
player._client.on("arm_animation", () => player._client.on("arm_animation", () =>
player._writeOthersNearby("animation", { player._writeOthersNearby("animation", {
entityId: player.entity.id, entityId: player.id,
animation: 0 animation: 0
})); }));
function setMetadata(metadata)
{
player.entity.metadata = metadata;
player._writeOthersNearby("entity_metadata", {
entityId: player.entity.id,
metadata: player.entity.metadata
});
}
player._client.on("entity_action", ({actionId} = {}) => { player._client.on("entity_action", ({actionId} = {}) => {
if(actionId == 3) { if(actionId == 3) {
setMetadata([{"key":0,"type":0,"value": 0x08}]); player.setAndUpdateMetadata([{"key":0,"type":0,"value": 0x08}]);
} else if(actionId == 4) { } else if(actionId == 4) {
setMetadata([{"key":0,"type":0,"value": 0x00}]); player.setAndUpdateMetadata([{"key":0,"type":0,"value": 0x00}]);
} else if(actionId == 0) { } else if(actionId == 0) {
setMetadata([{"key":0,"type":0,"value": 0x02}]); player.setAndUpdateMetadata([{"key":0,"type":0,"value": 0x02}]);
player.entity.crouching = true; player.crouching = true;
} else if(actionId == 1) { } else if(actionId == 1) {
setMetadata([{"key":0,"type":0,"value": 0x00}]); player.setAndUpdateMetadata([{"key":0,"type":0,"value": 0x00}]);
player.entity.crouching = false; player.crouching = false;
} }
}); });
}; };

View file

@ -33,7 +33,7 @@ module.exports.player=function(player,serv)
action(params) { action(params) {
var res = params.map((num, i) => { // parseInt paramaters var res = params.map((num, i) => { // parseInt paramaters
if (num.indexOf('~') == 0) { if (num.indexOf('~') == 0) {
return (player.entity.position[['', 'x', 'y', 'z'][i]] >> 5) + parseInt(num.slice(1) || 0); return (player.position[['', 'x', 'y', 'z'][i]] >> 5) + parseInt(num.slice(1) || 0);
} else { } else {
return parseInt(num); // return parseInt>>5 if position, not id return parseInt(num); // return parseInt>>5 if position, not id
} }

View file

@ -4,7 +4,7 @@ module.exports.player=function(player)
{ {
player._client.on('block_place', async ({location} = {}) => { player._client.on('block_place', async ({location} = {}) => {
var referencePosition=new Vec3(location.x,location.y,location.z); var referencePosition=new Vec3(location.x,location.y,location.z);
if (player.entity.crouching) return; if (player.crouching) return;
try { try {
var id = await player.world.getBlockType(referencePosition); var id = await player.world.getBlockType(referencePosition);
var blockAbove = await player.world.getBlockType(referencePosition.clone().add(new Vec3(0, 1, 0))); var blockAbove = await player.world.getBlockType(referencePosition.clone().add(new Vec3(0, 1, 0)));

View file

@ -11,7 +11,7 @@ module.exports.server=function(serv)
serv.getNearby= ({world,position,radius=8*16*32}) => serv.players.filter( player => serv.getNearby= ({world,position,radius=8*16*32}) => serv.players.filter( player =>
player.world == world && player.world == world &&
player.entity.position.distanceTo(position) <= radius player.position.distanceTo(position) <= radius
); );
serv.getNearbyEntities= ({world,position,radius=8*16*32}) => Object.keys(serv.entities) serv.getNearbyEntities= ({world,position,radius=8*16*32}) => Object.keys(serv.entities)
@ -22,25 +22,30 @@ module.exports.server=function(serv)
); );
}; };
module.exports.player=function(player,serv) module.exports.entity=function(entity,serv)
{ {
player._writeOthers= (packetName, packetFields) =>
player entity.getNearby = () => serv
.getOthers() .getNearbyEntities({
.forEach((otherPlayer) => otherPlayer._client.write(packetName, packetFields)); world: entity.world,
position: entity.position,
radius: entity.viewDistance*32
})
.filter((e) => e != entity);
player._writeOthersNearby = (packetName, packetFields) => entity.getOtherPlayers = () => serv.players.filter((p) => p != entity);
serv._writeArray(packetName, packetFields, player.nearbyPlayers());
player.getOthers = () => serv.players.filter((otherPlayer) => otherPlayer != player); entity.getOthers = () => serv.entities.filter((e) => e != entity);
player.getNearbyPlayers = (radius=player.entity.viewDistance*32) => serv.getNearby({ entity.getNearbyPlayers = (radius=entity.viewDistance*32) => entity.getNearby()
world: player.world, .filter((e) => e.type == 'player');
position: player.position,
radius: radius
});
player.nearbyPlayers = (radius=player.entity.viewDistance*32) => player.entity.nearbyEntities entity.nearbyPlayers = (radius=entity.viewDistance*32) => entity.nearbyEntities
.filter(e => e.type == 'player') .filter(e => e.type == 'player')
.map(e => e.player);
}; entity._writeOthers = (packetName, packetFields) =>
serv._writeArray(packetName, packetFields, entity.getOtherPlayers());
entity._writeOthersNearby = (packetName, packetFields) =>
serv._writeArray(packetName, packetFields, entity.getNearbyPlayers());
}

View file

@ -1,4 +1,4 @@
var Vec3 = require("vec3").Vec3 var Vec3 = require("vec3").Vec3;
module.exports.player=function(player,serv) module.exports.player=function(player,serv)
{ {
@ -76,7 +76,7 @@ module.exports.player=function(player,serv)
player.changeBlock(location,0,0); player.changeBlock(location,0,0);
// Drop block // Drop block
serv.spawnObject(2, player.world, location.offset(0.5, 0.5, 0.5), { serv.spawnObject(2, player.world, location.offset(0.5, 0.5, 0.5), {
velocity: Vec3(Math.random()*4 - 2, Math.random()*2 + 2, Math.random()*4 - 2), velocity: new Vec3(Math.random()*4 - 2, Math.random()*2 + 2, Math.random()*4 - 2),
itemId: currentlyDugBlock.type, itemId: currentlyDugBlock.type,
itemDamage: currentlyDugBlock.metadata itemDamage: currentlyDugBlock.metadata
}); });

View file

@ -1,7 +1,4 @@
var Entity=require("prismarine-entity"); var Entity=require("../entity");
var util = require('util');
var EventEmitter = require('events').EventEmitter;
util.inherits(Entity, EventEmitter);
var Vec3 = require("vec3").Vec3; var Vec3 = require("vec3").Vec3;
var entitiesByName=require("minecraft-data")(require("../version")).entitiesByName; var entitiesByName=require("minecraft-data")(require("../version")).entitiesByName;
@ -14,7 +11,6 @@ module.exports.server=function(serv,options) {
serv.initEntity = (type, entityType, world, position) => { serv.initEntity = (type, entityType, world, position) => {
serv.entityMaxId++; serv.entityMaxId++;
var entity = new Entity(serv.entityMaxId); var entity = new Entity(serv.entityMaxId);
EventEmitter.call(entity);
Object.keys(plugins) Object.keys(plugins)
.filter(pluginName => plugins[pluginName].entity!=undefined) .filter(pluginName => plugins[pluginName].entity!=undefined)
@ -35,9 +31,10 @@ module.exports.server=function(serv,options) {
object.yaw = yaw; object.yaw = yaw;
object.gravity = new Vec3(0, -20*32, 0); object.gravity = new Vec3(0, -20*32, 0);
object.terminalvelocity = new Vec3(27*32, 27*32, 27*32); object.terminalvelocity = new Vec3(27*32, 27*32, 27*32);
object.friction = (new Vec3(10*32, 0, 10*32)).floored(); object.friction = new Vec3(15*32, 0, 15*32);
object.size = new Vec3(0.25*32, 0.25*32, 0.25*32); // Hardcoded, will be dependent on type! object.size = new Vec3(0.25*32, 0.25*32, 0.25*32); // Hardcoded, will be dependent on type!
object.deathTime = 60*1000; // 60 seconds object.deathTime = 60*1000; // 60 seconds
object.pickupTime = 200;
object.itemId = itemId; object.itemId = itemId;
object.itemDamage = itemDamage; object.itemDamage = itemDamage;
@ -52,19 +49,17 @@ module.exports.server=function(serv,options) {
mob.yaw = yaw; mob.yaw = yaw;
mob.gravity = new Vec3(0, -20*32, 0); mob.gravity = new Vec3(0, -20*32, 0);
mob.terminalvelocity = new Vec3(27*32, 27*32, 27*32); mob.terminalvelocity = new Vec3(27*32, 27*32, 27*32);
mob.friction = new Vec3(10*32, 0, 10*32); mob.friction = new Vec3(15*32, 0, 15*32);
mob.size = new Vec3(0.75, 1.75, 0.75); mob.size = new Vec3(0.75, 1.75, 0.75);
mob.health = 20;
mob.metadata = metadata; mob.metadata = metadata;
mob.updateAndSpawn(); mob.updateAndSpawn();
}; };
serv.destroyEntity = entity => { serv.destroyEntity = entity => {
serv._writeNearby('entity_destroy', { entity._writeOthersNearby('entity_destroy', {
entityIds: [entity.id] entityIds: [entity.id]
}, {
position: entity.position,
world: entity.world
}); });
delete serv.entities[entity.id]; delete serv.entities[entity.id];
}; };
@ -76,6 +71,16 @@ module.exports.server=function(serv,options) {
if (entity.deathTime && Date.now() - entity.bornTime >= entity.deathTime) { if (entity.deathTime && Date.now() - entity.bornTime >= entity.deathTime) {
entity.destroy(); entity.destroy();
return; return;
} else if (entity.pickupTime && Date.now() - entity.bornTime >= entity.pickupTime) {
var players = serv.getNearby({
world: entity.world,
position: entity.position,
radius: 1.5*32 // Seems good for now
});
if (players.length) {
players[0].collect(entity);
entity.destroy();
}
} }
if (!entity.velocity || !entity.size) return; if (!entity.velocity || !entity.size) return;
var oldPosAndOnGround = await entity.calculatePhysics(delta); var oldPosAndOnGround = await entity.calculatePhysics(delta);
@ -99,7 +104,7 @@ module.exports.player=function(player,serv){
} }
}, },
action({id}) { action({id}) {
serv.spawnMob(id, player.world, player.entity.position.scaled(1/32), { serv.spawnMob(id, player.world, player.position.scaled(1/32), {
velocity: Vec3((Math.random() - 0.5) * 10, Math.random()*10 + 10, (Math.random() - 0.5) * 10) velocity: Vec3((Math.random() - 0.5) * 10, Math.random()*10 + 10, (Math.random() - 0.5) * 10)
}); });
} }
@ -117,7 +122,7 @@ module.exports.player=function(player,serv){
} }
}, },
action({id}) { action({id}) {
serv.spawnObject(id, player.world, player.entity.position.scaled(1/32), { serv.spawnObject(id, player.world, player.position.scaled(1/32), {
velocity: Vec3((Math.random() - 0.5) * 10, Math.random()*10 + 10, (Math.random() - 0.5) * 10) velocity: Vec3((Math.random() - 0.5) * 10, Math.random()*10 + 10, (Math.random() - 0.5) * 10)
}); });
} }
@ -133,7 +138,7 @@ module.exports.player=function(player,serv){
player.chat("No entity named "+name); player.chat("No entity named "+name);
return; return;
} }
serv.spawnMob(entity.id, player.world, player.entity.position.scaled(1/32), { serv.spawnMob(entity.id, player.world, player.position.scaled(1/32), {
velocity: Vec3((Math.random() - 0.5) * 10, Math.random()*10 + 10, (Math.random() - 0.5) * 10) velocity: Vec3((Math.random() - 0.5) * 10, Math.random()*10 + 10, (Math.random() - 0.5) * 10)
}); });
} }
@ -166,13 +171,18 @@ module.exports.entity=function(entity,serv){
entity.updateAndSpawn(); entity.updateAndSpawn();
}); });
entity.setMetadata = (data) => { entity.sendMetadata = (data) => {
serv._writeNearby('entity_metadata', { entity._writeOthersNearby('entity_metadata', {
entityId: entity.id, entityId: entity.id,
metadata: data metadata: data
}, entity); });
}; };
entity.setAndUpdateMetadata = (data) => {
entity.metadata = data;
entity.sendMetadata(data);
}
entity.destroy = () => { entity.destroy = () => {
serv.destroyEntity(entity); serv.destroyEntity(entity);
}; };
@ -182,7 +192,7 @@ module.exports.entity=function(entity,serv){
if (entity.type == 'player') { if (entity.type == 'player') {
return { return {
entityId: entity.id, entityId: entity.id,
playerUUID: entity.player._client.uuid, playerUUID: entity._client.uuid,
x: entity.position.x, x: entity.position.x,
y: entity.position.y, y: entity.position.y,
z: entity.position.z, z: entity.position.z,
@ -225,34 +235,61 @@ module.exports.entity=function(entity,serv){
} }
}; };
entity.getNearby = () => serv
.getNearbyEntities({
world: entity.world,
position: entity.position,
radius: entity.viewDistance*32
})
.filter((e) => e != entity);
entity.updateAndSpawn = () => { entity.updateAndSpawn = () => {
var updatedEntities=entity.getNearby(); var updatedEntities=entity.getNearby();
var entitiesToAdd=updatedEntities.filter(e => entity.nearbyEntities.indexOf(e)==-1); var entitiesToAdd=updatedEntities.filter(e => entity.nearbyEntities.indexOf(e)==-1);
var entitiesToRemove=entity.nearbyEntities.filter(e => updatedEntities.indexOf(e)==-1); var entitiesToRemove=entity.nearbyEntities.filter(e => updatedEntities.indexOf(e)==-1);
if (entity.type == 'player') { if (entity.type == 'player') {
entity.player.despawnEntities(entitiesToRemove); entity.despawnEntities(entitiesToRemove);
entitiesToAdd.forEach(entity.player.spawnEntity); entitiesToAdd.forEach(entity.spawnEntity);
entity.player.lastPositionPlayersUpdated=entity.position.clone();
} else {
entity.lastPositionPlayersUpdated=entity.position.clone();
} }
entity.lastPositionPlayersUpdated=entity.position.clone();
var playersToAdd = entitiesToAdd.filter(e => e.type == 'player').map(e => e.player); var playersToAdd = entitiesToAdd.filter(e => e.type == 'player');
var playersToRemove = entitiesToRemove.filter(e => e.type == 'player').map(e => e.player); var playersToRemove = entitiesToRemove.filter(e => e.type == 'player');
playersToRemove.forEach(p => p.despawnEntities([entity])); playersToRemove.forEach(p => p.despawnEntities([entity]));
playersToRemove.forEach(p => p.entity.nearbyEntities=p.entity.getNearby()); playersToRemove.forEach(p => p.nearbyEntities=p.getNearby());
playersToAdd.forEach(p => p.spawnEntity(entity)); playersToAdd.forEach(p => p.spawnEntity(entity));
playersToAdd.forEach(p => p.entity.nearbyEntities=p.entity.getNearby()); playersToAdd.forEach(p => p.nearbyEntities=p.getNearby());
entity.nearbyEntities=updatedEntities; entity.nearbyEntities=updatedEntities;
}; };
entity.collect = (collectEntity) => {
if (entity.type != 'player') serv.emit('error', 'Non-player entity (ttype ' + entity.type + ') cannot collect another entity');
else {
collectEntity._writeOthersNearby('collect', {
collectedEntityId: collectEntity.id,
collectorEntityId: entity.id
});
entity.playSoundAtSelf('random.pop');
}
}
entity.sendVelocity = (vel, maxVel) => {
var velocity = vel.scaled(32).floored(); // Make fixed point
var maxVelocity = maxVel.scaled(32).floored();
var scaledVelocity = velocity.scaled(8000/32/20).floored(); // from fixed-position/second to unit => 1/8000 blocks per tick
entity._writeOthersNearby('entity_velocity', {
entityId: entity.id,
velocityX: scaledVelocity.x,
velocityY: scaledVelocity.y,
velocityZ: scaledVelocity.z
});
if (entity.type != 'player') {
if (maxVelocity) entity.velocity = addVelocityWithMax(entity.velocity, velocity, maxVelocity);
else entity.velocity.add(velocity);
}
}
function addVelocityWithMax(current, newVel, max) {
var x, y, z;
if (current.x > max.x || current.x < -max.x) x = current.x;
else x = Math.max(-max.x, Math.min(max.x, current.x + newVel.x));
if (current.y > max.y || current.y < -max.y) y = current.y;
else y = Math.max(-max.y, Math.min(max.y, current.y + newVel.y));
if (current.z > max.z || current.z < -max.z) z = current.z;
else z = Math.max(-max.z, Math.min(max.z, current.z + newVel.z));
return new Vec3(x, y, z);
}
}; };

View file

@ -13,7 +13,7 @@ module.exports.player=function(player)
} }
player.heldItem = player.inventory[36+player.heldItemSlot]; player.heldItem = player.inventory[36+player.heldItemSlot];
player._writeOthersNearby("entity_equipment",{ player._writeOthersNearby("entity_equipment",{
entityId:player.entity.id, entityId:player.id,
slot:0, slot:0,
item:player.heldItem item:player.heldItem
}); });
@ -23,31 +23,31 @@ module.exports.player=function(player)
player.inventory[slot]=item; player.inventory[slot]=item;
if (slot==36) if (slot==36)
player._writeOthersNearby("entity_equipment",{ player._writeOthersNearby("entity_equipment",{
entityId:player.entity.id, entityId:player.id,
slot:0, slot:0,
item:item item:item
}); });
if (slot==5) if (slot==5)
player._writeOthersNearby("entity_equipment",{ player._writeOthersNearby("entity_equipment",{
entityId:player.entity.id, entityId:player.id,
slot:4, slot:4,
item:item item:item
}); });
if (slot==6) if (slot==6)
player._writeOthersNearby("entity_equipment",{ player._writeOthersNearby("entity_equipment",{
entityId:player.entity.id, entityId:player.id,
slot:3, slot:3,
item:item item:item
}); });
if (slot==7) if (slot==7)
player._writeOthersNearby("entity_equipment",{ player._writeOthersNearby("entity_equipment",{
entityId:player.entity.id, entityId:player.id,
slot:2, slot:2,
item:item item:item
}); });
if (slot==8) if (slot==8)
player._writeOthersNearby("entity_equipment",{ player._writeOthersNearby("entity_equipment",{
entityId:player.entity.id, entityId:player.id,
slot:1, slot:1,
item:item item:item
}); });

View file

@ -1,10 +1,9 @@
var Entity=require("prismarine-entity"); var Entity=require("prismarine-entity");
var Vec3 = require("vec3").Vec3 var Vec3 = require("vec3").Vec3;
var path = require('path'); var path = require('path');
var requireIndex = require('requireindex'); var requireIndex = require('requireindex');
var plugins = requireIndex(path.join(__dirname,'..', 'plugins')); var plugins = requireIndex(path.join(__dirname,'..', 'plugins'));
var Player=require("../player");
var Command = require('../command'); var Command = require('../command');
module.exports.server=function(serv,options) module.exports.server=function(serv,options)
@ -13,7 +12,7 @@ module.exports.server=function(serv,options)
client.on('error',error => serv.emit('clientError',client,error))); client.on('error',error => serv.emit('clientError',client,error)));
serv._server.on('login', async (client) => { serv._server.on('login', async (client) => {
var player=new Player(); var player = serv.initEntity('player', null, serv.overworld, new Vec3(0,0,0));
player._client=client; player._client=client;
player.commands = new Command({}); player.commands = new Command({});
Object.keys(plugins) Object.keys(plugins)
@ -34,14 +33,10 @@ module.exports.player=function(player,serv)
{ {
function addPlayer() function addPlayer()
{ {
player.entity=serv.initEntity('player', null, serv.overworld, new Vec3(0,0,0)); player.type = 'player';
player.entity.type = 'player'; player.health = 20;
player.entity.player=player; player.food = 20;
player.entity.health = 20; player.crouching = false; // Needs added in prismarine-entity later
player.entity.food = 20;
player.entity.crouching = false; // Needs added in prismarine-entity later
player.view=10;
player.world=serv.overworld;
player.username=player._client.username; player.username=player._client.username;
serv.players.push(player); serv.players.push(player);
serv.uuidToPlayer[player._client.uuid] = player; serv.uuidToPlayer[player._client.uuid] = player;
@ -51,8 +46,8 @@ module.exports.player=function(player,serv)
function sendPlayersWhenMove() function sendPlayersWhenMove()
{ {
player.on("positionChanged",() => { player.on("positionChanged",() => {
if(player.entity.position.distanceTo(player.lastPositionPlayersUpdated)>2*32) if(player.position.distanceTo(player.lastPositionPlayersUpdated)>2*32)
player.entity.updateAndSpawn(); player.updateAndSpawn();
}); });
} }
@ -60,7 +55,7 @@ module.exports.player=function(player,serv)
{ {
// send init data so client will start rendering world // send init data so client will start rendering world
player._client.write('login', { player._client.write('login', {
entityId: player.entity.id, entityId: player.id,
levelType: 'default', levelType: 'default',
gameMode: player.gameMode, gameMode: player.gameMode,
dimension: 0, dimension: 0,
@ -68,13 +63,13 @@ module.exports.player=function(player,serv)
reducedDebugInfo: false, reducedDebugInfo: false,
maxPlayers: serv._server.maxPlayers maxPlayers: serv._server.maxPlayers
}); });
player.entity.position=player.spawnPoint.toFixedPosition(); player.position=player.spawnPoint.toFixedPosition();
} }
function sendChunkWhenMove() function sendChunkWhenMove()
{ {
player.on("positionChanged", () => { player.on("positionChanged", () => {
if(!player.sendingChunks && player.entity.position.distanceTo(player.lastPositionChunkUpdated)>16*32) if(!player.sendingChunks && player.position.distanceTo(player.lastPositionChunkUpdated)>16*32)
player.sendRestMap(); player.sendRestMap();
}); });
} }
@ -150,7 +145,7 @@ module.exports.player=function(player,serv)
player.login = async () => player.login = async () =>
{ {
if (serv.uuidToPlayer[player._client.uuid]) { if (serv.uuidToPlayer[player._client.uuid]) {
player._client.end("You are already connected"); player._client.end("You are already connected");
return; return;
@ -165,12 +160,12 @@ module.exports.player=function(player,serv)
await player.sendMap(); await player.sendMap();
player.sendSpawnPosition(); player.sendSpawnPosition();
player.sendPosition(); player.sendPosition();
player.updateHealth(player.entity.health); player.updateHealth(player.health);
updateTime(); updateTime();
fillTabList(); fillTabList();
player.entity.updateAndSpawn(); player.updateAndSpawn();
announceJoin(); announceJoin();
player.emit("spawned"); player.emit("spawned");

View file

@ -2,7 +2,7 @@ module.exports.player=function(player,serv)
{ {
player.despawnPlayers = despawnedPlayers => { player.despawnPlayers = despawnedPlayers => {
player._client.write('entity_destroy', { player._client.write('entity_destroy', {
'entityIds': despawnedPlayers.map(p => p.entity.id) 'entityIds': despawnedPlayers.map(p => p.id)
}); });
}; };
@ -11,7 +11,7 @@ module.exports.player=function(player,serv)
}); });
player._client.on('end', () => { player._client.on('end', () => {
if(player.entity) { if(player) {
serv.broadcast(player.username + ' quit the game.', "yellow"); serv.broadcast(player.username + ' quit the game.', "yellow");
player._writeOthers('player_info', { player._writeOthers('player_info', {
action: 4, action: 4,
@ -20,7 +20,7 @@ module.exports.player=function(player,serv)
}] }]
}); });
player.nearbyPlayers().forEach(otherPlayer => otherPlayer.despawnPlayers([player])); player.nearbyPlayers().forEach(otherPlayer => otherPlayer.despawnPlayers([player]));
delete serv.entities[player.entity.id]; delete serv.entities[player.id];
player.emit('disconnected'); player.emit('disconnected');
var index = serv.players.indexOf(player); var index = serv.players.indexOf(player);
if (index > -1) { if (index > -1) {

View file

@ -1,4 +1,4 @@
var Vec3 = require("vec3").Vec3 var Vec3 = require("vec3").Vec3;
var dir = require("node-dir"); var dir = require("node-dir");
var fs = require("fs"); var fs = require("fs");
@ -61,15 +61,15 @@ function modpeApi() {
} }
function getPlayerX() { function getPlayerX() {
return player.entity.position.x/32; return player.position.x/32;
} }
function getPlayerY() { function getPlayerY() {
return player.entity.position.y/32; return player.position.y/32;
} }
function getPlayerZ() { function getPlayerZ() {
return player.entity.position.z/32; return player.position.z/32;
} }
function getPlayerEnt() { function getPlayerEnt() {

View file

@ -1,29 +1,27 @@
var Vec3 = require("vec3").Vec3 var Vec3 = require("vec3").Vec3;
module.exports.server=function(serv) { module.exports.server=function(serv) {
serv.emitParticle = (particle, world, position, {whitelist,blacklist=[],radius=32*32,longDistance,size,count}={}) => { serv.emitParticle = (particle, world, position, {whitelist,blacklist=[],radius=32*32,longDistance=true,size,count=1}={}) => {
var players = (typeof whitelist != 'undefined' ? (typeof whitelist == 'array' ? whitelist : [whitelist]) : serv.getNearby({ var players = (typeof whitelist != 'undefined' ? (typeof whitelist == 'array' ? whitelist : [whitelist]) : serv.getNearby({
world: world, world: world,
position: position.scaled(32).floored(), position: position.scaled(32).floored(),
radius: radius // 32 blocks, fixed position radius: radius // 32 blocks, fixed position
})); }));
if (!size) size = new Vec3(1.0, 1.0, 1.0); if (!size) size = new Vec3(1.0, 1.0, 1.0);
players.filter(player => blacklist.indexOf(player) == -1)
.forEach(player => { serv._writeArray('world_particles', {
player._client.write('world_particles', { particleId: particle,
particleId: particle, longDistance: longDistance,
longDistance: longDistance || true, x: position.x,
x: position.x, y: position.y,
y: position.y, z: position.z,
z: position.z, offsetX: size.x,
offsetX: size.x, offsetY: size.y,
offsetY: size.y, offsetZ: size.z,
offsetZ: size.z, particleData: 1.0,
particleData: 1.0, particles: count,
particles: count || 1, data: []
data: [] }, players.filter(p => blacklist.indexOf(p) == -1));
});
});
} }
}; };
@ -47,7 +45,7 @@ module.exports.player=function(player,serv){
return; return;
} }
player.chat('Emitting "' + particle + '" (count: ' + amount + ', size: ' + size.toString() + ')'); player.chat('Emitting "' + particle + '" (count: ' + amount + ', size: ' + size.toString() + ')');
serv.emitParticle(particle, player.world, player.entity.position.scaled(1/32), {count: amount,size: size}); serv.emitParticle(particle, player.world, player.position.scaled(1/32), {count: amount,size: size});
} }
}); });
}; };

View file

@ -1,5 +1,5 @@
var blocks=require("minecraft-data")(require("../version")).blocks; var blocks=require("minecraft-data")(require("../version")).blocks;
var Vec3 = require("vec3").Vec3 var Vec3 = require("vec3").Vec3;
module.exports.entity=function(entity){ module.exports.entity=function(entity){
entity.calculatePhysics = async (delta) => { entity.calculatePhysics = async (delta) => {

View file

@ -1,31 +1,36 @@
var Vec3 = require("vec3").Vec3;
module.exports.player=function(player,serv) module.exports.player=function(player,serv)
{ {
player.updateHealth = (health) => { player.updateHealth = (health) => {
player.entity.health = health; player.health = health;
player._client.write('update_health', { player._client.write('update_health', {
food: player.entity.food, food: player.food,
foodSaturation: 0.0, foodSaturation: 0.0,
health: player.entity.health health: player.health
}); });
}; };
function attackEntity(entityId) function attackEntity(entityId)
{ {
if (!serv.entities[entityId]) return; // ????? var attackedEntity = serv.entities[entityId];
var attackedPlayer = serv.entities[entityId].player; if(!attackedEntity || (attackedEntity.gameMode != 0 && attackedEntity.type == 'player')) return;
if(!attackedPlayer || attackedPlayer.gameMode!=0) return;
attackedPlayer.updateHealth(attackedPlayer.entity.health - 1);
serv.playSound('game.player.hurt', player.world, attackedPlayer.entity.position.scaled(1/32));
if(attackedPlayer.entity.health==0) attackedEntity.updateHealth(attackedEntity.health - 1);
attackedPlayer._writeOthers('entity_status',{ serv.playSound('game.player.hurt', player.world, attackedEntity.position.scaled(1/32));
entityId:attackedPlayer.entity.id,
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));
if(attackedEntity.health<=0)
attackedEntity._writeOthers('entity_status',{
entityId:attackedEntity.id,
entityStatus:3 entityStatus:3
}); });
else else
attackedPlayer._writeOthers('animation',{ attackedEntity._writeOthers('animation',{
entityId:attackedPlayer.entity.id, entityId:attackedEntity.id,
animation:1 animation:1
}); });
} }
@ -35,4 +40,13 @@ module.exports.player=function(player,serv)
attackEntity(target); attackEntity(target);
}); });
}; };
module.exports.entity=function(entity,serv)
{
if (entity.type != 'player') {
entity.updateHealth = (health) => {
entity.health = health;
}
}
}

View file

@ -10,8 +10,8 @@ module.exports.player=function(player)
}); });
player.sendPosition(); player.sendPosition();
player.updateHealth(20); player.updateHealth(20);
player.entity.nearbyEntities=[]; player.nearbyEntities=[];
player.entity.updateAndSpawn(); player.updateAndSpawn();
} }
}); });
}; };

View file

@ -9,7 +9,7 @@ module.exports.server=function(serv) {
})); }));
players.filter(player => blacklist.indexOf(player) == -1) players.filter(player => blacklist.indexOf(player) == -1)
.forEach(player => { .forEach(player => {
var pos = (position || player.entity.position.scaled(1/32)).scaled(8).floored(); var pos = (position || player.position.scaled(1/32)).scaled(8).floored();
player._client.write('named_sound_effect', { player._client.write('named_sound_effect', {
soundName: sound, soundName: sound,
x: pos.x, x: pos.x,
@ -39,7 +39,7 @@ module.exports.player=function(player,serv) {
}; };
player._client.on('block_place', ({location}={}) => { player._client.on('block_place', ({location}={}) => {
if (player.entity.crouching) return; if (player.crouching) return;
var pos=new Vec3(location.x,location.y,location.z); var pos=new Vec3(location.x,location.y,location.z);
player.world.getBlockType(pos).then((id) => { player.world.getBlockType(pos).then((id) => {
if (id != 25) return; if (id != 25) return;
@ -99,7 +99,13 @@ module.exports.player=function(player,serv) {
}, },
action({sound_name,volume,pitch}) { action({sound_name,volume,pitch}) {
player.chat('Playing "'+sound_name+'" (volume: ' + volume + ', pitch: ' + pitch + ')'); player.chat('Playing "'+sound_name+'" (volume: ' + volume + ', pitch: ' + pitch + ')');
serv.playSound(sound_name, player.world, player.entity.position.scaled(1/32), {volume: volume,pitch: pitch}); serv.playSound(sound_name, player.world, player.position.scaled(1/32), {volume: volume,pitch: pitch});
} }
}); });
};
module.exports.entity=function(entity,serv) {
entity.playSoundAtSelf = (sound, opt={}) => {
serv.playSound(sound, entity.world, entity.position.scaled(1/32), opt);
}
}; };

View file

@ -1,4 +1,4 @@
var Vec3 = require("vec3").Vec3 var Vec3 = require("vec3").Vec3;
Vec3.prototype.toFixedPosition=function() { Vec3.prototype.toFixedPosition=function() {
return this.scaled(32).floored(); return this.scaled(32).floored();
@ -19,18 +19,18 @@ module.exports.player=function(player)
{ {
var convYaw=conv(yaw); var convYaw=conv(yaw);
var convPitch=conv(pitch); var convPitch=conv(pitch);
if (convYaw == player.entity.yaw && convPitch == player.entity.pitch) return; if (convYaw == player.yaw && convPitch == player.pitch) return;
player._writeOthersNearby("entity_look", { player._writeOthersNearby("entity_look", {
entityId: player.entity.id, entityId: player.id,
yaw: convYaw, yaw: convYaw,
pitch: convPitch, pitch: convPitch,
onGround: onGround onGround: onGround
}); });
player.entity.yaw = convYaw; player.yaw = convYaw;
player.entity.pitch = convPitch; player.pitch = convPitch;
player.entity.onGround = onGround; player.onGround = onGround;
player._writeOthersNearby("entity_head_rotation", { player._writeOthersNearby("entity_head_rotation", {
entityId: player.entity.id, entityId: player.id,
headYaw: convYaw headYaw: convYaw
}); });
} }
@ -44,23 +44,23 @@ module.exports.player=function(player)
}); });
function sendRelativePositionChange(newPosition, onGround) { function sendRelativePositionChange(newPosition, onGround) {
if (player.entity.position.distanceTo(new Vec3(0, 0, 0)) != 0) { if (player.position.distanceTo(new Vec3(0, 0, 0)) != 0) {
var diff = newPosition.minus(player.entity.position); var diff = newPosition.minus(player.position);
if(diff.abs().x>127 || diff.abs().y>127 || diff.abs().z>127) if(diff.abs().x>127 || diff.abs().y>127 || diff.abs().z>127)
{ {
player._writeOthersNearby('entity_teleport', { player._writeOthersNearby('entity_teleport', {
entityId:player.entity.id, entityId:player.id,
x: newPosition.x, x: newPosition.x,
y: newPosition.y, y: newPosition.y,
z: newPosition.z, z: newPosition.z,
yaw: player.entity.yaw, yaw: player.yaw,
pitch: player.entity.pitch, pitch: player.pitch,
onGround: onGround onGround: onGround
}); });
} }
else if (diff.distanceTo(new Vec3(0, 0, 0)) != 0) { else if (diff.distanceTo(new Vec3(0, 0, 0)) != 0) {
player._writeOthersNearby('rel_entity_move', { player._writeOthersNearby('rel_entity_move', {
entityId: player.entity.id, entityId: player.id,
dX: diff.x, dX: diff.x,
dY: diff.y, dY: diff.y,
dZ: diff.z, dZ: diff.z,
@ -68,18 +68,18 @@ module.exports.player=function(player)
}); });
} }
} }
player.entity.position = newPosition; player.position = newPosition;
player.entity.onGround = onGround; player.onGround = onGround;
player.emit("positionChanged"); player.emit("positionChanged");
} }
player.sendPosition = () => { player.sendPosition = () => {
player._client.write('position', { player._client.write('position', {
x: player.entity.position.x/32, x: player.position.x/32,
y: player.entity.position.y/32, y: player.position.y/32,
z: player.entity.position.z/32, z: player.position.z/32,
yaw: player.entity.yaw, yaw: player.yaw,
pitch: player.entity.pitch, pitch: player.pitch,
flags: 0x00 flags: 0x00
}); });
}; };
@ -90,7 +90,7 @@ module.exports.entity=function(entity,serv){
var diff = entity.position.minus(oldPos); var diff = entity.position.minus(oldPos);
if(diff.abs().x>127 || diff.abs().y>127 || diff.abs().z>127) if(diff.abs().x>127 || diff.abs().y>127 || diff.abs().z>127)
serv._writeNearby('entity_teleport', { entity._writeOthersNearby('entity_teleport', {
entityId: entity.id, entityId: entity.id,
x: entity.position.x, x: entity.position.x,
y: entity.position.y, y: entity.position.y,
@ -98,7 +98,7 @@ module.exports.entity=function(entity,serv){
yaw: entity.yaw, yaw: entity.yaw,
pitch: entity.pitch, pitch: entity.pitch,
onGround: onGround onGround: onGround
}, entity); });
else if (diff.distanceTo(new Vec3(0, 0, 0)) != 0) serv._writeNearby('rel_entity_move', { else if (diff.distanceTo(new Vec3(0, 0, 0)) != 0) serv._writeNearby('rel_entity_move', {
entityId: entity.id, entityId: entity.id,
dX: diff.x, dX: diff.x,

View file

@ -1,4 +1,4 @@
var Vec3 = require("vec3").Vec3 var Vec3 = require("vec3").Vec3;
var spiralloop = require('spiralloop'); var spiralloop = require('spiralloop');
var Chunk = require('prismarine-chunk')(require("../version")); var Chunk = require('prismarine-chunk')(require("../version"));
@ -56,7 +56,7 @@ module.exports.player=function(player,serv) {
player.spawnEntity = entity => { player.spawnEntity = entity => {
player._client.write(entity.spawnPacketName, entity.getSpawnPacket()); player._client.write(entity.spawnPacketName, entity.getSpawnPacket());
if (typeof entity.itemId != 'undefined') { if (typeof entity.itemId != 'undefined') {
entity.setMetadata([{ entity.sendMetadata([{
"key": 10, "key": 10,
"type": 5, "type": 5,
"value": { "value": {
@ -91,9 +91,9 @@ module.exports.player=function(player,serv) {
player.sendNearbyChunks = (view,group) => player.sendNearbyChunks = (view,group) =>
{ {
player.lastPositionChunkUpdated=player.entity.position; player.lastPositionChunkUpdated=player.position;
var playerChunkX=Math.floor(player.entity.position.x/16/32); var playerChunkX=Math.floor(player.position.x/16/32);
var playerChunkZ=Math.floor(player.entity.position.z/16/32); var playerChunkZ=Math.floor(player.position.z/16/32);
return spiral([view*2,view*2]) return spiral([view*2,view*2])
.map(t => ({ .map(t => ({
@ -145,7 +145,7 @@ module.exports.player=function(player,serv) {
if(player.world == world) return Promise.resolve(); if(player.world == world) return Promise.resolve();
opt = opt || {}; opt = opt || {};
player.world = world; player.world = world;
player.entity.world = world; player.world = world;
player.loadedChunks={}; player.loadedChunks={};
if (typeof opt.gamemode != 'undefined') player.gameMode = opt.gamemode; if (typeof opt.gamemode != 'undefined') player.gameMode = opt.gamemode;
player._client.write("respawn",{ player._client.write("respawn",{
@ -154,9 +154,9 @@ module.exports.player=function(player,serv) {
gamemode: opt.gamemode || player.gameMode, gamemode: opt.gamemode || player.gameMode,
levelType:'default' levelType:'default'
}); });
player.entity.position=player.spawnPoint.toFixedPosition(); player.position=player.spawnPoint.toFixedPosition();
player.sendSpawnPosition(); player.sendSpawnPosition();
player.entity.updateAndSpawn(); player.updateAndSpawn();
await player.sendMap(); await player.sendMap();