mirror of
https://github.com/danbulant/flying-squid
synced 2026-06-16 04:51:08 +00:00
clean kick/ban system
This commit is contained in:
parent
2b8a24e2ef
commit
4bf03223dd
11 changed files with 231 additions and 180 deletions
27
doc/api.md
27
doc/api.md
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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 + ")" : ""));
|
||||
})
|
||||
|
||||
}
|
||||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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];
|
||||
});
|
||||
|
||||
|
||||
|
|
|
|||
29
lib/playerPlugins/moderation.js
Normal file
29
lib/playerPlugins/moderation.js
Normal 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;
|
||||
}
|
||||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
75
lib/serverPlugins/moderation.js
Normal file
75
lib/serverPlugins/moderation.js
Normal 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;
|
||||
}
|
||||
|
|
@ -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]
|
||||
|
|
|
|||
Loading…
Reference in a new issue