diff --git a/server/Converter.js b/server/Converter.js index b0f30f2..0562ec5 100644 --- a/server/Converter.js +++ b/server/Converter.js @@ -1,7 +1,23 @@ module.exports.toAbsoluteInt = function(float = 0.0) { - return Math.round(float * 32.0); + return Math.floor(float * 32.0); } module.exports.to360Fraction = function(float = 0.0) { - return Math.floor((float / 360) * 256); + if (float < 0) { + return Math.abs(Math.max(Math.floor((map(float, 0, -360, 360, 0) / 360) * 256) - 1, 0)); + } else if (float > 0) { + return Math.max(Math.floor((float / 360) * 256) - 1, 0); + } + //return Math.max(Math.floor((float / 360) * 256), 0) - 1; +} + +function map(input, inputMin, inputMax, outputMin, outputMax) { + const newv = (input - inputMin) / (inputMax - inputMin) * (outputMax - outputMin) + outputMin; + + if (outputMin < outputMax) return constrain(newv, outputMin, outputMax); + else return constrain(newv, outputMax, outputMin); +} + +function constrain(input, low, high) { + return Math.max(Math.min(input, high), low); } \ No newline at end of file diff --git a/server/Entities/EntityPlayer.js b/server/Entities/EntityPlayer.js index 36fbbe3..a7d9a4f 100644 --- a/server/Entities/EntityPlayer.js +++ b/server/Entities/EntityPlayer.js @@ -1,10 +1,65 @@ const EntityLiving = require("./EntityLiving.js"); +const user = require("../user.js"); + +const Converter = require("../Converter.js"); +const PacketMappingTable = require("../PacketMappingTable.js"); +const NamedPackets = require("../NamedPackets.js"); class EntityPlayer extends EntityLiving { - constructor(EID = 0, x = 0, y = 0, z = 0) { - super(EID, x, y, z); + constructor(parent = new user, x = 0, y = 0, z = 0) { + super(parent.id, x, y, z); - + this.lastX = 0; + this.lastY = 0; + this.lastZ = 0; + this.absX = 0; + this.absY = 0; + this.absZ = 0; + + this.absYaw = 0; + this.absPitch = 0; + + this.lastYaw = 0; + this.lastPitch = 0; + + this.allPacket = new PacketMappingTable[NamedPackets.EntityTeleport](this.EID, this.x, this.y, this.z, this.absYaw, this.absPitch); + this.allPacket.soup(); + this.allPacket.writePacket(); + + this.parentPlayer = parent; + } + + onTick() { + super.onTick(); + + this.absX = Math.floor(this.x); + this.absY = Math.floor(this.y); + this.absZ = Math.floor(this.z); + + this.absYaw = Math.floor(this.yaw); + this.absPitch = Math.floor(this.pitch); + + if ((this.absX != this.lastX || this.absY != this.lastY || this.absZ != this.lastZ)) { + // all + this.allPacket.writer.offset = 5; + this.allPacket.writer.writeInt(Converter.toAbsoluteInt(this.x)); + this.allPacket.writer.writeInt(Converter.toAbsoluteInt(this.y)); + this.allPacket.writer.writeInt(Converter.toAbsoluteInt(this.z)); + this.allPacket.writer.writeUByte(Converter.to360Fraction(this.absYaw)); + this.allPacket.writer.writeUByte(Converter.to360Fraction(this.absPitch)); + + global.sendToAllPlayersButSelf(this.EID, this.allPacket.toBuffer()); + } else if (this.absYaw != this.lastYaw || this.absPitch != this.lastPitch) { + // look only + global.sendToAllPlayersButSelf(this.EID, new PacketMappingTable[NamedPackets.EntityLook](this.EID, this.absYaw, this.absPitch).writePacket()); + } + + this.lastYaw = this.absYaw; + this.lastPitch = this.absPitch; + + this.lastX = this.absX; + this.lastY = this.absY; + this.lastZ = this.absZ; } } diff --git a/server/PacketMappingTable.js b/server/PacketMappingTable.js index b3b2083..dd31bcf 100644 --- a/server/PacketMappingTable.js +++ b/server/PacketMappingTable.js @@ -8,6 +8,8 @@ const Packet0KeepAlive = require("./Packets/Packet0KeepAlive.js"), Packet13PlayerPositionAndLook = require("./Packets/Packet13PlayerPositionAndLook.js"), Packet18Animation = require("./Packets/Packet18Animation.js"), Packet20NamedEntitySpawn = require("./Packets/Packet20NamedEntitySpawn.js"), + Packet32EntityLook = require("./Packets/Packet32EntityLook.js"), + Packet34EntityTeleport = require("./Packets/Packet34EntityTeleport.js"), Packet50PreChunk = require("./Packets/Packet50PreChunk.js"), Packet53BlockChange = require("./Packets/Packet53BlockChange.js"), Packet103SetSlot = require("./Packets/Packet103SetSlot.js"); @@ -23,6 +25,8 @@ const mappingTable = { 0x0D: Packet13PlayerPositionAndLook, 0x12: Packet18Animation, 0x14: Packet20NamedEntitySpawn, + 0x20: Packet32EntityLook, + 0x22: Packet34EntityTeleport, 0x32: Packet50PreChunk, 0x35: Packet53BlockChange, 0x67: Packet103SetSlot diff --git a/server/Packets/Packet.js b/server/Packets/Packet.js index e6916ef..6cfbe48 100644 --- a/server/Packets/Packet.js +++ b/server/Packets/Packet.js @@ -4,11 +4,13 @@ module.exports = class { constructor(packetID = 0x00) { this.id = packetID; + this.packetSize = 0; + this.writer = null; } writePacket() { - this.writer = new bufferStuff.Writer(); + this.writer = new bufferStuff.Writer(this.packetSize); this.writer.writeByte(this.id); diff --git a/server/Packets/Packet20NamedEntitySpawn.js b/server/Packets/Packet20NamedEntitySpawn.js index 22a4621..feefa7c 100644 --- a/server/Packets/Packet20NamedEntitySpawn.js +++ b/server/Packets/Packet20NamedEntitySpawn.js @@ -23,8 +23,8 @@ class Packet20NamedEntitySpawn extends Packet { this.writer.writeInt(this.absX); this.writer.writeInt(this.absY); this.writer.writeInt(this.absZ); - this.writer.writeByte(this.packedYaw); - this.writer.writeByte(this.packedPitch); + this.writer.writeUByte(this.packedYaw); + this.writer.writeUByte(this.packedPitch); this.writer.writeShort(this.currentItem); return this.toBuffer(); diff --git a/server/Packets/Packet32EntityLook.js b/server/Packets/Packet32EntityLook.js new file mode 100644 index 0000000..0602039 --- /dev/null +++ b/server/Packets/Packet32EntityLook.js @@ -0,0 +1,26 @@ +const Packet = require("./Packet.js"); +const Converter = require("../Converter.js"); + +class Packet32EntityLook extends Packet { + constructor(EID = 0, yaw = 0, pitch = 0) { + super(0x20); + + this.packetSize = 7; + + this.EID = EID; + this.packedYaw = Converter.to360Fraction(yaw); + this.packedPitch = Converter.to360Fraction(pitch); + } + + writePacket() { + super.writePacket(); + + this.writer.writeInt(this.EID); + this.writer.writeUByte(this.packedYaw); + this.writer.writeUByte(this.packedPitch); + + return this.toBuffer(); + } +} + +module.exports = Packet32EntityLook; \ No newline at end of file diff --git a/server/Packets/Packet34EntityTeleport.js b/server/Packets/Packet34EntityTeleport.js new file mode 100644 index 0000000..4993a15 --- /dev/null +++ b/server/Packets/Packet34EntityTeleport.js @@ -0,0 +1,34 @@ +const Packet = require("./Packet.js"); +const Converter = require("../Converter.js"); + +class Packet34EntityTeleport extends Packet { + constructor(EID = 0, x = 0, y = 0, z = 0, yaw = 0, pitch = 0) { + super(0x22); + + this.packetSize = 19; + + this.EID = EID; + this.absX = Converter.toAbsoluteInt(x); + this.absY = Converter.toAbsoluteInt(y); + this.absZ = Converter.toAbsoluteInt(z); + this.packedYaw = Converter.to360Fraction(yaw); + this.packedPitch = Converter.to360Fraction(pitch); + } + + soup() { + super.writePacket(); + this.writer.writeInt(this.EID); + } + + writePacket() { + this.writer.writeInt(this.absX); + this.writer.writeInt(this.absY); + this.writer.writeInt(this.absZ); + this.writer.writeUByte(this.packedYaw); + this.writer.writeUByte(this.packedPitch); + + return this.toBuffer(); + } +} + +module.exports = Packet34EntityTeleport; \ No newline at end of file diff --git a/server/server.js b/server/server.js index 56bc56a..99f6e27 100644 --- a/server/server.js +++ b/server/server.js @@ -22,9 +22,24 @@ global.getUserByKey = function(key) { return netUsers[key]; } +global.sendToAllPlayers = function(buffer = Buffer.alloc(0)) { + for (let key of netUserKeys) { + const user = netUsers[key]; + user.socket.write(buffer); + } +} + +global.sendToAllPlayersButSelf = function(id, buffer = Buffer.alloc(0)) { + for (let key of netUserKeys) { + if (key == id) continue; + const user = netUsers[key]; + user.socket.write(buffer); + } +} + function addUser(socket) { let user = new User(global.fromIDPool(), socket); - user.entityRef = new EntityPlayer(user.id, 8.5, 65.5, 8.5); + user.entityRef = new EntityPlayer(user, 8.5, 65.5, 8.5); netUsers[user.id] = user; netUserKeys = Object.keys(netUsers); @@ -95,7 +110,7 @@ module.exports.init = function(config) { for (let key of netUserKeys) { const user = netUsers[key]; - //user.entityRef.onTick(); + if (user.loginFinished) user.entityRef.onTick(); } // Send queued chunks to users @@ -177,8 +192,16 @@ module.exports.connection = async function(socket = new Socket) { } } - // Send this user to other online users + // Send this user to other online user + global.sendToAllPlayersButSelf(thisUser.id, new PacketMappingTable[NamedPackets.NamedEntitySpawn](thisUser.id, thisUser.username, thisUser.entityRef.x, thisUser.entityRef.y, thisUser.entityRef.z, thisUser.entityRef.yaw, thisUser.entityRef.pitch, 0).writePacket()); + // send all online users to this user + for (let key of netUserKeys) { + if (key == thisUser.id) continue; + const user = netUsers[key]; + + socket.write(new PacketMappingTable[NamedPackets.NamedEntitySpawn](user.id, user.username, user.entityRef.x, user.entityRef.y, user.entityRef.z, user.entityRef.yaw, user.entityRef.pitch, 0).writePacket()); + } break; case NamedPackets.Handshake: @@ -227,6 +250,27 @@ module.exports.connection = async function(socket = new Socket) { } break; + case NamedPackets.PlayerLook: + thisUser.entityRef.yaw = reader.readFloat() % 360 % -360; + thisUser.entityRef.pitch = reader.readFloat() % 360 % -360; + break; + + case NamedPackets.PlayerPosition: + thisUser.entityRef.x = reader.readDouble(); + thisUser.entityRef.y = reader.readDouble(); + reader.readDouble(); // stance + thisUser.entityRef.z = reader.readDouble(); + break; + + case NamedPackets.PlayerPositionAndLook: + thisUser.entityRef.x = reader.readDouble(); + thisUser.entityRef.y = reader.readDouble(); + reader.readDouble(); // stance + thisUser.entityRef.z = reader.readDouble(); + thisUser.entityRef.yaw = reader.readFloat() % 360 % -360; + thisUser.entityRef.pitch = reader.readFloat() % 360 % -360; + break; + case NamedPackets.Animation: const EID = reader.readInt(); const cachedPacket = new PacketMappingTable[NamedPackets.Animation](thisUser.id, reader.readByte()).writePacket();