more vote abuse control, and a new vote switch "W": allow or not "weak" kick/ban votes: when the player is not lagging, spamming, tking, or obviously cheating...
git-svn-id: svn://svn.code.sf.net/p/actiongame/code/trunk/ac@5152 e016b1c5-ed68-44aa-a2f7-31cac88cffde
This commit is contained in:
@@ -553,11 +553,13 @@
|
||||
<td>vote for coopedit mode</td></tr>
|
||||
<tr><td>p</td>
|
||||
<td>vote for a gamemode that is not supported by the map (default: no one can)</td></tr>
|
||||
<tr><td>w</td>
|
||||
<td>vote to kick/ban for "weak" reasons, i.e, the other player is not obviously lagging, nor teamkilling, nor spamming, nor cheating (as far as the server can detect it)</td></tr>
|
||||
</table>
|
||||
For example: -PbmA enables ban & mastermode to be voted by normal players but
|
||||
only admins can change autoteam. The '-P' parameter can be used several times on the commandline.
|
||||
For example, '-Pb -Pm -PA' is equivalent to '-PbmA'.
|
||||
The default settings are: "fkBMasRCDE".
|
||||
The default settings are: "fKBMasRCDEW".
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
|
||||
@@ -307,7 +307,7 @@ const char *modeacronymnames[] =
|
||||
"OSOK", "TOSOK", "BOSOK", "HTF", "TKTF", "KTF"
|
||||
};
|
||||
|
||||
const char *voteerrors[] = { "voting is currently disabled", "there is already a vote pending", "already voted", "can't vote that often", "this vote is not allowed in the current environment (singleplayer/multiplayer)", "no permission", "invalid vote" };
|
||||
const char *voteerrors[] = { "voting is currently disabled", "there is already a vote pending", "already voted", "can't vote that often", "this vote is not allowed in the current environment (singleplayer/multiplayer)", "no permission", "invalid vote", "server denied your call" };
|
||||
const char *mmfullnames[] = { "open", "private", "match" };
|
||||
|
||||
const char *fullmodestr(int n) { return (n>=-1 && size_t(n+1) < sizeof(modefullnames)/sizeof(modefullnames[0])) ? modefullnames[n+1] : "unknown"; }
|
||||
|
||||
@@ -53,7 +53,7 @@ extern const char *messagenames[SV_NUM];
|
||||
|
||||
enum { SA_KICK = 0, SA_BAN, SA_REMBANS, SA_MASTERMODE, SA_AUTOTEAM, SA_FORCETEAM, SA_GIVEADMIN, SA_MAP, SA_RECORDDEMO, SA_STOPDEMO, SA_CLEARDEMOS, SA_SERVERDESC, SA_SHUFFLETEAMS, SA_NUM};
|
||||
enum { VOTE_NEUTRAL = 0, VOTE_YES, VOTE_NO, VOTE_NUM };
|
||||
enum { VOTEE_DISABLED = 0, VOTEE_CUR, VOTEE_MUL, VOTEE_MAX, VOTEE_AREA, VOTEE_PERMISSION, VOTEE_INVALID, VOTEE_NUM };
|
||||
enum { VOTEE_DISABLED = 0, VOTEE_CUR, VOTEE_MUL, VOTEE_MAX, VOTEE_AREA, VOTEE_PERMISSION, VOTEE_INVALID, VOTEE_WEAK, VOTEE_NUM };
|
||||
enum { MM_OPEN = 0, MM_PRIVATE, MM_MATCH, MM_NUM }; enum { MM_MASK = 0x03 };
|
||||
enum { AT_DISABLED = 0, AT_ENABLED = 1, AT_SHUFFLE = 2, AT_NUM };
|
||||
enum { FA_PICKUP = 0, FA_STEAL, FA_DROP, FA_LOST, FA_RETURN, FA_SCORE, FA_NUM, FA_RESET };
|
||||
|
||||
+27
-12
@@ -1846,10 +1846,11 @@ void sendserveropinfo(int receiver)
|
||||
|
||||
struct voteinfo
|
||||
{
|
||||
bool boot;
|
||||
int owner, callmillis, result;
|
||||
serveraction *action;
|
||||
|
||||
voteinfo() : owner(0), callmillis(0), result(VOTE_NEUTRAL), action(NULL) {}
|
||||
voteinfo() : boot(false), owner(0), callmillis(0), result(VOTE_NEUTRAL), action(NULL) {}
|
||||
~voteinfo() { delete action; }
|
||||
|
||||
void end(int result)
|
||||
@@ -1866,7 +1867,7 @@ struct voteinfo
|
||||
}
|
||||
|
||||
bool isvalid() { return valid_client(owner) && action != NULL && action->isvalid(); }
|
||||
bool isalive() { return servmillis - callmillis < 40*1000; }
|
||||
bool isalive() { return servmillis - callmillis < 30*1000; }
|
||||
|
||||
void evaluate(bool forceend = false)
|
||||
{
|
||||
@@ -1921,7 +1922,7 @@ void scallvotesuc(voteinfo *v)
|
||||
DELETEP(curvote);
|
||||
curvote = v;
|
||||
clients[v->owner]->lastvotecall = servmillis;
|
||||
|
||||
clients[v->owner]->nvotes--; // successful votes do not count as abuse
|
||||
sendf(v->owner, 1, "ri", SV_CALLVOTESUC);
|
||||
logline(ACLOG_INFO, "[%s] client %s called a vote: %s", clients[v->owner]->hostname, clients[v->owner]->name, v->action->desc ? v->action->desc : "[unknown]");
|
||||
}
|
||||
@@ -1937,14 +1938,25 @@ bool scallvote(voteinfo *v, ENetPacket *msg) // true if a regular vote was calle
|
||||
{
|
||||
int area = isdedicated ? EE_DED_SERV : EE_LOCAL_SERV;
|
||||
int error = -1;
|
||||
client *c = clients[v->owner], *b = v->boot ? clients[cn2boot] : NULL;
|
||||
|
||||
if(!v || !v->isvalid()) error = VOTEE_INVALID;
|
||||
else if(v->action->role > clients[v->owner]->role) error = VOTEE_PERMISSION;
|
||||
else if(!(area & v->action->area)) error = VOTEE_AREA;
|
||||
else if(curvote && curvote->result==VOTE_NEUTRAL) error = VOTEE_CUR;
|
||||
else if(clients[v->owner]->role == CR_DEFAULT && v->action->isdisabled()) error = VOTEE_DISABLED;
|
||||
else if(clients[v->owner]->lastvotecall && servmillis - clients[v->owner]->lastvotecall < 60*1000 && clients[v->owner]->role != CR_ADMIN && numclients()>1)
|
||||
error = VOTEE_MAX;
|
||||
int time = servmillis - c->lastvotecall;
|
||||
if ( c->nvotes > 0 && time > 4*60*1000 ) c->nvotes -= time/(4*60*1000);
|
||||
if ( c->nvotes < 0 ) c->nvotes = 0;
|
||||
c->nvotes++;
|
||||
|
||||
if( !v || !v->isvalid() || (v->boot && !b) ) error = VOTEE_INVALID;
|
||||
else if( v->action->role > c->role ) error = VOTEE_PERMISSION;
|
||||
else if( !(area & v->action->area) ) error = VOTEE_AREA;
|
||||
else if( curvote && curvote->result==VOTE_NEUTRAL ) error = VOTEE_CUR;
|
||||
else if( c->role == CR_DEFAULT && v->action->isdisabled() ) error = VOTEE_DISABLED;
|
||||
else if( (c->lastvotecall && servmillis - c->lastvotecall < 60*1000 && c->role != CR_ADMIN && numclients()>1) || c->nvotes > 3 ) error = VOTEE_MAX;
|
||||
else if( c->role < roleconf('W') && v->boot == true && !is_lagging(b) && !b->mute && b->spamcount < 2 ) {
|
||||
/** not same team, with low ratio, not lagging, and not spamming... so, why to kick? */
|
||||
if ( !isteam(c->team, b->team) && b->state.frags < ( b->state.deaths ? b->state.deaths : 1 ) * 5 ) error = VOTEE_WEAK;
|
||||
/** same team, with low tk, not lagging, and not spamming... so, why to kick? */
|
||||
else if ( isteam(c->team, b->team) && b->state.teamkills <= c->state.teamkills ) error = VOTEE_WEAK;
|
||||
}
|
||||
|
||||
if(error>=0)
|
||||
{
|
||||
@@ -2756,7 +2768,7 @@ void process(ENetPacket *packet, int sender, int chan)
|
||||
while(curmsg<p.length()) cl->position.add(p.buf[curmsg++]);
|
||||
}
|
||||
if(maplayout && !m_demo && !m_coop) checkclientpos(cl);
|
||||
checkmove(cn, val);
|
||||
checkmove(cl, val);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -2801,7 +2813,7 @@ void process(ENetPacket *packet, int sender, int chan)
|
||||
while(curmsg<p.length()) cl->position.add(p.buf[curmsg++]);
|
||||
}
|
||||
if(maplayout && !m_demo && !m_coop) checkclientpos(cl);
|
||||
checkmove(cn, val);
|
||||
checkmove(cl, val);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -2931,6 +2943,7 @@ void process(ENetPacket *packet, int sender, int chan)
|
||||
case SV_CALLVOTE:
|
||||
{
|
||||
voteinfo *vi = new voteinfo;
|
||||
vi->boot = false;
|
||||
int type = getint(p);
|
||||
switch(type)
|
||||
{
|
||||
@@ -2949,6 +2962,7 @@ void process(ENetPacket *packet, int sender, int chan)
|
||||
getstring(text, p);
|
||||
filtertext(text, text);
|
||||
vi->action = new kickaction(cn2boot, newstring(text));
|
||||
vi->boot = true;
|
||||
break;
|
||||
}
|
||||
case SA_BAN:
|
||||
@@ -2957,6 +2971,7 @@ void process(ENetPacket *packet, int sender, int chan)
|
||||
getstring(text, p);
|
||||
filtertext(text, text);
|
||||
vi->action = new banaction(cn2boot, newstring(text));
|
||||
vi->boot = true;
|
||||
break;
|
||||
}
|
||||
case SA_REMBANS:
|
||||
|
||||
+4
-2
@@ -226,7 +226,7 @@ struct client // server side version of "dynent" type
|
||||
int skin[2];
|
||||
int vote;
|
||||
int role;
|
||||
int connectmillis;
|
||||
int connectmillis, lmillis, ldt, spj;
|
||||
int mute, spam, lastvc; // server side voice comm spam control
|
||||
int acversion, acbuildtype;
|
||||
bool isauthed; // for passworded servers
|
||||
@@ -253,6 +253,7 @@ struct client // server side version of "dynent" type
|
||||
medals md;
|
||||
bool upspawnp;
|
||||
vec spawnp;
|
||||
int nvotes;
|
||||
|
||||
gameevent &addevent()
|
||||
{
|
||||
@@ -281,6 +282,7 @@ struct client // server side version of "dynent" type
|
||||
md.reset();
|
||||
upspawnp = false;
|
||||
spawnp = vec(-1e10f, -1e10f, -1e10f);
|
||||
lmillis = ldt = spj = 0;
|
||||
}
|
||||
|
||||
void reset()
|
||||
@@ -301,7 +303,7 @@ struct client // server side version of "dynent" type
|
||||
spectcn = FPCN_VOID;
|
||||
mapchange();
|
||||
freshgame = false; // don't spawn into running games
|
||||
mute = spam = lastvc = badspeech = badmillis = 0;
|
||||
mute = spam = lastvc = badspeech = badmillis = nvotes = 0;
|
||||
}
|
||||
|
||||
void zap()
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
enum { EE_LOCAL_SERV = 1, EE_DED_SERV = 1<<1 }; // execution environment
|
||||
|
||||
int roleconf(int key)
|
||||
{ // current defaults: "fGkBMasRCDE"
|
||||
{ // current defaults: "fGkBMasRCDEW"
|
||||
if(strchr(scl.voteperm, tolower(key))) return CR_DEFAULT;
|
||||
if(strchr(scl.voteperm, toupper(key))) return CR_ADMIN;
|
||||
return (key) == tolower(key) ? CR_DEFAULT : CR_ADMIN;
|
||||
|
||||
@@ -452,6 +452,10 @@ void checkfrag (client *target, client *actor, int gun, bool gib)
|
||||
}
|
||||
}
|
||||
|
||||
inline bool is_lagging(client *cl)
|
||||
{
|
||||
return ( cl->spj > 80 || gamemillis - cl->lmillis > 400 );
|
||||
}
|
||||
|
||||
/**
|
||||
If you read README.txt you must know that AC does not have cheat protection implemented.
|
||||
@@ -469,9 +473,12 @@ This part is here for compatibility purposes.
|
||||
If you know nothing about these detections, please, just ignore it.
|
||||
*/
|
||||
|
||||
inline void checkmove (int cn, int *v)
|
||||
inline void checkmove (client *cl, int *v)
|
||||
{
|
||||
client *cl = clients[cn];
|
||||
cl->ldt = gamemillis - cl->lmillis;
|
||||
cl->lmillis = gamemillis;
|
||||
if ( cl->ldt < 30 ) cl->ldt = 30;
|
||||
cl->spj = (( 7 * cl->spj + cl->ldt ) >> 3);
|
||||
if ( !cl->upspawnp ) {
|
||||
cl->spawnp = cl->state.o;
|
||||
cl->upspawnp = true;
|
||||
|
||||
Reference in New Issue
Block a user