More string migrations
FossilOrigin-Name: d0e460fce1af321d6d9198053a792128cd2ec85873976822e9ee42c939238026
This commit is contained in:
parent
bc8e7c17cc
commit
dfa30474cf
1 changed files with 120 additions and 84 deletions
184
src/server.mm
184
src/server.mm
|
@ -5,17 +5,20 @@
|
||||||
|
|
||||||
enum { ST_EMPTY, ST_LOCAL, ST_TCPIP };
|
enum { ST_EMPTY, ST_LOCAL, ST_TCPIP };
|
||||||
|
|
||||||
struct client // server side version of "dynent" type
|
// server side version of "dynent" type
|
||||||
{
|
@interface Client: OFObject
|
||||||
int type;
|
@property (nonatomic) int type;
|
||||||
ENetPeer *peer;
|
@property (nonatomic) ENetPeer *peer;
|
||||||
string hostname;
|
@property (copy, nonatomic) OFString *hostname;
|
||||||
string mapvote;
|
@property (copy, nonatomic) OFString *mapvote;
|
||||||
string name;
|
@property (copy, nonatomic) OFString *name;
|
||||||
int modevote;
|
@property (nonatomic) int modevote;
|
||||||
};
|
@end
|
||||||
|
|
||||||
vector<client> clients;
|
@implementation Client
|
||||||
|
@end
|
||||||
|
|
||||||
|
static OFMutableArray<Client *> *clients;
|
||||||
|
|
||||||
int maxclients = 8;
|
int maxclients = 8;
|
||||||
static OFString *smapname;
|
static OFString *smapname;
|
||||||
|
@ -28,8 +31,8 @@ struct server_entity {
|
||||||
|
|
||||||
vector<server_entity> sents;
|
vector<server_entity> sents;
|
||||||
|
|
||||||
bool notgotitems =
|
// true when map has changed and waiting for clients to send item
|
||||||
true; // true when map has changed and waiting for clients to send item
|
bool notgotitems = true;
|
||||||
int mode = 0;
|
int mode = 0;
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -56,20 +59,19 @@ int bsend = 0, brec = 0, laststatus = 0, lastsec = 0;
|
||||||
|
|
||||||
void process(ENetPacket *packet, int sender);
|
void process(ENetPacket *packet, int sender);
|
||||||
void multicast(ENetPacket *packet, int sender);
|
void multicast(ENetPacket *packet, int sender);
|
||||||
void disconnect_client(int n, char *reason);
|
void disconnect_client(int n, OFString *reason);
|
||||||
|
|
||||||
void
|
void
|
||||||
send(int n, ENetPacket *packet)
|
send(int n, ENetPacket *packet)
|
||||||
{
|
{
|
||||||
if (!packet)
|
if (!packet)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
switch (clients[n].type) {
|
switch (clients[n].type) {
|
||||||
case ST_TCPIP: {
|
case ST_TCPIP:
|
||||||
enet_peer_send(clients[n].peer, 0, packet);
|
enet_peer_send(clients[n].peer, 0, packet);
|
||||||
bsend += packet->dataLength;
|
bsend += packet->dataLength;
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
|
|
||||||
case ST_LOCAL:
|
case ST_LOCAL:
|
||||||
localservertoclient(packet->data, packet->dataLength);
|
localservertoclient(packet->data, packet->dataLength);
|
||||||
break;
|
break;
|
||||||
|
@ -112,9 +114,10 @@ sendservmsg(OFString *msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
disconnect_client(int n, char *reason)
|
disconnect_client(int n, OFString *reason)
|
||||||
{
|
{
|
||||||
printf("disconnecting client (%s) [%s]\n", clients[n].hostname, reason);
|
[OFStdOut writeFormat:@"disconnecting client (%@) [%@]\n",
|
||||||
|
clients[n].hostname, reason];
|
||||||
enet_peer_disconnect(clients[n].peer);
|
enet_peer_disconnect(clients[n].peer);
|
||||||
clients[n].type = ST_EMPTY;
|
clients[n].type = ST_EMPTY;
|
||||||
send2(true, -1, SV_CDIS, n);
|
send2(true, -1, SV_CDIS, n);
|
||||||
|
@ -143,37 +146,44 @@ pickup(uint i, int sec, int sender) // server side item pickup, acknowledge
|
||||||
void
|
void
|
||||||
resetvotes()
|
resetvotes()
|
||||||
{
|
{
|
||||||
loopv(clients) clients[i].mapvote[0] = 0;
|
for (Client *client in clients)
|
||||||
|
client.mapvote = @"";
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
vote(char *map, int reqmode, int sender)
|
vote(OFString *map, int reqmode, int sender)
|
||||||
{
|
{
|
||||||
strcpy_s(clients[sender].mapvote, map);
|
clients[sender].mapvote = map;
|
||||||
clients[sender].modevote = reqmode;
|
clients[sender].modevote = reqmode;
|
||||||
|
|
||||||
int yes = 0, no = 0;
|
int yes = 0, no = 0;
|
||||||
loopv(clients) if (clients[i].type != ST_EMPTY)
|
for (Client *client in clients) {
|
||||||
{
|
if (client.type != ST_EMPTY) {
|
||||||
if (clients[i].mapvote[0]) {
|
if (client.mapvote.length > 0) {
|
||||||
if (strcmp(clients[i].mapvote, map) == 0 &&
|
if ([client.mapvote isEqual:map] &&
|
||||||
clients[i].modevote == reqmode)
|
client.modevote == reqmode)
|
||||||
yes++;
|
yes++;
|
||||||
else
|
else
|
||||||
no++;
|
no++;
|
||||||
} else
|
} else
|
||||||
no++;
|
no++;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (yes == 1 && no == 0)
|
if (yes == 1 && no == 0)
|
||||||
return true; // single player
|
return true; // single player
|
||||||
|
|
||||||
@autoreleasepool {
|
@autoreleasepool {
|
||||||
OFString *msg =
|
OFString *msg =
|
||||||
[OFString stringWithFormat:
|
[OFString stringWithFormat:
|
||||||
@"%s suggests %@ on map %s (set map to vote)",
|
@"%@ suggests %@ on map %@ (set map to vote)",
|
||||||
clients[sender].name, modestr(reqmode), map];
|
clients[sender].name, modestr(reqmode), map];
|
||||||
sendservmsg(msg);
|
sendservmsg(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (yes / (float)(yes + no) <= 0.5f)
|
if (yes / (float)(yes + no) <= 0.5f)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
sendservmsg(@"vote passed");
|
sendservmsg(@"vote passed");
|
||||||
resetvotes();
|
resetvotes();
|
||||||
return true;
|
return true;
|
||||||
|
@ -188,7 +198,7 @@ process(ENetPacket *packet, int sender) // sender may be -1
|
||||||
{
|
{
|
||||||
if (ENET_NET_TO_HOST_16(*(ushort *)packet->data) !=
|
if (ENET_NET_TO_HOST_16(*(ushort *)packet->data) !=
|
||||||
packet->dataLength) {
|
packet->dataLength) {
|
||||||
disconnect_client(sender, "packet length");
|
disconnect_client(sender, @"packet length");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -205,7 +215,9 @@ process(ENetPacket *packet, int sender) // sender may be -1
|
||||||
|
|
||||||
case SV_INITC2S:
|
case SV_INITC2S:
|
||||||
sgetstr();
|
sgetstr();
|
||||||
strcpy_s(clients[cn].name, text);
|
@autoreleasepool {
|
||||||
|
clients[cn].name = @(text);
|
||||||
|
}
|
||||||
sgetstr();
|
sgetstr();
|
||||||
getint(p);
|
getint(p);
|
||||||
break;
|
break;
|
||||||
|
@ -215,9 +227,11 @@ process(ENetPacket *packet, int sender) // sender may be -1
|
||||||
int reqmode = getint(p);
|
int reqmode = getint(p);
|
||||||
if (reqmode < 0)
|
if (reqmode < 0)
|
||||||
reqmode = 0;
|
reqmode = 0;
|
||||||
|
@autoreleasepool {
|
||||||
if (smapname.length > 0 && !mapreload &&
|
if (smapname.length > 0 && !mapreload &&
|
||||||
!vote(text, reqmode, sender))
|
!vote(@(text), reqmode, sender))
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
mapreload = false;
|
mapreload = false;
|
||||||
mode = reqmode;
|
mode = reqmode;
|
||||||
minremain = mode & 1 ? 15 : 10;
|
minremain = mode & 1 ? 15 : 10;
|
||||||
|
@ -256,9 +270,9 @@ process(ENetPacket *packet, int sender) // sender may be -1
|
||||||
|
|
||||||
case SV_POS: {
|
case SV_POS: {
|
||||||
cn = getint(p);
|
cn = getint(p);
|
||||||
if (cn < 0 || cn >= clients.length() ||
|
if (cn < 0 || cn >= clients.count ||
|
||||||
clients[cn].type == ST_EMPTY) {
|
clients[cn].type == ST_EMPTY) {
|
||||||
disconnect_client(sender, "client num");
|
disconnect_client(sender, @"client num");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
int size = msgsizelookup(type);
|
int size = msgsizelookup(type);
|
||||||
|
@ -291,7 +305,7 @@ process(ENetPacket *packet, int sender) // sender may be -1
|
||||||
default: {
|
default: {
|
||||||
int size = msgsizelookup(type);
|
int size = msgsizelookup(type);
|
||||||
if (size == -1) {
|
if (size == -1) {
|
||||||
disconnect_client(sender, "tag type");
|
disconnect_client(sender, @"tag type");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
loopi(size - 1) getint(p);
|
loopi(size - 1) getint(p);
|
||||||
|
@ -299,7 +313,7 @@ process(ENetPacket *packet, int sender) // sender may be -1
|
||||||
}
|
}
|
||||||
|
|
||||||
if (p > end) {
|
if (p > end) {
|
||||||
disconnect_client(sender, "end of packet");
|
disconnect_client(sender, @"end of packet");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
multicast(packet, sender);
|
multicast(packet, sender);
|
||||||
|
@ -319,7 +333,7 @@ send_welcome(int n)
|
||||||
putint(p, *smapname.UTF8String);
|
putint(p, *smapname.UTF8String);
|
||||||
}
|
}
|
||||||
sendstring(serverpassword, p);
|
sendstring(serverpassword, p);
|
||||||
putint(p, clients.length() > maxclients);
|
putint(p, clients.count > maxclients);
|
||||||
if (smapname.length > 0) {
|
if (smapname.length > 0) {
|
||||||
putint(p, SV_MAPCHANGE);
|
putint(p, SV_MAPCHANGE);
|
||||||
sendstring(smapname, p);
|
sendstring(smapname, p);
|
||||||
|
@ -336,13 +350,10 @@ send_welcome(int n)
|
||||||
void
|
void
|
||||||
multicast(ENetPacket *packet, int sender)
|
multicast(ENetPacket *packet, int sender)
|
||||||
{
|
{
|
||||||
loopv(clients)
|
size_t count = clients.count;
|
||||||
{
|
for (size_t i = 0; i < count; i++)
|
||||||
if (i == sender)
|
|
||||||
continue;
|
|
||||||
send(i, packet);
|
send(i, packet);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
localclienttoserver(ENetPacket *packet)
|
localclienttoserver(ENetPacket *packet)
|
||||||
|
@ -352,11 +363,21 @@ localclienttoserver(ENetPacket *packet)
|
||||||
enet_packet_destroy(packet);
|
enet_packet_destroy(packet);
|
||||||
}
|
}
|
||||||
|
|
||||||
client &
|
Client *
|
||||||
addclient()
|
addclient()
|
||||||
{
|
{
|
||||||
loopv(clients) if (clients[i].type == ST_EMPTY) return clients[i];
|
for (Client *client in clients)
|
||||||
return clients.add();
|
if (client.type == ST_EMPTY)
|
||||||
|
return client;
|
||||||
|
|
||||||
|
Client *client = [[Client alloc] init];
|
||||||
|
|
||||||
|
if (clients == nil)
|
||||||
|
clients = [[OFMutableArray alloc] init];
|
||||||
|
|
||||||
|
[clients addObject:client];
|
||||||
|
|
||||||
|
return client;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -379,8 +400,11 @@ startintermission()
|
||||||
void
|
void
|
||||||
resetserverifempty()
|
resetserverifempty()
|
||||||
{
|
{
|
||||||
loopv(clients) if (clients[i].type != ST_EMPTY) return;
|
for (Client *client in clients)
|
||||||
clients.setsize(0);
|
if (client.type != ST_EMPTY)
|
||||||
|
return;
|
||||||
|
|
||||||
|
[clients removeAllObjects];
|
||||||
smapname = @"";
|
smapname = @"";
|
||||||
resetvotes();
|
resetvotes();
|
||||||
resetitems();
|
resetitems();
|
||||||
|
@ -416,13 +440,17 @@ serverslice(int seconds,
|
||||||
checkintermission();
|
checkintermission();
|
||||||
if (interm && seconds > interm) {
|
if (interm && seconds > interm) {
|
||||||
interm = 0;
|
interm = 0;
|
||||||
loopv(clients) if (clients[i].type != ST_EMPTY)
|
size_t i = 0;
|
||||||
{
|
for (Client *client in clients) {
|
||||||
send2(true, i, SV_MAPRELOAD,
|
if (client.type != ST_EMPTY) {
|
||||||
0); // ask a client to trigger map reload
|
// ask a client to trigger map reload
|
||||||
|
send2(true, i, SV_MAPRELOAD, 0);
|
||||||
mapreload = true;
|
mapreload = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
i++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
resetserverifempty();
|
resetserverifempty();
|
||||||
|
@ -431,16 +459,20 @@ serverslice(int seconds,
|
||||||
return; // below is network only
|
return; // below is network only
|
||||||
|
|
||||||
int numplayers = 0;
|
int numplayers = 0;
|
||||||
loopv(clients) if (clients[i].type != ST_EMPTY)++ numplayers;
|
for (Client *client in clients)
|
||||||
serverms(mode, numplayers, minremain, smapname, seconds,
|
if (client.type != ST_EMPTY)
|
||||||
clients.length() >= maxclients);
|
numplayers++;
|
||||||
|
|
||||||
if (seconds - laststatus >
|
serverms(mode, numplayers, minremain, smapname, seconds,
|
||||||
60) // display bandwidth stats, useful for server ops
|
clients.count >= maxclients);
|
||||||
{
|
|
||||||
|
// display bandwidth stats, useful for server ops
|
||||||
|
if (seconds - laststatus > 60) {
|
||||||
nonlocalclients = 0;
|
nonlocalclients = 0;
|
||||||
loopv(clients) if (clients[i].type == ST_TCPIP)
|
for (Client *client in clients)
|
||||||
|
if (client.type == ST_TCPIP)
|
||||||
nonlocalclients++;
|
nonlocalclients++;
|
||||||
|
|
||||||
laststatus = seconds;
|
laststatus = seconds;
|
||||||
if (nonlocalclients || bsend || brec)
|
if (nonlocalclients || bsend || brec)
|
||||||
printf("status: %d remote clients, %.1f send, %.1f rec "
|
printf("status: %d remote clients, %.1f send, %.1f rec "
|
||||||
|
@ -454,18 +486,21 @@ serverslice(int seconds,
|
||||||
if (enet_host_service(serverhost, &event, timeout) > 0) {
|
if (enet_host_service(serverhost, &event, timeout) > 0) {
|
||||||
switch (event.type) {
|
switch (event.type) {
|
||||||
case ENET_EVENT_TYPE_CONNECT: {
|
case ENET_EVENT_TYPE_CONNECT: {
|
||||||
client &c = addclient();
|
Client *c = addclient();
|
||||||
c.type = ST_TCPIP;
|
c.type = ST_TCPIP;
|
||||||
c.peer = event.peer;
|
c.peer = event.peer;
|
||||||
c.peer->data = (void *)(&c - &clients[0]);
|
c.peer->data = (void *)(clients.count - 1);
|
||||||
char hn[1024];
|
char hn[1024];
|
||||||
strcpy_s(c.hostname,
|
@autoreleasepool {
|
||||||
|
c.hostname =
|
||||||
(enet_address_get_host(
|
(enet_address_get_host(
|
||||||
&c.peer->address, hn, sizeof(hn)) == 0)
|
&c.peer->address, hn, sizeof(hn)) == 0
|
||||||
? hn
|
? @(hn)
|
||||||
: "localhost");
|
: @"localhost");
|
||||||
printf("client connected (%s)\n", c.hostname);
|
}
|
||||||
send_welcome(lastconnect = &c - &clients[0]);
|
[OFStdOut
|
||||||
|
writeFormat:@"client connected (%@)\n", c.hostname];
|
||||||
|
send_welcome(lastconnect = clients.count - 1);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ENET_EVENT_TYPE_RECEIVE:
|
case ENET_EVENT_TYPE_RECEIVE:
|
||||||
|
@ -478,16 +513,16 @@ serverslice(int seconds,
|
||||||
case ENET_EVENT_TYPE_DISCONNECT:
|
case ENET_EVENT_TYPE_DISCONNECT:
|
||||||
if ((intptr_t)event.peer->data < 0)
|
if ((intptr_t)event.peer->data < 0)
|
||||||
break;
|
break;
|
||||||
printf("disconnected client (%s)\n",
|
[OFStdOut writeFormat:@"disconnected client (%@)\n",
|
||||||
clients[(intptr_t)event.peer->data].hostname);
|
clients[(size_t)event.peer->data].hostname];
|
||||||
clients[(intptr_t)event.peer->data].type = ST_EMPTY;
|
clients[(size_t)event.peer->data].type = ST_EMPTY;
|
||||||
send2(true, -1, SV_CDIS, (intptr_t)event.peer->data);
|
send2(true, -1, SV_CDIS, (intptr_t)event.peer->data);
|
||||||
event.peer->data = (void *)-1;
|
event.peer->data = (void *)-1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (numplayers > maxclients)
|
if (numplayers > maxclients)
|
||||||
disconnect_client(lastconnect, "maxclients reached");
|
disconnect_client(lastconnect, @"maxclients reached");
|
||||||
}
|
}
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
|
@ -504,17 +539,18 @@ cleanupserver()
|
||||||
void
|
void
|
||||||
localdisconnect()
|
localdisconnect()
|
||||||
{
|
{
|
||||||
loopv(clients) if (clients[i].type == ST_LOCAL) clients[i].type =
|
for (Client *client in clients)
|
||||||
ST_EMPTY;
|
if (client.type == ST_LOCAL)
|
||||||
|
client.type = ST_EMPTY;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
localconnect()
|
localconnect()
|
||||||
{
|
{
|
||||||
client &c = addclient();
|
Client *c = addclient();
|
||||||
c.type = ST_LOCAL;
|
c.type = ST_LOCAL;
|
||||||
strcpy_s(c.hostname, "local");
|
c.hostname = @"local";
|
||||||
send_welcome(&c - &clients[0]);
|
send_welcome(clients.count - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -526,7 +562,7 @@ initserver(bool dedicated, int uprate, OFString *sdesc, OFString *ip,
|
||||||
servermsinit(master ? master : @"wouter.fov120.com/cube/masterserver/",
|
servermsinit(master ? master : @"wouter.fov120.com/cube/masterserver/",
|
||||||
sdesc, dedicated);
|
sdesc, dedicated);
|
||||||
|
|
||||||
if (isdedicated = dedicated) {
|
if ((isdedicated = dedicated)) {
|
||||||
ENetAddress address = { ENET_HOST_ANY, CUBE_SERVER_PORT };
|
ENetAddress address = { ENET_HOST_ANY, CUBE_SERVER_PORT };
|
||||||
@autoreleasepool {
|
@autoreleasepool {
|
||||||
if (ip.length > 0 &&
|
if (ip.length > 0 &&
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue