implement KK's ban, mute and cuff

This commit is contained in:
Bill Currie 2001-09-09 04:51:08 +00:00
parent 1757dfcc75
commit 882adf295a
4 changed files with 282 additions and 15 deletions

View file

@ -135,6 +135,12 @@ typedef struct
#define MAX_BACK_BUFFERS 8
#define MAX_STUFFTEXT 512
typedef enum {
ft_ban,
ft_mute, // mute penalty save over disconnect
ft_cuff, // cuff penatly save over disconnect
} filtertype_t;
typedef struct client_s
{
sv_client_state_t state;
@ -215,7 +221,8 @@ typedef struct client_s
netchan_t netchan;
int msecs, msec_cheating;
double last_check;
int stdver;
double cuff_time;
int stdver;
} client_t;
// a client can leave the server in one of four ways:
@ -422,6 +429,10 @@ void Con_DPrintf (const char *fmt, ...) __attribute__((format(printf,1,2)));
//
// sv_main.c
//
void SV_SavePenaltyFilter (client_t *cl, filtertype_t type, double pentime);
double SV_RestorePenaltyFilter (client_t *cl, filtertype_t type);
void SV_Shutdown (void);
void SV_Frame (float time);
void SV_FinalMessage (const char *message);

View file

@ -514,6 +514,126 @@ SV_Status_f (void)
SV_Printf ("\n");
}
#define MAXPENALTY 10.0
void
SV_Cuff_f (void)
{
int i, uid;
double mins = 0.5;
qboolean all = false, done = false;
client_t *cl;
char text[1024];
if (Cmd_Argc() != 2 && Cmd_Argc() != 3) {
SV_Printf ("usage: cuff <name/userid/ALL> [minutes]\n"
" (default = 0.5, 0 = cancel cuff).\n");
return;
}
if (strequal (Cmd_Argv(1), "ALL")) {
all = true;
} else {
if (SV_Match_User (Cmd_Argv(1), &uid)) {
if (!uid)
return;
} else {
uid = atoi(Cmd_Argv(1)); // assume userid
}
}
if (Cmd_Argc() == 3) {
mins = atof(Cmd_Argv(2));
if (mins < 0.0 || mins > MAXPENALTY)
mins = MAXPENALTY;
}
for (i = 0, cl = svs.clients; i < MAX_CLIENTS; i++, cl++) {
if (!cl->state)
continue;
if (all || (cl->userid == uid)) {
cl->cuff_time = realtime + mins*60.0;
done = true;
if (mins) {
sprintf(text,
"You are cuffed for %.1f minutes\n\n"
"reconnecting won't help...\n", mins);
ClientReliableWrite_Begin(cl,svc_centerprint, 2+strlen(text));
ClientReliableWrite_String (cl, text);
}
if (!all)
break;
}
}
if (done) {
if (mins)
SV_BroadcastPrintf (PRINT_HIGH, "%s cuffed for %.1f minutes.\n",
all? "All Users" : cl->name, mins);
else
SV_BroadcastPrintf (PRINT_HIGH, "%s un-cuffed.\n",
all? "All Users" : cl->name);
} else {
SV_Printf (all? "No users\n" : "Couldn't find user %s\n", Cmd_Argv(1));
}
}
void
SV_Mute_f (void)
{
int i, uid;
double mins = 0.5;
qboolean all = false, done = false;
client_t *cl;
char text[1024];
if (Cmd_Argc() != 2 && Cmd_Argc() != 3) {
SV_Printf ("usage: mute <name/userid/ALL> [minutes]\n"
" (default = 0.5, 0 = cancel mute).\n");
return;
}
if (strequal(Cmd_Argv(1),"ALL")) {
all = true;
} else {
if (SV_Match_User (Cmd_Argv(1), &uid)) {
if (!uid)
return;
} else {
uid = atoi(Cmd_Argv(1));
}
}
if (Cmd_Argc() == 3) {
mins = atof(Cmd_Argv(2));
if (mins < 0.0 || mins > MAXPENALTY)
mins = MAXPENALTY;
}
for (i = 0, cl = svs.clients; i < MAX_CLIENTS; i++, cl++) {
if (!cl->state)
continue;
if (all || (cl->userid == uid)) {
cl->lockedtill = realtime + mins*60.0;
done = true;
if (mins) {
sprintf(text, "You are muted for %.1f minutes\n\n"
"reconnecting won't help...\n", mins);
ClientReliableWrite_Begin(cl,svc_centerprint, 2+strlen(text));
ClientReliableWrite_String (cl, text);
}
if (!all)
break;
}
}
if (done) {
if (mins)
SV_BroadcastPrintf (PRINT_HIGH, "%s muted for %.1f minutes.\n",
all? "All Users" : cl->name, mins);
else
SV_BroadcastPrintf (PRINT_HIGH, "%s allowed to speak.\n",
all? "All Users" : cl->name);
} else {
SV_Printf (all? "No users\n" : "Couldn't find user %s\n",
Cmd_Argv(1));
}
}
void
SV_Tell (const char *prefix)
{
@ -559,6 +679,47 @@ SV_Tell (const char *prefix)
SV_Printf ("Couldn't find user %s\n", Cmd_Argv(1));
}
void
SV_Ban_f (void)
{
int i, uid;
double mins = 30.0;
client_t *cl;
if (Cmd_Argc() != 2 && Cmd_Argc() != 3) {
SV_Printf ("usage: ban <name/userid> [minutes]\n"
" (default = 30, 0 = permanent).\n");
return;
}
if (SV_Match_User(Cmd_Argv(1), &uid)) {
if (!uid)
return;
} else {
uid = atoi(Cmd_Argv(1));
}
if (Cmd_Argc() == 3) {
mins = atof(Cmd_Argv(2));
if (mins<0.0 || mins > 1000000.0) // bout 2 yrs
mins = 0.0;
}
for (i = 0, cl = svs.clients; i < MAX_CLIENTS; i++, cl++) {
if (!cl->state)
continue;
if (cl->userid == uid) {
SV_BroadcastPrintf (PRINT_HIGH, "Admin Banned user %s %s\n",
cl->name, mins ? va("for %.1f minutes",mins)
: "permanently");
SV_DropClient (cl);
Cmd_ExecuteString (
va ("addip %s %f",
NET_BaseAdrToString(cl->netchan.remote_address), mins),
src_command);
return;
}
}
Con_Printf ("Couldn't find user %s\n", Cmd_Argv(1));
}
void
SV_ConSay (const char *prefix)
{
@ -1004,9 +1165,11 @@ SV_InitOperatorCommands (void)
Cmd_AddCommand ("tell", SV_Tell_f, "Say something to a specific user on "
"the server. Will show up as the name 'Console' (or "
"'Admin') in game");
//XXX Cmd_AddCommand ("ban", SV_Ban_f);
//XXX Cmd_AddCommand ("cuff", SV_Cuff_f);
//XXX Cmd_AddCommand ("mute", SV_Mute_f);
Cmd_AddCommand ("ban", SV_Ban_f, "ban a player for a specified time");
Cmd_AddCommand ("cuff", SV_Cuff_f, "\"hand-cuff\" a player for a "
"specified time");
Cmd_AddCommand ("mute", SV_Mute_f, "silience a player for a specified "
"time");
cl_warncmd = Cvar_Get ("cl_warncmd", "1", CVAR_NONE, NULL, "Toggles the "
"display of error messages for unknown commands");

View file

@ -249,6 +249,9 @@ SV_FinalMessage (const char *message)
void
SV_DropClient (client_t *drop)
{
SV_SavePenaltyFilter (drop, ft_mute, drop->lockedtill);
SV_SavePenaltyFilter (drop, ft_cuff, drop->cuff_time);
// add the disconnect
MSG_WriteByte (&drop->netchan.message, svc_disconnect);
@ -830,7 +833,7 @@ SVC_DirectConnect (void)
for (i = 0; i < 10; i++)
newcl->whensaid[i] = 0.0;
newcl->whensaidhead = 0;
newcl->lockedtill = 0;
newcl->lockedtill = SV_RestorePenaltyFilter(newcl, ft_mute);
// call the progs to get default spawn parms for the new client
PR_ExecuteProgram (&sv_pr_state, sv_funcs.SetNewParms);
@ -848,6 +851,7 @@ SVC_DirectConnect (void)
newcl->msec_cheating = 0;
newcl->last_check = -1;
newcl->cuff_time = SV_RestorePenaltyFilter(newcl, ft_cuff);
}
int
@ -1045,6 +1049,7 @@ SV_ConnectionlessPacket (void)
typedef struct {
unsigned int mask;
unsigned int compare;
double time;
} ipfilter_t;
#define MAX_IPFILTERS 1024
@ -1052,6 +1057,7 @@ typedef struct {
cvar_t *filterban;
int numipfilters;
ipfilter_t ipfilters[MAX_IPFILTERS];
filtertype_t filttypes[MAX_IPFILTERS];
qboolean
StringToFilter (const char *s, ipfilter_t * f)
@ -1091,6 +1097,26 @@ StringToFilter (const char *s, ipfilter_t * f)
return true;
}
void
CleanIPlist (void)
{
int i, j;
for (i=0 ; i<numipfilters ; i++) {
if (ipfilters[i].time && (ipfilters[i].time < realtime))
ipfilters[i].compare = 0xffffffff;
if (ipfilters[i].compare == 0xffffffff) {
for (j=i+1 ; j<numipfilters ; j++) {
ipfilters[j - 1] = ipfilters[j];
filttypes[j - 1] = filttypes[j];
}
numipfilters--;
i--;
Sys_Printf ("CleanIPlist: an IP filter removed.\n");
}
}
}
void
SV_AddIP_f (void)
{
@ -1228,7 +1254,7 @@ SV_netDoSvalues_f (void)
}
void
SV_SendBan (void)
SV_SendBan (double till)
{
char data[128];
@ -1237,25 +1263,89 @@ SV_SendBan (void)
data[0] = data[1] = data[2] = data[3] = 0xff;
data[4] = A2C_PRINT;
data[5] = 0;
strncat (data, "\nbanned.\n", sizeof (data) - strlen (data));
if (till) {
snprintf (data + 5, sizeof (data) - 5,
"\nbanned for %.1f more minutes.\n", (till - realtime)/60.0);
} else {
snprintf (data + 5, sizeof (data) - 5, "\nbanned permanently.\n");
}
NET_SendPacket (strlen (data), data, net_from);
}
qboolean
SV_FilterPacket (void)
SV_FilterPacket (double *until)
{
int i;
unsigned int in;
in = *(unsigned int *) net_from.ip;
for (i = 0; i < numipfilters; i++)
if ((in & ipfilters[i].mask) == ipfilters[i].compare)
return filterban->int_val;
for (i = 0; i < numipfilters; i++) {
if (filttypes[i] != ft_ban)
continue;
if ((in & ipfilters[i].mask) == ipfilters[i].compare) {
if (!ipfilters[i].time) {
// normal ban
return filterban->int_val;
} else if (ipfilters[i].time > realtime) {
*until = ipfilters[i].time;
return true; // banned no matter what
} else {
// time expired, set free
ipfilters[i].compare = 0xffffffff;
}
}
}
return !filterban->int_val;
}
return !filterban->int_val; // FIXME eh?
void
SV_SavePenaltyFilter (client_t *cl, filtertype_t type, double pentime)
{
int i;
unsigned int ip;
ip = *(unsigned int *) cl->netchan.remote_address.ip;
// delete any existing penalty filter of same type
for (i=0 ; i<numipfilters; i++) {
if ( type == filttypes[i] && ip == ipfilters[i].compare ) {
ipfilters[i].compare = 0xffffffff;
break;
}
}
CleanIPlist();
// save a new penalty
if ( pentime < realtime ) // no point
return;
Con_Printf ("Penalty saved for user=%d\n",cl->userid);
ipfilters[numipfilters].mask = 0;
ipfilters[numipfilters].compare = ip;
ipfilters[numipfilters].time = pentime;
filttypes[numipfilters] = type;
numipfilters++;
return;
}
double
SV_RestorePenaltyFilter (client_t *cl, filtertype_t type)
{
int i;
unsigned int ip;
ip = * (unsigned int *) cl->netchan.remote_address.ip;
CleanIPlist ();
// search for existing penalty filter of same type
for (i=0 ; i<numipfilters; i++) {
if (type == filttypes[i] && ip == ipfilters[i].compare) {
Sys_Printf("Penalty restored for user=%d\n",cl->userid);
return ipfilters[i].time;
}
}
return 0.0;
}
void
@ -1264,11 +1354,12 @@ SV_ReadPackets (void)
client_t *cl;
int qport, i;
qboolean good;
double until;
good = false;
while (NET_GetPacket ()) {
if (SV_FilterPacket ()) {
SV_SendBan (); // tell them we aren't listening...
if (SV_FilterPacket (&until)) {
SV_SendBan (until); // tell them we aren't listening...
continue;
}
// check for connectionless packet (0xffffffff) first

View file

@ -1502,6 +1502,8 @@ SV_RunCmd (usercmd_t *ucmd, qboolean inside)
SVfloat (sv_player, button2) = (ucmd->buttons & 2) >> 1;
if (ucmd->impulse)
SVfloat (sv_player, impulse) = ucmd->impulse;
if (host_client->cuff_time > realtime)
SVfloat (sv_player, button0) = SVfloat (sv_player, impulse) = 0;
//
// angles