mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2025-02-20 10:43:29 +00:00
implement KK's ban, mute and cuff
This commit is contained in:
parent
1757dfcc75
commit
882adf295a
4 changed files with 282 additions and 15 deletions
|
@ -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);
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue