More string migrations

FossilOrigin-Name: d0e460fce1af321d6d9198053a792128cd2ec85873976822e9ee42c939238026
This commit is contained in:
Jonathan Schleifer 2025-03-15 12:05:41 +00:00
parent bc8e7c17cc
commit dfa30474cf

View file

@ -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++;
} else
no++; no++;
} else }
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;
if (smapname.length > 0 && !mapreload && @autoreleasepool {
!vote(text, reqmode, sender)) if (smapname.length > 0 && !mapreload &&
return; !vote(@(text), reqmode, sender))
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,12 +350,9 @@ 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
@ -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,12 +440,16 @@ 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
mapreload = true; send2(true, i, SV_MAPRELOAD, 0);
break; mapreload = true;
break;
}
i++;
} }
} }
@ -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)
nonlocalclients++; if (client.type == ST_TCPIP)
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 {
(enet_address_get_host( c.hostname =
&c.peer->address, hn, sizeof(hn)) == 0) (enet_address_get_host(
? hn &c.peer->address, hn, sizeof(hn)) == 0
: "localhost"); ? @(hn)
printf("client connected (%s)\n", c.hostname); : @"localhost");
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 &&