mirror of
https://github.com/danbulant/flying-squid
synced 2026-06-24 17:21:43 +00:00
commit
2a64559dc2
14 changed files with 376 additions and 59 deletions
|
|
@ -32,7 +32,7 @@
|
||||||
"prismarine-block": "0.1.0",
|
"prismarine-block": "0.1.0",
|
||||||
"prismarine-chunk": "0.2.1",
|
"prismarine-chunk": "0.2.1",
|
||||||
"prismarine-entity": "0.1.0",
|
"prismarine-entity": "0.1.0",
|
||||||
"prismarine-world": "0.3.1",
|
"prismarine-world": "0.3.3",
|
||||||
"prismarine-world-sync": "0.1.0",
|
"prismarine-world-sync": "0.1.0",
|
||||||
"random-seed": "^0.2.0",
|
"random-seed": "^0.2.0",
|
||||||
"request-promise": "^0.4.3",
|
"request-promise": "^0.4.3",
|
||||||
|
|
|
||||||
|
|
@ -307,6 +307,24 @@ function inject(serv, player) {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
base.add({
|
||||||
|
base: 'spawn',
|
||||||
|
info: 'Spawn an entity',
|
||||||
|
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.entity.position.scaled(1/32), {
|
||||||
|
velocity: Vec3((Math.random() - 0.5) * 10, Math.random()*10 + 10, (Math.random() - 0.5) * 10)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
serv.commands = base;
|
serv.commands = base;
|
||||||
|
|
||||||
player.handleCommand = (str) => {
|
player.handleCommand = (str) => {
|
||||||
|
|
|
||||||
|
|
@ -8,15 +8,17 @@ function inject(serv,player)
|
||||||
.forEach((otherPlayer) => otherPlayer._client.write(packetName, packetFields));
|
.forEach((otherPlayer) => otherPlayer._client.write(packetName, packetFields));
|
||||||
|
|
||||||
player._writeOthersNearby = (packetName, packetFields) =>
|
player._writeOthersNearby = (packetName, packetFields) =>
|
||||||
serv._writeArray(packetName, packetFields, player.nearbyPlayers);
|
serv._writeArray(packetName, packetFields, player.nearbyPlayers());
|
||||||
|
|
||||||
player.getOthers = () => serv.players.filter((otherPlayer) => otherPlayer != player);
|
player.getOthers = () => serv.players.filter((otherPlayer) => otherPlayer != player);
|
||||||
|
|
||||||
player.getNearby = () => serv
|
player.getNearbyPlayers = (radius=player.entity.viewDistance*32) => serv.getNearby({
|
||||||
.getNearby({
|
world: player.world,
|
||||||
world: player.world,
|
position: player.position,
|
||||||
position: player.entity.position,
|
radius: radius
|
||||||
radius: player.playerViewDistance*32
|
});
|
||||||
})
|
|
||||||
.filter((p) => p != player);
|
player.nearbyPlayers = (radius=player.entity.viewDistance*32) => player.entity.nearbyEntities
|
||||||
|
.filter(e => e.type == 'player')
|
||||||
|
.map(e => e.player);
|
||||||
}
|
}
|
||||||
|
|
@ -70,12 +70,19 @@ function inject(serv,player)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function completeDigging(location)
|
async function completeDigging(location)
|
||||||
{
|
{
|
||||||
clearInterval(animationInterval);
|
clearInterval(animationInterval);
|
||||||
var diggingTime=new Date()-startDiggingTime;
|
var diggingTime=new Date()-startDiggingTime;
|
||||||
if(expectedDiggingTime-diggingTime<100)
|
if(expectedDiggingTime-diggingTime<100) {
|
||||||
player.changeBlock(location,0,0);
|
player.changeBlock(location,0,0);
|
||||||
|
// Drop block
|
||||||
|
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),
|
||||||
|
itemId: currentlyDugBlock.type,
|
||||||
|
itemDamage: currentlyDugBlock.metadata
|
||||||
|
});
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
player._client.write("block_change",{
|
player._client.write("block_change",{
|
||||||
|
|
|
||||||
|
|
@ -7,46 +7,25 @@ function inject(serv,player)
|
||||||
{
|
{
|
||||||
function addPlayer()
|
function addPlayer()
|
||||||
{
|
{
|
||||||
serv.entityMaxId++;
|
player.entity=serv.initEntity('player', null, serv.overworld, Vec3(0,0,0));
|
||||||
player.entity=new Entity(serv.entityMaxId);
|
player.entity.type = 'player';
|
||||||
serv.entities[player.entity.id]=player.entity;
|
|
||||||
player.entity.player=player;
|
player.entity.player=player;
|
||||||
player.entity.health = 20;
|
player.entity.health = 20;
|
||||||
player.entity.food = 20;
|
player.entity.food = 20;
|
||||||
player.entity.crouching = false; // Needs added in prismarine-entity later
|
player.entity.crouching = false; // Needs added in prismarine-entity later
|
||||||
player.playerViewDistance = 150;
|
|
||||||
player.view=10;
|
player.view=10;
|
||||||
player.world=serv.overworld;
|
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;
|
||||||
player.loadedChunks={};
|
player.loadedChunks={};
|
||||||
player.nearbyPlayers=[];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
player.updateAndSpawnNearbyPlayers = () =>
|
|
||||||
{
|
|
||||||
player.lastPositionPlayersUpdated=player.entity.position;
|
|
||||||
var updatedPlayers=player.getNearby();
|
|
||||||
var playersToAdd=updatedPlayers.filter(p => player.nearbyPlayers.indexOf(p)==-1);
|
|
||||||
var playersToRemove=player.nearbyPlayers.filter(p => updatedPlayers.indexOf(p)==-1);
|
|
||||||
player.despawnPlayers(playersToRemove);
|
|
||||||
playersToAdd.forEach(player.spawnAPlayer);
|
|
||||||
|
|
||||||
playersToRemove.forEach(p => p.despawnPlayers([player]));
|
|
||||||
playersToRemove.forEach(p => p.nearbyPlayers=p.getNearby());
|
|
||||||
playersToAdd.forEach(p => p.spawnAPlayer(player));
|
|
||||||
playersToAdd.forEach(p => p.nearbyPlayers=p.getNearby());
|
|
||||||
|
|
||||||
player.nearbyPlayers=updatedPlayers;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
function sendPlayersWhenMove()
|
function sendPlayersWhenMove()
|
||||||
{
|
{
|
||||||
player.on("positionChanged",() => {
|
player.on("positionChanged",() => {
|
||||||
if(player.entity.position.distanceTo(player.lastPositionPlayersUpdated)>2*32)
|
if(player.entity.position.distanceTo(player.lastPositionPlayersUpdated)>2*32)
|
||||||
player.updateAndSpawnNearbyPlayers();
|
player.entity.updateAndSpawn();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -173,7 +152,7 @@ function inject(serv,player)
|
||||||
|
|
||||||
updateTime();
|
updateTime();
|
||||||
fillTabList();
|
fillTabList();
|
||||||
player.updateAndSpawnNearbyPlayers();
|
player.entity.updateAndSpawn();
|
||||||
|
|
||||||
announceJoin();
|
announceJoin();
|
||||||
player.emit("spawned");
|
player.emit("spawned");
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,10 @@ function inject(serv,player)
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
player.despawnEntities = entities => player._client.write('entity_destroy', {
|
||||||
|
'entityIds': entities.map(e => e.id)
|
||||||
|
});
|
||||||
|
|
||||||
player._client.on('end', () => {
|
player._client.on('end', () => {
|
||||||
if(player.entity) {
|
if(player.entity) {
|
||||||
serv.broadcast(player.username + ' quit the game.', "yellow");
|
serv.broadcast(player.username + ' quit the game.', "yellow");
|
||||||
|
|
@ -17,7 +21,7 @@ function inject(serv,player)
|
||||||
UUID: player._client.uuid
|
UUID: player._client.uuid
|
||||||
}]
|
}]
|
||||||
});
|
});
|
||||||
player.nearbyPlayers.forEach(otherPlayer => otherPlayer.despawnPlayers([player]));
|
player.nearbyPlayers().forEach(otherPlayer => otherPlayer.despawnPlayers([player]));
|
||||||
delete serv.entities[player.entity.id];
|
delete serv.entities[player.entity.id];
|
||||||
player.emit('disconnected');
|
player.emit('disconnected');
|
||||||
var index = serv.players.indexOf(player);
|
var index = serv.players.indexOf(player);
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,16 @@
|
||||||
|
var blocks=require("minecraft-data")(require("../version")).blocks;
|
||||||
var vec3 = require("vec3");
|
var vec3 = require("vec3");
|
||||||
|
|
||||||
|
var materialToSound = {
|
||||||
|
undefined: 'stone',
|
||||||
|
'rock': 'stone',
|
||||||
|
'dirt': 'grass',
|
||||||
|
'plant': 'grass',
|
||||||
|
'wool': 'cloth',
|
||||||
|
'web': 'cloth',
|
||||||
|
'wood': 'wood'
|
||||||
|
}
|
||||||
|
|
||||||
module.exports=inject;
|
module.exports=inject;
|
||||||
|
|
||||||
function inject(serv,player)
|
function inject(serv,player)
|
||||||
|
|
@ -11,7 +22,10 @@ function inject(serv,player)
|
||||||
var placedPosition=referencePosition.plus(directionVector);
|
var placedPosition=referencePosition.plus(directionVector);
|
||||||
player.world.getBlockType(referencePosition).then((id) => {
|
player.world.getBlockType(referencePosition).then((id) => {
|
||||||
if([25].indexOf(id) != -1) return;
|
if([25].indexOf(id) != -1) return;
|
||||||
serv.playSound('random.click', player.world, placedPosition.clone().add(vec3(0.5, 0.5, 0.5)));
|
var sound = 'dig.' + (materialToSound[blocks[heldItem.blockId].material] || 'stone');
|
||||||
|
serv.playSound(sound, player.world, placedPosition.clone().add(vec3(0.5, 0.5, 0.5)), {
|
||||||
|
pitch: 0.8
|
||||||
|
});
|
||||||
if(heldItem.blockId!=323){
|
if(heldItem.blockId!=323){
|
||||||
player.changeBlock(placedPosition,heldItem.blockId,heldItem.itemDamage);
|
player.changeBlock(placedPosition,heldItem.blockId,heldItem.itemDamage);
|
||||||
}else if(direction==1){
|
}else if(direction==1){
|
||||||
|
|
|
||||||
|
|
@ -14,8 +14,9 @@ function inject(serv, player)
|
||||||
|
|
||||||
function attackEntity(entityId)
|
function attackEntity(entityId)
|
||||||
{
|
{
|
||||||
|
if (!serv.entities[entityId]) return; // ?????
|
||||||
var attackedPlayer = serv.entities[entityId].player;
|
var attackedPlayer = serv.entities[entityId].player;
|
||||||
if(attackedPlayer.gameMode!=0) return;
|
if(!attackedPlayer || attackedPlayer.gameMode!=0) return;
|
||||||
attackedPlayer.updateHealth(attackedPlayer.entity.health - 1);
|
attackedPlayer.updateHealth(attackedPlayer.entity.health - 1);
|
||||||
serv.playSound('game.player.hurt', player.world, attackedPlayer.entity.position.scaled(1/32));
|
serv.playSound('game.player.hurt', player.world, attackedPlayer.entity.position.scaled(1/32));
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -12,10 +12,10 @@ function inject(serv,player)
|
||||||
|
|
||||||
// float (degrees) --> byte (1/256 "degrees")
|
// float (degrees) --> byte (1/256 "degrees")
|
||||||
function conv(f){
|
function conv(f){
|
||||||
var b = (f % 360) * 256 / 360;
|
var b = Math.floor((f % 360) * 256 / 360);
|
||||||
if (b < -128) b += 256;
|
if (b < -128) b += 256;
|
||||||
else if (b > 127) b -= 256;
|
else if (b > 127) b -= 256;
|
||||||
return Math.floor(b);
|
return b;
|
||||||
}
|
}
|
||||||
function sendLook(yaw,pitch,onGround)
|
function sendLook(yaw,pitch,onGround)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -5,18 +5,18 @@ module.exports = inject;
|
||||||
|
|
||||||
function inject(serv, player) {
|
function inject(serv, player) {
|
||||||
|
|
||||||
player.spawnAPlayer = spawnedPlayer => {
|
player.spawnEntity = entity => {
|
||||||
player._client.write('named_entity_spawn', {
|
player._client.write(entity.spawnPacketName, entity.getSpawnPacket());
|
||||||
entityId: spawnedPlayer.entity.id,
|
if (typeof entity.itemId != 'undefined') {
|
||||||
playerUUID: spawnedPlayer._client.uuid,
|
entity.setMetadata([{
|
||||||
x: spawnedPlayer.entity.position.x,
|
"key": 10,
|
||||||
y: spawnedPlayer.entity.position.y,
|
"type": 5,
|
||||||
z: spawnedPlayer.entity.position.z,
|
"value": {
|
||||||
yaw: spawnedPlayer.entity.yaw,
|
blockId: entity.itemId,
|
||||||
pitch: spawnedPlayer.entity.pitch,
|
itemDamage: entity.itemDamage
|
||||||
currentItem: 0,
|
}
|
||||||
metadata: spawnedPlayer.entity.metadata
|
}]);
|
||||||
});
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
player.sendChunk = (chunkX,chunkZ,column) =>
|
player.sendChunk = (chunkX,chunkZ,column) =>
|
||||||
|
|
@ -96,6 +96,7 @@ function inject(serv, player) {
|
||||||
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.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",{
|
||||||
|
|
@ -106,7 +107,7 @@ function inject(serv, player) {
|
||||||
});
|
});
|
||||||
player.entity.position=player.spawnPoint.toFixedPosition();
|
player.entity.position=player.spawnPoint.toFixedPosition();
|
||||||
player.sendSpawnPosition();
|
player.sendSpawnPosition();
|
||||||
player.updateAndSpawnNearbyPlayers();
|
player.entity.updateAndSpawn();
|
||||||
|
|
||||||
await player.sendMap();
|
await player.sendMap();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -11,8 +11,15 @@ function inject(serv,settings)
|
||||||
serv._writeNearby= (packetName, packetFields, loc) =>
|
serv._writeNearby= (packetName, packetFields, loc) =>
|
||||||
serv._writeArray(packetName, packetFields, serv.getNearby(loc));
|
serv._writeArray(packetName, packetFields, serv.getNearby(loc));
|
||||||
|
|
||||||
serv.getNearby= loc => serv.players.filter( player =>
|
serv.getNearby= ({world,position,radius=8*16*32}) => serv.players.filter( player =>
|
||||||
player.world == loc.world &&
|
player.world == world &&
|
||||||
player.entity.position.distanceTo(loc.position) <= loc.radius
|
player.entity.position.distanceTo(position) <= radius
|
||||||
|
);
|
||||||
|
|
||||||
|
serv.getNearbyEntities= ({world,position,radius=8*16*32}) => Object.keys(serv.entities)
|
||||||
|
.map(eId => serv.entities[eId])
|
||||||
|
.filter(entity =>
|
||||||
|
entity.world == world &&
|
||||||
|
entity.position.distanceTo(position) <= radius
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -14,7 +14,7 @@ function inject(serv, settings) {
|
||||||
|
|
||||||
serv.time = 0;
|
serv.time = 0;
|
||||||
|
|
||||||
serv.on('tick', (count) => {
|
serv.on('tick', (delta,count) => {
|
||||||
if (!serv.doDaylightCycle) return;
|
if (!serv.doDaylightCycle) return;
|
||||||
if (count % 20 == 0) {
|
if (count % 20 == 0) {
|
||||||
serv.setTime((serv.time + 20) % 24000); // Vanilla only does it every second
|
serv.setTime((serv.time + 20) % 24000); // Vanilla only does it every second
|
||||||
|
|
|
||||||
280
src/lib/serverPlugins/entities.js
Normal file
280
src/lib/serverPlugins/entities.js
Normal file
|
|
@ -0,0 +1,280 @@
|
||||||
|
var Entity=require("prismarine-entity");
|
||||||
|
var blocks=require("minecraft-data")(require("../version")).blocks;
|
||||||
|
var mobs=require("minecraft-data")(require("../version")).entitiesByName;
|
||||||
|
var vec3 = require("vec3");
|
||||||
|
var EventEmitter = require('events').EventEmitter;
|
||||||
|
var util = require('util');
|
||||||
|
|
||||||
|
module.exports = inject;
|
||||||
|
|
||||||
|
function inject(serv) {
|
||||||
|
|
||||||
|
util.inherits(Entity, EventEmitter);
|
||||||
|
|
||||||
|
serv.initEntity = (type, entityType, world, position) => {
|
||||||
|
serv.entityMaxId++;
|
||||||
|
var entity = new Entity(serv.entityMaxId);
|
||||||
|
EventEmitter.call(entity);
|
||||||
|
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("positionChanged",() => {
|
||||||
|
if(entity.position.distanceTo(entity.lastPositionPlayersUpdated)>2*32)
|
||||||
|
entity.updateAndSpawn();
|
||||||
|
});
|
||||||
|
|
||||||
|
entity.setMetadata = (data) => {
|
||||||
|
serv._writeNearby('entity_metadata', {
|
||||||
|
entityId: entity.id,
|
||||||
|
metadata: data
|
||||||
|
}, entity);
|
||||||
|
};
|
||||||
|
|
||||||
|
entity.destroy = () => {
|
||||||
|
serv.destroyEntity(entity);
|
||||||
|
};
|
||||||
|
|
||||||
|
entity.calculatePhysics = async (delta) => {
|
||||||
|
if (entity.gravity) {
|
||||||
|
addGravity(entity, 'x', delta);
|
||||||
|
addGravity(entity, 'y', delta);
|
||||||
|
addGravity(entity, 'z', delta);
|
||||||
|
}
|
||||||
|
|
||||||
|
var vSign = getSign(entity.velocity);
|
||||||
|
var sizeSigned = vec3(vSign.x * entity.size.x, vSign.y * entity.size.y, vSign.z * entity.size.z);
|
||||||
|
|
||||||
|
var xVec = entity.position.offset(entity.velocity.x*delta + sizeSigned.x/2, 0, 0).scaled(1/32).floored();
|
||||||
|
var yVec = entity.position.offset(0, entity.velocity.y*delta + sizeSigned.y/2, 0).scaled(1/32).floored();
|
||||||
|
var zVec = entity.position.offset(0, 0, entity.velocity.z*delta + sizeSigned.z/2).scaled(1/32).floored();
|
||||||
|
|
||||||
|
// Get block for each (x/y/z)Vec, check to avoid duplicate getBlockTypes
|
||||||
|
var xBlock = blocks[await entity.world.getBlockType(xVec)].boundingBox == 'block';
|
||||||
|
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);
|
||||||
|
entity.velocity.z = getFriction(entity.velocity.x, entity.friction.x, delta);
|
||||||
|
}
|
||||||
|
|
||||||
|
var oldPos = entity.position.clone();
|
||||||
|
|
||||||
|
entity.position.x += getMoveAmount('x', xBlock, entity, delta, sizeSigned.x);
|
||||||
|
entity.position.y += getMoveAmount('y', yBlock, entity, delta, sizeSigned.y);
|
||||||
|
entity.position.z += getMoveAmount('z', zBlock, entity, delta, sizeSigned.z);
|
||||||
|
|
||||||
|
//serv.emitParticle(30, serv.overworld, entity.position.scaled(1/32), { size: vec3(0, 0, 0) });
|
||||||
|
return { oldPos: oldPos, onGround: yBlock}
|
||||||
|
};
|
||||||
|
|
||||||
|
entity.sendPosition = ({oldPos,onGround}) => {
|
||||||
|
var diff = entity.position.minus(oldPos);
|
||||||
|
|
||||||
|
if(diff.abs().x>127 || diff.abs().y>127 || diff.abs().z>127)
|
||||||
|
serv._writeNearby('entity_teleport', {
|
||||||
|
entityId: entity.id,
|
||||||
|
x: entity.position.x,
|
||||||
|
y: entity.position.y,
|
||||||
|
z: entity.position.z,
|
||||||
|
yaw: entity.yaw,
|
||||||
|
pitch: entity.pitch,
|
||||||
|
onGround: onGround
|
||||||
|
}, entity);
|
||||||
|
else serv._writeNearby('rel_entity_move', {
|
||||||
|
entityId: entity.id,
|
||||||
|
dX: diff.x,
|
||||||
|
dY: diff.y,
|
||||||
|
dZ: diff.z,
|
||||||
|
onGround: onGround
|
||||||
|
}, entity);
|
||||||
|
|
||||||
|
entity.emit('positionChanged', oldPos);
|
||||||
|
}
|
||||||
|
|
||||||
|
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.player._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.getNearby = () => serv
|
||||||
|
.getNearbyEntities({
|
||||||
|
world: entity.world,
|
||||||
|
position: entity.position,
|
||||||
|
radius: entity.viewDistance*32
|
||||||
|
})
|
||||||
|
.filter((e) => e != entity);
|
||||||
|
|
||||||
|
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.player.despawnEntities(entitiesToRemove);
|
||||||
|
entitiesToAdd.forEach(entity.player.spawnEntity);
|
||||||
|
entity.player.lastPositionPlayersUpdated=entity.position.clone();
|
||||||
|
} else {
|
||||||
|
entity.lastPositionPlayersUpdated=entity.position.clone();
|
||||||
|
}
|
||||||
|
|
||||||
|
var playersToAdd = entitiesToAdd.filter(e => e.type == 'player').map(e => e.player);
|
||||||
|
var playersToRemove = entitiesToRemove.filter(e => e.type == 'player').map(e => e.player);
|
||||||
|
|
||||||
|
playersToRemove.forEach(p => p.despawnEntities([entity]));
|
||||||
|
playersToRemove.forEach(p => p.entity.nearbyEntities=p.entity.getNearby());
|
||||||
|
playersToAdd.forEach(p => p.spawnEntity(entity));
|
||||||
|
playersToAdd.forEach(p => p.entity.nearbyEntities=p.entity.getNearby());
|
||||||
|
|
||||||
|
entity.nearbyEntities=updatedEntities;
|
||||||
|
};
|
||||||
|
|
||||||
|
return entity;
|
||||||
|
}
|
||||||
|
|
||||||
|
serv.spawnObject = (type, world, position, {pitch=0,yaw=0,velocity=vec3(0,0,0),data=1,itemId,itemDamage=0}={}) => {
|
||||||
|
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 = vec3(0, -20*32, 0);
|
||||||
|
object.terminalvelocity = vec3(27*32, 27*32, 27*32);
|
||||||
|
object.friction = vec3(10*32, 0, 10*32).floored();
|
||||||
|
object.size = vec3(0.25*32, 0.25*32, 0.25*32); // Hardcoded, will be dependent on type!
|
||||||
|
object.deathTime = 60*1000; // 60 seconds
|
||||||
|
object.itemId = itemId;
|
||||||
|
object.itemDamage = itemDamage;
|
||||||
|
|
||||||
|
object.updateAndSpawn();
|
||||||
|
}
|
||||||
|
|
||||||
|
serv.spawnMob = (type, world, position, {pitch=0,yaw=0,headPitch=0,velocity=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 = vec3(0, -20*32, 0);
|
||||||
|
mob.terminalvelocity = vec3(27*32, 27*32, 27*32);
|
||||||
|
mob.friction = vec3(10*32, 0, 10*32);
|
||||||
|
mob.size = vec3(0.75, 1.75, 0.75);
|
||||||
|
mob.metadata = metadata;
|
||||||
|
|
||||||
|
mob.updateAndSpawn();
|
||||||
|
}
|
||||||
|
|
||||||
|
serv.on('tick', function(delta) {
|
||||||
|
Promise.all(
|
||||||
|
Object.keys(serv.entities).map(async (id) => {
|
||||||
|
var entity = serv.entities[id];
|
||||||
|
if (entity.deathTime && Date.now() - entity.bornTime >= entity.deathTime) {
|
||||||
|
entity.destroy();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!entity.velocity || !entity.size) return;
|
||||||
|
var oldPosAndOnGround = await entity.calculatePhysics(delta);
|
||||||
|
if (!oldPosAndOnGround.oldPos.equals(vec3(0,0,0)))
|
||||||
|
if (entity.type == 'mob') entity.sendPosition(oldPosAndOnGround);
|
||||||
|
})
|
||||||
|
).catch((err)=> setTimeout(() => {throw err;},0));
|
||||||
|
});
|
||||||
|
|
||||||
|
serv.destroyEntity = entity => {
|
||||||
|
serv._writeNearby('entity_destroy', {
|
||||||
|
entityIds: [entity.id]
|
||||||
|
}, {
|
||||||
|
position: entity.position,
|
||||||
|
world: entity.world
|
||||||
|
});
|
||||||
|
delete serv.entities[entity.id];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function getMoveAmount(dir, block, entity, delta, sizeSigned) {
|
||||||
|
if (block) {
|
||||||
|
entity.velocity[dir] = 0;
|
||||||
|
return Math.floor(-1 * (entity.position[dir] + sizeSigned/2 - floorInDirection(entity.position[dir], -sizeSigned)));
|
||||||
|
} else {
|
||||||
|
return Math.floor(entity.velocity[dir] * delta);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function getSign(vec) {
|
||||||
|
return vec3(Math.sign(vec.x), Math.sign(vec.y), Math.sign(vec.z));
|
||||||
|
}
|
||||||
|
|
||||||
|
function floorInDirection(a, b) {
|
||||||
|
return b < 0 ? Math.floor(a) : Math.ceil(a);
|
||||||
|
}
|
||||||
|
|
||||||
|
function addGravity(entity, dir, delta) {
|
||||||
|
if (entity.velocity[dir] < entity.terminalvelocity[dir] && entity.velocity[dir] > -entity.terminalvelocity[dir]) {
|
||||||
|
entity.velocity[dir] = clamp(-entity.terminalvelocity[dir], entity.velocity[dir] + entity.gravity[dir] * delta, entity.terminalvelocity[dir]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function getFriction(vel, fric, delta) {
|
||||||
|
return vel > 0 ? Math.max(0, vel - fric*delta) : Math.min(0, vel + fric*delta);
|
||||||
|
}
|
||||||
|
|
||||||
|
function clamp(a, b, c) {
|
||||||
|
return Math.max(a, Math.min(b, c));
|
||||||
|
}
|
||||||
|
|
@ -3,6 +3,7 @@ module.exports = inject;
|
||||||
|
|
||||||
function inject(serv, settings) {
|
function inject(serv, settings) {
|
||||||
serv.tickCount = 0;
|
serv.tickCount = 0;
|
||||||
|
serv.lastTickTime = 0;
|
||||||
|
|
||||||
|
|
||||||
serv.setTickInterval = ticksPerSecond => {
|
serv.setTickInterval = ticksPerSecond => {
|
||||||
|
|
@ -10,7 +11,10 @@ function inject(serv, settings) {
|
||||||
|
|
||||||
serv.tickInterval = setInterval(() => {
|
serv.tickInterval = setInterval(() => {
|
||||||
serv.tickCount++;
|
serv.tickCount++;
|
||||||
serv.emit('tick', serv.tickCount);
|
var time = (Date.now() - serv.lastTickTime) / 1000;
|
||||||
|
if (time > 100) time = 0;
|
||||||
|
serv.emit('tick', time, serv.tickCount);
|
||||||
|
serv.lastTickTime = Date.now();
|
||||||
}, 1000/ticksPerSecond);
|
}, 1000/ticksPerSecond);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue