read motd from file (multilanguage); auto reload changed serverinfo and motd files

git-svn-id: svn://svn.code.sf.net/p/actiongame/code/trunk/ac@4527 e016b1c5-ed68-44aa-a2f7-31cac88cffde
This commit is contained in:
ac_stef
2009-06-19 12:51:25 +00:00
parent ef4138701e
commit 01ab8df5db
6 changed files with 88 additions and 23 deletions
+14
View File
@@ -0,0 +1,14 @@
// extended serverinfo file
// ========================
// WARNING: You can NOT use CubeScript in here!!
//
// This text file is read, whenever a the MOTD is sent to a client.
// Comments are removed, also leading and trailing blanks and empty lines.
//
// Don't use more than 80 characters per line. You can use colors and TABs.
// The available colors are: 0: green, 1: blue, 2: yellow, 3: red, 4: gray, 5: white, 6: dark brown, 7: dark red
//
// Example:
// BobsInstagibServer \f3play nicely!
// contact me at [email protected]
+2
View File
@@ -420,6 +420,8 @@ void sendintro()
0);
sendstring(player1->name, p);
sendstring(genpwdhash(player1->name, clientpassword, sessionid), p);
const char *lang = getalias("LANG");
sendstring(!lang || strlen(lang) != 2 ? "" : lang, p);
putint(p, connectrole);
clientpassword[0] = '\0';
connectrole = CR_DEFAULT;
+11
View File
@@ -159,6 +159,17 @@ void filterservdesc(char *dst, const char *src, int len)
*dst = '\0';
}
void filterlang(char *d, const char *s)
{
if(strlen(s) == 2)
{
loopi(2) d[i] = tolower(s[i]);
d[2] = '\0';
if(islower(d[0]) && islower(d[1])) return;
}
*d = '\0';
}
void cutcolorstring(char *text, int len)
{ // limit string length, ignore color codes
while(*text)
+5 -5
View File
@@ -689,6 +689,7 @@ extern void getstring(char *t, ucharbuf &p, int len = MAXTRANS);
extern void filtertext(char *dst, const char *src, int whitespace = 1, int len = sizeof(string)-1);
extern void filterrichtext(char *dst, const char *src, int len = sizeof(string)-1);
extern void filterservdesc(char *dst, const char *src, int len = sizeof(string)-1);
extern void filterlang(char *d, const char *s);
extern void cutcolorstring(char *text, int len);
extern void startintermission();
extern void restoreserverstate(vector<entity> &ents);
@@ -727,7 +728,7 @@ extern bool logline(int level, const char *msg, ...);
struct servercommandline
{
int uprate, serverport, syslogfacility, filethres, syslogthres, maxdemos, maxclients, kickthreshold, banthreshold, verbose;
const char *ip, *master, *logident, *serverpassword, *adminpasswd, *demopath, *maprot, *pwdfile, *blfile, *nbfile, *infopath;
const char *ip, *master, *logident, *serverpassword, *adminpasswd, *demopath, *maprot, *pwdfile, *blfile, *nbfile, *infopath, *motdpath;
bool demoeverymatch, logtimestamp;
string motd, servdesc_full, servdesc_pre, servdesc_suf, voteperm, mapperm;
int clfilenesting;
@@ -737,7 +738,7 @@ struct servercommandline
maxclients(DEFAULTCLIENTS), kickthreshold(-5), banthreshold(-6), verbose(0),
ip(""), master(NULL), logident(""), serverpassword(""), adminpasswd(""), demopath(""),
maprot("config/maprot.cfg"), pwdfile("config/serverpwd.cfg"), blfile("config/serverblacklist.cfg"), nbfile("config/nicknameblacklist.cfg"),
infopath("config/serverinfo"),
infopath("config/serverinfo"), motdpath("config/motd"),
demoeverymatch(true), logtimestamp(false),
clfilenesting(0)
{
@@ -750,7 +751,7 @@ struct servercommandline
const char *a = arg + 2 + strspn(arg + 2, " ");
int ai = atoi(a);
switch(arg[1])
{ // todo: egjlqEGHJOQUYZ
{ // todo: egjlqEGHJQUYZ
case 'u': uprate = ai; break;
case 'f': if(ai > 0 && ai < 65536) serverport = ai; break;
case 'i': ip = a; break;
@@ -785,6 +786,7 @@ struct servercommandline
case 'K': nbfile = a; break;
case 'I': infopath = a; break;
case 'o': filterrichtext(motd, a); break;
case 'O': motdpath = a; break;
case 'n':
{
char *t = servdesc_full;
@@ -800,7 +802,6 @@ struct servercommandline
case 'P': s_strcat(voteperm, a); break;
case 'M': s_strcat(mapperm, a); break;
case 'V': verbose++; break;
#ifdef STANDALONE
case 'C': if(*a && clfilenesting < 3)
{
extern char *loadcfgfile(char *cfg, const char *name, int *len);
@@ -825,7 +826,6 @@ struct servercommandline
clfilenesting--;
break;
}
#endif
default: return false;
}
return true;
+48 -17
View File
@@ -28,6 +28,7 @@ void changeclientrole(int client, int role, char *pwd = NULL, bool force=false);
int mapavailable(const char *mapname);
void getservermap(void);
mapstats *getservermapstats(const char *mapname, bool getlayout = false);
const char *getmotd(const char *lang);
int findmappath(const char *mapname, char *filename = NULL);
enum { MAP_NOTFOUND = 0, MAP_TEMP, MAP_CUSTOM, MAP_LOCAL, MAP_OFFICIAL };
@@ -244,6 +245,7 @@ struct client // server side version of "dynent" type
ENetPeer *peer;
string hostname;
string name, team;
char lang[3];
int ping;
int skin;
int vote;
@@ -2765,11 +2767,12 @@ void welcomepacket(ucharbuf &p, int n, ENetPacket *packet, bool forcedeath)
}
putint(p, SV_AUTOTEAM);
putint(p, autoteam ? 1 : 0);
if(scl.motd[0])
const char *motd = scl.motd[0] ? scl.motd : getmotd(c ? c->lang : "");
if(motd)
{
CHECKSPACE(5+2*(int)strlen(scl.motd)+1);
CHECKSPACE(5+2*(int)strlen(motd)+1);
putint(p, SV_TEXT);
sendstring(scl.motd, p);
sendstring(motd, p);
}
#undef CHECKSPACE
@@ -2844,6 +2847,8 @@ void process(ENetPacket *packet, int sender, int chan) // sender may be -1
getstring(text, p);
s_strcpy(cl->pwd, text);
getstring(text, p);
filterlang(cl->lang, text);
int wantrole = getint(p);
cl->state.nextprimary = getint(p);
bool banned = isbanned(sender);
@@ -3795,9 +3800,9 @@ void extping_namelist(ucharbuf &p)
#define MAXINFOLINELEN 100 // including color codes
const char *readserverinfo(const char *lang)
char *readserverinfo(const char *fnbase, const char *lang)
{
s_sprintfd(fname)("%s_%s.txt", scl.infopath, lang);
s_sprintfd(fname)("%s_%s.txt", fnbase, lang);
path(fname);
int len, n;
char *c, *s, *t, *buf = loadfile(fname, &len);
@@ -3815,32 +3820,58 @@ const char *readserverinfo(const char *lang)
*t = '\0';
delete[] buf;
if(!*nbuf) DELETEA(nbuf);
logline(ACLOG_DEBUG,"read file \"%s\"", fname);
return nbuf;
}
struct serverinfotext { char lang[3]; const char *info; };
struct serverinfotext { int type; char lang[3]; char *info; int lastcheck; };
vector<serverinfotext> serverinfotexts;
enum { SINFO_EXT = 0, SINFO_MOTD, SINFO_NUM };
const char *sinfo_fns[] = { scl.infopath, scl.motdpath };
const char *getserverinfo(const char *lang)
const char *getserverinfo(int type, const char *lang)
{
if(!islower(lang[0]) || !islower(lang[1])) return NULL;
serverinfotext s;
loopi(3) s.lang[i] = lang[i];
serverinfotext sn = { type, { 0, 0, 0 }, NULL, 0} , *s = &sn;
filterlang(sn.lang, lang);
if(!sn.lang[0] || type < 0 || type >= SINFO_NUM) return NULL;
loopv(serverinfotexts)
{
if(!strcmp(s.lang, serverinfotexts[i].lang) && serverinfotexts[i].info) return serverinfotexts[i].info;
serverinfotext &si = serverinfotexts[i];
if(si.type == s->type && !strcmp(si.lang, s->lang))
{
if(servmillis - si.lastcheck > (si.info ? 15 : 45) * 60 * 1000)
{ // re-read existing files after 15 minutes; search missing again after 45 minutes
DELETEA(si.info);
s = &si;
}
else return si.info;
}
}
s.info = readserverinfo(lang);
serverinfotexts.add(s);
return s.info;
s->info = readserverinfo(sinfo_fns[type], lang);
s->lastcheck = servmillis;
if(s == &sn) serverinfotexts.add(*s);
if(s->type == SINFO_MOTD && s->info)
{
char *c = s->info;
while(*c) { c += strlen(c); if(c[1]) *c++ = '\n'; }
if(strlen(s->info) > _MAXDEFSTR) s->info[_MAXDEFSTR] = '\0'; // keep MOTD at sane lengths
}
return s->info;
}
const char *getmotd(const char *lang)
{
const char *motd;
if(*lang && (motd = getserverinfo(SINFO_MOTD, lang))) return motd;
return getserverinfo(SINFO_MOTD, "en");
}
void extping_serverinfo(ucharbuf &pi, ucharbuf &po)
{
char lang[3];
lang[0] = tolower(getint(pi)); lang[1] = tolower(getint(pi)); lang[2] = '\0';
const char *reslang = lang, *buf = getserverinfo(lang); // try client language
if(!buf) buf = getserverinfo(reslang = "en"); // try english
const char *reslang = lang, *buf = getserverinfo(SINFO_EXT, lang); // try client language
if(!buf) buf = getserverinfo(SINFO_EXT, reslang = "en"); // try english
sendstring(buf ? reslang : "", po);
if(buf)
{
@@ -4006,7 +4037,7 @@ void initserver(bool dedicated)
readpwdfile(scl.pwdfile);
readipblacklist(scl.blfile);
nbl.readnickblacklist(scl.nbfile);
getserverinfo("en"); // cache 'en' serverinfo
getserverinfo(SINFO_EXT, "en"); // cache 'en' serverinfo
if(scl.demoeverymatch) logline(ACLOG_VERBOSE, "recording demo of every game (holding up to %d in memory)", scl.maxdemos);
if(scl.demopath[0]) logline(ACLOG_VERBOSE,"all recorded demos will be written to: \"%s\"", scl.demopath);
if(scl.voteperm[0]) logline(ACLOG_VERBOSE,"vote permission string: \"%s\"", scl.voteperm);
+8 -1
View File
@@ -79,7 +79,14 @@ struct mapaction : serveraction
}
loopv(scl.adminonlymaps)
{
if(!strcmp(behindpath(map), scl.adminonlymaps[i])) role = CR_ADMIN;
const char *s = scl.adminonlymaps[i], *h = strchr(s, '#'), *m = behindpath(map);
int sl = strlen(s);
if(h && h != s)
{
sl = (int) (h - s);
if(mode != atoi(h + 1)) continue;
}
if(sl == strlen(m) && !strncmp(m, scl.adminonlymaps[i], sl)) role = CR_ADMIN;
}
}
else mapok = true;