mirror of
https://github.com/danbulant/flying-squid
synced 2026-06-24 09:11:43 +00:00
Continue refactoring : client now in a player object, methods added to that player object, progress on #3
This commit is contained in:
parent
3070acff44
commit
2e371e741f
13 changed files with 460 additions and 334 deletions
|
|
@ -19,7 +19,7 @@ Before running or building it is recommended that you configure the server in co
|
||||||
Documentation for how to operate and how to customize your server are coming soon!
|
Documentation for how to operate and how to customize your server are coming soon!
|
||||||
|
|
||||||
## Dev Documentation
|
## Dev Documentation
|
||||||
For development see [api.md](docs/api.md)
|
For development see [api.md](doc/api.md)
|
||||||
|
|
||||||
## Contributors
|
## Contributors
|
||||||
|
|
||||||
|
|
|
||||||
151
doc/api.md
Normal file
151
doc/api.md
Normal file
|
|
@ -0,0 +1,151 @@
|
||||||
|
# API
|
||||||
|
|
||||||
|
## Classes
|
||||||
|
|
||||||
|
### CraftyJS.Entity
|
||||||
|
|
||||||
|
Entities represent players, mobs, and objects. They are emitted
|
||||||
|
in many events, and you can access your own entity with `bot.entity`.
|
||||||
|
|
||||||
|
#### entity.id
|
||||||
|
|
||||||
|
#### entity.type
|
||||||
|
|
||||||
|
Choices:
|
||||||
|
|
||||||
|
* `player`
|
||||||
|
* `mob`
|
||||||
|
* `object`
|
||||||
|
* `global` - lightning
|
||||||
|
* `orb` - experience orb.
|
||||||
|
* `other` - introduced with a recent Minecraft update and not yet recognized or used by a third-party mod
|
||||||
|
|
||||||
|
#### entity.username
|
||||||
|
|
||||||
|
If the entity type is `player`, this field will be set.
|
||||||
|
|
||||||
|
#### entity.mobType
|
||||||
|
|
||||||
|
If the entity type is `mob`, this field will be set.
|
||||||
|
|
||||||
|
#### entity.displayName
|
||||||
|
|
||||||
|
Field set for mob and object. A long name in multiple words.
|
||||||
|
|
||||||
|
#### entity.entityType
|
||||||
|
|
||||||
|
Field set for mob and object. The numerical type of the entity (1,2,...)
|
||||||
|
|
||||||
|
#### entity.kind
|
||||||
|
|
||||||
|
Field set for mob and object. The kind of entity (for example Hostile mobs, Passive mobs, NPCs).
|
||||||
|
|
||||||
|
#### entity.name
|
||||||
|
|
||||||
|
Field set for mob and object. A short name for the entity.
|
||||||
|
|
||||||
|
#### entity.objectType
|
||||||
|
|
||||||
|
If the entity type is `object`, this field will be set.
|
||||||
|
|
||||||
|
#### entity.count
|
||||||
|
|
||||||
|
If the entity type is `orb`, this field will be how much experience you
|
||||||
|
get from collecting the orb.
|
||||||
|
|
||||||
|
#### entity.position
|
||||||
|
|
||||||
|
#### entity.velocity
|
||||||
|
|
||||||
|
#### entity.yaw
|
||||||
|
|
||||||
|
#### entity.pitch
|
||||||
|
|
||||||
|
#### entity.height
|
||||||
|
|
||||||
|
#### entity.onGround
|
||||||
|
|
||||||
|
#### entity.equipment[5]
|
||||||
|
|
||||||
|
* `0` - held item
|
||||||
|
* `1` - shoes
|
||||||
|
* `2` - legging
|
||||||
|
* `3` - torso
|
||||||
|
* `4` - head
|
||||||
|
|
||||||
|
|
||||||
|
#### entity.heldItem
|
||||||
|
|
||||||
|
Equivalent to `entity.equipment[0]`.
|
||||||
|
|
||||||
|
#### entity.metadata
|
||||||
|
|
||||||
|
See http://wiki.vg/Entities#Entity_Metadata_Format for more details.
|
||||||
|
|
||||||
|
## MCServer
|
||||||
|
|
||||||
|
### CraftyJS.createMCServer(options)
|
||||||
|
|
||||||
|
Create and return an instance of the class MCServer.
|
||||||
|
|
||||||
|
options is an object containing the settings
|
||||||
|
|
||||||
|
### Properties
|
||||||
|
|
||||||
|
#### serv.entityMaxId
|
||||||
|
|
||||||
|
Current maximum entity id
|
||||||
|
|
||||||
|
#### serv.players
|
||||||
|
|
||||||
|
Array of connected players
|
||||||
|
|
||||||
|
#### serv.uuidToPlayer
|
||||||
|
|
||||||
|
Object uuid to players
|
||||||
|
|
||||||
|
#### serv.world
|
||||||
|
|
||||||
|
The map
|
||||||
|
|
||||||
|
### Methods
|
||||||
|
|
||||||
|
#### serv.createLog()
|
||||||
|
|
||||||
|
create the log file
|
||||||
|
|
||||||
|
#### serv.log(message)
|
||||||
|
|
||||||
|
logs a `message`
|
||||||
|
|
||||||
|
|
||||||
|
## Player
|
||||||
|
|
||||||
|
### Properties
|
||||||
|
|
||||||
|
#### player.entity
|
||||||
|
|
||||||
|
The entity of the player, of type `CraftyJS.Entity`
|
||||||
|
|
||||||
|
|
||||||
|
### Methods
|
||||||
|
|
||||||
|
#### player.login()
|
||||||
|
|
||||||
|
login
|
||||||
|
|
||||||
|
### player.others(client)
|
||||||
|
|
||||||
|
return the other players than `player`
|
||||||
|
|
||||||
|
### Low level properties
|
||||||
|
|
||||||
|
#### player._client
|
||||||
|
|
||||||
|
The internal implementation to communicate with a client
|
||||||
|
|
||||||
|
### Low level methods
|
||||||
|
|
||||||
|
### player._writeOthers(packetName, packetFields)
|
||||||
|
|
||||||
|
write to other players than `player` the packet `packetName` with fields `packetFields`
|
||||||
50
docs/api.md
50
docs/api.md
|
|
@ -1,50 +0,0 @@
|
||||||
# API
|
|
||||||
|
|
||||||
## MCServer
|
|
||||||
|
|
||||||
### CraftyJS.createMCServer(options)
|
|
||||||
|
|
||||||
Create and return an instance of the class MCServer.
|
|
||||||
|
|
||||||
options is an object containing the settings
|
|
||||||
|
|
||||||
### Properties
|
|
||||||
|
|
||||||
#### serv.entityMaxId
|
|
||||||
|
|
||||||
Current maximum entity id
|
|
||||||
|
|
||||||
#### serv.playersConnected
|
|
||||||
|
|
||||||
Array of connected players
|
|
||||||
|
|
||||||
#### serv.uuidToPlayer
|
|
||||||
|
|
||||||
Object uuid to players
|
|
||||||
|
|
||||||
#### serv.world
|
|
||||||
|
|
||||||
The map
|
|
||||||
|
|
||||||
### Methods
|
|
||||||
|
|
||||||
### serv.login(client)
|
|
||||||
|
|
||||||
login `client`
|
|
||||||
|
|
||||||
### serv.createLog()
|
|
||||||
|
|
||||||
create the log file
|
|
||||||
|
|
||||||
### serv.log(message)
|
|
||||||
|
|
||||||
logs a `message`
|
|
||||||
|
|
||||||
### serv.otherClients(client)
|
|
||||||
|
|
||||||
return the other clients than `client`
|
|
||||||
|
|
||||||
### serv.writeOthers(client,packetName, packetFields)
|
|
||||||
|
|
||||||
write to other clients than `client` the packet `packetName` with fields `packetFields`
|
|
||||||
|
|
||||||
10
index.js
10
index.js
|
|
@ -4,7 +4,7 @@ var util = require('util');
|
||||||
var path = require('path');
|
var path = require('path');
|
||||||
var requireIndex = require('requireindex');
|
var requireIndex = require('requireindex');
|
||||||
var serverPlugins = requireIndex(path.join(__dirname, 'lib', 'serverPlugins'));
|
var serverPlugins = requireIndex(path.join(__dirname, 'lib', 'serverPlugins'));
|
||||||
var clientPlugins = requireIndex(path.join(__dirname, 'lib', 'clientPlugins'));
|
var playerPlugins = requireIndex(path.join(__dirname, 'lib', 'playerPlugins'));
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
createMCServer:createMCServer
|
createMCServer:createMCServer
|
||||||
|
|
@ -46,9 +46,11 @@ MCServer.prototype.connect = function(options) {
|
||||||
});
|
});
|
||||||
|
|
||||||
self._server.on('login', function (client) {
|
self._server.on('login', function (client) {
|
||||||
for(var pluginName in clientPlugins) {
|
var player={};
|
||||||
clientPlugins[pluginName](self, client, options);
|
player._client=client;
|
||||||
|
for(var pluginName in playerPlugins) {
|
||||||
|
playerPlugins[pluginName](self, player, options);
|
||||||
}
|
}
|
||||||
self.login(client);
|
player.login();
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,35 +0,0 @@
|
||||||
var vec3 = require("vec3");
|
|
||||||
|
|
||||||
module.exports=inject;
|
|
||||||
|
|
||||||
function toFixedPosition(p)
|
|
||||||
{
|
|
||||||
return new vec3(Math.floor(p.x*32),Math.floor(p.y*32),Math.floor(p.z*32))
|
|
||||||
}
|
|
||||||
|
|
||||||
function inject(serv,client)
|
|
||||||
{
|
|
||||||
client.on('position', function (packet) {
|
|
||||||
var position = new vec3(packet.x, packet.y, packet.z);
|
|
||||||
var onGround = packet.onGround;
|
|
||||||
sendRelativePositionChange(client, toFixedPosition(position), onGround);
|
|
||||||
});
|
|
||||||
|
|
||||||
function sendRelativePositionChange(client, newPosition, onGround) {
|
|
||||||
if (serv.uuidToPlayer[client.uuid].position) {
|
|
||||||
var diff = newPosition.minus(serv.uuidToPlayer[client.uuid].position);
|
|
||||||
if (diff.distanceTo(new vec3(0, 0, 0)) != 0) {
|
|
||||||
|
|
||||||
serv.writeOthers(client,'rel_entity_move', {
|
|
||||||
entityId: client.id,
|
|
||||||
dX: diff.x,
|
|
||||||
dY: diff.y,
|
|
||||||
dZ: diff.z,
|
|
||||||
onGround: onGround
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
serv.uuidToPlayer[client.uuid].position = newPosition;
|
|
||||||
serv.uuidToPlayer[client.uuid].onGround = onGround;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
24
lib/entity.js
Normal file
24
lib/entity.js
Normal file
|
|
@ -0,0 +1,24 @@
|
||||||
|
var Vec3 = require('vec3').Vec3;
|
||||||
|
|
||||||
|
module.exports = Entity;
|
||||||
|
|
||||||
|
function Entity(id) {
|
||||||
|
this.id = id;
|
||||||
|
this.type = null;
|
||||||
|
this.position = new Vec3(0, 0, 0);
|
||||||
|
this.velocity = new Vec3(0, 0, 0);
|
||||||
|
this.yaw = 0;
|
||||||
|
this.pitch = 0;
|
||||||
|
this.onGround = true;
|
||||||
|
this.height = 0;
|
||||||
|
this.effects = {};
|
||||||
|
// 0 = held item, 1-4 = armor slot
|
||||||
|
this.equipment = new Array(5);
|
||||||
|
this.heldItem = this.equipment[0]; // shortcut to equipment[0]
|
||||||
|
this.isValid = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
Entity.prototype.setEquipment = function(index, item) {
|
||||||
|
this.equipment[index] = item;
|
||||||
|
this.heldItem = this.equipment[0];
|
||||||
|
};
|
||||||
16
lib/playerPlugins/communication.js
Normal file
16
lib/playerPlugins/communication.js
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
module.exports=inject;
|
||||||
|
|
||||||
|
function inject(serv,player)
|
||||||
|
{
|
||||||
|
player._writeOthers=function(packetName, packetFields) {
|
||||||
|
player.getOthers().forEach(function (otherPlayer) {
|
||||||
|
otherPlayer._client.write(packetName, packetFields);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
player.getOthers = function() {
|
||||||
|
return serv.players.filter(function (otherPlayer) {
|
||||||
|
return otherPlayer != player
|
||||||
|
});
|
||||||
|
};
|
||||||
|
}
|
||||||
227
lib/playerPlugins/login.js
Normal file
227
lib/playerPlugins/login.js
Normal file
|
|
@ -0,0 +1,227 @@
|
||||||
|
var Entity=require("../entity");
|
||||||
|
|
||||||
|
module.exports=inject;
|
||||||
|
|
||||||
|
function transformUuid(s)
|
||||||
|
{
|
||||||
|
return s.split("-").map(function(item) { return parseInt(item, 16); });
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function inject(serv,player)
|
||||||
|
{
|
||||||
|
player.login=login;
|
||||||
|
|
||||||
|
function addPlayer()
|
||||||
|
{
|
||||||
|
serv.entityMaxId++;
|
||||||
|
player.entity=new Entity(serv.entityMaxId);
|
||||||
|
serv.players.push(player);
|
||||||
|
serv.uuidToPlayer[player._client.uuid] = player;
|
||||||
|
}
|
||||||
|
|
||||||
|
function sendLogin()
|
||||||
|
{
|
||||||
|
// send init data so client will start rendering world
|
||||||
|
player._client.write('login', {
|
||||||
|
entityId: player.entity.id,
|
||||||
|
levelType: 'default',
|
||||||
|
gameMode: 0,
|
||||||
|
dimension: 0,
|
||||||
|
difficulty: 0,
|
||||||
|
reducedDebugInfo: false,
|
||||||
|
maxPlayers: serv._server.maxPlayers
|
||||||
|
});
|
||||||
|
}
|
||||||
|
function sendMap()
|
||||||
|
{
|
||||||
|
player._client.write('map_chunk', {
|
||||||
|
x: 0,
|
||||||
|
z: 0,
|
||||||
|
groundUp: true,
|
||||||
|
bitMap: 0xffff,
|
||||||
|
chunkData: serv.world.dump()
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function sendInitialPosition()
|
||||||
|
{
|
||||||
|
player._client.write('position', {
|
||||||
|
x: 6,
|
||||||
|
y: 53,
|
||||||
|
z: 6,
|
||||||
|
yaw: 0,
|
||||||
|
pitch: 0,
|
||||||
|
flags: 0x00
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateTime()
|
||||||
|
{
|
||||||
|
player._client.write('update_time', {
|
||||||
|
age: [0, 0],
|
||||||
|
time: [0, 1]
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateGameState()
|
||||||
|
{
|
||||||
|
player._client.write('game_state_change', {
|
||||||
|
reason: 3,
|
||||||
|
gameMode: 0
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function announceLogin()
|
||||||
|
{
|
||||||
|
player._client.on('chat', function (data) {
|
||||||
|
var message = '<' + client.username + '>' + ' ' + data.message;
|
||||||
|
playerChat(message, client.username);
|
||||||
|
console.log("[INFO] " + message);
|
||||||
|
serv.log("[INFO] " + message);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function fillTabList()
|
||||||
|
{
|
||||||
|
player._writeOthers('player_info',{
|
||||||
|
action: 0,
|
||||||
|
data: [{
|
||||||
|
UUID: transformUuid(player._client.uuid),
|
||||||
|
name: player._client.username,
|
||||||
|
properties: [],
|
||||||
|
gamemode: 0,
|
||||||
|
ping: 1,
|
||||||
|
hasDisplayName: true,
|
||||||
|
displayName: player._client.username
|
||||||
|
}]
|
||||||
|
});
|
||||||
|
|
||||||
|
player._client.write('player_info', {
|
||||||
|
action: 0,
|
||||||
|
data: serv.players
|
||||||
|
.map(function (otherPlayer) {
|
||||||
|
return {
|
||||||
|
UUID: transformUuid(otherPlayer._client.uuid),
|
||||||
|
name: otherPlayer._client.username,
|
||||||
|
properties: [],
|
||||||
|
gamemode: 0,
|
||||||
|
ping: 1,
|
||||||
|
hasDisplayName: true,
|
||||||
|
displayName: otherPlayer._client.username
|
||||||
|
};
|
||||||
|
})
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function spawn()
|
||||||
|
{
|
||||||
|
player.getOthers().forEach(function (otherPlayer) {
|
||||||
|
var pos = otherPlayer.entity.position;
|
||||||
|
player._client.write('named_entity_spawn', {
|
||||||
|
entityId: otherPlayer.entity.id,
|
||||||
|
playerUUID: transformUuid(otherPlayer._client.uuid),
|
||||||
|
x: pos ? pos.x : 6 * 32,
|
||||||
|
y: pos ? pos.y : 53 * 32,
|
||||||
|
z: pos ? pos.z : 6 * 32,
|
||||||
|
yaw: 0,
|
||||||
|
pitch: 0,
|
||||||
|
currentItem: 0,
|
||||||
|
metadata: []
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
player._writeOthers('named_entity_spawn',{
|
||||||
|
entityId: player.entity.id,
|
||||||
|
playerUUID: transformUuid(player._client.uuid),
|
||||||
|
x: 6 * 32,
|
||||||
|
y: 53 * 32,
|
||||||
|
z: 6 * 32,
|
||||||
|
yaw: 0,
|
||||||
|
pitch: 0,
|
||||||
|
currentItem: 0,
|
||||||
|
metadata: []
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function announceJoin()
|
||||||
|
{
|
||||||
|
broadcast(player._client.username + ' joined the game.', "yellow");
|
||||||
|
var addr = player._client.socket.remoteAddress + ':' + player._client.socket.remotePort;
|
||||||
|
console.log("[INFO]: " + player._client.username + ' connected', '(' + addr + ')');
|
||||||
|
serv.log("[INFO]: " + player._client.username + ' connected', '(' + addr + ')');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function playerChat(message, exclude, username) {
|
||||||
|
var client;
|
||||||
|
//translate = username ? 'chat.type.text' : 'chat.type.text';
|
||||||
|
username = username || '';
|
||||||
|
for(var clientId in server.clients) {
|
||||||
|
if(!serv._server.clients.hasOwnProperty(clientId)) continue;
|
||||||
|
|
||||||
|
client = serv._server.clients[clientId];
|
||||||
|
if(client !== exclude) {
|
||||||
|
var msg = {
|
||||||
|
"text": username + message
|
||||||
|
};
|
||||||
|
client.write('chat', { message: JSON.stringify(msg), position: 0 });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
function broadcast(message, color) {
|
||||||
|
var client;
|
||||||
|
for(var clientId in serv._server.clients) {
|
||||||
|
if(!serv._server.clients.hasOwnProperty(clientId)) continue;
|
||||||
|
|
||||||
|
client = serv._server.clients[clientId];
|
||||||
|
var msg = {
|
||||||
|
"text": message,
|
||||||
|
"color": color
|
||||||
|
};
|
||||||
|
client.write('chat', { message: JSON.stringify(msg), position: 0 });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function login()
|
||||||
|
{
|
||||||
|
if (serv.uuidToPlayer[player._client.uuid]) {
|
||||||
|
player._client.end("You are already connected");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
addPlayer();
|
||||||
|
sendLogin();
|
||||||
|
sendMap();
|
||||||
|
sendInitialPosition();
|
||||||
|
|
||||||
|
console.log("[INFO]: position written, player spawning...");
|
||||||
|
serv.log("[INFO]: position written, player spawning...");
|
||||||
|
|
||||||
|
updateTime();
|
||||||
|
updateGameState();
|
||||||
|
announceLogin();
|
||||||
|
fillTabList();
|
||||||
|
spawn();
|
||||||
|
|
||||||
|
announceJoin();
|
||||||
|
|
||||||
|
|
||||||
|
var addr = player._client.socket.remoteAddress + ':' + player._client.socket.remotePort;
|
||||||
|
player._client.on('end', function () {
|
||||||
|
broadcast(player._client.username + ' joined the game.', "yellow");
|
||||||
|
console.log("[INFO]: " + player._client.username + ' disconnected', '(' + addr + ')');
|
||||||
|
serv.log("[INFO]: " + player._client.username + ' disconnected', '(' + addr + ')');
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
player._client.on('error', function (error) {
|
||||||
|
console.log('[ERR] ' + error.stack);
|
||||||
|
serv.log('[ERR]: Client: ' + error.stack);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
34
lib/playerPlugins/updatePositions.js
Normal file
34
lib/playerPlugins/updatePositions.js
Normal file
|
|
@ -0,0 +1,34 @@
|
||||||
|
var vec3 = require("vec3");
|
||||||
|
|
||||||
|
module.exports=inject;
|
||||||
|
|
||||||
|
function toFixedPosition(p)
|
||||||
|
{
|
||||||
|
return new vec3(Math.floor(p.x*32),Math.floor(p.y*32),Math.floor(p.z*32))
|
||||||
|
}
|
||||||
|
|
||||||
|
function inject(serv,player)
|
||||||
|
{
|
||||||
|
player._client.on('position', function (packet) {
|
||||||
|
var position = new vec3(packet.x, packet.y, packet.z);
|
||||||
|
var onGround = packet.onGround;
|
||||||
|
sendRelativePositionChange(toFixedPosition(position), onGround);
|
||||||
|
});
|
||||||
|
|
||||||
|
function sendRelativePositionChange(newPosition, onGround) {
|
||||||
|
if (player.entity.position.distanceTo(new vec3(0, 0, 0)) != 0) {
|
||||||
|
var diff = newPosition.minus(player.entity.position);
|
||||||
|
if (diff.distanceTo(new vec3(0, 0, 0)) != 0) {
|
||||||
|
player._writeOthers('rel_entity_move', {
|
||||||
|
entityId: player.entity.id,
|
||||||
|
dX: diff.x,
|
||||||
|
dY: diff.y,
|
||||||
|
dZ: diff.z,
|
||||||
|
onGround: onGround
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
player.entity.position = newPosition;
|
||||||
|
player.entity.onGround = onGround;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,16 +0,0 @@
|
||||||
module.exports=inject;
|
|
||||||
|
|
||||||
function inject(serv)
|
|
||||||
{
|
|
||||||
serv.writeOthers=function(client,packetName, packetFields) {
|
|
||||||
serv.otherClients(client).forEach(function (otherClient) {
|
|
||||||
otherClient.write(packetName, packetFields);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
serv.otherClients = function(client) {
|
|
||||||
return serv.playersConnected.filter(function (otherClient) {
|
|
||||||
return otherClient != client
|
|
||||||
});
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
@ -1,227 +0,0 @@
|
||||||
module.exports=inject;
|
|
||||||
|
|
||||||
function transformUuid(s)
|
|
||||||
{
|
|
||||||
return s.split("-").map(function(item) { return parseInt(item, 16); });
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function inject(serv)
|
|
||||||
{
|
|
||||||
serv.login=login;
|
|
||||||
|
|
||||||
function addPlayer(client)
|
|
||||||
{
|
|
||||||
serv.entityMaxId++;
|
|
||||||
client.id = serv.entityMaxId;
|
|
||||||
serv.playersConnected.push(client);
|
|
||||||
console.log(client.uuid);
|
|
||||||
serv.uuidToPlayer[client.uuid] = client;
|
|
||||||
}
|
|
||||||
|
|
||||||
function sendLogin(client)
|
|
||||||
{
|
|
||||||
// send init data so client will start rendering world
|
|
||||||
client.write('login', {
|
|
||||||
entityId: client.id,
|
|
||||||
levelType: 'default',
|
|
||||||
gameMode: 0,
|
|
||||||
dimension: 0,
|
|
||||||
difficulty: 0,
|
|
||||||
reducedDebugInfo: false,
|
|
||||||
maxPlayers: serv._server.maxPlayers
|
|
||||||
});
|
|
||||||
}
|
|
||||||
function sendMap(client)
|
|
||||||
{
|
|
||||||
client.write('map_chunk', {
|
|
||||||
x: 0,
|
|
||||||
z: 0,
|
|
||||||
groundUp: true,
|
|
||||||
bitMap: 0xffff,
|
|
||||||
chunkData: serv.world.dump()
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function sendInitialPosition(client)
|
|
||||||
{
|
|
||||||
client.write('position', {
|
|
||||||
x: 6,
|
|
||||||
y: 53,
|
|
||||||
z: 6,
|
|
||||||
yaw: 0,
|
|
||||||
pitch: 0,
|
|
||||||
flags: 0x00
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function updateTime(client)
|
|
||||||
{
|
|
||||||
client.write('update_time', {
|
|
||||||
age: [0, 0],
|
|
||||||
time: [0, 1]
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function updateGameState(client)
|
|
||||||
{
|
|
||||||
client.write('game_state_change', {
|
|
||||||
reason: 3,
|
|
||||||
gameMode: 0
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function announceLogin(client)
|
|
||||||
{
|
|
||||||
client.on('chat', function (data) {
|
|
||||||
var message = '<' + client.username + '>' + ' ' + data.message;
|
|
||||||
playerChat(message, client.username);
|
|
||||||
console.log("[INFO] " + message);
|
|
||||||
serv.log("[INFO] " + message);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function fillTabList(client)
|
|
||||||
{
|
|
||||||
serv.otherClients(client).forEach(function (otherClient) {
|
|
||||||
otherClient.write('player_info', {
|
|
||||||
action: 0,
|
|
||||||
data: [{
|
|
||||||
UUID: transformUuid(client.uuid),
|
|
||||||
name: client.username,
|
|
||||||
properties: [],
|
|
||||||
gamemode: 0,
|
|
||||||
ping: 1,
|
|
||||||
hasDisplayName: true,
|
|
||||||
displayName: client.username
|
|
||||||
}]
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
client.write('player_info', {
|
|
||||||
action: 0,
|
|
||||||
data: serv.playersConnected
|
|
||||||
.map(function (otherClient) {
|
|
||||||
return {
|
|
||||||
UUID: transformUuid(otherClient.uuid),
|
|
||||||
name: otherClient.username,
|
|
||||||
properties: [],
|
|
||||||
gamemode: 0,
|
|
||||||
ping: 1,
|
|
||||||
hasDisplayName: true,
|
|
||||||
displayName: otherClient.username
|
|
||||||
};
|
|
||||||
})
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function spawn(client)
|
|
||||||
{
|
|
||||||
serv.otherClients(client).forEach(function (otherClient) {
|
|
||||||
var pos = serv.uuidToPlayer[otherClient.uuid].position;
|
|
||||||
client.write('named_entity_spawn', {
|
|
||||||
entityId: otherClient.id,
|
|
||||||
playerUUID: transformUuid(otherClient.uuid),
|
|
||||||
x: pos ? pos.x : 6 * 32,
|
|
||||||
y: pos ? pos.y : 53 * 32,
|
|
||||||
z: pos ? pos.z : 6 * 32,
|
|
||||||
yaw: 0,
|
|
||||||
pitch: 0,
|
|
||||||
currentItem: 0,
|
|
||||||
metadata: []
|
|
||||||
});
|
|
||||||
otherClient.write('named_entity_spawn', {
|
|
||||||
entityId: client.id,
|
|
||||||
playerUUID: transformUuid(client.uuid),
|
|
||||||
x: 6 * 32,
|
|
||||||
y: 53 * 32,
|
|
||||||
z: 6 * 32,
|
|
||||||
yaw: 0,
|
|
||||||
pitch: 0,
|
|
||||||
currentItem: 0,
|
|
||||||
metadata: []
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function announceJoin(client)
|
|
||||||
{
|
|
||||||
broadcast(client.username + ' joined the game.', "yellow");
|
|
||||||
var addr = client.socket.remoteAddress + ':' + client.socket.remotePort;
|
|
||||||
console.log("[INFO]: " + client.username + ' connected', '(' + addr + ')');
|
|
||||||
serv.log("[INFO]: " + client.username + ' connected', '(' + addr + ')');
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function playerChat(message, exclude, username) {
|
|
||||||
var client;
|
|
||||||
//translate = username ? 'chat.type.text' : 'chat.type.text';
|
|
||||||
username = username || '';
|
|
||||||
for(var clientId in server.clients) {
|
|
||||||
if(!serv._server.clients.hasOwnProperty(clientId)) continue;
|
|
||||||
|
|
||||||
client = serv._server.clients[clientId];
|
|
||||||
if(client !== exclude) {
|
|
||||||
var msg = {
|
|
||||||
"text": username + message
|
|
||||||
};
|
|
||||||
client.write('chat', { message: JSON.stringify(msg), position: 0 });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
function broadcast(message, color) {
|
|
||||||
var client;
|
|
||||||
for(var clientId in serv._server.clients) {
|
|
||||||
if(!serv._server.clients.hasOwnProperty(clientId)) continue;
|
|
||||||
|
|
||||||
client = serv._server.clients[clientId];
|
|
||||||
var msg = {
|
|
||||||
"text": message,
|
|
||||||
"color": color
|
|
||||||
};
|
|
||||||
client.write('chat', { message: JSON.stringify(msg), position: 0 });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function login(client)
|
|
||||||
{
|
|
||||||
if (serv.uuidToPlayer[client.uuid]) {
|
|
||||||
client.end("You are already connected");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
addPlayer(client);
|
|
||||||
sendLogin(client);
|
|
||||||
sendMap(client);
|
|
||||||
sendInitialPosition(client);
|
|
||||||
|
|
||||||
console.log("[INFO]: position written, player spawning...");
|
|
||||||
serv.log("[INFO]: position written, player spawning...");
|
|
||||||
|
|
||||||
updateTime(client);
|
|
||||||
updateGameState(client);
|
|
||||||
announceLogin(client);
|
|
||||||
fillTabList(client);
|
|
||||||
spawn(client);
|
|
||||||
|
|
||||||
announceJoin(client);
|
|
||||||
|
|
||||||
|
|
||||||
var addr = client.socket.remoteAddress + ':' + client.socket.remotePort;
|
|
||||||
client.on('end', function () {
|
|
||||||
broadcast(client.username + ' joined the game.', "yellow");
|
|
||||||
console.log("[INFO]: " + client.username + ' disconnected', '(' + addr + ')');
|
|
||||||
serv.log("[INFO]: " + client.username + ' disconnected', '(' + addr + ')');
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
client.on('error', function (error) {
|
|
||||||
console.log('[ERR] ' + error.stack);
|
|
||||||
serv.log('[ERR]: Client: ' + error.stack);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -3,6 +3,6 @@ module.exports=inject;
|
||||||
function inject(serv)
|
function inject(serv)
|
||||||
{
|
{
|
||||||
serv.entityMaxId=0;
|
serv.entityMaxId=0;
|
||||||
serv.playersConnected=[];
|
serv.players=[];
|
||||||
serv.uuidToPlayer={};
|
serv.uuidToPlayer={};
|
||||||
}
|
}
|
||||||
Loading…
Reference in a new issue