OctaCore/src/engine/server.cc

160 lines
2.8 KiB
C++

// server.cpp: little more than enhanced multicaster
// runs dedicated or as client coroutine
#include "engine.hh"
#define LOGSTRLEN 512
static FILE *logfile = NULL;
void closelogfile()
{
if(logfile)
{
fclose(logfile);
logfile = NULL;
}
}
FILE *getlogfile()
{
#ifdef WIN32
return logfile;
#else
return logfile ? logfile : stdout;
#endif
}
void setlogfile(const char *fname)
{
closelogfile();
if(fname && fname[0])
{
fname = findfile(fname, "w");
if(fname) logfile = fopen(fname, "w");
}
FILE *f = getlogfile();
if(f) setvbuf(f, NULL, _IOLBF, BUFSIZ);
}
void logoutf(const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
logoutfv(fmt, args);
va_end(args);
}
static void writelog(FILE *file, const char *buf)
{
static uchar ubuf[512];
size_t len = strlen(buf), carry = 0;
while(carry < len)
{
size_t numu = encodeutf8(ubuf, sizeof(ubuf)-1, &((const uchar *)buf)[carry], len - carry, &carry);
if(carry >= len) ubuf[numu++] = '\n';
fwrite(ubuf, 1, numu, file);
}
}
static void writelogv(FILE *file, const char *fmt, va_list args)
{
static char buf[LOGSTRLEN];
vformatstring(buf, fmt, args, sizeof(buf));
writelog(file, buf);
}
#define DEFAULTCLIENTS 8
enum { ST_EMPTY, ST_LOCAL, ST_TCPIP };
struct client // server side version of "dynent" type
{
int type;
int num;
string hostname;
void *info;
};
vector<client *> clients;
int laststatus = 0;
int localclients = 0;
bool hasnonlocalclients() { return false; }
bool haslocalclients() { return localclients!=0; }
client &addclient(int type)
{
client *c = NULL;
loopv(clients) if(clients[i]->type==ST_EMPTY)
{
c = clients[i];
break;
}
if(!c)
{
c = new client;
c->num = clients.length();
clients.add(c);
}
c->type = type;
switch(type)
{
case ST_LOCAL: localclients++; break;
}
return *c;
}
void delclient(client *c)
{
if(!c) return;
switch(c->type)
{
case ST_LOCAL: localclients--; break;
case ST_EMPTY: return;
}
c->type = ST_EMPTY;
}
void cleanupserver()
{
}
void updatetime()
{
}
void localdisconnect(bool cleanup)
{
bool disconnected = false;
loopv(clients) if(clients[i]->type==ST_LOCAL)
{
delclient(clients[i]);
disconnected = true;
}
if(!disconnected) return;
game::gamedisconnect(cleanup);
mainmenu = 1;
}
void localconnect()
{
if(initing) return;
client &c = addclient(ST_LOCAL);
copystring(c.hostname, "local");
game::gameconnect(false);
}
void logoutfv(const char *fmt, va_list args)
{
FILE *f = getlogfile();
if(f) writelogv(f, fmt, args);
}
void initserver()
{
}