mc-beta-server/server/server.js

292 lines
8.4 KiB
JavaScript
Raw Normal View History

2021-08-12 04:58:56 +01:00
const bufferStuff = require("./bufferStuff.js");
const ChunkManager = require("./chunkManager.js");
const User = require("./user.js");
2021-08-20 22:42:00 +01:00
const EntityPlayer = require("./Entities/EntityPlayer.js");
2021-08-12 04:58:56 +01:00
const PacketMappingTable = require("./PacketMappingTable.js");
const NamedPackets = require("./NamedPackets.js");
2021-08-20 22:42:00 +01:00
const Converter = require("./Converter.js");
2021-08-11 15:05:14 +01:00
2021-08-12 01:44:18 +01:00
const Socket = require("net").Socket;
2021-08-12 04:58:56 +01:00
let idPool = 1;
global.fromIDPool = function() {
const oldVal = idPool;
idPool++;
return oldVal;
}
let netUsers = {},
netUserKeys = Object.keys(netUsers);
2021-08-12 08:41:08 +01:00
global.getUserByKey = function(key) {
return netUsers[key];
}
2021-08-12 04:58:56 +01:00
function addUser(socket) {
let user = new User(global.fromIDPool(), socket);
2021-08-20 22:42:00 +01:00
user.entityRef = new EntityPlayer(user.id, 8.5, 65.5, 8.5);
2021-08-12 04:58:56 +01:00
netUsers[user.id] = user;
netUserKeys = Object.keys(netUsers);
return user;
}
2021-08-12 08:41:08 +01:00
function removeUser(id) {
delete netUsers[id];
netUserKeys = Object.keys(netUsers);
2021-08-12 04:58:56 +01:00
}
let config = {};
let entities = {};
2021-08-15 11:33:08 +01:00
let entityKeys = {};
2021-08-12 04:58:56 +01:00
global.chunkManager = new ChunkManager();
2021-08-12 08:41:08 +01:00
global.generatingChunks = false;
2021-08-12 04:58:56 +01:00
2021-08-18 01:25:55 +01:00
let tickInterval, tickCounter = BigInt(0), worldTime = 0;
2021-08-12 04:58:56 +01:00
let tickRate = BigInt(20);
2021-08-11 15:05:14 +01:00
2021-08-12 01:44:18 +01:00
module.exports.init = function(config) {
2021-08-12 04:58:56 +01:00
config = config;
2021-08-12 01:44:18 +01:00
console.log(`Up! Running at 0.0.0.0:${config.port}`);
2021-08-12 04:58:56 +01:00
tickInterval = setInterval(() => {
2021-08-15 11:33:08 +01:00
// Runs every sec
if (tickCounter % tickRate == 0) {
for (let key of netUserKeys) {
2021-08-15 11:33:08 +01:00
const user = netUsers[key];
user.socket.write(new PacketMappingTable[NamedPackets.KeepAlive]().writePacket());
2021-08-18 01:25:55 +01:00
if (user.loginFinished) user.socket.write(new PacketMappingTable[NamedPackets.TimeUpdate](BigInt(worldTime)).writePacket());
}
}
2021-08-15 11:33:08 +01:00
// Do chunk updates
2021-08-20 22:42:00 +01:00
// Don't update if chunk is generating
2021-08-12 08:41:08 +01:00
if (!global.generatingChunks) {
let itemsToRemove = [];
2021-08-15 11:33:08 +01:00
// Do a max of 128 chunk updates per tick
2021-08-12 08:41:08 +01:00
for (let i = 0; i < Math.min(global.chunkManager.queuedBlockUpdates.getLength(), 128); i++) {
const chunkUpdateKey = global.chunkManager.queuedBlockUpdates.itemKeys[i];
const chunkUpdate = global.chunkManager.queuedBlockUpdates.items[chunkUpdateKey];
2021-08-20 22:42:00 +01:00
// Don't update if chunk is nonexistant
if (global.chunkManager.chunks[chunkUpdate[1]] == null) continue;
if (global.chunkManager.chunks[chunkUpdate[1]][chunkUpdate[2]] == null) continue;
2021-08-12 08:41:08 +01:00
itemsToRemove.push(chunkUpdateKey);
try {
global.chunkManager.chunks[chunkUpdate[1]][chunkUpdate[2]][chunkUpdate[3]][chunkUpdate[4]][chunkUpdate[5]] = chunkUpdate[0];
const packet = new PacketMappingTable[NamedPackets.BlockChange](chunkUpdate[4] + (16 * chunkUpdate[1]), chunkUpdate[3], chunkUpdate[5] + (16 * chunkUpdate[2]), chunkUpdate[0]).writePacket();
2021-08-20 22:42:00 +01:00
for (let userKey of netUserKeys) {
2021-08-12 08:41:08 +01:00
const user = netUsers[userKey];
if (user.loginFinished) user.socket.write(packet);
}
2021-08-20 22:42:00 +01:00
} catch (e) {
console.error(e);
}
2021-08-12 08:41:08 +01:00
}
for (let item of itemsToRemove) {
global.chunkManager.queuedBlockUpdates.remove(item, false);
}
}
2021-08-15 11:33:08 +01:00
// Entity update!
for (let key of netUserKeys) {
const user = netUsers[key];
2021-08-21 08:38:12 +01:00
2021-08-20 22:42:00 +01:00
//user.entityRef.onTick();
2021-08-15 11:33:08 +01:00
}
// Send queued chunks to users
2021-08-12 04:58:56 +01:00
for (let key of netUserKeys) {
2021-08-15 00:21:41 +01:00
const user = netUsers[key];
if (user.loginFinished) {
let itemsToRemove = [];
for (let i = 0; i < Math.min(user.chunksToSend.getLength(), 128); i++) {
const chunkKey = user.chunksToSend.itemKeys[i];
itemsToRemove.push(chunkKey);
user.socket.write(user.chunksToSend.items[chunkKey]);
}
2021-08-12 04:58:56 +01:00
2021-08-15 00:21:41 +01:00
for (let item of itemsToRemove) {
user.chunksToSend.remove(item, false);
}
2021-08-12 04:58:56 +01:00
2021-08-15 00:21:41 +01:00
user.chunksToSend.regenerateIterableArray();
2021-08-12 04:58:56 +01:00
}
}
tickCounter++;
2021-08-18 01:25:55 +01:00
worldTime++;
2021-08-12 04:58:56 +01:00
}, 1000 / parseInt(tickRate.toString()));
2021-08-12 01:44:18 +01:00
}
2021-08-12 08:41:08 +01:00
module.exports.connection = async function(socket = new Socket) {
2021-08-12 04:58:56 +01:00
const thisUser = addUser(socket);
2021-08-12 01:44:18 +01:00
socket.on('data', function(chunk) {
2021-08-12 04:58:56 +01:00
const reader = new bufferStuff.Reader(chunk);
2021-08-15 00:21:41 +01:00
const packetID = reader.readByte();
switch(packetID) {
2021-08-20 22:42:00 +01:00
case NamedPackets.Disconnect:
removeUser(thisUser.id);
break;
2021-08-12 04:58:56 +01:00
case NamedPackets.KeepAlive:
2021-08-20 22:42:00 +01:00
2021-08-12 04:58:56 +01:00
break;
case NamedPackets.LoginRequest:
socket.write(new PacketMappingTable[NamedPackets.LoginRequest](reader.readInt(), reader.readString(), reader.readLong(), reader.readByte()).writePacket(thisUser.id));
socket.write(new PacketMappingTable[NamedPackets.SpawnPosition]().writePacket());
for (let x = -3; x < 4; x++) {
for (let z = -3; z < 4; z++) {
socket.write(new PacketMappingTable[NamedPackets.PreChunk](x, z, true).writePacket());
}
}
2021-08-15 11:33:08 +01:00
// Place a layer of glass under the player so they don't fall n' die
for (let x = 0; x < 16; x++) {
for (let z = 0; z < 16; z++) {
socket.write(new PacketMappingTable[NamedPackets.BlockChange](x, 64, z, 20, 0).writePacket());
}
}
2021-08-12 04:58:56 +01:00
socket.write(new PacketMappingTable[NamedPackets.Player](true).writePacket());
2021-08-18 01:25:55 +01:00
const joinMessage = new PacketMappingTable[NamedPackets.ChatMessage](`\u00A7e${thisUser.username} has joined the game`).writePacket();
for (let key of netUserKeys) {
netUsers[key].socket.write(joinMessage);
}
2021-08-12 04:58:56 +01:00
2021-08-20 22:42:00 +01:00
socket.write(new PacketMappingTable[NamedPackets.SetSlot](0, 36, 3, 64, 0).writePacket());
2021-08-12 04:58:56 +01:00
socket.write(new PacketMappingTable[NamedPackets.PlayerPositionAndLook](8.5, 65 + 1.6200000047683716, 65, 8.5, 0, 0, false).writePacket());
thisUser.loginFinished = true;
2021-08-12 08:41:08 +01:00
2021-08-20 22:42:00 +01:00
// Send chunks
2021-08-12 08:41:08 +01:00
for (let x = -3; x < 4; x++) {
for (let z = -3; z < 4; z++) {
global.chunkManager.multiBlockChunk(x, z, thisUser);
}
}
2021-08-20 22:42:00 +01:00
// Send this user to other online users
2021-08-12 04:58:56 +01:00
break;
case NamedPackets.Handshake:
thisUser.username = reader.readString();
socket.write(new PacketMappingTable[NamedPackets.Handshake](thisUser.username).writePacket());
break;
2021-08-15 00:21:41 +01:00
2021-08-15 11:33:08 +01:00
case NamedPackets.ChatMessage:
const message = reader.readString();
// Hacky commands until I made a command system
if (message.startsWith("/")) {
const command = message.substring(1, message.length).split(" ");
console.log(command);
if (command[0] == "time") {
if (command.length < 2) {
} else if (command[1] == "set") {
if (command.length < 3) {
} else {
switch (command[2]) {
case "day":
2021-08-18 01:25:55 +01:00
worldTime = (24000 * (worldTime / 24000));
2021-08-15 11:33:08 +01:00
break;
case "noon":
2021-08-18 01:25:55 +01:00
worldTime = (24000 * (worldTime / 24000)) + 6000;
2021-08-15 11:33:08 +01:00
break;
case "sunset":
2021-08-18 01:25:55 +01:00
worldTime = (24000 * (worldTime / 24000)) + 12000;
2021-08-15 11:33:08 +01:00
break;
case "midnight":
2021-08-18 01:25:55 +01:00
worldTime = (24000 * (worldTime / 24000)) + 18000;
2021-08-15 11:33:08 +01:00
break;
}
}
}
}
} else {
// Send player's message to all players
const cachedPacket = new PacketMappingTable[NamedPackets.ChatMessage](`<${thisUser.username}> ${message}`).writePacket();
for (let key of netUserKeys) {
netUsers[key].socket.write(cachedPacket);
}
}
break;
2021-08-20 22:42:00 +01:00
case NamedPackets.Animation:
const EID = reader.readInt();
const cachedPacket = new PacketMappingTable[NamedPackets.Animation](thisUser.id, reader.readByte()).writePacket();
for (let key of netUserKeys) {
if (netUsers[key].id !== thisUser.id) netUsers[key].socket.write(cachedPacket);
}
break;
case NamedPackets.PlayerDigging:
const status = reader.readByte();
if (status == 2) {
const x = reader.readInt();
const y = reader.readByte();
const z = reader.readInt();
global.chunkManager.setBlock(0, x, y, z);
}
break;
case NamedPackets.PlayerBlockPlacement:
const x = reader.readInt();
const y = reader.readByte();
const z = reader.readInt();
let xOff = 0, yOff = 0, zOff = 0;
switch (reader.readByte()) { // direction
case 0: yOff = -1; break;
case 1: yOff = 1; break;
case 2: zOff = -1; break;
case 3: zOff = 1; break;
case 4: xOff = -1; break;
case 5: xOff = 1; break;
}
const block = reader.readShort();
global.chunkManager.setBlock(block, x + xOff, y + yOff, z + zOff);
break;
2021-08-15 00:21:41 +01:00
case NamedPackets.Player:
break;
default:
2021-08-18 01:25:55 +01:00
console.log(toHexValue(packetID));
2021-08-15 00:21:41 +01:00
break;
2021-08-12 04:58:56 +01:00
}
2021-08-12 01:44:18 +01:00
});
socket.on('end', function() {
console.log("Connection closed");
2021-08-12 08:41:08 +01:00
removeUser(thisUser.id);
2021-08-12 01:44:18 +01:00
});
socket.on('error', function(err) {
console.log("Connection error!");
2021-08-12 08:41:08 +01:00
removeUser(thisUser.id);
2021-08-12 01:44:18 +01:00
});
2021-08-18 01:25:55 +01:00
}
function toHexValue(val = 0x00) {
if (val < 16) return `0x0${val.toString(16).toUpperCase()}`;
else return `0x${val.toString(16).toUpperCase()}`;
2021-08-11 15:05:14 +01:00
}