clean kick/ban system

This commit is contained in:
Romain Beaumont 2015-09-06 17:07:12 +02:00
parent 2b8a24e2ef
commit 4bf03223dd
11 changed files with 231 additions and 180 deletions

View file

@ -41,6 +41,8 @@
- ["chat" (message)](#chat-message)
- [Methods](#methods-1)
- [player.login()](#playerlogin)
- [player.ban(reason)](#playerbanreason)
- [player.kick(reason)](#playerkickreason)
- [player.getOthers()](#playergetothers)
- [player.chat(message)](#playerchatmessage)
- [player.changeBlock(position,blockType)](#playerchangeblockpositionblocktype)
@ -50,8 +52,6 @@
- [player.setGameMode(gameMode)](#playersetgamemodegamemode)
- [player.handleCommand(command)](#playerhandlecommandcommand)
- [player.updateHealth(health)](#playerupdatehealthhealth)
- [player.kick(reason)](#playerkickreason)
- [player.ban(banReason,kickReason)](#playerbanbanreasonkickreason)
- [Low level properties](#low-level-properties)
- [player._client](#player_client)
- [Low level methods](#low-level-methods)
@ -148,8 +148,6 @@ Returns player object with that username or, if no such player is on the server,
Bans players given a username. Mainly used if player is not online, otherwise use `player.ban()`.
Callback first argument returns `true` if there is a UUID for that username, `false` otherwise.
#### server.ban(uuid,reason)
Ban player given a uuid. If the player is online, using `player.ban()`. Bans with reason or `You are banned!`.
@ -158,8 +156,6 @@ Ban player given a uuid. If the player is online, using `player.ban()`. Bans wit
Pardons a player given a username.
Callback returns `false` if UUID does not exist or player is not banned. It returns `true` otherwise.
#### server.pardon(uuid)
Pardons a player given their uuid. Returns `false` if they are not banned.
@ -210,6 +206,14 @@ Fires when the player says `message`.
login
#### player.ban(reason)
bans player with `reason`
#### player.kick(reason)
kicks player with `reason`
#### player.getOthers()
return the other players than `player`
@ -222,7 +226,8 @@ sends `message` to the player
change the block at position `position` to `blockType`
this will not change the block for the user themself. It is mainly useful when a user places a block and only needs to send it to other players on the server
this will not change the block for the user themself. It is mainly useful when a user places a block
and only needs to send it to other players on the server
#### player.sendBlock(position,blockType)
@ -250,14 +255,6 @@ handle `command`
update the player health.
#### player.kick(reason)
Kicks a player with the reason given or `You were kicked!`.
#### player.ban(banReason,kickReason)
Kicks the player with `kickReason`, then bans them with reason `banReason`.
### Low level properties
#### player._client

View file

@ -35,6 +35,12 @@ function inject(serv,player)
}
```
## Logs and event
In order to keep logging independent from the rest of the server and to let people react in other ways than logging,
server and player events should be emitting and the logging should only take place in response to these events
in log.js of playerPlugins or serverPlugins.
## Creating external plugins
Create a new repo, which will be published to npm when ready to be used.
@ -54,7 +60,8 @@ function inject(serv)
}
```
In the init function, you can use anything craftyjs provide (see [index.js](https://github.com/mhsjlw/flying-squid/blob/master/index.js#L11)).
In the init function, you can use anything craftyjs provide
(see [index.js](https://github.com/mhsjlw/flying-squid/blob/master/index.js#L11)).
In the inject function you can use everything documented in the [api.md](api.md) to add functionnalities to the serv object.
@ -87,4 +94,6 @@ function injectPlayer(serv,player)
}
```
In this document, we explained how to create a simple plugin with just one file, but you can cut your code in several files by having several inject function and putting them in different files, just like flying-squid does for its internal plugins.
In this document, we explained how to create a simple plugin with just one file, but you can cut your code
in several files by having several inject function and putting them in different files, just like flying-squid does
for its internal plugins.

View file

@ -1,90 +1,95 @@
var Vec3 = require('vec3');
module.exports=inject;
module.exports = inject;
function inject(serv, player, options)
{
function handleCommand(command)
{
function inject(serv, player, options) {
function handleCommand(command) {
var results;
if(options.commands[command])
if (options.commands[command])
player.chat("" + options.commands[command]);
else if(results=command.match(/^gamemode ([0-3])$/)) {
var gameMode=parseInt(results[1]);
else if (results = command.match(/^gamemode ([0-3])$/)) {
var gameMode = parseInt(results[1]);
player.setGameMode(gameMode);
}
else if(results=command.match(/^setblock/)) { // Like old version which uses ids
results = command.match(/^setblock (~|~?-?[0-9]*) (~|~?-?[0-9]*) (~|~?-?[0-9]*) ([0-9]{1,3})/);
if(!results) {
player.chat("Usage: /setblock <x> <y> <z> <id>");
}
else {
results = results.map(function(num, i) { // parseInt paramaters
if (num.indexOf('~') == 0) {
return (player.entity.position[['','x', 'y', 'z'][i]]>>5) + parseInt(num.slice(1) || 0);
}
else
return parseInt(num); // return parseInt>>5 if position, not id
});
serv.setBlock(new Vec3(results[1], results[2], results[3]), results[4]);
}
else if (results = command.match(/^setblock/)) { // Like old version which uses ids
results = command.match(/^setblock (~|~?-?[0-9]*) (~|~?-?[0-9]*) (~|~?-?[0-9]*) ([0-9]{1,3})/);
if (!results) {
player.chat("Usage: /setblock <x> <y> <z> <id>");
}
else {
results = results.map(function (num, i) { // parseInt paramaters
if (num.indexOf('~') == 0) {
return (player.entity.position[['', 'x', 'y', 'z'][i]] >> 5) + parseInt(num.slice(1) || 0);
}
else
return parseInt(num); // return parseInt>>5 if position, not id
});
serv.setBlock(new Vec3(results[1], results[2], results[3]), results[4]);
}
}
else if(results=command.match(/^kick/)) {
results = command.match(/^kick ([a-zA-Z0-9]+) ?(.*)/);
if (!results) {
player.chat("Usage: /kick <player> [reason]");
else if (results = command.match(/^kick/)) {
results = command.match(/^kick ([a-zA-Z0-9]+)(?: (.*))?/);
if (!results) {
player.chat("Usage: /kick <player> [reason]");
}
else {
var username = results[1];
var reason = results[2];
var kickPlayer = serv.getPlayer(username);
if (!kickPlayer)
player.chat(results[1] + " is not on this server!");
else {
kickPlayer.kick(reason);
kickPlayer.emit("kicked",player,reason);
}
}
}
else if (results = command.match(/^ban/)) {
results = command.match(/^ban ([a-zA-Z0-9]+)(?: (.*))?/);
if (!results) {
player.chat("Usage: /ban <player> [reason]");
}
else {
username = results[1];
reason = results[2];
var banPlayer = serv.getPlayer(username);
if (banPlayer) {
banPlayer.ban(reason);
serv.emit("banned",player,username,reason);
}
else {
var kickPlayer = serv.getPlayer(results[1]);
if (!kickPlayer) {
player.chat(results[1] + " is not on this server!");
serv.banUsername(username, reason, function (err) {
if(err) {
player.chat(results[1] + " is not a valid player!");
}
else {
kickPlayer.kick(results[2] ? "\"" + results[2] + "\"" : "Kicked from server.");
serv.log(player.username + " kicked " + results[1] + (results[2] ? " (" + results[2] + ")" : ""));
serv.emit("banned",player,username,reason);
player.chat(results[1] + " was banned");
}
});
}
}
}
else if(results=command.match(/^ban/)) {
results = command.match(/^ban ([a-zA-Z0-9]+) ?(.*)/);
if (!results) {
player.chat("Usage: /ban <player> [reason]");
}
else {
var banPlayer = serv.getPlayer(results[1]);
var kickReason = "You were banned!" + (results[2] ? " Reason: " + results[2] : "");
var banReason = "You are banned!" + (results[2] ? " Reason: " + results[2] : "");
if (banPlayer) banPlayer.ban(banReason, kickReason);
else {
serv.banUsername(results[1], banReason, function(success) {
if (success) {
serv.log(player.username + " banned " + results[1] + (results[2] ? " (" + results[2] + ")" : ""));
player.chat(results[1] + " was banned");
} else {
player.chat(results[1] + " is not a valid player!");
}
});
}
}
}
else if(results=command.match(/^pardon/)) {
results = command.match(/^pardon ([a-zA-Z0-9]+)/);
if (!results) {
player.chat("Usage: /pardon <player>");
}
else {
serv.pardonUsername(results[1], function(success) {;
if (success) {
player.chat(results[1] + " is unbanned");
} else {
player.chat(results[1] + " is not banned");
}
});
}
else if (results = command.match(/^pardon/)) {
results = command.match(/^pardon ([a-zA-Z0-9]+)/);
if (!results) {
player.chat("Usage: /pardon <player>");
}
else {
serv.pardonUsername(results[1], function (err) {
if(err) {
player.chat(results[1] + " is not banned");
}
else {
player.chat(results[1] + " is unbanned");
}
});
}
}
else
player.chat("Invalid command.");
}
player.handleCommand=handleCommand;
player.handleCommand = handleCommand;
}

View file

@ -24,4 +24,8 @@ function inject(serv,player)
serv.log("[INFO] " + message);
});
player.on("kicked",function(kicker,reason){
serv.log(kicker.username + " kicked " + player.username + (reason ? " (" + reason + ")" : ""));
})
}

View file

@ -1,6 +1,4 @@
var Entity=require("prismarine-entity");
var vec3 = require("vec3");
var moment = require("moment");
module.exports=inject;
@ -9,16 +7,6 @@ function transformUuid(s)
return s.split("-").map(function(item) { return parseInt(item, 16); });
}
function plainUuid(s)
{
return s.replace(/-/g, '');
}
function toFixedPosition(p)
{
return new vec3(Math.floor(p.x*32),Math.floor(p.y*32),Math.floor(p.z*32))
}
function inject(serv,player)
{
function addPlayer()
@ -99,18 +87,6 @@ function inject(serv,player)
});
player.gameMode=gameMode;
}
function kick(reason)
{
player._client.write('kick_disconnect', {
reason: reason ? JSON.stringify(reason) : '"You were kicked!"'
});
}
function ban(reason, kickReason) {
player.kick(kickReason || reason || "You were banned!");
serv.ban(plainUuid(player._client.uuid), reason);
}
function fillTabList()
{
@ -165,7 +141,6 @@ function inject(serv,player)
function spawn()
{
var spawnPoint=toFixedPosition(player.spawnPoint);
player._writeOthers('named_entity_spawn',{
entityId: player.entity.id,
playerUUID: transformUuid(player._client.uuid),
@ -192,13 +167,12 @@ function inject(serv,player)
player._client.end("You are already connected");
return;
}
addPlayer(); // Added before kicking so no errors in deleting entity
if (serv.bannedPlayers[plainUuid(player._client.uuid)]) {
player.kick(serv.bannedPlayers[plainUuid(player._client.uuid)].reason);
return;
if (serv.bannedPlayers[player._client.uuid]) {
player.kick(serv.bannedPlayers[player._client.uuid].reason);
return;
}
addPlayer();
sendLogin();
sendMap();
sendSpawnPosition();
@ -217,8 +191,6 @@ function inject(serv,player)
player.setGameMode=setGameMode;
player.kick=kick;
player.ban=ban;
player.login=login;
player.sendInitialPosition=sendInitialPosition;
player.spawn=spawn;

View file

@ -8,21 +8,23 @@ function transformUuid(s)
function inject(serv,player)
{
player._client.on('end', function () {
serv.broadcast(player.username + ' quit the game.', "yellow");
player._writeOthers('player_info', {
action: 4,
data: [{
UUID: transformUuid(player._client.uuid)
}]
});
player._writeOthers('entity_destroy', {'entityIds': [player.entity.id]});
delete serv.entities[player.entity.id];
player.emit('disconnected');
var index = serv.players.indexOf(player);
if (index > -1) {
serv.players.splice(index,1);
if(player.entity) {
serv.broadcast(player.username + ' quit the game.', "yellow");
player._writeOthers('player_info', {
action: 4,
data: [{
UUID: transformUuid(player._client.uuid)
}]
});
player._writeOthers('entity_destroy', {'entityIds': [player.entity.id]});
delete serv.entities[player.entity.id];
player.emit('disconnected');
var index = serv.players.indexOf(player);
if (index > -1) {
serv.players.splice(index, 1);
}
delete serv.uuidToPlayer[player._client.uuid];
}
delete serv.uuidToPlayer[player._client.uuid];
});

View file

@ -0,0 +1,29 @@
var moment=require("moment");
module.exports=inject;
function inject(serv,player)
{
function kick(reason)
{
player._client.write('kick_disconnect', {
reason: reason ? JSON.stringify(reason) : '"You were kicked!"'
});
}
function ban(reason) {
reason = reason || "You were banned!";
player.kick(reason);
var uuid=player._client.uuid;
serv.ban(uuid, reason);
}
function pardon() {
var uuid=player._client.uuid;
return serv.pardon(uuid);
}
player.kick=kick;
player.ban=ban;
player.pardon=pardon;
}

View file

@ -16,6 +16,10 @@ function inject(serv,settings)
log('[INFO]: Server listening on port '+port);
});
serv.on("banned",function(banner,bannedUsername,reason){
serv.log(banner.username + " banned " + bannedUsername + (reason ? " (" + reason + ")" : ""));
});
var logFile=path.join("logs",timeStarted + ".log");
function log(message) {

View file

@ -2,8 +2,6 @@ var path = require('path');
var requireIndex = require('requireindex');
var playerPlugins = requireIndex(path.join(__dirname,'..', 'playerPlugins'));
var Player=require("../player");
var moment=require("moment");
var request=require("request");
module.exports = inject;
@ -18,48 +16,4 @@ function inject(serv,options)
serv.emit("newPlayer",player);
player.login();
});
function ban(uuid, reason) {
serv.bannedPlayers[uuid] = {
time: +moment(),
reason: reason || "You are banned!"
};
}
function getUUIDFromUsername(username, cb) {
request('https://api.mojang.com/users/profiles/minecraft/' + username, function(err, res, body) {
cb(body ? JSON.parse(body).id : null);
});
}
function banUsername(username, reason, cb) {
serv.getUUIDFromUsername(username, function(uuid) {
if (!uuid) return cb ? cb(false) : false;
serv.ban(uuid, reason);
if (cb) cb(true);
});
}
function pardonUsername(username, cb) {
serv.getUUIDFromUsername(username, function(uuid) {
if (!cb) return;
if (!uuid) return cb(false);
else return cb(pardon(uuid));
});
}
function pardon(uuid) {
if (serv.bannedPlayers[uuid]) {
delete serv.bannedPlayers[uuid];
return true;
} else {
return false;
}
}
serv.bannedPlayers = {};
serv.ban = ban;
serv.banUsername = banUsername;
serv.pardonUsername = pardonUsername;
serv.getUUIDFromUsername = getUUIDFromUsername;
}

View file

@ -0,0 +1,75 @@
var moment=require("moment");
var request=require("request");
var nodeUuid=require('node-uuid');
module.exports = inject;
function inject(serv)
{
function ban(uuid, reason) {
serv.bannedPlayers[uuid] = {
time: +moment(),
reason: reason || "You are banned!"
};
}
function uuidInParts(plainUUID)
{
return nodeUuid.unparse(nodeUuid.parse(plainUUID));
}
function getUUIDFromUsername(username, cb) {
request('https://api.mojang.com/users/profiles/minecraft/' + username, function(err, res, body) {
if(!body || err)
{
cb(new Error("username not found"));
return;
}
cb(null,uuidInParts(JSON.parse(body).id));
});
}
function banUsername(username, reason, cb) {
serv.getUUIDFromUsername(username, function(err,uuid) {
if(err)
{
cb(err);
return;
}
serv.ban(uuid, reason);
cb();
});
}
function pardonUsername(username, cb) {
serv.getUUIDFromUsername(username, function(err,uuid) {
if(err)
{
cb(err);
return;
}
var result=pardon(uuid);
if(!result)
{
cb(new Error("Player wasn't banned."));
return;
}
cb();
});
}
function pardon(uuid) {
if (serv.bannedPlayers[uuid]) {
delete serv.bannedPlayers[uuid];
return true;
}
return false;
}
serv.bannedPlayers = {};
serv.ban = ban;
serv.banUsername = banUsername;
serv.pardonUsername = pardonUsername;
serv.getUUIDFromUsername = getUUIDFromUsername;
}

View file

@ -6,7 +6,7 @@ function inject(serv)
serv.players=[];
serv.uuidToPlayer={};
serv.entities={};
function getPlayer(username) {
for (var p in serv.players) {
if (serv.players[p].username == username) return serv.players[p]