improve code with webstorm suggestion + split entities.js into spawn.js and other files

This commit is contained in:
Romain Beaumont 2015-11-28 18:23:26 +01:00
parent a4c208ec5e
commit b5d22e57f9
30 changed files with 361 additions and 360 deletions

View file

@ -83,6 +83,6 @@ You can add server plugins and player plugins in your package, following [CONTRI
- [@roblabla](https://github.com/roblabla) for helping out with the protocols
- [@rom1504](https://github.com/rom1504) for massive contributions to the code
- [@demipixel](https://github.com/demipixel)
- The PrismarineJS team for creating prismarine-chunk and node-minecraft-protcol
- The PrismarineJS team for creating prismarine-chunk and node-minecraft-protocol
- [wiki.vg](http://wiki.vg/Protocol) for documenting minecraft protocols
- All of our other awesome contributors!

View file

@ -511,10 +511,10 @@ player.on('move_cancel', ({position}, cancel) => {
});
```
If we keep Plugin B and replace Plugin A with Plugin C, we'll see that the player can move freely but will not recieve the
If we keep Plugin B and replace Plugin A with Plugin C, we'll see that the player can move freely but will not receive the
word "HI" and other players will be unable to see their movements.
Finally, there is hidden cancel. This is the second paramater in cancel, and allows plugins to hide the fact that they cancelled
Finally, there is hidden cancel. This is the second parameter in cancel, and allows plugins to hide the fact that they cancelled
the default action from other plugins. It's best not to use this, but I know somebody will someday need this.
Plugin D
@ -529,9 +529,9 @@ their position and other players will not see the player move.
#### FORMAT
Defition of behavior.
Definition of behavior.
- var1: Variable with value, can be changed (default: defaultValue)
- var2 (u): Variable with value. You can change it however it will not have any effect on the defautl action (and could screw with other plugins, watch out!). U stands for unused
- var2 (u): Variable with value. You can change it however it will not have any effect on the default action (and could screw with other plugins, watch out!). U stands for unused
Default: What happens if this isn't cancelled.
@ -819,7 +819,7 @@ sends `message` to the player
change the block at position `position` to `blockType` and `blockData`
this will not change the block for the user themself. It is mainly useful when a user places a block
this will not change the block for the user himself. It is mainly useful when a user places a block
and only needs to send it to other players on the server
#### player.sendBlock(position,blockType,blockData)

View file

@ -11,7 +11,7 @@ module.exports = (obj) => {
cancelCount++;
}
defaultCancel = dC;
}
};
await obj.emitThen(eventName + '_cancel', data, cancel).catch((err)=> setTimeout(() => {throw err;},0));
await obj.emitThen(eventName, data, cancelled, cancelCount).catch((err)=> setTimeout(() => {throw err;},0));
@ -22,4 +22,4 @@ module.exports = (obj) => {
await obj.emitThen(eventName + '_done', data, cancelled).catch((err)=> setTimeout(() => {throw err;},0));
return data;
}
}
};

View file

@ -15,9 +15,9 @@ class Command {
var ended = space + '(.*)';
var finded = command.match(new RegExp('^' + key + ended));
if(finded) {
res = [this.hash[key], finded];
var found = command.match(new RegExp('^' + key + ended));
if(found) {
res = [this.hash[key], found];
}
}

View file

@ -2,8 +2,8 @@ var Behavior = require('../behavior');
module.exports.server = function(serv) {
serv.behavior = new Behavior(serv);
}
};
module.exports.entity = function(entity, serv) {
module.exports.entity = function (entity) {
entity.behavior = new Behavior(entity);
}
};

View file

@ -15,9 +15,9 @@ module.exports.player=function(player,serv)
player.sendBlock = (position, blockType, blockData) => // Call from player.setBlock unless you want "local" fake blocks
player.behavior('sendBlock', {
position: position,
id: blockType,
data: blockData
}, ({position, id, damage}) => {
blockType: blockType,
blockData: blockData
}, ({position, blockType, blockData}) => {
player._client.write("block_change",{
location:position,
type:blockType<<4 | blockData
@ -38,7 +38,7 @@ module.exports.player=function(player,serv)
return results;
},
action(params) {
var res = params.map((num, i) => { // parseInt paramaters
var res = params.map((num, i) => { // parseInt parameters
if (num.indexOf('~') == 0) {
return (player.position[['', 'x', 'y', 'z'][i]] >> 5) + parseInt(num.slice(1) || 0);
} else {

View file

@ -17,7 +17,7 @@ module.exports.player=function(player,serv)
player.behavior('chat', {
message: message,
broadcastMessage: '<' + player.username + '>' + ' ' + message
}, ({message, broadcast, broadcastMessage}) => {
}, ({broadcastMessage}) => {
serv.broadcast(broadcastMessage);
});
}

View file

@ -25,4 +25,4 @@ module.exports.player=function(player)
}
});
}
};

View file

@ -76,7 +76,7 @@ module.exports.player=function(player) {
player.handleCommand = async (str) => {
try {
var res = await player.commands.use(str)
var res = await player.commands.use(str);
if (res) player.chat('' + res);
}
catch(err) {

View file

@ -41,11 +41,11 @@ module.exports.entity=function(entity,serv)
.filter((e) => e.type == 'player');
entity.nearbyPlayers = (radius=entity.viewDistance*32) => entity.nearbyEntities
.filter(e => e.type == 'player')
.filter(e => e.type == 'player');
entity._writeOthers = (packetName, packetFields) =>
serv._writeArray(packetName, packetFields, entity.getOtherPlayers());
entity._writeOthersNearby = (packetName, packetFields) =>
serv._writeArray(packetName, packetFields, entity.getNearbyPlayers());
}
};

View file

@ -18,7 +18,7 @@ module.exports.server=function(serv) {
old: serv.time,
newTime: serv.time + 20
}, ({newTime}) => {
serv.setTime((serv.time + 20) % 24000); // Vanilla only does it every second
serv.setTime(newTime % 24000); // Vanilla only does it every second
});
}
})
@ -29,7 +29,7 @@ module.exports.player=function(player,serv){
base: 'night',
info: 'to change a time to night',
usage: '/night',
action(params) {
action() {
return player.handleCommand('time set night');
}
});
@ -68,7 +68,7 @@ module.exports.player=function(player,serv){
base: 'day',
info: 'to change a time to day',
usage: '/day',
action(params) {
action() {
return player.handleCommand('time set day');
}
});

View file

@ -35,7 +35,7 @@ module.exports.player=function(player,serv)
.catch((err)=> setTimeout(() => {throw err;},0))
});
function diggingTime(location)
function diggingTime()
{
// assume holding nothing and usual conditions
return currentlyDugBlock.digTime();
@ -69,7 +69,7 @@ module.exports.player=function(player,serv)
start: startDigging,
timePassed: currentDiggingTime,
position: location
}, ({lastState, state}) => {
}, ({state}) => {
lastDestroyState=state;
player._writeOthersNearby("block_break_animation",{
"entityId":currentAnimationId,
@ -97,7 +97,6 @@ module.exports.player=function(player,serv)
var diggingTime=new Date()-startDiggingTime;
var stop = false;
if(expectedDiggingTime-diggingTime<100) {
stop = true;
stop = player.behavior('forceCancelDig', {
stop: true,
start: startDiggingTime,

View file

@ -1,71 +1,6 @@
var Entity = require("../entity");
var Version = require("../version")
var Vec3 = require("vec3").Vec3;
var ItemStack = require("prismarine-item")(Version)
var entitiesByName=require("minecraft-data")(Version).entitiesByName;
var path = require('path');
var requireIndex = require('requireindex');
var plugins = requireIndex(path.join(__dirname,'..', 'plugins'));
module.exports.server=function(serv,options) {
serv.initEntity = (type, entityType, world, position) => {
serv.entityMaxId++;
var entity = new Entity(serv.entityMaxId);
Object.keys(plugins)
.filter(pluginName => plugins[pluginName].entity!=undefined)
.forEach(pluginName => plugins[pluginName].entity(entity, serv, options));
entity.initEntity(type, entityType, world, position);
serv.emit("newEntity",entity);
return entity;
};
serv.spawnObject = (type, world, position, {pitch=0,yaw=0,velocity=new Vec3(0,0,0),data=1,itemId,itemDamage=0,pickupTime=undefined,deathTime=undefined}) => {
var object = serv.initEntity('object', type, world, position.scaled(32).floored());
object.data = data;
object.velocity = velocity.scaled(32).floored();
object.pitch = pitch;
object.yaw = yaw;
object.gravity = new Vec3(0, -20*32, 0);
object.terminalvelocity = new Vec3(27*32, 27*32, 27*32);
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.deathTime = deathTime;
object.pickupTime = pickupTime;
object.itemId = itemId;
object.itemDamage = itemDamage;
object.updateAndSpawn();
};
serv.spawnMob = (type, world, position, {pitch=0,yaw=0,headPitch=0,velocity=new Vec3(0,0,0),metadata=[]}={}) => {
var mob = serv.initEntity('mob', type, world, position.scaled(32).floored());
mob.velocity = velocity.scaled(32).floored();
mob.pitch = pitch;
mob.headPitch = headPitch;
mob.yaw = yaw;
mob.gravity = new Vec3(0, -20*32, 0);
mob.terminalvelocity = new Vec3(27*32, 27*32, 27*32);
mob.friction = new Vec3(15*32, 0, 15*32);
mob.size = new Vec3(0.75, 1.75, 0.75);
mob.health = 20;
mob.metadata = metadata;
mob.updateAndSpawn();
};
serv.destroyEntity = entity => {
entity._writeOthersNearby('entity_destroy', {
entityIds: [entity.id]
});
delete serv.entities[entity.id];
};
serv.on('tick', function(delta) {
Promise.all(
Object.keys(serv.entities).map(async (id) => {
@ -92,86 +27,7 @@ module.exports.server=function(serv,options) {
});
};
module.exports.player=function(player,serv){
player.commands.add({
base: 'spawn',
info: 'Spawn a mob',
usage: '/spawn <entity_id>',
parse(str) {
var results=str.match(/(\d+)/);
if (!results) return false;
return {
id: parseInt(results[1])
}
},
action({id}) {
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)
});
}
});
player.commands.add({
base: 'spawnObject',
info: 'Spawn an object',
usage: '/spawnObject <entity_id>',
parse(str) {
var results=str.match(/(\d+)/);
if (!results) return false;
return {
id: parseInt(results[1])
}
},
action({id}) {
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)
});
}
});
player.commands.add({
base: 'summon',
info: 'Summon an entity',
usage: '/summon <entity_name>',
action(name) {
var entity=entitiesByName[name];
if(!entity) {
player.chat("No entity named "+name);
return;
}
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)
});
}
});
};
module.exports.entity=function(entity,serv){
entity.initEntity=(type, entityType, world, position)=>{
entity.type = type;
entity.spawnPacketName = '';
entity.entityType = entityType;
entity.world = world;
entity.position = position;
entity.lastPositionPlayersUpdated = entity.position.clone();
entity.nearbyEntities = [];
entity.viewDistance = 150;
entity.bornTime = Date.now();
serv.entities[entity.id] = entity;
if (entity.type == 'player') entity.spawnPacketName = 'named_entity_spawn';
else if (entity.type == 'object') entity.spawnPacketName = 'spawn_entity';
else if (entity.type == 'mob') entity.spawnPacketName = 'spawn_entity_living';
};
entity.on("move",() => {
if(entity.position.distanceTo(entity.lastPositionPlayersUpdated)>2*32)
entity.updateAndSpawn();
});
module.exports.entity=function(entity){
entity.sendMetadata = (data) => {
entity._writeOthersNearby('entity_metadata', {
entityId: entity.id,
@ -182,142 +38,5 @@ module.exports.entity=function(entity,serv){
entity.setAndUpdateMetadata = (data) => {
entity.metadata = data;
entity.sendMetadata(data);
}
entity.destroy = () => {
serv.destroyEntity(entity);
};
entity.getSpawnPacket = () => {
var scaledVelocity = entity.velocity.scaled(8000/32/20).floored(); // from fixed-position/second to unit => 1/8000 blocks per tick
if (entity.type == 'player') {
return {
entityId: entity.id,
playerUUID: entity._client.uuid,
x: entity.position.x,
y: entity.position.y,
z: entity.position.z,
yaw: entity.yaw,
pitch: entity.pitch,
currentItem: 0,
metadata: entity.metadata
}
} else if (entity.type == 'object') {
return {
entityId: entity.id,
type: entity.entityType,
x: entity.position.x,
y: entity.position.y,
z: entity.position.z,
pitch: entity.pitch,
yaw: entity.yaw,
objectData: {
intField: entity.data,
velocityX: scaledVelocity.x,
velocityY: scaledVelocity.y,
velocityZ: scaledVelocity.z
}
}
} else if (entity.type == 'mob') {
return {
entityId: entity.id,
type: entity.entityType,
x: entity.position.x,
y: entity.position.y,
z: entity.position.z,
yaw: entity.yaw,
pitch: entity.pitch,
headPitch: entity.headPitch,
velocityX: scaledVelocity.x,
velocityY: scaledVelocity.y,
velocityZ: scaledVelocity.z,
metadata: entity.metadata
}
}
};
entity.updateAndSpawn = () => {
var updatedEntities=entity.getNearby();
var entitiesToAdd=updatedEntities.filter(e => entity.nearbyEntities.indexOf(e)==-1);
var entitiesToRemove=entity.nearbyEntities.filter(e => updatedEntities.indexOf(e)==-1);
if (entity.type == 'player') {
entity.despawnEntities(entitiesToRemove);
entitiesToAdd.forEach(entity.spawnEntity);
}
entity.lastPositionPlayersUpdated=entity.position.clone();
var playersToAdd = entitiesToAdd.filter(e => e.type == 'player');
var playersToRemove = entitiesToRemove.filter(e => e.type == 'player');
playersToRemove.forEach(p => p.despawnEntities([entity]));
playersToRemove.forEach(p => p.nearbyEntities=p.getNearby());
playersToAdd.forEach(p => p.spawnEntity(entity));
playersToAdd.forEach(p => p.nearbyEntities=p.getNearby());
entity.nearbyEntities=updatedEntities;
};
entity.collect = (collectEntity) => {
if (entity.type != 'player'){
serv.emit('error',new Error('[ERROR] Non-player entity (type ' + entity.type + ') cannot collect another entity'));
return;
}
// Add it to a stack already in the player's inventory if possible
for(var itemKey in entity.inventory.slots){
var item = entity.inventory.slots[itemKey]
if(item == undefined) continue;
if(item.type == collectEntity.itemId){
item.count += 1
entity.inventory.updateSlot(itemKey, item)
collectEntity._writeOthersNearby('collect', {
collectedEntityId: collectEntity.id,
collectorEntityId: entity.id
});
entity.playSoundAtSelf('random.pop');
collectEntity.destroy()
return;
}
}
// If we couldn't add it to a already existing stack, put it in a new stack if the inventory has room
var emptySlot = entity.inventory.firstEmptyInventorySlot()
if(emptySlot != null){
collectEntity._writeOthersNearby('collect', {
collectedEntityId: collectEntity.id,
collectorEntityId: entity.id
});
entity.playSoundAtSelf('random.pop');
var newItem = new ItemStack(collectEntity.itemId, 1, collectEntity.damage)
entity.inventory.updateSlot(emptySlot, newItem)
collectEntity.destroy()
}
}
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

@ -18,10 +18,10 @@ module.exports.server = function(serv, settings) {
};
serv.pluginCount++;
if (serv.externalPluginsLoaded && plugin.server) serv.plugins[name].server.call(p, serv, settings);
}
};
for (var p in settings.plugins) {
if (settings.plugins[p].disabled) continue;
Object.keys(settings.plugins).forEach((p) =>{
if (settings.plugins[p].disabled) return;
try {
require.resolve(p); // Check if it exists, if not do catch, otherwise jump to bottom
} catch (err) {
@ -34,11 +34,11 @@ module.exports.server = function(serv, settings) {
return;
}
serv.addPlugin(p, require(p), settings.plugins[p]);
}
});
for (var p in serv.plugins) {
Object.keys(serv.plugins).forEach((p) =>{
if (serv.plugins[p].server) serv.plugins[p].server.call(serv.plugins[p], serv, settings);
}
});
serv.externalPluginsLoaded = true;
};
@ -59,10 +59,10 @@ module.exports.entity = function(entity, serv) {
entity.getData = (pluginName) => {
if (typeof pluginName == 'object') pluginName = pluginName.name;
return entity.pluginData[pluginName] || null;
}
};
Object.keys(serv.plugins).forEach(p => {
var plugin = serv.plugins[p];
if (plugin.entity) plugin.entity.call(plugin, entity, serv);
});
}
};

View file

@ -1,16 +1,16 @@
var Version = require("../version")
var Windows = require("prismarine-windows")(Version).windows
var ItemStack = require("prismarine-item")(Version)
var Version = require("../version");
var Windows = require("prismarine-windows")(Version).windows;
var ItemStack = require("prismarine-item")(Version);
module.exports.player = function(player)
module.exports.player = function(player,serv)
{
player.heldItemSlot = 0
player.heldItem = new ItemStack(256, 1)
player.inventory = new Windows.InventoryWindow(0, "Inventory", 44)
player.heldItemSlot = 0;
player.heldItem = new ItemStack(256, 1);
player.inventory = new Windows.InventoryWindow(0, "Inventory", 44);
player._client.on("held_item_slot", ({slotId} = {}) => {
player.heldItemSlot = slotId;
player.heldItem = player.inventory.slots[36 + player.heldItemSlot]
player.heldItem = player.inventory.slots[36 + player.heldItemSlot];
player._writeOthersNearby("entity_equipment",{
entityId: player.id,
@ -51,7 +51,7 @@ module.exports.player = function(player)
// (Nothing to do with held_item_slot)
// DANGER! crashes because windows.js hasn't implemented it yet.
return;
break
break;
case 3:
// Middle click
@ -131,16 +131,16 @@ module.exports.player = function(player)
catch(err) {
serv.emit('error',err);
}
})
});
player._client.on("set_creative_slot", ({slot,item} ={}) => {
if(item.blockId == -1){
player.inventory.updateSlot(slot, undefined)
player.inventory.updateSlot(slot, undefined);
return;
}
var newItem = ItemStack.fromNotch(item);
player.inventory.updateSlot(slot, newItem)
player.inventory.updateSlot(slot, newItem);
if (slot==5)
player._writeOthersNearby("entity_equipment",{
@ -170,7 +170,6 @@ module.exports.player = function(player)
});
player.inventory.on("windowUpdate", function(){
var items = player.inventory.slots
// Update held item
player._writeOthersNearby("entity_equipment",{
@ -180,13 +179,49 @@ module.exports.player = function(player)
});
// Update slots in inventory
for(var itemIndex in items){
var item = items[itemIndex]
for(var itemIndex=0;itemIndex<player.inventory.slots.length;itemIndex++) {
var item = player.inventory.slots[itemIndex];
player._client.write("set_slot", {
windowId: 0,
slot: itemIndex,
item: ItemStack.toNotch(item)
})
}
})
});
player.collect = (collectEntity) => {
// Add it to a stack already in the player's inventory if possible
for(var itemKey=0;itemKey<player.inventory.slots.length;itemKey++) {
var item = player.inventory.slots[itemKey];
if(item == undefined) continue;
if(item.type == collectEntity.itemId){
item.count += 1;
player.inventory.updateSlot(itemKey, item);
collectEntity._writeOthersNearby('collect', {
collectedEntityId: collectEntity.id,
collectorEntityId: player.id
});
player.playSoundAtSelf('random.pop');
collectEntity.destroy();
return;
}
}
// If we couldn't add it to a already existing stack, put it in a new stack if the inventory has room
var emptySlot = player.inventory.firstEmptyInventorySlot();
if(emptySlot != null){
collectEntity._writeOthersNearby('collect', {
collectedEntityId: collectEntity.id,
collectorEntityId: player.id
});
player.playSoundAtSelf('random.pop');
var newItem = new ItemStack(collectEntity.itemId, 1, collectEntity.damage);
player.inventory.updateSlot(emptySlot, newItem);
collectEntity.destroy()
}
};
};

View file

@ -23,15 +23,15 @@ module.exports.server=function(serv)
if(!body) throw new Error("username not found");
return uuidInParts(JSON.parse(body).id)
})
.catch(err => {throw new Error("username not found");});
.catch(err => {throw err;});
};
serv.banUsername = (username, reason, cb) => {
serv.banUsername = (username, reason) => {
return serv.getUUIDFromUsername(username)
.then(uuid => serv.ban(uuid, reason));
};
serv.pardonUsername = (username, cb) => {
serv.pardonUsername = (username) => {
return serv.getUUIDFromUsername(username)
.then(pardon);
};

View file

@ -149,7 +149,7 @@ module.exports.server=function(serv,settings)
function injectPlayer(player,serv) {
log("Injected into player");
initSquid(player, serv, vec3);
initSquid(player, serv, Vec3);
newLevel();
player._client.on("block_dig", function (packet) {

View file

@ -2,7 +2,7 @@ var Vec3 = require("vec3").Vec3;
module.exports.server=function(serv) {
serv.emitParticle = (particle, world, position, {whitelist,blacklist=[],radius=32*32,longDistance=true,size=new Vec3(1, 1, 1),count=1}={}) => {
var players = (typeof whitelist != 'undefined' ? (typeof whitelist == 'array' ? whitelist : [whitelist]) : serv.getNearby({
var players = (typeof whitelist != 'undefined' ? (whitelist instanceof Array ? whitelist : [whitelist]) : serv.getNearby({
world: world,
position: position.scaled(32).floored(),
radius: radius // 32 blocks, fixed position

View file

@ -21,7 +21,6 @@ module.exports.entity=function(entity){
var yBlock = yVec.equals(xVec) ? xBlock : blocks[await entity.world.getBlockType(yVec)].boundingBox == 'block';
var zBlock = zVec.equals(yVec) ? yBlock : (zVec.equals(xVec) ? xBlock : blocks[await entity.world.getBlockType(zVec)].boundingBox == 'block');
var old = entity.position.clone();
if (xBlock || yBlock || zBlock) {
entity.velocity.x = getFriction(entity.velocity.x, entity.friction.x, delta);

View file

@ -26,8 +26,8 @@ module.exports.player=function(player,serv)
position: placedPosition,
reference: referencePosition,
playSound: true,
sound: 'dig.' + (materialToSound[blocks[heldItem.blockId].material] || 'stone'),
}, ({direction, heldItem, position, reference, playSound, sound, id, damage}) => {
sound: 'dig.' + (materialToSound[blocks[heldItem.blockId].material] || 'stone')
}, ({direction, heldItem, position, playSound, sound, id, damage}) => {
if (playSound) {
serv.playSound(sound, player.world, placedPosition.clone().add(new Vec3(0.5, 0.5, 0.5)), {
pitch: 0.8

View file

@ -25,7 +25,7 @@ module.exports.player=function(player,serv)
velocity: attackedEntity.position.minus(player.position).plus(new Vec3(0, 0.5, 0)).scaled(5),
maxVelocity: new Vec3(4, 4, 4),
animation: true
}, ({attackedEntity, sound, playSound, damage, velocity, maxVelocity, animation}) => {
}, ({attackedEntity, sound, damage, velocity, maxVelocity, animation}) => {
attackedEntity.updateHealth(attackedEntity.health - damage);
serv.playSound(sound, player.world, attackedEntity.position.scaled(1/32));
@ -51,11 +51,11 @@ module.exports.player=function(player,serv)
};
module.exports.entity=function(entity,serv)
module.exports.entity=function(entity)
{
if (entity.type != 'player') {
entity.updateHealth = (health) => {
entity.health = health;
}
}
}
};

View file

@ -2,7 +2,7 @@ var Vec3 = require('vec3').Vec3;
module.exports.server=function(serv) {
serv.playSound = (sound, world, position, {whitelist,blacklist=[],radius=32*32,volume=1.0,pitch=1.0}={}) => {
var players = (typeof whitelist != 'undefined' ? (typeof whitelist == 'array' ? whitelist : [whitelist]) : serv.getNearby({
var players = (typeof whitelist != 'undefined' ? (typeof whitelist instanceof Array ? whitelist : [whitelist]) : serv.getNearby({
world: world,
position: position.scaled(32).floored(),
radius: radius // 32 blocks, fixed position
@ -40,7 +40,7 @@ module.exports.player=function(player,serv) {
serv.playSound(sound, player.world, null, opt);
};
player.on('placeBlock_cancel', async ({position, reference}, cancel) => {
player.on('placeBlock_cancel', async ({reference}, cancel) => {
if (player.crouching) return;
var id = await player.world.getBlockType(reference);
if (id != 25) return;

223
src/lib/plugins/spawn.js Normal file
View file

@ -0,0 +1,223 @@
var version = require("../version");
var entitiesByName=require("minecraft-data")(version).entitiesByName;
var Entity = require("../entity");
var path = require('path');
var requireIndex = require('requireindex');
var plugins = requireIndex(path.join(__dirname,'..', 'plugins'));
var Vec3 = require("vec3").Vec3;
module.exports.server=function(serv,options) {
serv.initEntity = (type, entityType, world, position) => {
serv.entityMaxId++;
var entity = new Entity(serv.entityMaxId);
Object.keys(plugins)
.filter(pluginName => plugins[pluginName].entity!=undefined)
.forEach(pluginName => plugins[pluginName].entity(entity, serv, options));
entity.initEntity(type, entityType, world, position);
serv.emit("newEntity",entity);
return entity;
};
serv.spawnObject = (type, world, position, {pitch=0,yaw=0,velocity=new Vec3(0,0,0),data=1,itemId,itemDamage=0,pickupTime=undefined,deathTime=undefined}) => {
var object = serv.initEntity('object', type, world, position.scaled(32).floored());
object.data = data;
object.velocity = velocity.scaled(32).floored();
object.pitch = pitch;
object.yaw = yaw;
object.gravity = new Vec3(0, -20*32, 0);
object.terminalvelocity = new Vec3(27*32, 27*32, 27*32);
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.deathTime = deathTime;
object.pickupTime = pickupTime;
object.itemId = itemId;
object.itemDamage = itemDamage;
object.updateAndSpawn();
};
serv.spawnMob = (type, world, position, {pitch=0,yaw=0,headPitch=0,velocity=new Vec3(0,0,0),metadata=[]}={}) => {
var mob = serv.initEntity('mob', type, world, position.scaled(32).floored());
mob.velocity = velocity.scaled(32).floored();
mob.pitch = pitch;
mob.headPitch = headPitch;
mob.yaw = yaw;
mob.gravity = new Vec3(0, -20*32, 0);
mob.terminalvelocity = new Vec3(27*32, 27*32, 27*32);
mob.friction = new Vec3(15*32, 0, 15*32);
mob.size = new Vec3(0.75, 1.75, 0.75);
mob.health = 20;
mob.metadata = metadata;
mob.updateAndSpawn();
};
serv.destroyEntity = entity => {
entity._writeOthersNearby('entity_destroy', {
entityIds: [entity.id]
});
delete serv.entities[entity.id];
};
};
module.exports.player=function(player,serv){
player.commands.add({
base: 'spawn',
info: 'Spawn a mob',
usage: '/spawn <entity_id>',
parse(str) {
var results=str.match(/(\d+)/);
if (!results) return false;
return {
id: parseInt(results[1])
}
},
action({id}) {
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)
});
}
});
player.commands.add({
base: 'spawnObject',
info: 'Spawn an object',
usage: '/spawnObject <entity_id>',
parse(str) {
var results=str.match(/(\d+)/);
if (!results) return false;
return {
id: parseInt(results[1])
}
},
action({id}) {
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)
});
}
});
player.commands.add({
base: 'summon',
info: 'Summon an entity',
usage: '/summon <entity_name>',
action(name) {
var entity=entitiesByName[name];
if(!entity) {
player.chat("No entity named "+name);
return;
}
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)
});
}
});
};
module.exports.entity=function(entity,serv) {
entity.initEntity=(type, entityType, world, position)=>{
entity.type = type;
entity.spawnPacketName = '';
entity.entityType = entityType;
entity.world = world;
entity.position = position;
entity.lastPositionPlayersUpdated = entity.position.clone();
entity.nearbyEntities = [];
entity.viewDistance = 150;
entity.bornTime = Date.now();
serv.entities[entity.id] = entity;
if (entity.type == 'player') entity.spawnPacketName = 'named_entity_spawn';
else if (entity.type == 'object') entity.spawnPacketName = 'spawn_entity';
else if (entity.type == 'mob') entity.spawnPacketName = 'spawn_entity_living';
};
entity.getSpawnPacket = () => {
var scaledVelocity = entity.velocity.scaled(8000/32/20).floored(); // from fixed-position/second to unit => 1/8000 blocks per tick
if (entity.type == 'player') {
return {
entityId: entity.id,
playerUUID: entity._client.uuid,
x: entity.position.x,
y: entity.position.y,
z: entity.position.z,
yaw: entity.yaw,
pitch: entity.pitch,
currentItem: 0,
metadata: entity.metadata
}
} else if (entity.type == 'object') {
return {
entityId: entity.id,
type: entity.entityType,
x: entity.position.x,
y: entity.position.y,
z: entity.position.z,
pitch: entity.pitch,
yaw: entity.yaw,
objectData: {
intField: entity.data,
velocityX: scaledVelocity.x,
velocityY: scaledVelocity.y,
velocityZ: scaledVelocity.z
}
}
} else if (entity.type == 'mob') {
return {
entityId: entity.id,
type: entity.entityType,
x: entity.position.x,
y: entity.position.y,
z: entity.position.z,
yaw: entity.yaw,
pitch: entity.pitch,
headPitch: entity.headPitch,
velocityX: scaledVelocity.x,
velocityY: scaledVelocity.y,
velocityZ: scaledVelocity.z,
metadata: entity.metadata
}
}
};
entity.updateAndSpawn = () => {
var updatedEntities=entity.getNearby();
var entitiesToAdd=updatedEntities.filter(e => entity.nearbyEntities.indexOf(e)==-1);
var entitiesToRemove=entity.nearbyEntities.filter(e => updatedEntities.indexOf(e)==-1);
if (entity.type == 'player') {
entity.despawnEntities(entitiesToRemove);
entitiesToAdd.forEach(entity.spawnEntity);
}
entity.lastPositionPlayersUpdated=entity.position.clone();
var playersToAdd = entitiesToAdd.filter(e => e.type == 'player');
var playersToRemove = entitiesToRemove.filter(e => e.type == 'player');
playersToRemove.forEach(p => p.despawnEntities([entity]));
playersToRemove.forEach(p => p.nearbyEntities=p.getNearby());
playersToAdd.forEach(p => p.spawnEntity(entity));
playersToAdd.forEach(p => p.nearbyEntities=p.getNearby());
entity.nearbyEntities=updatedEntities;
};
entity.on("move",() => {
if(entity.position.distanceTo(entity.lastPositionPlayersUpdated)>2*32)
entity.updateAndSpawn();
});
entity.destroy = () => {
serv.destroyEntity(entity);
};
};

View file

@ -105,7 +105,7 @@ module.exports.entity=function(entity,serv){
old: oldPos,
onGround: onGround
}, ({old,onGround}) => {
var diff = entity.position.minus(oldPos);
var diff = entity.position.minus(old);
if(diff.abs().x>127 || diff.abs().y>127 || diff.abs().z>127)
entity._writeOthersNearby('entity_teleport', {
@ -128,4 +128,33 @@ module.exports.entity=function(entity,serv){
entity.position = oldPos;
});
};
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

@ -129,7 +129,7 @@ module.exports.player=function(player,serv,settings) {
if(!loaded) player.loadedChunks[key]=1;
return !loaded;
})
.reduce((acc,{chunkX,chunkZ},i)=> {
.reduce((acc,{chunkX,chunkZ})=> {
var p=acc
.then(() => player.world.getColumn(chunkX, chunkZ))
.then((column) => player.sendChunk(chunkX, chunkZ, column));

View file

@ -3,7 +3,7 @@ var Vec3 = require('vec3').Vec3;
var blocks=require("minecraft-data")(require("../version")).blocks;
function generation() {
function generateSimpleChunk(chunkX, chunkZ) {
function generateSimpleChunk() {
var chunk = new Chunk();
var i=2;

View file

@ -2,7 +2,7 @@ var Chunk = require('prismarine-chunk')(require("../version"));
var Vec3 = require('vec3').Vec3;
function generation() {
function generateSimpleChunk(chunkX, chunkZ) {
function generateSimpleChunk() {
var chunk = new Chunk();
for (var x = 0; x < 16; x++) {

View file

@ -15,7 +15,7 @@ function generation({seed,level=50}={}) {
let data;
if (y < bedrockheightbottom) block = 7;
else if (y < 50) block = 87;
else if (y < level) block = 87;
else if (y > 127 - bedrockheighttop) block = 7;
var pos = new Vec3(x, y, z);

View file

@ -2,7 +2,7 @@ var Chunk = require('prismarine-chunk')(require("../version"));
var Vec3 = require('vec3').Vec3;
function generation({opt='default',bottom_id=7,middle_id=1,top_id=2,middle_thickness=3,debug=false}={}) {
function generateChunk(chunkX,chunkZ) {
function generateChunk() {
var chunk=new Chunk();
var height = middle_thickness + 1;
var DEBUG_POINTS = [new Vec3(0, height, 0), new Vec3(15, height, 0), new Vec3(0, height, 15), new Vec3(15, height, 15)];
@ -19,11 +19,8 @@ function generation({opt='default',bottom_id=7,middle_id=1,top_id=2,middle_thick
}
}
if (debug) {
for (var d in DEBUG_POINTS) {
chunk.setBlockType(DEBUG_POINTS[d], 35);
}
}
if (debug)
DEBUG_POINTS.forEach(p => chunk.setBlockType(p, 35));
return chunk;
}
return generateChunk;

View file

@ -41,7 +41,7 @@ describe("Server with mineflayer connection", function() {
describe("commands",function(){
it("has an help command", function(done) {
bot.once("message",function(message){
bot.once("message",function(){
done();
});
bot.chat("/help");