git-svn-id: svn://svn.code.sf.net/p/actiongame/code/trunk/ac@3996 e016b1c5-ed68-44aa-a2f7-31cac88cffde
274 lines
7.6 KiB
C
274 lines
7.6 KiB
C
// available server actions
|
|
|
|
enum { EE_LOCAL_SERV = 1, EE_DED_SERV = 1<<1 }; // execution environment
|
|
|
|
int roleconf(int key)
|
|
{ // current defaults: "fGkBMasRCDxP"
|
|
if(strchr(voteperm, tolower(key))) return CR_DEFAULT;
|
|
if(strchr(voteperm, toupper(key))) return CR_ADMIN;
|
|
return (key) == tolower(key) ? CR_DEFAULT : CR_ADMIN;
|
|
}
|
|
|
|
struct serveraction
|
|
{
|
|
int role; // required client role
|
|
int area; // only on ded servers
|
|
string desc;
|
|
|
|
virtual void perform() = 0;
|
|
virtual bool isvalid() { return true; }
|
|
virtual bool isdisabled() { return false; }
|
|
serveraction() : role(CR_DEFAULT), area(EE_DED_SERV) { desc[0] = '\0'; }
|
|
virtual ~serveraction() { }
|
|
};
|
|
|
|
struct mapaction : serveraction
|
|
{
|
|
char *map;
|
|
int mode;
|
|
void perform()
|
|
{
|
|
if(isdedicated && numclients() > 2 && smode >= 0 && smode != 1 && gamemillis > gamelimit/4)
|
|
{
|
|
forceintermission = true;
|
|
nextgamemode = mode;
|
|
s_strcpy(nextmapname, map);
|
|
}
|
|
else
|
|
{
|
|
resetmap(map, mode);
|
|
}
|
|
}
|
|
bool isvalid() { return serveraction::isvalid() && mode != GMODE_DEMO && map[0]; }
|
|
bool isdisabled() { return configsets.inrange(curcfgset) && !configsets[curcfgset].vote; }
|
|
mapaction(char *map, int mode, int caller) : map(map), mode(mode)
|
|
{
|
|
if(isdedicated)
|
|
{
|
|
bool notify = valid_client(caller) && clients[caller]->role == CR_DEFAULT;
|
|
mapstats *ms = getservermapstats(map);
|
|
if(strchr(voteperm, 'X') && !ms) // admin needed for unknown maps
|
|
{
|
|
role = CR_ADMIN;
|
|
if(notify) sendservmsg("the server does not have this map", caller);
|
|
}
|
|
if(ms && !strchr(voteperm, 'p')) // admin needed for mismatched modes
|
|
{
|
|
int smode = mode; // 'borrow' the mode macros by replacing a global by a local var
|
|
bool spawns = (m_teammode && !m_ktf) ? ms->hasteamspawns : ms->hasffaspawns;
|
|
bool flags = m_flags && !m_htf ? ms->hasflags : true;
|
|
if(!spawns || !flags)
|
|
{
|
|
role = CR_ADMIN;
|
|
s_sprintfd(msg)("\f3map \"%s\" does not support \"%s\": ", behindpath(map), modestr(mode, false));
|
|
if(!spawns) s_strcat(msg, "player spawns");
|
|
if(!spawns && !flags) s_strcat(msg, " and ");
|
|
if(!flags) s_strcat(msg, "flag bases");
|
|
s_strcat(msg, " missing");
|
|
if(notify) sendservmsg(msg, caller);
|
|
logger->writeline(log::info, "%s", msg);
|
|
}
|
|
}
|
|
}
|
|
area |= EE_LOCAL_SERV; // local too
|
|
s_sprintf(desc)("load map '%s' in mode '%s'", map, modestr(mode));
|
|
}
|
|
~mapaction() { DELETEA(map); }
|
|
};
|
|
|
|
struct demoplayaction : serveraction
|
|
{
|
|
char *map;
|
|
void perform() { resetmap(map, GMODE_DEMO); }
|
|
demoplayaction(char *map) : map(map)
|
|
{
|
|
area = EE_LOCAL_SERV; // only local
|
|
}
|
|
|
|
~demoplayaction() { DELETEA(map); }
|
|
};
|
|
|
|
struct playeraction : serveraction
|
|
{
|
|
int cn;
|
|
ENetAddress address;
|
|
void disconnect(int reason)
|
|
{
|
|
int i = findcnbyaddress(&address);
|
|
if(i >= 0) disconnect_client(i, reason);
|
|
}
|
|
virtual bool isvalid() { return valid_client(cn) && clients[cn]->role != CR_ADMIN; } // actions can't be done on admins
|
|
playeraction(int cn) : cn(cn)
|
|
{
|
|
if(isvalid()) address = clients[cn]->peer->address;
|
|
};
|
|
};
|
|
|
|
struct forceteamaction : playeraction
|
|
{
|
|
void perform() { forceteam(cn, team_opposite(team_int(clients[cn]->team)), true); }
|
|
virtual bool isvalid() { return m_teammode && valid_client(cn); }
|
|
forceteamaction(int cn, int caller) : playeraction(cn)
|
|
{
|
|
if(cn != caller) role = roleconf('f');
|
|
if(isvalid()) s_sprintf(desc)("force player %s to the enemy team", clients[cn]->name);
|
|
}
|
|
};
|
|
|
|
struct giveadminaction : playeraction
|
|
{
|
|
void perform() { changeclientrole(cn, CR_ADMIN, NULL, true); }
|
|
giveadminaction(int cn) : playeraction(cn)
|
|
{
|
|
role = CR_ADMIN;
|
|
// role = roleconf('G');
|
|
}
|
|
};
|
|
|
|
struct kickaction : playeraction
|
|
{
|
|
bool wasvalid;
|
|
void perform() { disconnect(DISC_MKICK); }
|
|
virtual bool isvalid() { return wasvalid || playeraction::isvalid(); }
|
|
kickaction(int cn) : playeraction(cn)
|
|
{
|
|
wasvalid = false;
|
|
role = roleconf('k');
|
|
if(isvalid())
|
|
{
|
|
wasvalid = true;
|
|
s_sprintf(desc)("kick player %s", clients[cn]->name);
|
|
}
|
|
}
|
|
};
|
|
|
|
struct banaction : playeraction
|
|
{
|
|
bool wasvalid;
|
|
void perform()
|
|
{
|
|
ban b = { address, servmillis+20*60*1000 };
|
|
bans.add(b);
|
|
disconnect(DISC_MBAN);
|
|
}
|
|
virtual bool isvalid() { return wasvalid || playeraction::isvalid(); }
|
|
banaction(int cn) : playeraction(cn)
|
|
{
|
|
role = roleconf('B');
|
|
if(isvalid())
|
|
{
|
|
wasvalid = true;
|
|
s_sprintf(desc)("ban player %s", clients[cn]->name);
|
|
}
|
|
}
|
|
};
|
|
|
|
struct removebansaction : serveraction
|
|
{
|
|
void perform() { bans.setsize(0); }
|
|
removebansaction()
|
|
{
|
|
role = roleconf('B');
|
|
s_strcpy(desc, "remove all bans");
|
|
}
|
|
};
|
|
|
|
struct mastermodeaction : serveraction
|
|
{
|
|
int mode;
|
|
void perform() { mastermode = mode; }
|
|
bool isvalid() { return mode >= 0 && mode < MM_NUM; }
|
|
mastermodeaction(int mode) : mode(mode)
|
|
{
|
|
role = roleconf('M');
|
|
if(isvalid()) s_sprintf(desc)("change mastermode to '%s'", mmfullname(mode));
|
|
}
|
|
};
|
|
|
|
struct enableaction : serveraction
|
|
{
|
|
bool enable;
|
|
enableaction(bool enable) : enable(enable) {}
|
|
};
|
|
|
|
struct autoteamaction : enableaction
|
|
{
|
|
void perform()
|
|
{
|
|
sendf(-1, 1, "ri2", SV_AUTOTEAM, (autoteam = enable) == 1 ? AT_ENABLED : AT_DISABLED);
|
|
if(m_teammode && enable) refillteams(true);
|
|
}
|
|
autoteamaction(bool enable) : enableaction(enable)
|
|
{
|
|
role = roleconf('a');
|
|
if(isvalid()) s_sprintf(desc)("%s autoteam", enable ? "enable" : "disable");
|
|
}
|
|
};
|
|
|
|
struct shuffleteamaction : serveraction
|
|
{
|
|
void perform()
|
|
{
|
|
sendf(-1, 1, "ri2", SV_AUTOTEAM, AT_SHUFFLE);
|
|
shuffleteams();
|
|
}
|
|
bool isvalid() { return serveraction::isvalid() && m_teammode; }
|
|
shuffleteamaction()
|
|
{
|
|
role = roleconf('s');
|
|
if(isvalid()) s_strcpy(desc, "shuffle teams");
|
|
}
|
|
};
|
|
|
|
struct recorddemoaction : enableaction
|
|
{
|
|
void perform() { demonextmatch = enable; }
|
|
recorddemoaction(bool enable) : enableaction(enable)
|
|
{
|
|
role = roleconf('R');
|
|
if(isvalid()) s_sprintf(desc)("%s demorecord", enable ? "enable" : "disable");
|
|
}
|
|
};
|
|
|
|
struct stopdemoaction : serveraction
|
|
{
|
|
void perform()
|
|
{
|
|
if(m_demo) enddemoplayback();
|
|
else enddemorecord();
|
|
}
|
|
stopdemoaction()
|
|
{
|
|
role = CR_ADMIN;
|
|
area |= EE_LOCAL_SERV;
|
|
s_strcpy(desc, "stop demo");
|
|
}
|
|
};
|
|
|
|
struct cleardemosaction : serveraction
|
|
{
|
|
int demo;
|
|
void perform() { cleardemos(demo); }
|
|
cleardemosaction(int demo) : demo(demo)
|
|
{
|
|
role = roleconf('C');
|
|
if(isvalid()) s_sprintf(desc)("clear demo %d", demo);
|
|
}
|
|
};
|
|
|
|
struct serverdescaction : serveraction
|
|
{
|
|
char *sdesc;
|
|
int cn;
|
|
ENetAddress address;
|
|
void perform() { updatesdesc(sdesc, &address); }
|
|
bool isvalid() { return serveraction::isvalid() && updatedescallowed() && valid_client(cn); }
|
|
serverdescaction(char *sdesc, int cn) : sdesc(sdesc), cn(cn)
|
|
{
|
|
role = roleconf('D');
|
|
s_sprintf(desc)("set server description to '%s'", sdesc);
|
|
if(isvalid()) address = clients[cn]->peer->address;
|
|
}
|
|
~serverdescaction() { DELETEA(sdesc); }
|
|
};
|