diff --git a/src/pocketnode/Server.js b/src/pocketnode/Server.js index 4edd069..84e99d2 100644 --- a/src/pocketnode/Server.js +++ b/src/pocketnode/Server.js @@ -13,6 +13,10 @@ const ConsoleCommandReader = pocketnode("command/ConsoleCommandReader"); const HelpCommand = pocketnode("command/defaults/HelpCommand"); const StopCommand = pocketnode("command/defaults/StopCommand"); const PluginsCommand = pocketnode("command/defaults/PluginsCommand"); +const SayCommand = pocketnode("command/defaults/SayCommand"); + +const EventHandler = pocketnode("event/EventHandler"); +const TestEvent = pocketnode("event/TestEvent"); const Player = pocketnode("player/Player"); const PlayerList = pocketnode("player/PlayerList"); @@ -66,6 +70,7 @@ class Server { this._players = new PlayerList(); this._loggedInPlayers = new PlayerList(); this._playerList = new PlayerList(); + this._eventSystem = new EventHandler(this); this._levels = new Map(); @@ -144,7 +149,6 @@ class Server { } start(){ - //block banned ips this._tickCounter = 0; @@ -159,6 +163,7 @@ class Server { this.getCommandMap().registerCommand(new HelpCommand()); this.getCommandMap().registerCommand(new StopCommand()); this.getCommandMap().registerCommand(new PluginsCommand()); + this.getCommandMap().registerCommand(new SayCommand()); } /** @@ -353,6 +358,7 @@ class Server { } broadcastMessage(message, recipients = this.getOnlinePlayers()){ + this.getLogger().info(message); recipients.forEach(recipient => recipient.sendMessage(message)); return recipients.length; @@ -607,6 +613,10 @@ class Server { onPlayerCompleteLoginSequence(player){ } + + getEventSystem(){ + return this._eventSystem; + } } -module.exports = Server; \ No newline at end of file +module.exports = Server; diff --git a/src/pocketnode/command/defaults/SayCommand.js b/src/pocketnode/command/defaults/SayCommand.js new file mode 100644 index 0000000..030dbff --- /dev/null +++ b/src/pocketnode/command/defaults/SayCommand.js @@ -0,0 +1,18 @@ +const Command = pocketnode("command/Command"); +const TextFormat = pocketnode("utils/TextFormat"); + +class SayCommand extends Command { + constructor(){ + super("say", "Send a message to the server.", "pocketnode.command.say", []); + } + + execute(sender, args){ + let message = ""; + args.forEach(elem => { + message += elem + " "; + }); + sender.getServer().broadcastMessage("§b[SERVER] " + message); + } +} + +module.exports = SayCommand; diff --git a/src/pocketnode/event/Event.js b/src/pocketnode/event/Event.js new file mode 100644 index 0000000..c58c0e4 --- /dev/null +++ b/src/pocketnode/event/Event.js @@ -0,0 +1,51 @@ +/* + * _____ _ _ _ _ _ + * | __ \ | | | | | \ | | | | + * | |__) |__ ___| | _____| |_| \| | ___ __| | ___ + * | ___/ _ \ / __| |/ / _ \ __| . ` |/ _ \ / _` |/ _ \ + * | | | (_) | (__| < __/ |_| |\ | (_) | (_| | __/ + * |_| \___/ \___|_|\_\___|\__|_| \_|\___/ \__,_|\___| + * + * @author PocketNode Team + * @link https://pocketnode.me +*/ +class Event { + + constructor(){ + this.eventName = null; + this.isCancelled = false; + } + + /** + * @return string + */ + getEventName(){ + return this.eventName ? null : this.constructor.name; + } + + /** + * @return bool + * + * @throws Error + */ + isCancelled(){ + //if(!(this instanceof Cancellable)){ + // throw new Error("Event is not Cancellable"); + //} + return this.isCancelled === true; + } + + /** + * @param bool value + * + * @throws Error + */ + setCancelled(value = true){ + //if(!(this instanceof Cancellable)){ + // throw new Error("Event is not Cancellable"); + //} + this.isCancelled = value; + } + +} +module.exports = Event; diff --git a/src/pocketnode/event/EventHandler.js b/src/pocketnode/event/EventHandler.js new file mode 100644 index 0000000..53f91e5 --- /dev/null +++ b/src/pocketnode/event/EventHandler.js @@ -0,0 +1,37 @@ +/* + * _____ _ _ _ _ _ + * | __ \ | | | | | \ | | | | + * | |__) |__ ___| | _____| |_| \| | ___ __| | ___ + * | ___/ _ \ / __| |/ / _ \ __| . ` |/ _ \ / _` |/ _ \ + * | | | (_) | (__| < __/ |_| |\ | (_) | (_| | __/ + * |_| \___/ \___|_|\_\___|\__|_| \_|\___/ \__,_|\___| + * + * @author PocketNode Team + * @link https://pocketnode.me +*/ +const EventEmitter = require('events').EventEmitter; +const Event = pocketnode("event/Event"); + +class EventHandler extends EventEmitter { + + constructor(server){ + super(); + this.server = server; + this.emitter = new EventEmitter(); + } + + callEvent(ev){ + if(typeof ev !== "string" && typeof ev !== "number" && typeof ev !== "boolean" && typeof ev.isEvent !== null){ + this.emitter.emit(ev.getEventName(), ev); + } else { + this.server.getLogger().error("Calling event '" + ev.toString() + "' with non Event object"); + } + } + + getEmitter(){ + return this.emitter; + } + +} + +module.exports = EventHandler; diff --git a/src/pocketnode/event/TestEvent.js b/src/pocketnode/event/TestEvent.js new file mode 100644 index 0000000..e9b77cc --- /dev/null +++ b/src/pocketnode/event/TestEvent.js @@ -0,0 +1,21 @@ +/* + * _____ _ _ _ _ _ + * | __ \ | | | | | \ | | | | + * | |__) |__ ___| | _____| |_| \| | ___ __| | ___ + * | ___/ _ \ / __| |/ / _ \ __| . ` |/ _ \ / _` |/ _ \ + * | | | (_) | (__| < __/ |_| |\ | (_) | (_| | __/ + * |_| \___/ \___|_|\_\___|\__|_| \_|\___/ \__,_|\___| + * + * @author PocketNode Team + * @link https://pocketnode.me +*/ +const Event = pocketnode("event/Event"); + +class TestEvent extends Event{ + + constructor(){ + super(); + } + +} +module.exports = TestEvent; diff --git a/src/pocketnode/event/player/PlayerEvent.js b/src/pocketnode/event/player/PlayerEvent.js new file mode 100644 index 0000000..3c94cca --- /dev/null +++ b/src/pocketnode/event/player/PlayerEvent.js @@ -0,0 +1,26 @@ +/* + * _____ _ _ _ _ _ + * | __ \ | | | | | \ | | | | + * | |__) |__ ___| | _____| |_| \| | ___ __| | ___ + * | ___/ _ \ / __| |/ / _ \ __| . ` |/ _ \ / _` |/ _ \ + * | | | (_) | (__| < __/ |_| |\ | (_) | (_| | __/ + * |_| \___/ \___|_|\_\___|\__|_| \_|\___/ \__,_|\___| + * + * @author PocketNode Team + * @link https://pocketnode.me +*/ +const Event = pocketnode("event/Event"); + +class PlayerEvent extends Event { + + constructor(){ + super(); + this.player; + } + + getPlayer(){ + return this.player; + } + +} +module.exports = PlayerEvent; diff --git a/src/pocketnode/event/player/PlayerJoinEvent.js b/src/pocketnode/event/player/PlayerJoinEvent.js new file mode 100644 index 0000000..334e53b --- /dev/null +++ b/src/pocketnode/event/player/PlayerJoinEvent.js @@ -0,0 +1,45 @@ +/* + * _____ _ _ _ _ _ + * | __ \ | | | | | \ | | | | + * | |__) |__ ___| | _____| |_| \| | ___ __| | ___ + * | ___/ _ \ / __| |/ / _ \ __| . ` |/ _ \ / _` |/ _ \ + * | | | (_) | (__| < __/ |_| |\ | (_) | (_| | __/ + * |_| \___/ \___|_|\_\___|\__|_| \_|\___/ \__,_|\___| + * + * @author PocketNode Team + * @link https://pocketnode.me +*/ +const PlayerEvent = pocketnode("event/player/PlayerEvent"); + +class PlayerJoinEvent extends PlayerEvent { + + + /** + * PlayerJoinEvent constructor. + * + * @param Player player + * @param TextContainer|string joinMessage + */ + constructor(player, joinMessage){ + super(); + this.player = player; + /** @var string|TextContainer */ + this.joinMessage = joinMessage; + } + + /** + * @param string|TextContainer joinMessage + */ + setJoinMessage(joinMessage){ + this.joinMessage = joinMessage; + } + + /** + * @return string|TextContainer + */ + getJoinMessage(){ + return this.joinMessage; + } + +} +module.exports = PlayerJoinEvent; diff --git a/src/pocketnode/event/player/PlayerQuitEvent.js b/src/pocketnode/event/player/PlayerQuitEvent.js new file mode 100644 index 0000000..47ec407 --- /dev/null +++ b/src/pocketnode/event/player/PlayerQuitEvent.js @@ -0,0 +1,51 @@ +/* + * _____ _ _ _ _ _ + * | __ \ | | | | | \ | | | | + * | |__) |__ ___| | _____| |_| \| | ___ __| | ___ + * | ___/ _ \ / __| |/ / _ \ __| . ` |/ _ \ / _` |/ _ \ + * | | | (_) | (__| < __/ |_| |\ | (_) | (_| | __/ + * |_| \___/ \___|_|\_\___|\__|_| \_|\___/ \__,_|\___| + * + * @author PocketNode Team + * @link https://pocketnode.me +*/ +const PlayerEvent = pocketnode("event/player/PlayerEvent"); + +class PlayerQuitEvent extends PlayerEvent{ + + + /** + * @param Player player + * @param TranslationContainer|string quitMessage + * @param string quitReason + */ + constructor(player, quitMessage, quitReason){ + super(); + this.player = player; + this.quitMessage = quitMessage; + this.quitReason = quitReason; + } + + /** + * @param TranslationContainer|string quitMessage + */ + setQuitMessage(quitMessage){ + this.quitMessage = quitMessage; + } + + /** + * @return TranslationContainer|string + */ + getQuitMessage(){ + return this.quitMessage; + } + + /** + * @return string + */ + getQuitReason(){ + return this.quitReason; + } + +} +module.exports = PlayerQuitEvent; diff --git a/src/pocketnode/level/Position.js b/src/pocketnode/level/Position.js index ab29293..790dc80 100644 --- a/src/pocketnode/level/Position.js +++ b/src/pocketnode/level/Position.js @@ -117,4 +117,4 @@ class Position extends Vector3 { } -module.exports = Position; \ No newline at end of file +module.exports = Position; diff --git a/src/pocketnode/logger/Logger.js b/src/pocketnode/logger/Logger.js index 2a6eee9..797ca43 100644 --- a/src/pocketnode/logger/Logger.js +++ b/src/pocketnode/logger/Logger.js @@ -80,4 +80,4 @@ class Logger { } } -module.exports = Logger; \ No newline at end of file +module.exports = Logger; diff --git a/src/pocketnode/network/RakNetAdapter.js b/src/pocketnode/network/RakNetAdapter.js index 7c34d14..5748157 100644 --- a/src/pocketnode/network/RakNetAdapter.js +++ b/src/pocketnode/network/RakNetAdapter.js @@ -91,4 +91,4 @@ class RakNetAdapter { } } -module.exports = RakNetAdapter; \ No newline at end of file +module.exports = RakNetAdapter; diff --git a/src/pocketnode/network/minecraft/protocol/DataPacket.js b/src/pocketnode/network/minecraft/protocol/DataPacket.js index e2d4675..041be7b 100644 --- a/src/pocketnode/network/minecraft/protocol/DataPacket.js +++ b/src/pocketnode/network/minecraft/protocol/DataPacket.js @@ -176,4 +176,4 @@ class DataPacket extends BinaryStream { } } -module.exports = DataPacket; \ No newline at end of file +module.exports = DataPacket; diff --git a/src/pocketnode/player/Player.js b/src/pocketnode/player/Player.js index 23154b7..9d26fbb 100644 --- a/src/pocketnode/player/Player.js +++ b/src/pocketnode/player/Player.js @@ -20,6 +20,9 @@ const Skin = pocketnode("entity/Skin"); const TextFormat = pocketnode("utils/TextFormat"); const Base64 = pocketnode("utils/Base64"); +const PlayerJoinEvent = pocketnode("event/player/PlayerJoinEvent"); +const PlayerQuitEvent = pocketnode("event/player/PlayerQuitEvent"); + class Player extends CommandSender { static get SURVIVAL(){return 0} static get CREATIVE(){return 1} @@ -61,7 +64,7 @@ class Player extends CommandSender { this._needACK = {}; } - + constructor(server, clientId, ip, port){ super(server); this.initVars(); @@ -83,7 +86,7 @@ class Player extends CommandSender { isConnected(){ return this._sessionAdapter !== null; } - + static isValidUserName(name){ return name.toLowerCase() !== "rcon" && name.toLowerCase() !== "console" && name.length >= 1 && name.length <= 16 && /[^A-Za-z0-9_ ]/.test(name); } @@ -431,6 +434,14 @@ class Player extends CommandSender { this.spawned = false; + var ev = new PlayerQuitEvent(this, "A Player quit due to " + reason, reason) + this.server.getEventSystem().callEvent(ev); + if(ev.getQuitMessage().length > 0){ + var message = ev.getQuitMessage(); + this.server.broadcastMessage(message); + } else { + this.server.getLogger().warning("Player quit message is blank or null."); + } this.server.getLogger().info(TextFormat.AQUA + this.getName() + TextFormat.WHITE + " (" + this._ip + ":" + this._port + ") has disconnected due to " + reason); if(this.loggedIn){ @@ -492,7 +503,13 @@ class Player extends CommandSender { this.server.addOnlinePlayer(this); this.server.onPlayerCompleteLoginSequence(this); - + var ev = new PlayerJoinEvent(this, "A Player Joined!") + this.server.getEventSystem().callEvent(ev); + if(ev.getJoinMessage().length > 0){ + this.server.broadcastMessage(ev.getJoinMessage()); + } else { + this.server.getLogger().warning("Player join message is blank or null."); + } //this.sendPlayStatus(PlayStatusPacket.PLAYER_SPAWN); } @@ -502,9 +519,7 @@ class Player extends CommandSender { //} //this.resetCraftingGridType(); - message = TextFormat.clean(message, false);//this._removeFormat); - message = message.split("\n"); for(let i in message){ let messagePart = message[i]; @@ -517,7 +532,6 @@ class Player extends CommandSender { this.server.getCommandMap().dispatchCommand(this, messagePart.substr(1)); }else{ let msg = "<:player> :message".replace(":player", this.getName()).replace(":message", messagePart); - this.server.getLogger().info(msg); this.server.broadcastMessage(msg); } } diff --git a/src/pocketnode/player/PlayerList.js b/src/pocketnode/player/PlayerList.js index 6ed9e07..e5001bd 100644 --- a/src/pocketnode/player/PlayerList.js +++ b/src/pocketnode/player/PlayerList.js @@ -1,6 +1,7 @@ const Player = pocketnode("player/Player"); class PlayerList extends Map { + addPlayer(id, player){ CheckTypes([Player, player]); this.set(id, player); @@ -23,4 +24,4 @@ class PlayerList extends Map { } } -module.exports = PlayerList; \ No newline at end of file +module.exports = PlayerList;