Index: src/client.mm ================================================================== --- src/client.mm +++ src/client.mm @@ -183,11 +183,11 @@ COMMANDN(connect, connects, ARG_1STR) COMMANDN(disconnect, trydisconnect, ARG_NONE) // collect c2s messages conveniently -vector messages; +static OFMutableArray *messages; void addmsg(int rel, int num, int type, ...) { if (demoplayback) @@ -195,22 +195,35 @@ if (num != msgsizelookup(type)) { fatal([OFString stringWithFormat:@"inconsistant msg size for %d (%d != %d)", type, num, msgsizelookup(type)]); } - if (messages.length() == 100) { + if (messages.count == 100) { conoutf(@"command flood protection (type %d)", type); return; } - ivector &msg = messages.add(); - msg.add(num); - msg.add(rel); - msg.add(type); + + OFMutableData *msg = [OFMutableData dataWithItemSize:sizeof(int) + capacity:num + 2]; + [msg addItem:&num]; + [msg addItem:&rel]; + [msg addItem:&type]; + va_list marker; va_start(marker, type); - loopi(num - 1) msg.add(va_arg(marker, int)); + loopi(num - 1) + { + int tmp = va_arg(marker, int); + [msg addItem:&tmp]; + } va_end(marker); + [msg makeImmutable]; + + if (messages == nil) + messages = [[OFMutableArray alloc] init]; + + [messages addObject:msg]; } void server_err() { @@ -311,44 +324,44 @@ if (!m_noitems) putitems(p); putint(p, -1); senditemstoserver = false; serveriteminitdone = true; - }; + } if (ctext[0]) // player chat, not flood protected for // now { packet->flags = ENET_PACKET_FLAG_RELIABLE; putint(p, SV_TEXT); sendstring(ctext, p); ctext[0] = 0; - }; + } if (!c2sinit) // tell other clients who I am { packet->flags = ENET_PACKET_FLAG_RELIABLE; c2sinit = true; putint(p, SV_INITC2S); sendstring(player1->name, p); sendstring(player1->team, p); putint(p, player1->lifesequence); - }; - loopv(messages) // send messages collected during the - // previous frames - { - ivector &msg = messages[i]; - if (msg[1]) + } + for (OFData *msg in messages) { + // send messages collected during the previous + // frames + if (*(int *)[msg itemAtIndex:1]) packet->flags = ENET_PACKET_FLAG_RELIABLE; - loopi(msg[0]) putint(p, msg[i + 2]); - }; - messages.setsize(0); + loopi(*(int *)[msg itemAtIndex:0]) + putint(p, *(int *)[msg itemAtIndex:i + 2]); + } + [messages removeAllObjects]; if (lastmillis - lastping > 250) { putint(p, SV_PING); putint(p, lastmillis); lastping = lastmillis; - }; - }; + } + } *(ushort *)start = ENET_HOST_TO_NET_16(p - start); enet_packet_resize(packet, p - start); incomingdemodata(start, p - start, true); if (clienthost) { enet_host_broadcast(clienthost, 0, packet); Index: src/console.mm ================================================================== --- src/console.mm +++ src/console.mm @@ -157,21 +157,23 @@ { char *cb = SDL_GetClipboardText(); strcat_s(commandbuf, cb); } -cvector vhistory; +static OFMutableArray *vhistory; int histpos = 0; void history(int n) { static bool rec = false; - if (!rec && n >= 0 && n < vhistory.length()) { + if (!rec && n >= 0 && n < vhistory.count) { rec = true; - execute(vhistory[vhistory.length() - n - 1]); + OFString *cmd = vhistory[vhistory.count - n - 1]; + std::unique_ptr copy(strdup(cmd.UTF8String)); + execute(copy.get()); rec = false; } } COMMAND(history, ARG_1INT) @@ -190,22 +192,30 @@ for (int i = 0; commandbuf[i]; i++) if (!commandbuf[i + 1]) commandbuf[i] = 0; resetcomplete(); break; - }; + } case SDLK_UP: - if (histpos) - strcpy_s( - commandbuf, vhistory[--histpos]); + if (histpos) { + @autoreleasepool { + strcpy_s(commandbuf, + vhistory[--histpos] + .UTF8String); + } + } break; case SDLK_DOWN: - if (histpos < vhistory.length()) - strcpy_s( - commandbuf, vhistory[histpos++]); + if (histpos < vhistory.count) { + @autoreleasepool { + strcpy_s(commandbuf, + vhistory[histpos++] + .UTF8String); + } + } break; case SDLK_TAB: complete(commandbuf); break; @@ -220,32 +230,43 @@ default: resetcomplete(); if (cooked) { char add[] = {(char)cooked, 0}; strcat_s(commandbuf, add); - }; - }; + } + } } else { if (code == SDLK_RETURN) { if (commandbuf[0]) { - if (vhistory.empty() || - strcmp( - vhistory.last(), commandbuf)) { - vhistory.add(newstring( - commandbuf)); // cap this? - }; - histpos = vhistory.length(); + @autoreleasepool { + OFString *cmdbuf = + @(commandbuf); + + if (vhistory == nil) + vhistory = + [[OFMutableArray + alloc] init]; + + if (vhistory.count == 0 || + ![vhistory.lastObject + isEqual:cmdbuf]) { + // cap this? + [vhistory + addObject:cmdbuf]; + } + } + histpos = vhistory.count; if (commandbuf[0] == '/') execute(commandbuf, true); else toserver(commandbuf); - }; + } saycommand(NULL); } else if (code == SDLK_ESCAPE) { saycommand(NULL); - }; - }; + } + } } else if (!menukey(code, isdown)) { // keystrokes go to menu for (KeyMapping *mapping in keyMappings) { if (mapping.code == code) { Index: src/cube.h ================================================================== --- src/cube.h +++ src/cube.h @@ -280,12 +280,10 @@ float u, v, x, y, z; uchar r, g, b, a; }; typedef vector dvector; -typedef vector cvector; -typedef vector ivector; // globals ooh naughty extern sqr *world, *wmip[]; // map data, the mips are sequential 2D arrays in memory Index: src/sound.mm ================================================================== --- src/sound.mm +++ src/sound.mm @@ -126,19 +126,33 @@ vector samples; #else vector samples; #endif -cvector snames; +static OFMutableArray *snames; int -registersound(char *name) +registersound(char *name_) { - loopv(snames) if (strcmp(snames[i], name) == 0) return i; - snames.add(newstring(name)); - samples.add(NULL); - return samples.length() - 1; + @autoreleasepool { + OFString *name = @(name_); + + int i = 0; + for (OFString *iter in snames) { + if ([iter isEqual:name]) + return i; + + i++; + } + + if (snames == nil) + snames = [[OFMutableArray alloc] init]; + + [snames addObject:name]; + samples.add(NULL); + return samples.length() - 1; + } } COMMAND(registersound, ARG_1EST) void cleansound() @@ -238,11 +252,11 @@ return; } if (!samples[n]) { OFString *path = [OFString - stringWithFormat:@"packages/sounds/%s.wav", snames[n]]; + stringWithFormat:@"packages/sounds/%@.wav", snames[n]]; OFIRI *IRI = [Cube.sharedInstance.gameDataIRI IRIByAppendingPathComponent:path]; #ifdef USE_MIXER samples[n] =