mirror of
https://github.com/MrMasrozYTLIVE/MCServer.git
synced 2024-12-25 10:38:21 -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 {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 {Player} from "./Player";
|
||||
|
||||
export class MinecraftServer {
|
||||
public server: Server = new Server();
|
||||
public static debug: boolean = true;
|
||||
|
||||
public static PlayerManagers = new Map<String, PlayerManager>();
|
||||
// EntityMap = new Map<Number, IEntity>();
|
||||
|
||||
public async start() {
|
||||
@ -18,7 +20,7 @@ export class MinecraftServer {
|
||||
this.server.on('connection', socket => {
|
||||
if(MinecraftServer.debug) console.log('New connection!');
|
||||
|
||||
PlayerManager.handleConnection(socket);
|
||||
new PlayerManager("Unknown", socket).handleConnection();
|
||||
});
|
||||
|
||||
this.server.on('close', this.stop);
|
||||
|
@ -1,8 +1,12 @@
|
||||
import {Socket} from "node:net";
|
||||
import {IEntity} from "./IEntity";
|
||||
import {PlayerManager} from "./utils/PlayerManager";
|
||||
|
||||
export class Player implements IEntity {
|
||||
public entityID: Number;
|
||||
public username: String;
|
||||
public socket: Socket;
|
||||
public playerManager: PlayerManager;
|
||||
|
||||
public xPosition: number = 0;
|
||||
public yPosition: number = 100;
|
||||
@ -12,10 +16,9 @@ export class Player implements IEntity {
|
||||
public pitch: number = 0;
|
||||
public onGround: boolean = false;
|
||||
|
||||
constructor(public options: IPlayerOption) {}
|
||||
}
|
||||
|
||||
export interface IPlayerOption {
|
||||
client: Socket,
|
||||
username: String
|
||||
constructor(username: String, socket: Socket, playerManager: PlayerManager) {
|
||||
this.username = username;
|
||||
this.socket = socket;
|
||||
this.playerManager = playerManager;
|
||||
}
|
||||
}
|
@ -18,5 +18,4 @@ export interface IPacketOption {
|
||||
player?: Player,
|
||||
packetID: PacketEnum,
|
||||
name?: string,
|
||||
kickReason?: string
|
||||
}
|
@ -12,7 +12,7 @@ export class PacketKeepAlive extends Packet {
|
||||
}
|
||||
|
||||
readData(reader: IReader, player: Player) {
|
||||
PlayerManager.sendPacket(player, this);
|
||||
player.playerManager.sendPacket(this);
|
||||
}
|
||||
|
||||
writeData() {
|
||||
|
@ -4,9 +4,11 @@ import {createWriter, Endian, IReader} from "bufferstuff";
|
||||
import {Player} from "../../../Player";
|
||||
import {randomInt} from "node:crypto";
|
||||
import {PlayerManager} from "../../../utils/PlayerManager";
|
||||
import {MinecraftServer} from "../../../MinecraftServer";
|
||||
import {Socket} from "node:net";
|
||||
|
||||
export class PacketHandshake extends Packet {
|
||||
constructor() {
|
||||
constructor(public playerManager: PlayerManager) {
|
||||
super({
|
||||
packetID: PacketEnum.Handshake
|
||||
})
|
||||
@ -14,22 +16,27 @@ export class PacketHandshake extends Packet {
|
||||
|
||||
readData(reader: IReader, player: Player) {
|
||||
const username = reader.readString16();
|
||||
|
||||
player = this.playerManager.player;
|
||||
this.playerManager.username = username;
|
||||
player.username = 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;
|
||||
}
|
||||
|
||||
if(username.length > 16) {
|
||||
PlayerManager.kickPlayer(player, `Your username is too long!`);
|
||||
player.playerManager.kickPlayer(`Your username is too long!`);
|
||||
return;
|
||||
}
|
||||
|
||||
player.options.username = username;
|
||||
player.username = username;
|
||||
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() {
|
||||
|
@ -7,8 +7,10 @@ import {PacketChat} from "../player/PacketChat";
|
||||
import {PlayerManager} from "../../../utils/PlayerManager";
|
||||
import {PacketPreChunk} from "../world/PacketPreChunk";
|
||||
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() {
|
||||
super({
|
||||
packetID: PacketEnum.Login
|
||||
@ -17,18 +19,18 @@ export class PacketHandshake extends Packet {
|
||||
|
||||
readData(reader: IReader, player: Player) {
|
||||
const protocol = reader.readInt();
|
||||
if(protocol > 14) PlayerManager.kickPlayer(player, `Server is outdated!`);
|
||||
else if (protocol < 14) PlayerManager.kickPlayer(player, `Client is outdated!`);
|
||||
if(protocol > 14) player.playerManager.kickPlayer(`Server is outdated!`);
|
||||
else if (protocol < 14) player.playerManager.kickPlayer(`Client is outdated!`);
|
||||
|
||||
const username = reader.readString16();
|
||||
const seed = reader.readLong();
|
||||
const dimension = reader.readByte();
|
||||
PlayerManager.sendPacket(player, this);
|
||||
PlayerManager.sendPacket(player, PacketManager.getPacket(PacketEnum.PositionLook));
|
||||
player.playerManager.sendPacket(this);
|
||||
player.playerManager.sendPacket(new PacketPositionLook());
|
||||
PlayerManager.sendPacketToAll(new PacketChat(`§e<${username}> has joined the game.`));
|
||||
|
||||
PlayerManager.sendPacket(player, new PacketPreChunk());
|
||||
PlayerManager.sendPacket(player, new PacketMapChunk());
|
||||
player.playerManager.sendPacket(new PacketPreChunk());
|
||||
player.playerManager.sendPacket(new PacketMapChunk());
|
||||
}
|
||||
|
||||
writeData() {
|
||||
|
@ -12,7 +12,7 @@ export class PacketServerList extends Packet {
|
||||
}
|
||||
|
||||
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() {
|
||||
|
@ -13,7 +13,7 @@ export class PacketChat extends Packet {
|
||||
}
|
||||
|
||||
readData(reader: IReader, player: Player) {
|
||||
this.message = `<${player.options.username}> ${reader.readString16()}`
|
||||
this.message = `<${player.username}> ${reader.readString16()}`
|
||||
|
||||
PlayerManager.sendPacketToAll(this);
|
||||
}
|
||||
|
@ -12,7 +12,7 @@ export class PacketDisconnectKick extends Packet {
|
||||
}
|
||||
|
||||
readData(reader: IReader, player: Player) {
|
||||
PlayerManager.playerDisconnected(player.options.client);
|
||||
player.playerManager.playerDisconnected();
|
||||
}
|
||||
|
||||
writeData() {
|
||||
|
@ -3,7 +3,7 @@ import {PacketEnum} from "../../../utils/PacketEnum";
|
||||
import {createWriter, Endian, IReader} from "bufferstuff";
|
||||
import {Player} from "../../../Player";
|
||||
|
||||
export class PacketKick extends Packet {
|
||||
export class PacketPositionLook extends Packet {
|
||||
constructor() {
|
||||
super({
|
||||
packetID: PacketEnum.PositionLook
|
||||
|
@ -6,80 +6,74 @@ import {Socket} from "node:net";
|
||||
import {createReader, Endian} from "bufferstuff";
|
||||
import {PacketManager} from "./PacketManager";
|
||||
import {MinecraftServer} from "../MinecraftServer";
|
||||
import {PacketEnum} from "./PacketEnum";
|
||||
import {PacketHandshake} from "../packet/impl/login/PacketHandshake";
|
||||
|
||||
export class PlayerManager {
|
||||
static PlayerMap = new Map<Socket, Player>();
|
||||
static SocketMap = new Map<String, Socket>();
|
||||
public player: Player;
|
||||
|
||||
public static handleConnection(socket: Socket) {
|
||||
if(!PlayerManager.PlayerMap.has(socket)) PlayerManager.PlayerMap.set(socket, new Player({
|
||||
client: socket,
|
||||
username: "Unknown"
|
||||
}));
|
||||
constructor(public username: string, public socket: Socket) {
|
||||
this.player = new Player(username, socket, this);
|
||||
}
|
||||
|
||||
socket.on('data', data => {
|
||||
public handleConnection() {
|
||||
this.socket.on('data', data => {
|
||||
const reader = createReader(Endian.BE, data);
|
||||
|
||||
const packetID = reader.readUByte();
|
||||
let packet: Packet;
|
||||
packet = PacketManager.getPacket(packetID);
|
||||
|
||||
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}`);
|
||||
if(packetID == PacketEnum.Handshake) {
|
||||
new PacketHandshake(this).readData(reader, null);
|
||||
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);
|
||||
socket.on('timeout', PlayerManager.playerDisconnected);
|
||||
this.socket.on('close', () => this.playerDisconnected());
|
||||
this.socket.on('timeout', () => this.playerDisconnected());
|
||||
}
|
||||
|
||||
public static sendPacket(player: Player, packet: Packet) {
|
||||
if(!packet || !player) {
|
||||
console.log(`Tried to sent packet to player where either player or packet is null!`)
|
||||
public sendPacket(packet: Packet) {
|
||||
if(!packet) {
|
||||
console.log(`Tried to sent null packet!`)
|
||||
return;
|
||||
}
|
||||
|
||||
if(MinecraftServer.debug) console.log(`Sending Packet: ${packet.options.name} (${packet.options.packetID}) to ${player.options.username}`);
|
||||
packet.options.player = player;
|
||||
if(MinecraftServer.debug) console.log(`Sending Packet: ${packet.options.name} (${packet.options.packetID}) to ${this.username}`);
|
||||
packet.options.player = this.player;
|
||||
|
||||
player.options.client.write(packet.writeData());
|
||||
this.player.socket.write(packet.writeData());
|
||||
}
|
||||
|
||||
public static sendPacketToAll(packet: Packet) {
|
||||
PlayerManager.PlayerMap.forEach(player => {
|
||||
PlayerManager.sendPacket(player, packet);
|
||||
MinecraftServer.PlayerManagers.forEach(manager => {
|
||||
manager.sendPacket(packet);
|
||||
})
|
||||
}
|
||||
|
||||
public static kickPlayer(player: Player, reason: string) {
|
||||
if(!player) {
|
||||
console.log(`Tried to kick null player!`);
|
||||
return;
|
||||
}
|
||||
|
||||
PlayerManager.sendPacket(player, new PacketDisconnectKick(reason));
|
||||
this.playerDisconnected(player.options.client);
|
||||
public kickPlayer(reason: string) {
|
||||
this.sendPacket(new PacketDisconnectKick(reason));
|
||||
}
|
||||
|
||||
public static playerDisconnected(socket: Socket) {
|
||||
const player = PlayerManager.PlayerMap.get(socket);
|
||||
if(!player) return;
|
||||
public playerDisconnected() {
|
||||
if(MinecraftServer.debug) console.log(`Player ${this.username} left. Deleting from the map!`);
|
||||
MinecraftServer.PlayerManagers.delete(this.username);
|
||||
|
||||
const username = player.options.username;
|
||||
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.`));
|
||||
PlayerManager.sendPacketToAll(new PacketChat(`§e<${this.username}> left the game.`));
|
||||
}
|
||||
|
||||
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