mirror of
https://github.com/MrMasrozYTLIVE/MCServer.git
synced 2024-11-25 14:28:22 -05:00
Reworked PlayerManager system and *kinda* made my code a bit better. Still have a lot of work to do tho.
This commit is contained in:
parent
00e2cad9fa
commit
8847842c88
@ -1,12 +1,14 @@
|
|||||||
import { PacketManager } from "./utils/PacketManager";
|
import { PacketManager } from "./utils/PacketManager";
|
||||||
import {PlayerManager} from "./utils/PlayerManager";
|
import {PlayerManager} from "./utils/PlayerManager";
|
||||||
import {Server} from "node:net";
|
import {Server} from "node:net"; // TODO: Replace with https://bun.sh/docs/api/tcp
|
||||||
import {PacketDisconnectKick} from "./packet/impl/player/PacketDisconnectKick";
|
import {PacketDisconnectKick} from "./packet/impl/player/PacketDisconnectKick";
|
||||||
|
import {Player} from "./Player";
|
||||||
|
|
||||||
export class MinecraftServer {
|
export class MinecraftServer {
|
||||||
public server: Server = new Server();
|
public server: Server = new Server();
|
||||||
public static debug: boolean = true;
|
public static debug: boolean = true;
|
||||||
|
|
||||||
|
public static PlayerManagers = new Map<String, PlayerManager>();
|
||||||
// EntityMap = new Map<Number, IEntity>();
|
// EntityMap = new Map<Number, IEntity>();
|
||||||
|
|
||||||
public async start() {
|
public async start() {
|
||||||
@ -18,7 +20,7 @@ export class MinecraftServer {
|
|||||||
this.server.on('connection', socket => {
|
this.server.on('connection', socket => {
|
||||||
if(MinecraftServer.debug) console.log('New connection!');
|
if(MinecraftServer.debug) console.log('New connection!');
|
||||||
|
|
||||||
PlayerManager.handleConnection(socket);
|
new PlayerManager("Unknown", socket).handleConnection();
|
||||||
});
|
});
|
||||||
|
|
||||||
this.server.on('close', this.stop);
|
this.server.on('close', this.stop);
|
||||||
|
@ -1,8 +1,12 @@
|
|||||||
import {Socket} from "node:net";
|
import {Socket} from "node:net";
|
||||||
import {IEntity} from "./IEntity";
|
import {IEntity} from "./IEntity";
|
||||||
|
import {PlayerManager} from "./utils/PlayerManager";
|
||||||
|
|
||||||
export class Player implements IEntity {
|
export class Player implements IEntity {
|
||||||
public entityID: Number;
|
public entityID: Number;
|
||||||
|
public username: String;
|
||||||
|
public socket: Socket;
|
||||||
|
public playerManager: PlayerManager;
|
||||||
|
|
||||||
public xPosition: number = 0;
|
public xPosition: number = 0;
|
||||||
public yPosition: number = 100;
|
public yPosition: number = 100;
|
||||||
@ -12,10 +16,9 @@ export class Player implements IEntity {
|
|||||||
public pitch: number = 0;
|
public pitch: number = 0;
|
||||||
public onGround: boolean = false;
|
public onGround: boolean = false;
|
||||||
|
|
||||||
constructor(public options: IPlayerOption) {}
|
constructor(username: String, socket: Socket, playerManager: PlayerManager) {
|
||||||
}
|
this.username = username;
|
||||||
|
this.socket = socket;
|
||||||
export interface IPlayerOption {
|
this.playerManager = playerManager;
|
||||||
client: Socket,
|
}
|
||||||
username: String
|
|
||||||
}
|
}
|
@ -18,5 +18,4 @@ export interface IPacketOption {
|
|||||||
player?: Player,
|
player?: Player,
|
||||||
packetID: PacketEnum,
|
packetID: PacketEnum,
|
||||||
name?: string,
|
name?: string,
|
||||||
kickReason?: string
|
|
||||||
}
|
}
|
@ -12,7 +12,7 @@ export class PacketKeepAlive extends Packet {
|
|||||||
}
|
}
|
||||||
|
|
||||||
readData(reader: IReader, player: Player) {
|
readData(reader: IReader, player: Player) {
|
||||||
PlayerManager.sendPacket(player, this);
|
player.playerManager.sendPacket(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
writeData() {
|
writeData() {
|
||||||
|
@ -4,9 +4,11 @@ import {createWriter, Endian, IReader} from "bufferstuff";
|
|||||||
import {Player} from "../../../Player";
|
import {Player} from "../../../Player";
|
||||||
import {randomInt} from "node:crypto";
|
import {randomInt} from "node:crypto";
|
||||||
import {PlayerManager} from "../../../utils/PlayerManager";
|
import {PlayerManager} from "../../../utils/PlayerManager";
|
||||||
|
import {MinecraftServer} from "../../../MinecraftServer";
|
||||||
|
import {Socket} from "node:net";
|
||||||
|
|
||||||
export class PacketHandshake extends Packet {
|
export class PacketHandshake extends Packet {
|
||||||
constructor() {
|
constructor(public playerManager: PlayerManager) {
|
||||||
super({
|
super({
|
||||||
packetID: PacketEnum.Handshake
|
packetID: PacketEnum.Handshake
|
||||||
})
|
})
|
||||||
@ -14,22 +16,27 @@ export class PacketHandshake extends Packet {
|
|||||||
|
|
||||||
readData(reader: IReader, player: Player) {
|
readData(reader: IReader, player: Player) {
|
||||||
const username = reader.readString16();
|
const username = reader.readString16();
|
||||||
|
|
||||||
|
player = this.playerManager.player;
|
||||||
|
this.playerManager.username = username;
|
||||||
|
player.username = username;
|
||||||
|
|
||||||
if(PlayerManager.getPlayer(username)) {
|
if(PlayerManager.getPlayer(username)) {
|
||||||
PlayerManager.kickPlayer(player, `Player with same username is already on the server.`);
|
player.playerManager.kickPlayer(`Player with same username is already on the server.`);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(username.length > 16) {
|
if(username.length > 16) {
|
||||||
PlayerManager.kickPlayer(player, `Your username is too long!`);
|
player.playerManager.kickPlayer(`Your username is too long!`);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
player.options.username = username;
|
player.username = username;
|
||||||
player.entityID = randomInt(0, 100);
|
player.entityID = randomInt(0, 100);
|
||||||
|
|
||||||
PlayerManager.SocketMap.set(username, player.options.client);
|
MinecraftServer.PlayerManagers.set(username, player.playerManager);
|
||||||
|
|
||||||
PlayerManager.sendPacket(player, this);
|
player.playerManager.sendPacket(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
writeData() {
|
writeData() {
|
||||||
|
@ -7,8 +7,10 @@ import {PacketChat} from "../player/PacketChat";
|
|||||||
import {PlayerManager} from "../../../utils/PlayerManager";
|
import {PlayerManager} from "../../../utils/PlayerManager";
|
||||||
import {PacketPreChunk} from "../world/PacketPreChunk";
|
import {PacketPreChunk} from "../world/PacketPreChunk";
|
||||||
import {PacketMapChunk} from "../world/PacketMapChunk";
|
import {PacketMapChunk} from "../world/PacketMapChunk";
|
||||||
|
import {PacketPosition} from "../player/PacketPosition";
|
||||||
|
import {PacketPositionLook} from "../player/PacketPositionLook";
|
||||||
|
|
||||||
export class PacketHandshake extends Packet {
|
export class PacketLogin extends Packet {
|
||||||
constructor() {
|
constructor() {
|
||||||
super({
|
super({
|
||||||
packetID: PacketEnum.Login
|
packetID: PacketEnum.Login
|
||||||
@ -17,18 +19,18 @@ export class PacketHandshake extends Packet {
|
|||||||
|
|
||||||
readData(reader: IReader, player: Player) {
|
readData(reader: IReader, player: Player) {
|
||||||
const protocol = reader.readInt();
|
const protocol = reader.readInt();
|
||||||
if(protocol > 14) PlayerManager.kickPlayer(player, `Server is outdated!`);
|
if(protocol > 14) player.playerManager.kickPlayer(`Server is outdated!`);
|
||||||
else if (protocol < 14) PlayerManager.kickPlayer(player, `Client is outdated!`);
|
else if (protocol < 14) player.playerManager.kickPlayer(`Client is outdated!`);
|
||||||
|
|
||||||
const username = reader.readString16();
|
const username = reader.readString16();
|
||||||
const seed = reader.readLong();
|
const seed = reader.readLong();
|
||||||
const dimension = reader.readByte();
|
const dimension = reader.readByte();
|
||||||
PlayerManager.sendPacket(player, this);
|
player.playerManager.sendPacket(this);
|
||||||
PlayerManager.sendPacket(player, PacketManager.getPacket(PacketEnum.PositionLook));
|
player.playerManager.sendPacket(new PacketPositionLook());
|
||||||
PlayerManager.sendPacketToAll(new PacketChat(`§e<${username}> has joined the game.`));
|
PlayerManager.sendPacketToAll(new PacketChat(`§e<${username}> has joined the game.`));
|
||||||
|
|
||||||
PlayerManager.sendPacket(player, new PacketPreChunk());
|
player.playerManager.sendPacket(new PacketPreChunk());
|
||||||
PlayerManager.sendPacket(player, new PacketMapChunk());
|
player.playerManager.sendPacket(new PacketMapChunk());
|
||||||
}
|
}
|
||||||
|
|
||||||
writeData() {
|
writeData() {
|
||||||
|
@ -12,7 +12,7 @@ export class PacketServerList extends Packet {
|
|||||||
}
|
}
|
||||||
|
|
||||||
readData(reader: IReader, player: Player) {
|
readData(reader: IReader, player: Player) {
|
||||||
PlayerManager.kickPlayer(player, `Beta 1.7.3 Server§0§0`);
|
player.playerManager.kickPlayer(`Beta 1.7.3 Server§0§0`);
|
||||||
}
|
}
|
||||||
|
|
||||||
writeData() {
|
writeData() {
|
||||||
|
@ -13,7 +13,7 @@ export class PacketChat extends Packet {
|
|||||||
}
|
}
|
||||||
|
|
||||||
readData(reader: IReader, player: Player) {
|
readData(reader: IReader, player: Player) {
|
||||||
this.message = `<${player.options.username}> ${reader.readString16()}`
|
this.message = `<${player.username}> ${reader.readString16()}`
|
||||||
|
|
||||||
PlayerManager.sendPacketToAll(this);
|
PlayerManager.sendPacketToAll(this);
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,7 @@ export class PacketDisconnectKick extends Packet {
|
|||||||
}
|
}
|
||||||
|
|
||||||
readData(reader: IReader, player: Player) {
|
readData(reader: IReader, player: Player) {
|
||||||
PlayerManager.playerDisconnected(player.options.client);
|
player.playerManager.playerDisconnected();
|
||||||
}
|
}
|
||||||
|
|
||||||
writeData() {
|
writeData() {
|
||||||
|
@ -3,7 +3,7 @@ import {PacketEnum} from "../../../utils/PacketEnum";
|
|||||||
import {createWriter, Endian, IReader} from "bufferstuff";
|
import {createWriter, Endian, IReader} from "bufferstuff";
|
||||||
import {Player} from "../../../Player";
|
import {Player} from "../../../Player";
|
||||||
|
|
||||||
export class PacketKick extends Packet {
|
export class PacketPositionLook extends Packet {
|
||||||
constructor() {
|
constructor() {
|
||||||
super({
|
super({
|
||||||
packetID: PacketEnum.PositionLook
|
packetID: PacketEnum.PositionLook
|
||||||
|
@ -6,80 +6,74 @@ import {Socket} from "node:net";
|
|||||||
import {createReader, Endian} from "bufferstuff";
|
import {createReader, Endian} from "bufferstuff";
|
||||||
import {PacketManager} from "./PacketManager";
|
import {PacketManager} from "./PacketManager";
|
||||||
import {MinecraftServer} from "../MinecraftServer";
|
import {MinecraftServer} from "../MinecraftServer";
|
||||||
|
import {PacketEnum} from "./PacketEnum";
|
||||||
|
import {PacketHandshake} from "../packet/impl/login/PacketHandshake";
|
||||||
|
|
||||||
export class PlayerManager {
|
export class PlayerManager {
|
||||||
static PlayerMap = new Map<Socket, Player>();
|
public player: Player;
|
||||||
static SocketMap = new Map<String, Socket>();
|
|
||||||
|
|
||||||
public static handleConnection(socket: Socket) {
|
constructor(public username: string, public socket: Socket) {
|
||||||
if(!PlayerManager.PlayerMap.has(socket)) PlayerManager.PlayerMap.set(socket, new Player({
|
this.player = new Player(username, socket, this);
|
||||||
client: socket,
|
}
|
||||||
username: "Unknown"
|
|
||||||
}));
|
|
||||||
|
|
||||||
socket.on('data', data => {
|
public handleConnection() {
|
||||||
|
this.socket.on('data', data => {
|
||||||
const reader = createReader(Endian.BE, data);
|
const reader = createReader(Endian.BE, data);
|
||||||
|
|
||||||
const packetID = reader.readUByte();
|
const packetID = reader.readUByte();
|
||||||
let packet: Packet;
|
if(packetID == PacketEnum.Handshake) {
|
||||||
packet = PacketManager.getPacket(packetID);
|
new PacketHandshake(this).readData(reader, null);
|
||||||
|
|
||||||
if(packet === undefined) {
|
|
||||||
if(MinecraftServer.debug) console.log(`Received Unknown packet: ${packetID}. Kicking the player.`);
|
|
||||||
PlayerManager.kickPlayer(PlayerManager.PlayerMap.get(socket), `Sent unknown packet ${packetID}`);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(MinecraftServer.debug) console.log(`Received Packet: ${packet.options.name} (${packetID})`);
|
let packet: Packet = PacketManager.getPacket(packetID);
|
||||||
|
|
||||||
packet.readData(reader, PlayerManager.PlayerMap.get(socket));
|
if(packet === undefined) {
|
||||||
|
if(MinecraftServer.debug) console.log(`Received Unknown packet: ${packetID}. Kicking the player.`);
|
||||||
|
this.kickPlayer(`Sent unknown packet ${packetID}`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(MinecraftServer.debug && packetID != PacketEnum.Position && packetID != PacketEnum.PositionLook)
|
||||||
|
console.log(`Received Packet: ${packet.options.name} (${packetID})`);
|
||||||
|
|
||||||
|
packet.readData(reader, this.player);
|
||||||
});
|
});
|
||||||
|
|
||||||
socket.on('close', PlayerManager.playerDisconnected);
|
this.socket.on('close', () => this.playerDisconnected());
|
||||||
socket.on('timeout', PlayerManager.playerDisconnected);
|
this.socket.on('timeout', () => this.playerDisconnected());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static sendPacket(player: Player, packet: Packet) {
|
public sendPacket(packet: Packet) {
|
||||||
if(!packet || !player) {
|
if(!packet) {
|
||||||
console.log(`Tried to sent packet to player where either player or packet is null!`)
|
console.log(`Tried to sent null packet!`)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(MinecraftServer.debug) console.log(`Sending Packet: ${packet.options.name} (${packet.options.packetID}) to ${player.options.username}`);
|
if(MinecraftServer.debug) console.log(`Sending Packet: ${packet.options.name} (${packet.options.packetID}) to ${this.username}`);
|
||||||
packet.options.player = player;
|
packet.options.player = this.player;
|
||||||
|
|
||||||
player.options.client.write(packet.writeData());
|
this.player.socket.write(packet.writeData());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static sendPacketToAll(packet: Packet) {
|
public static sendPacketToAll(packet: Packet) {
|
||||||
PlayerManager.PlayerMap.forEach(player => {
|
MinecraftServer.PlayerManagers.forEach(manager => {
|
||||||
PlayerManager.sendPacket(player, packet);
|
manager.sendPacket(packet);
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
public static kickPlayer(player: Player, reason: string) {
|
public kickPlayer(reason: string) {
|
||||||
if(!player) {
|
this.sendPacket(new PacketDisconnectKick(reason));
|
||||||
console.log(`Tried to kick null player!`);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
PlayerManager.sendPacket(player, new PacketDisconnectKick(reason));
|
|
||||||
this.playerDisconnected(player.options.client);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static playerDisconnected(socket: Socket) {
|
public playerDisconnected() {
|
||||||
const player = PlayerManager.PlayerMap.get(socket);
|
if(MinecraftServer.debug) console.log(`Player ${this.username} left. Deleting from the map!`);
|
||||||
if(!player) return;
|
MinecraftServer.PlayerManagers.delete(this.username);
|
||||||
|
|
||||||
const username = player.options.username;
|
PlayerManager.sendPacketToAll(new PacketChat(`§e<${this.username}> left the game.`));
|
||||||
if(MinecraftServer.debug) console.log(`Player ${username} left. Deleting from the map!`);
|
|
||||||
PlayerManager.SocketMap.delete(username);
|
|
||||||
PlayerManager.PlayerMap.delete(socket);
|
|
||||||
|
|
||||||
PlayerManager.sendPacketToAll(new PacketChat(`§e<${username}> left the game.`));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static getPlayer(username: String) {
|
public static getPlayer(username: String) {
|
||||||
return PlayerManager.PlayerMap.get(PlayerManager.SocketMap.get(username));
|
return MinecraftServer.PlayerManagers.get(username)?.player;
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user