diff --git a/src/Command.h b/src/Command.h index 6758593..3b3ba0c 100644 --- a/src/Command.h +++ b/src/Command.h @@ -2,17 +2,27 @@ OF_ASSUME_NONNULL_BEGIN +#define COMMAND(name, nargs, block_) \ + OF_CONSTRUCTOR() \ + { \ + enqueueInit(^{ \ + [Identifier \ + addIdentifier:[Command commandWithName:@ #name \ + argumentsTypes:nargs \ + block:block_]]; \ + }); \ + } + @interface Command: Identifier -@property (readonly, nonatomic) void (*function)(); @property (readonly, nonatomic) int argumentsTypes; + (instancetype)commandWithName:(OFString *)name - function:(void (*)())function - argumentsTypes:(int)argumentsTypes; + argumentsTypes:(int)argumentsTypes + block:(id)block; - (instancetype)initWithName:(OFString *)name OF_UNAVAILABLE; - (instancetype)initWithName:(OFString *)name - function:(void (*)())function - argumentsTypes:(int)argumentsTypes; + argumentsTypes:(int)argumentsTypes + block:(id)block; - (int)callWithArguments:(OFArray *)arguments isDown:(bool)isDown; @end diff --git a/src/Command.m b/src/Command.m index d591c15..e295416 100644 --- a/src/Command.m +++ b/src/Command.m @@ -20,23 +20,27 @@ padArguments(OFArray *arguments, size_t count) } @implementation Command +{ + id _block; +} + + (instancetype)commandWithName:(OFString *)name - function:(void (*)())function argumentsTypes:(int)argumentsTypes + block:(id)block { return [[self alloc] initWithName:name - function:function - argumentsTypes:argumentsTypes]; + argumentsTypes:argumentsTypes + block:block]; } - (instancetype)initWithName:(OFString *)name - function:(void (*)())function argumentsTypes:(int)argumentsTypes + block:(id)block { self = [super initWithName:name]; - _function = function; _argumentsTypes = argumentsTypes; + _block = block; return self; } @@ -47,14 +51,14 @@ padArguments(OFArray *arguments, size_t count) case ARG_1INT: if (isDown) { arguments = padArguments(arguments, 2); - ((void(__cdecl *)(int))_function)( + ((void (^)(int))_block)( [arguments[1] cube_intValueWithBase:0]); } break; case ARG_2INT: if (isDown) { arguments = padArguments(arguments, 3); - ((void(__cdecl *)(int, int))_function)( + ((void (^)(int, int))_block)( [arguments[1] cube_intValueWithBase:0], [arguments[2] cube_intValueWithBase:0]); } @@ -62,7 +66,7 @@ padArguments(OFArray *arguments, size_t count) case ARG_3INT: if (isDown) { arguments = padArguments(arguments, 4); - ((void(__cdecl *)(int, int, int))_function)( + ((void (^)(int, int, int))_block)( [arguments[1] cube_intValueWithBase:0], [arguments[2] cube_intValueWithBase:0], [arguments[3] cube_intValueWithBase:0]); @@ -71,7 +75,7 @@ padArguments(OFArray *arguments, size_t count) case ARG_4INT: if (isDown) { arguments = padArguments(arguments, 5); - ((void(__cdecl *)(int, int, int, int))_function)( + ((void (^)(int, int, int, int))_block)( [arguments[1] cube_intValueWithBase:0], [arguments[2] cube_intValueWithBase:0], [arguments[3] cube_intValueWithBase:0], @@ -80,57 +84,55 @@ padArguments(OFArray *arguments, size_t count) break; case ARG_NONE: if (isDown) - ((void(__cdecl *)())_function)(); + ((void (^)())_block)(); break; case ARG_1STR: if (isDown) { arguments = padArguments(arguments, 2); - ((void(__cdecl *)(OFString *))_function)(arguments[1]); + ((void (^)(OFString *))_block)(arguments[1]); } break; case ARG_2STR: if (isDown) { arguments = padArguments(arguments, 3); - ((void(__cdecl *)(OFString *, OFString *))_function)( + ((void (^)(OFString *, OFString *))_block)( arguments[1], arguments[2]); } break; case ARG_3STR: if (isDown) { arguments = padArguments(arguments, 4); - ((void(__cdecl *)( - OFString *, OFString *, OFString *))_function)( + ((void (^)(OFString *, OFString *, OFString *))_block)( arguments[1], arguments[2], arguments[3]); } break; case ARG_5STR: if (isDown) { arguments = padArguments(arguments, 6); - ((void(__cdecl *)(OFString *, OFString *, OFString *, - OFString *, OFString *))_function)(arguments[1], + ((void (^)(OFString *, OFString *, OFString *, + OFString *, OFString *))_block)(arguments[1], arguments[2], arguments[3], arguments[4], arguments[5]); } break; case ARG_DOWN: - ((void(__cdecl *)(bool))_function)(isDown); + ((void (^)(bool))_block)(isDown); break; case ARG_DWN1: arguments = padArguments(arguments, 2); - ((void(__cdecl *)(bool, OFString *))_function)( - isDown, arguments[1]); + ((void (^)(bool, OFString *))_block)(isDown, arguments[1]); break; case ARG_1EXP: if (isDown) { arguments = padArguments(arguments, 2); - return ((int(__cdecl *)(int))_function)( + return ((int (^)(int))_block)( execute(arguments[1], isDown)); } break; case ARG_2EXP: if (isDown) { arguments = padArguments(arguments, 3); - return ((int(__cdecl *)(int, int))_function)( + return ((int (^)(int, int))_block)( execute(arguments[1], isDown), execute(arguments[2], isDown)); } @@ -138,21 +140,20 @@ padArguments(OFArray *arguments, size_t count) case ARG_1EST: if (isDown) { arguments = padArguments(arguments, 2); - return ((int(__cdecl *)(OFString *))_function)( - arguments[1]); + return ((int (^)(OFString *))_block)(arguments[1]); } break; case ARG_2EST: if (isDown) { arguments = padArguments(arguments, 3); - return ((int(__cdecl *)(OFString *, - OFString *))_function)(arguments[1], arguments[2]); + return ((int (^)(OFString *, OFString *))_block)( + arguments[1], arguments[2]); } break; case ARG_VARI: if (isDown) // limit, remove - ((void(__cdecl *)(OFString *))_function)([[arguments + ((void (^)(OFString *))_block)([[arguments objectsInRange:OFMakeRange(1, arguments.count - 1)] componentsJoinedByString:@" "]); break; diff --git a/src/Cube.m b/src/Cube.m index 876b54e..de4f665 100644 --- a/src/Cube.m +++ b/src/Cube.m @@ -2,6 +2,7 @@ #include "cube.h" +#import "Command.h" #import "DynamicEntity.h" OF_APPLICATION_DELEGATE(Cube) @@ -373,16 +374,11 @@ fatal(OFConstantString *s, ...) [OFApplication terminateWithStatus:1]; } -void -quit() // normal exit -{ +// normal exit +COMMAND(quit, ARG_NONE, ^{ [Cube.sharedInstance quit]; -} -COMMAND(quit, ARG_NONE) +}) -void -screenshot() -{ +COMMAND(screenshot, ARG_NONE, ^{ [Cube.sharedInstance screenshot]; -} -COMMAND(screenshot, ARG_NONE) +}) diff --git a/src/Identifier.h b/src/Identifier.h index 6b5421c..af3274f 100644 --- a/src/Identifier.h +++ b/src/Identifier.h @@ -5,6 +5,9 @@ OF_ASSUME_NONNULL_BEGIN @interface Identifier: OFObject @property (readonly, copy, nonatomic) OFString *name; ++ (void)addIdentifier:(__kindof Identifier *)identifier; ++ (__kindof Identifier *)identifierForName:(OFString *)name; ++ (void)enumerateIdentifiersUsingBlock:(void (^)(__kindof Identifier *))block; - (instancetype)init OF_UNAVAILABLE; - (instancetype)initWithName:(OFString *)name; @end diff --git a/src/Identifier.m b/src/Identifier.m index 2057724..e000cd4 100644 --- a/src/Identifier.m +++ b/src/Identifier.m @@ -1,6 +1,33 @@ #import "Identifier.h" +// contains ALL vars/commands/aliases +static OFMutableDictionary *identifiers; + @implementation Identifier ++ (void)initialize +{ + if (self == Identifier.class) + identifiers = [[OFMutableDictionary alloc] init]; +} + ++ (void)addIdentifier:(__kindof Identifier *)identifier +{ + identifiers[identifier.name] = identifier; +} + ++ (__kindof Identifier *)identifierForName:(OFString *)name +{ + return identifiers[name]; +} + ++ (void)enumerateIdentifiersUsingBlock:(void (^)(__kindof Identifier *))block +{ + [identifiers enumerateKeysAndObjectsUsingBlock:^( + OFString *name, __kindof Identifier *identifier, bool *stop) { + block(identifier); + }]; +} + - (instancetype)initWithName:(OFString *)name { self = [super init]; diff --git a/src/clientextras.m b/src/clientextras.m index 6f8d003..c85dd56 100644 --- a/src/clientextras.m +++ b/src/clientextras.m @@ -2,6 +2,7 @@ #include "cube.h" +#import "Command.h" #import "DynamicEntity.h" #import "Monster.h" @@ -177,9 +178,7 @@ renderscores() // sendmap/getmap commands, should be replaced by more intuitive map downloading -void -sendmap(OFString *mapname) -{ +COMMAND(sendmap, ARG_1STR, (^(OFString *mapname) { if (mapname.length > 0) save_world(mapname); changemap(mapname); @@ -210,11 +209,9 @@ sendmap(OFString *mapname) @"\"getmap\" to receive it]", mapname]; toserver(msg); -} +})) -void -getmap() -{ +COMMAND(getmap, ARG_NONE, ^{ ENetPacket *packet = enet_packet_create(NULL, MAXTRANS, ENET_PACKET_FLAG_RELIABLE); unsigned char *start = packet->data; @@ -224,7 +221,4 @@ getmap() enet_packet_resize(packet, p - start); sendpackettoserv(packet); conoutf(@"requesting map from server..."); -} - -COMMAND(sendmap, ARG_1STR) -COMMAND(getmap, ARG_NONE) +}) diff --git a/src/clientgame.m b/src/clientgame.m index e60a926..aad16cf 100644 --- a/src/clientgame.m +++ b/src/clientgame.m @@ -2,6 +2,7 @@ #include "cube.h" +#import "Command.h" #import "DynamicEntity.h" #import "Entity.h" #import "Monster.h" @@ -10,12 +11,9 @@ int nextmode = 0; // nextmode becomes gamemode after next map load VAR(gamemode, 1, 0, 0); -static void -mode(int n) -{ +COMMAND(mode, ARG_1INT, ^(int n) { addmsg(1, 2, SV_GAMEMODE, nextmode = n); -} -COMMAND(mode, ARG_1INT) +}) bool intermission = false; @@ -142,13 +140,10 @@ respawn() int sleepwait = 0; static OFString *sleepcmd = nil; -void -sleepf(OFString *msec, OFString *cmd) -{ +COMMAND(sleep, ARG_2STR, ^(OFString *msec, OFString *cmd) { sleepwait = msec.cube_intValue + lastmillis; sleepcmd = cmd; -} -COMMANDN(sleep, sleepf, ARG_2STR) +}) void updateworld(int millis) // main game update loop @@ -240,43 +235,34 @@ spawnplayer(DynamicEntity *d) // movement input code #define dir(name, v, d, s, os) \ - static void name(bool isdown) \ - { \ - player1.s = isdown; \ - player1.v = isdown ? d : (player1.os ? -(d) : 0); \ + COMMAND(name, ARG_DOWN, ^(bool isDown) { \ + player1.s = isDown; \ + player1.v = isDown ? d : (player1.os ? -(d) : 0); \ player1.lastMove = lastmillis; \ - } + }) dir(backward, move, -1, k_down, k_up); dir(forward, move, 1, k_up, k_down); dir(left, strafe, 1, k_left, k_right); dir(right, strafe, -1, k_right, k_left); -void -attack(bool on) -{ +COMMAND(attack, ARG_DOWN, ^(bool on) { if (intermission) return; if (editmode) editdrag(on); else if ((player1.attacking = on)) respawn(); -} +}) -void -jumpn(bool on) -{ +COMMAND(jump, ARG_DOWN, ^(bool on) { if (!intermission && (player1.jumpNext = on)) respawn(); -} +}) -COMMAND(backward, ARG_DOWN) -COMMAND(forward, ARG_DOWN) -COMMAND(left, ARG_DOWN) -COMMAND(right, ARG_DOWN) -COMMANDN(jump, jumpn, ARG_DOWN) -COMMAND(attack, ARG_DOWN) -COMMAND(showscores, ARG_DOWN) +COMMAND(showscores, ARG_DOWN, ^(bool isDown) { + showscores(isDown); +}) void fixplayer1range() @@ -440,4 +426,6 @@ startmap(OFString *name) // called just after a map load conoutf(@"game mode is %@", modestr(gamemode)); } -COMMANDN(map, changemap, ARG_1STR) +COMMAND(map, ARG_1STR, ^(OFString *name) { + changemap(name); +}) diff --git a/src/clients.m b/src/clients.m index 3eeb5f9..f52e08c 100644 --- a/src/clients.m +++ b/src/clients.m @@ -2,6 +2,7 @@ #include "cube.h" +#import "Command.h" #import "DynamicEntity.h" static ENetHost *clienthost = NULL; @@ -60,7 +61,7 @@ throttle() throttle_interval * 1000, throttle_accel, throttle_decel); } -void +static void newname(OFString *name) { c2sinit = false; @@ -70,9 +71,12 @@ newname(OFString *name) player1.name = name; } -COMMANDN(name, newname, ARG_1STR) -void +COMMAND(name, ARG_1STR, ^(OFString *name) { + newname(name); +}) + +static void newteam(OFString *name) { c2sinit = false; @@ -82,7 +86,10 @@ newteam(OFString *name) player1.team = name; } -COMMANDN(team, newteam, ARG_1STR) + +COMMAND(team, ARG_1STR, ^(OFString *name) { + newteam(name); +}) void writeclientinfo(OFStream *stream) @@ -177,16 +184,18 @@ toserver(OFString *text) ctext = text; } -void -echo(OFString *text) -{ +COMMAND(echo, ARG_VARI, ^(OFString *text) { conoutf(@"%@", text); -} - -COMMAND(echo, ARG_VARI) -COMMANDN(say, toserver, ARG_VARI) -COMMANDN(connect, connects, ARG_1STR) -COMMANDN(disconnect, trydisconnect, ARG_NONE) +}) +COMMAND(say, ARG_VARI, ^(OFString *text) { + toserver(text); +}) +COMMAND(connect, ARG_1STR, ^(OFString *servername) { + connects(servername); +}) +COMMAND(disconnect, ARG_NONE, ^{ + trydisconnect(); +}) // collect c2s messages conveniently @@ -239,12 +248,9 @@ bool senditemstoserver = false; // after a map change, since server doesn't have map data OFString *clientpassword; -void -password(OFString *p) -{ +COMMAND(password, ARG_1STR, ^(OFString *p) { clientpassword = p; -} -COMMAND(password, ARG_1STR) +}) bool netmapstart() diff --git a/src/commands.m b/src/commands.m index 6ae5a7a..e2018b0 100644 --- a/src/commands.m +++ b/src/commands.m @@ -9,9 +9,6 @@ #import "OFString+Cube.h" #import "Variable.h" -// contains ALL vars/commands/aliases -static OFMutableDictionary *identifiers; - static void cleanup(char **string) { @@ -21,16 +18,13 @@ cleanup(char **string) void alias(OFString *name, OFString *action) { - Alias *alias = identifiers[name]; + Alias *alias = [Identifier identifierForName:name]; - if (alias == nil) { - alias = [Alias aliasWithName:name action:action persisted:true]; - - if (identifiers == nil) - identifiers = [[OFMutableDictionary alloc] init]; - - identifiers[name] = alias; - } else { + if (alias == nil) + [Identifier addIdentifier:[Alias aliasWithName:name + action:action + persisted:true]]; + else { if ([alias isKindOfClass:Alias.class]) alias.action = action; else @@ -38,49 +32,54 @@ alias(OFString *name, OFString *action) @"cannot redefine builtin %@ with an alias", name); } } -COMMAND(alias, ARG_2STR) + +COMMAND(alias, ARG_2STR, ^(OFString *name, OFString *action) { + alias(name, action); +}) int variable(OFString *name, int min, int cur, int max, int *storage, void (*function)(), bool persisted) { - Variable *variable = [Variable variableWithName:name - min:min - max:max - storage:storage - function:function - persisted:persisted]; - - if (identifiers == nil) - identifiers = [[OFMutableDictionary alloc] init]; - - identifiers[name] = variable; - + [Identifier addIdentifier:[Variable variableWithName:name + min:min + max:max + storage:storage + function:function + persisted:persisted]]; return cur; } void setvar(OFString *name, int i) { - *[identifiers[name] storage] = i; + Variable *variable = [Identifier identifierForName:name]; + + if ([variable isKindOfClass:Variable.class]) + *variable.storage = i; } int getvar(OFString *name) { - return *[identifiers[name] storage]; + Variable *variable = [Identifier identifierForName:name]; + + if ([variable isKindOfClass:Variable.class]) + return *variable.storage; + + return 0; } bool identexists(OFString *name) { - return (identifiers[name] != nil); + return ([Identifier identifierForName:name] != nil); } OFString * getalias(OFString *name) { - Alias *alias = identifiers[name]; + Alias *alias = [Identifier identifierForName:name]; if ([alias isKindOfClass:Alias.class]) return alias.action; @@ -88,21 +87,6 @@ getalias(OFString *name) return nil; } -bool -addcommand(OFString *name, void (*function)(), int argumentsTypes) -{ - Command *command = [Command commandWithName:name - function:function - argumentsTypes:argumentsTypes]; - - if (identifiers == nil) - identifiers = [[OFMutableDictionary alloc] init]; - - identifiers[name] = command; - - return false; -} - // parse any nested set of () or [] static char * parseexp(char **p, int right) @@ -168,7 +152,8 @@ parseword(char **p) OFString * lookup(OFString *n) { - __kindof Identifier *identifier = identifiers[[n substringFromIndex:1]]; + __kindof Identifier *identifier = + [Identifier identifierForName:[n substringFromIndex:1]]; if ([identifier isKindOfClass:Variable.class]) { return [OFString stringWithFormat:@"%d", *[identifier storage]]; @@ -275,7 +260,7 @@ execute(OFString *string, bool isDown) if (c.length == 0) continue; - val = executeIdentifier(identifiers[c], + val = executeIdentifier([Identifier identifierForName:c], [OFArray arrayWithObjects:w count:numargs], isDown); } @@ -307,8 +292,8 @@ complete(OFMutableString *s) } __block int idx = 0; - [identifiers enumerateKeysAndObjectsUsingBlock:^( - OFString *name, Identifier *identifier, bool *stop) { + [Identifier enumerateIdentifiersUsingBlock:^( + __kindof Identifier *identifier) { if (strncmp(identifier.name.UTF8String, s.UTF8String + 1, completesize) == 0 && idx++ == completeidx) @@ -348,6 +333,10 @@ exec(OFString *cfgfile) conoutf(@"could not read \"%@\"", cfgfile); } +COMMAND(exec, ARG_1STR, ^(OFString *cfgfile) { + exec(cfgfile); +}) + void writecfg() { @@ -370,34 +359,36 @@ writecfg() writeclientinfo(stream); [stream writeString:@"\n"]; - [identifiers enumerateKeysAndObjectsUsingBlock:^( - OFString *name, __kindof Identifier *identifier, bool *stop) { - if (![identifier isKindOfClass:Variable.class] || - ![identifier persisted]) - return; + [Identifier + enumerateIdentifiersUsingBlock:^(__kindof Identifier *identifier) { + if (![identifier isKindOfClass:Variable.class] || + ![identifier persisted]) + return; - [stream writeFormat:@"%@ %d\n", identifier.name, - *[identifier storage]]; - }]; + [stream writeFormat:@"%@ %d\n", identifier.name, + *[identifier storage]]; + }]; [stream writeString:@"\n"]; writebinds(stream); [stream writeString:@"\n"]; - [identifiers enumerateKeysAndObjectsUsingBlock:^( - OFString *name, __kindof Identifier *identifier, bool *stop) { - if (![identifier isKindOfClass:Alias.class] || - [identifier.name hasPrefix:@"nextmap_"]) - return; + [Identifier + enumerateIdentifiersUsingBlock:^(__kindof Identifier *identifier) { + if (![identifier isKindOfClass:Alias.class] || + [identifier.name hasPrefix:@"nextmap_"]) + return; - [stream writeFormat:@"alias \"%@\" [%@]\n", identifier.name, - [identifier action]]; - }]; + [stream writeFormat:@"alias \"%@\" [%@]\n", identifier.name, + [identifier action]]; + }]; [stream close]; } -COMMAND(writecfg, ARG_NONE) +COMMAND(writecfg, ARG_NONE, ^{ + writecfg(); +}) // below the commands that implement a small imperative language. thanks to the // semantics of () and [] expressions, any control construct can be defined @@ -409,36 +400,28 @@ intset(OFString *name, int v) alias(name, [OFString stringWithFormat:@"%d", v]); } -void -ifthen(OFString *cond, OFString *thenp, OFString *elsep) -{ +COMMAND(if, ARG_3STR, ^(OFString *cond, OFString *thenp, OFString *elsep) { execute((![cond hasPrefix:@"0"] ? thenp : elsep), true); -} +}) -void -loopa(OFString *times, OFString *body) -{ +COMMAND(loop, ARG_2STR, ^(OFString *times, OFString *body) { int t = times.cube_intValue; for (int i = 0; i < t; i++) { intset(@"i", i); execute(body, true); } -} +}) -void -whilea(OFString *cond, OFString *body) -{ +COMMAND(while, ARG_2STR, ^(OFString *cond, OFString *body) { while (execute(cond, true)) execute(body, true); -} +}) -void -onrelease(bool on, OFString *body) -{ +COMMAND(onrelease, ARG_DWN1, ^(bool on, OFString *body) { if (!on) execute(body, true); -} +}) void concat(OFString *s) @@ -446,15 +429,15 @@ concat(OFString *s) alias(@"s", s); } -void -concatword(OFString *s) -{ - concat([s stringByReplacingOccurrencesOfString:@" " withString:@""]); -} +COMMAND(concat, ARG_VARI, ^(OFString *s) { + concat(s); +}) -int -listlen(OFString *a_) -{ +COMMAND(concatword, ARG_VARI, ^(OFString *s) { + concat([s stringByReplacingOccurrencesOfString:@" " withString:@""]); +}) + +COMMAND(listlen, ARG_1EST, ^(OFString *a_) { const char *a = a_.UTF8String; if (!*a) @@ -466,11 +449,9 @@ listlen(OFString *a_) n++; return n + 1; -} +}) -void -at(OFString *s_, OFString *pos) -{ +COMMAND(at, ARG_2STR, ^(OFString *s_, OFString *pos) { int n = pos.cube_intValue; char *copy __attribute__((__cleanup__(cleanup))) = strdup(s_.UTF8String); @@ -481,91 +462,48 @@ at(OFString *s_, OFString *pos) } s[strcspn(s, " \0")] = 0; concat(@(s)); -} +}) -COMMANDN(loop, loopa, ARG_2STR) -COMMANDN(while, whilea, ARG_2STR) -COMMANDN(if, ifthen, ARG_3STR) -COMMAND(onrelease, ARG_DWN1) -COMMAND(exec, ARG_1STR) -COMMAND(concat, ARG_VARI) -COMMAND(concatword, ARG_VARI) -COMMAND(at, ARG_2STR) -COMMAND(listlen, ARG_1EST) - -int -add(int a, int b) -{ +COMMAND(+, ARG_2EXP, ^(int a, int b) { return a + b; -} -COMMANDN(+, add, ARG_2EXP) +}) -int -mul(int a, int b) -{ +COMMAND(*, ARG_2EXP, ^(int a, int b) { return a * b; -} -COMMANDN(*, mul, ARG_2EXP) +}) -int -sub(int a, int b) -{ +COMMAND(-, ARG_2EXP, ^(int a, int b) { return a - b; -} -COMMANDN(-, sub, ARG_2EXP) +}) -int -divi(int a, int b) -{ +COMMAND(div, ARG_2EXP, ^(int a, int b) { return b ? a / b : 0; -} -COMMANDN(div, divi, ARG_2EXP) +}) -int -mod(int a, int b) -{ +COMMAND(mod, ARG_2EXP, ^(int a, int b) { return b ? a % b : 0; -} -COMMAND(mod, ARG_2EXP) +}) -int -equal(int a, int b) -{ +COMMAND(=, ARG_2EXP, ^(int a, int b) { return (int)(a == b); -} -COMMANDN(=, equal, ARG_2EXP) +}) -int -lt(int a, int b) -{ +COMMAND(<, ARG_2EXP, ^(int a, int b) { return (int)(a < b); -} -COMMANDN(<, lt, ARG_2EXP) +}) -int -gt(int a, int b) -{ +COMMAND(>, ARG_2EXP, ^(int a, int b) { return (int)(a > b); -} -COMMANDN(>, gt, ARG_2EXP) +}) -int -strcmpa(OFString *a, OFString *b) -{ +COMMAND(strcmp, ARG_2EST, ^(OFString *a, OFString *b) { return [a isEqual:b]; -} -COMMANDN(strcmp, strcmpa, ARG_2EST) +}) -int -rndn(int a) -{ - return a > 0 ? rnd(a) : 0; -} -COMMANDN(rnd, rndn, ARG_1EXP) +COMMAND(rnd, ARG_1EXP, ^(int a) { + return (a > 0 ? rnd(a) : 0); +}) -int -explastmillis() -{ +COMMAND(millis, ARG_1EXP, ^(int unused) { return lastmillis; -} -COMMANDN(millis, explastmillis, ARG_1EXP) +}) diff --git a/src/console.m b/src/console.m index 376fa00..f065dad 100644 --- a/src/console.m +++ b/src/console.m @@ -4,6 +4,7 @@ #include +#import "Command.h" #import "ConsoleLine.h" #import "KeyMapping.h" #import "OFString+Cube.h" @@ -17,14 +18,11 @@ int conskip = 0; bool saycommandon = false; static OFMutableString *commandbuf; -void -setconskip(int n) -{ +COMMAND(conskip, ARG_1INT, ^(int n) { conskip += n; if (conskip < 0) conskip = 0; -} -COMMANDN(conskip, setconskip, ARG_1INT) +}) static void conline(OFString *sf, bool highlight) // add a line to the console buffer @@ -104,9 +102,7 @@ renderconsole() static OFMutableArray *keyMappings = nil; -void -keymap(OFString *code, OFString *key, OFString *action) -{ +COMMAND(keymap, ARG_3STR, ^(OFString *code, OFString *key, OFString *action) { if (keyMappings == nil) keyMappings = [[OFMutableArray alloc] init]; @@ -114,12 +110,9 @@ keymap(OFString *code, OFString *key, OFString *action) name:key]; mapping.action = action; [keyMappings addObject:mapping]; -} -COMMAND(keymap, ARG_3STR) +}) -void -bindkey(OFString *key, OFString *action) -{ +COMMAND(bind, ARG_2STR, ^(OFString *key, OFString *action) { for (KeyMapping *mapping in keyMappings) { if ([mapping.name caseInsensitiveCompare:key] == OFOrderedSame) { @@ -129,11 +122,11 @@ bindkey(OFString *key, OFString *action) } conoutf(@"unknown key \"%@\"", key); -} -COMMANDN(bind, bindkey, ARG_2STR) +}) -void -saycommand(OFString *init) // turns input to the command line on or off +// turns input to the command line on or off +static void +saycommand(OFString *init) { saycommandon = (init != nil); if (saycommandon) @@ -149,15 +142,15 @@ saycommand(OFString *init) // turns input to the command line on or off commandbuf = [init mutableCopy]; } -COMMAND(saycommand, ARG_VARI) -void -mapmsg(OFString *s) -{ +COMMAND(saycommand, ARG_VARI, ^(OFString *init) { + saycommand(init); +}) + +COMMAND(mapmsg, ARG_1STR, ^(OFString *s) { memset(hdr.maptitle, '\0', sizeof(hdr.maptitle)); strncpy(hdr.maptitle, s.UTF8String, 127); -} -COMMAND(mapmsg, ARG_1STR) +}) void pasteconsole() @@ -168,9 +161,7 @@ pasteconsole() static OFMutableArray *vhistory; static int histpos = 0; -void -history(int n) -{ +COMMAND(history, ARG_1INT, ^(int n) { static bool rec = false; if (!rec && n >= 0 && n < vhistory.count) { @@ -178,8 +169,7 @@ history(int n) execute(vhistory[vhistory.count - n - 1], true); rec = false; } -} -COMMAND(history, ARG_1INT) +}) void keypress(int code, bool isDown) diff --git a/src/cube.h b/src/cube.h index 6702598..c67c418 100644 --- a/src/cube.h +++ b/src/cube.h @@ -340,14 +340,6 @@ enum { // nasty macros for registering script functions, abuses globals to avoid // excessive infrastructure -#define COMMANDN(name, fun, nargs) \ - OF_CONSTRUCTOR() \ - { \ - enqueueInit(^{ \ - addcommand(@ #name, (void (*)())fun, nargs); \ - }); \ - } -#define COMMAND(name, nargs) COMMANDN(name, name, nargs) #define VARP(name, min, cur, max) \ int name; \ OF_CONSTRUCTOR() \ diff --git a/src/editing.m b/src/editing.m index ba231cd..52df707 100644 --- a/src/editing.m +++ b/src/editing.m @@ -3,6 +3,7 @@ #include "cube.h" +#import "Command.h" #import "DynamicEntity.h" #import "Monster.h" #import "OFString+Cube.h" @@ -78,7 +79,10 @@ toggleedit() selset = false; editing = editmode; } -COMMANDN(edittoggle, toggleedit, ARG_NONE) + +COMMAND(edittoggle, ARG_NONE, ^{ + toggleedit(); +}) void correctsel() // ensures above invariant @@ -120,14 +124,12 @@ noselection() if (noteditmode() || multiplayer()) \ return; -void -selectpos(int x, int y, int xs, int ys) -{ +COMMAND(select, ARG_4INT, (^(int x, int y, int xs, int ys) { struct block s = { x, y, xs, ys }; sel = s; selh = 0; correctsel(); -} +})) void makesel() @@ -272,9 +274,7 @@ makeundo() pruneundos(undomegs << 20); } -void -editundo() -{ +COMMAND(undo, ARG_NONE, ^{ EDITMP; if (undos.count == 0) { conoutf(@"nothing more to undo"); @@ -284,24 +284,20 @@ editundo() [undos removeLastItem]; blockpaste(p); OFFreeMemory(p); -} +}) static struct block *copybuf = NULL; -void -copy() -{ +COMMAND(copy, ARG_NONE, ^{ EDITSELMP; if (copybuf) OFFreeMemory(copybuf); copybuf = blockcopy(&sel); -} +}) -void -paste() -{ +COMMAND(paste, ARG_NONE, ^{ EDITMP; if (!copybuf) { conoutf(@"nothing to paste"); @@ -318,7 +314,7 @@ paste() copybuf->x = sel.x; copybuf->y = sel.y; blockpaste(copybuf); -} +}) void tofronttex() // maintain most recently used of the texture lists when applying @@ -378,7 +374,10 @@ editheight(int flr, int amount) editheightxy(isfloor, amount, &sel); addmsg(1, 7, SV_EDITH, sel.x, sel.y, sel.xs, sel.ys, isfloor, amount); } -COMMAND(editheight, ARG_2INT) + +COMMAND(editheight, ARG_2INT, ^(int flr, int amount) { + editheight(flr, amount); +}) void edittexxy(int type, int t, const struct block *sel) @@ -399,9 +398,7 @@ edittexxy(int type, int t, const struct block *sel) }); } -void -edittex(int type, int dir) -{ +COMMAND(edittex, ARG_2INT, ^(int type, int dir) { EDITSEL; if (type < 0 || type > 3) @@ -419,11 +416,9 @@ edittex(int type, int dir) int t = lasttex = hdr.texlists[atype][i]; edittexxy(type, t, &sel); addmsg(1, 7, SV_EDITT, sel.x, sel.y, sel.xs, sel.ys, type, t); -} +}) -void -replace() -{ +COMMAND(replace, ARG_NONE, (^{ EDITSELMP; for (int x = 0; x < ssize; x++) { @@ -452,7 +447,7 @@ replace() struct block b = { 0, 0, ssize, ssize }; remip(&b, 0); -} +})) void edittypexy(int type, const struct block *sel) @@ -460,7 +455,7 @@ edittypexy(int type, const struct block *sel) loopselxy(s->type = type); } -void +static void edittype(int type) { EDITSEL; @@ -476,26 +471,17 @@ edittype(int type) addmsg(1, 6, SV_EDITS, sel.x, sel.y, sel.xs, sel.ys, type); } -void -heightfield(int t) -{ +COMMAND(heightfield, ARG_1INT, ^(int t) { edittype(t == 0 ? FHF : CHF); -} -COMMAND(heightfield, ARG_1INT) +}) -void -solid(int t) -{ +COMMAND(solid, ARG_1INT, ^(int t) { edittype(t == 0 ? SPACE : SOLID); -} -COMMAND(solid, ARG_1INT) +}) -void -corner() -{ +COMMAND(corner, ARG_NONE, ^{ edittype(CORNER); -} -COMMAND(corner, ARG_NONE) +}) void editequalisexy(bool isfloor, const struct block *sel) @@ -517,17 +503,14 @@ editequalisexy(bool isfloor, const struct block *sel) }); } -void -equalize(int flr) -{ +COMMAND(equalize, ARG_1INT, ^(int flr) { bool isfloor = (flr == 0); EDITSEL; editequalisexy(isfloor, &sel); addmsg(1, 6, SV_EDITE, sel.x, sel.y, sel.xs, sel.ys, isfloor); -} -COMMAND(equalize, ARG_1INT) +}) void setvdeltaxy(int delta, const struct block *sel) @@ -536,22 +519,18 @@ setvdeltaxy(int delta, const struct block *sel) remipmore(sel, 0); } -void -setvdelta(int delta) -{ +COMMAND(vdelta, ARG_1INT, ^(int delta) { EDITSEL; setvdeltaxy(delta, &sel); addmsg(1, 6, SV_EDITD, sel.x, sel.y, sel.xs, sel.ys, delta); -} +}) #define MAXARCHVERT 50 int archverts[MAXARCHVERT][MAXARCHVERT]; bool archvinit = false; -void -archvertex(int span, int vert, int delta) -{ +COMMAND(archvertex, ARG_3INT, ^(int span, int vert, int delta) { if (!archvinit) { archvinit = true; for (int s = 0; s < MAXARCHVERT; s++) @@ -561,11 +540,9 @@ archvertex(int span, int vert, int delta) if (span >= MAXARCHVERT || vert >= MAXARCHVERT || span < 0 || vert < 0) return; archverts[span][vert] = delta; -} +}) -void -arch(int sidedelta, int _a) -{ +COMMAND(arch, ARG_2INT, ^(int sidedelta, int _a) { EDITSELMP; sel.xs++; @@ -585,11 +562,9 @@ arch(int sidedelta, int _a) : (archverts[sel->ys - 1][y] + (x == 0 || x == sel->xs - 1 ? sidedelta : 0))); remipmore(sel, 0); -} +}) -void -slope(int xd, int yd) -{ +COMMAND(slope, ARG_2INT, ^(int xd, int yd) { EDITSELMP; int off = 0; @@ -606,11 +581,9 @@ slope(int xd, int yd) struct block *sel = sel_; loopselxy(s->vdelta = xd * x + yd * y + off); remipmore(sel, 0); -} +}) -void -perlin(int scale, int seed, int psize) -{ +COMMAND(perlin, ARG_3INT, ^(int scale, int seed, int psize) { EDITSELMP; sel.xs++; @@ -630,7 +603,7 @@ perlin(int scale, int seed, int psize) sel.xs--; sel.ys--; -} +}) VARF( fullbright, 0, 0, 1, if (fullbright) { @@ -640,37 +613,20 @@ VARF( world[i].r = world[i].g = world[i].b = 176; }); -void -edittag(int tag) -{ +COMMAND(edittag, ARG_1INT, ^(int tag) { EDITSELMP; struct block *sel_ = &sel; // Ugly hack to make the macro work. struct block *sel = sel_; loopselxy(s->tag = tag); -} +}) -void -newent(OFString *what, OFString *a1, OFString *a2, OFString *a3, OFString *a4) -{ - EDITSEL; +COMMAND(newent, ARG_5STR, + ^(OFString *what, OFString *a1, OFString *a2, OFString *a3, OFString *a4) { + EDITSEL; - newentity(sel.x, sel.y, (int)player1.origin.z, what, - [a1 cube_intValueWithBase:0], [a2 cube_intValueWithBase:0], - [a3 cube_intValueWithBase:0], [a4 cube_intValueWithBase:0]); -} - -COMMANDN(select, selectpos, ARG_4INT) -COMMAND(edittag, ARG_1INT) -COMMAND(replace, ARG_NONE) -COMMAND(archvertex, ARG_3INT) -COMMAND(arch, ARG_2INT) -COMMAND(slope, ARG_2INT) -COMMANDN(vdelta, setvdelta, ARG_1INT) -COMMANDN(undo, editundo, ARG_NONE) -COMMAND(copy, ARG_NONE) -COMMAND(paste, ARG_NONE) -COMMAND(edittex, ARG_2INT) -COMMAND(newent, ARG_5STR) -COMMAND(perlin, ARG_3INT) + newentity(sel.x, sel.y, (int)player1.origin.z, what, + [a1 cube_intValueWithBase:0], [a2 cube_intValueWithBase:0], + [a3 cube_intValueWithBase:0], [a4 cube_intValueWithBase:0]); + }) diff --git a/src/menus.m b/src/menus.m index 472800d..5fe141a 100644 --- a/src/menus.m +++ b/src/menus.m @@ -4,6 +4,7 @@ #import "Menu.h" +#import "Command.h" #import "DynamicEntity.h" #import "MenuItem.h" @@ -20,9 +21,7 @@ menuset(int menu) menus[1].menusel = 0; } -void -showmenu(OFString *name) -{ +COMMAND(showmenu, ARG_1STR, ^(OFString *name) { int i = 0; for (Menu *menu in menus) { if (i > 1 && [menu.name isEqual:name]) { @@ -31,8 +30,7 @@ showmenu(OFString *name) } i++; } -} -COMMAND(showmenu, ARG_1STR) +}) void sortmenu() @@ -97,7 +95,10 @@ newmenu(OFString *name) [menus addObject:[Menu menuWithName:name]]; } -COMMAND(newmenu, ARG_1STR) + +COMMAND(newmenu, ARG_1STR, ^(OFString *name) { + newmenu(name); +}) void menumanual(int m, int n, OFString *text) @@ -109,17 +110,14 @@ menumanual(int m, int n, OFString *text) [menus[m].items addObject:item]; } -void -menuitem(OFString *text, OFString *action) -{ +COMMAND(menuitem, ARG_2STR, ^(OFString *text, OFString *action) { Menu *menu = menus.lastObject; MenuItem *item = [MenuItem itemWithText:text action:(action.length > 0 ? action : text)]; [menu.items addObject:item]; -} -COMMAND(menuitem, ARG_2STR) +}) bool menukey(int code, bool isdown) diff --git a/src/protos.h b/src/protos.h index 2f7a69f..c2bfdc1 100644 --- a/src/protos.h +++ b/src/protos.h @@ -10,7 +10,6 @@ extern int variable(OFString *name, int min, int cur, int max, int *storage, extern void setvar(OFString *name, int i); extern int getvar(OFString *name); extern bool identexists(OFString *name); -extern bool addcommand(OFString *name, void (*fun)(), int narg); extern int execute(OFString *p, bool down); extern void exec(OFString *cfgfile); extern bool execfile(OFIRI *cfgfile); diff --git a/src/rendercubes.m b/src/rendercubes.m index 51d202a..5feb70c 100644 --- a/src/rendercubes.m +++ b/src/rendercubes.m @@ -3,6 +3,8 @@ #include "cube.h" +#import "Command.h" + static struct vertex *verts = NULL; int curvert; static int curmaxverts = 10000; @@ -61,12 +63,9 @@ int ol3r, ol3g, ol3b, ol4r, ol4g, ol4b; int firstindex; bool showm = false; -void -showmip() -{ +COMMAND(showmip, ARG_NONE, ^{ showm = !showm; -} -COMMAND(showmip, ARG_NONE) +}) void mipstats(int a, int b, int c) diff --git a/src/renderextras.m b/src/renderextras.m index ca0a5cc..698a604 100644 --- a/src/renderextras.m +++ b/src/renderextras.m @@ -2,6 +2,7 @@ #include "cube.h" +#import "Command.h" #import "DynamicEntity.h" #import "Entity.h" @@ -203,9 +204,7 @@ renderents() } } -void -loadsky(OFString *basename) -{ +COMMAND(loadsky, ARG_1STR, (^(OFString *basename) { static OFString *lastsky = @""; basename = [basename stringByReplacingOccurrencesOfString:@"\\" @@ -230,8 +229,7 @@ loadsky(OFString *basename) } lastsky = basename; -} -COMMAND(loadsky, ARG_1STR) +})) float cursordepth = 0.9f; GLint viewport[4]; diff --git a/src/rendergl.m b/src/rendergl.m index 4da4934..4168914 100644 --- a/src/rendergl.m +++ b/src/rendergl.m @@ -2,6 +2,7 @@ #include "cube.h" +#import "Command.h" #import "DynamicEntity.h" #import "Monster.h" #import "OFString+Cube.h" @@ -185,16 +186,11 @@ purgetextures() int curtexnum = 0; -void -texturereset() -{ +COMMAND(texturereset, ARG_NONE, ^{ curtexnum = 0; -} -COMMAND(texturereset, ARG_NONE) +}) -void -texture(OFString *aframe, OFString *name) -{ +COMMAND(texture, ARG_2STR, (^(OFString *aframe, OFString *name) { int num = curtexnum++, frame = aframe.cube_intValue; if (num < 0 || num >= 256 || frame < 0 || frame >= MAXFRAMES) @@ -203,8 +199,7 @@ texture(OFString *aframe, OFString *name) mapping[num][frame] = 1; mapname[num][frame] = [name stringByReplacingOccurrencesOfString:@"\\" withString:@"/"]; -} -COMMAND(texture, ARG_2STR) +})) int lookuptexture(int tex, int *xs, int *ys) diff --git a/src/rendermd2.m b/src/rendermd2.m index 8cf2e08..7297fc7 100644 --- a/src/rendermd2.m +++ b/src/rendermd2.m @@ -2,6 +2,7 @@ #include "cube.h" +#import "Command.h" #import "DynamicEntity.h" #import "MD2.h" #import "MapModelInfo.h" @@ -54,31 +55,27 @@ loadmodel(OFString *name) return m; } -void -mapmodel( - OFString *rad, OFString *h, OFString *zoff, OFString *snap, OFString *name) -{ - MD2 *m = loadmodel([name stringByReplacingOccurrencesOfString:@"\\" - withString:@"/"]); - m.mmi = [MapModelInfo infoWithRad:rad.cube_intValue - h:h.cube_intValue - zoff:zoff.cube_intValue - snap:snap.cube_intValue - name:m.loadname]; +COMMAND(mapmodel, ARG_5STR, + ^(OFString *rad, OFString *h, OFString *zoff, OFString *snap, + OFString *name) { + MD2 *m = + loadmodel([name stringByReplacingOccurrencesOfString:@"\\" + withString:@"/"]); + m.mmi = [MapModelInfo infoWithRad:rad.cube_intValue + h:h.cube_intValue + zoff:zoff.cube_intValue + snap:snap.cube_intValue + name:m.loadname]; - if (mapmodels == nil) - mapmodels = [[OFMutableArray alloc] init]; + if (mapmodels == nil) + mapmodels = [[OFMutableArray alloc] init]; - [mapmodels addObject:m]; -} -COMMAND(mapmodel, ARG_5STR) + [mapmodels addObject:m]; + }) -void -mapmodelreset() -{ +COMMAND(mapmodelreset, ARG_NONE, ^{ [mapmodels removeAllObjects]; -} -COMMAND(mapmodelreset, ARG_NONE) +}) MapModelInfo * getmminfo(int i) diff --git a/src/savegamedemo.m b/src/savegamedemo.m index b79da0a..8e55d15 100644 --- a/src/savegamedemo.m +++ b/src/savegamedemo.m @@ -3,6 +3,7 @@ #include "cube.h" +#import "Command.h" #import "DynamicEntity.h" #import "Entity.h" #import "Monster.h" @@ -129,9 +130,7 @@ savestate(OFIRI *IRI) } } -void -savegame(OFString *name) -{ +COMMAND(savegame, ARG_1STR, (^(OFString *name) { if (!m_classicsp) { conoutf(@"can only save classic sp games"); return; @@ -143,8 +142,7 @@ savegame(OFString *name) savestate(IRI); stop(); conoutf(@"wrote %@", IRI.string); -} -COMMAND(savegame, ARG_1STR) +})) void loadstate(OFIRI *IRI) @@ -184,15 +182,12 @@ out: stop(); } -void -loadgame(OFString *name) -{ +COMMAND(loadgame, ARG_1STR, (^(OFString *name) { OFString *path = [OFString stringWithFormat:@"savegames/%@.csgz", name]; OFIRI *IRI = [Cube.sharedInstance.userDataIRI IRIByAppendingPathComponent:path]; loadstate(IRI); -} -COMMAND(loadgame, ARG_1STR) +})) void loadgameout() @@ -268,9 +263,7 @@ int playbacktime = 0; int ddamage, bdamage; OFVector3D dorig; -void -record(OFString *name) -{ +COMMAND(record, ARG_1STR, (^(OFString *name) { if (m_sp) { conoutf(@"cannot record singleplayer games"); return; @@ -289,8 +282,7 @@ record(OFString *name) demorecording = true; starttime = lastmillis; ddamage = bdamage = 0; -} -COMMAND(record, ARG_1STR) +})) void demodamage(int damage, const OFVector3D *o) @@ -337,16 +329,13 @@ incomingdemodata(unsigned char *buf, int len, bool extras) } } -void -demo(OFString *name) -{ +COMMAND(demo, ARG_1STR, (^(OFString *name) { OFString *path = [OFString stringWithFormat:@"demos/%@.cdgz", name]; OFIRI *IRI = [Cube.sharedInstance.userDataIRI IRIByAppendingPathComponent:path]; loadstate(IRI); demoloading = true; -} -COMMAND(demo, ARG_1STR) +})) void stopreset() @@ -549,13 +538,10 @@ demoplaybackstep() // if(player1->state!=CS_DEAD) showscores(false); } -void -stopn() -{ +COMMAND(stop, ARG_NONE, ^{ if (demoplayback) stopreset(); else stop(); conoutf(@"demo stopped"); -} -COMMANDN(stop, stopn, ARG_NONE) +}) diff --git a/src/serverbrowser.m b/src/serverbrowser.m index d363965..dc11386 100644 --- a/src/serverbrowser.m +++ b/src/serverbrowser.m @@ -4,6 +4,7 @@ #include "SDL_thread.h" #include "cube.h" +#import "Command.h" #import "ResolverResult.h" #import "ResolverThread.h" #import "ServerInfo.h" @@ -126,6 +127,10 @@ addserver(OFString *servername) [servers addObject:[ServerInfo infoWithName:servername]]; } +COMMAND(addserver, ARG_1STR, ^(OFString *servername) { + addserver(servername); +}) + void pingservers() { @@ -245,7 +250,7 @@ refreshservers() }]; } -void +static void servermenu() { if (pingsock == ENET_SOCKET_NULL) { @@ -262,9 +267,11 @@ servermenu() menuset(1); } -void -updatefrommaster() -{ +COMMAND(servermenu, ARG_NONE, ^{ + servermenu(); +}) + +COMMAND(updatefrommaster, ARG_NONE, ^{ const int MAXUPD = 32000; unsigned char buf[MAXUPD]; unsigned char *reply = retrieveservers(buf, MAXUPD); @@ -276,11 +283,7 @@ updatefrommaster() execute(@((char *)reply), true); } servermenu(); -} - -COMMAND(addserver, ARG_1STR) -COMMAND(servermenu, ARG_NONE) -COMMAND(updatefrommaster, ARG_NONE) +}) void writeservercfg() diff --git a/src/sound.m b/src/sound.m index 5164eb5..d45f81d 100644 --- a/src/sound.m +++ b/src/sound.m @@ -1,5 +1,6 @@ #include "cube.h" +#import "Command.h" #import "DynamicEntity.h" #include @@ -47,9 +48,7 @@ initsound() Mix_AllocateChannels(MAXCHAN); } -void -music(OFString *name) -{ +COMMAND(music, ARG_1STR, (^(OFString *name) { if (nosound) return; @@ -69,15 +68,12 @@ music(OFString *name) Mix_VolumeMusic((musicvol * MAXVOL) / 255); } } -} -COMMAND(music, ARG_1STR) +})) static OFMutableData *samples; static OFMutableArray *snames; -int -registersound(OFString *name) -{ +COMMAND(registersound, ARG_1EST, ^int(OFString *name) { int i = 0; for (OFString *iter in snames) { if ([iter isEqual:name]) @@ -98,8 +94,7 @@ registersound(OFString *name) [samples addItem:&sample]; return samples.count - 1; -} -COMMAND(registersound, ARG_1EST) +}) void cleansound() @@ -216,9 +211,6 @@ playsound(int n, const OFVector3D *loc) updatechanvol(chan, loc); } -void -sound(int n) -{ +COMMAND(sound, ARG_1INT, ^(int n) { playsound(n, NULL); -} -COMMAND(sound, ARG_1INT) +}) diff --git a/src/weapon.m b/src/weapon.m index d0ff131..ae2df82 100644 --- a/src/weapon.m +++ b/src/weapon.m @@ -2,6 +2,7 @@ #include "cube.h" +#import "Command.h" #import "DynamicEntity.h" #import "Monster.h" #import "OFString+Cube.h" @@ -62,14 +63,11 @@ reloadtime(int gun) return guns[gun].attackdelay; } -void -weapon(OFString *a1, OFString *a2, OFString *a3) -{ +COMMAND(weapon, ARG_3STR, ^(OFString *a1, OFString *a2, OFString *a3) { selectgun((a1.length > 0 ? a1.cube_intValue : -1), (a2.length > 0 ? a2.cube_intValue : -1), (a3.length > 0 ? a3.cube_intValue : -1)); -} -COMMAND(weapon, ARG_3STR) +}) // create random spread of rays for the shotgun void diff --git a/src/world.m b/src/world.m index bef58fc..3b60ec5 100644 --- a/src/world.m +++ b/src/world.m @@ -2,6 +2,7 @@ #include "cube.h" +#import "Command.h" #import "DynamicEntity.h" #import "Entity.h" #import "Monster.h" @@ -91,7 +92,10 @@ trigger(int tag, int type, bool savegame) if (type == 2) [Monster endSinglePlayerWithAllKilled:false]; } -COMMAND(trigger, ARG_2INT) + +COMMAND(trigger, ARG_2INT, ^(int tag, int type, bool savegame) { + trigger(tag, type, savegame); +}) // main geometric mipmapping routine, recursively rebuild mipmaps within block // b. tries to produce cube out of 4 lower level mips as well as possible, sets @@ -304,9 +308,7 @@ closestent() // used for delent and edit mode ent display return (bdist == 99999 ? -1 : best); } -void -entproperty(int prop, int amount) -{ +COMMAND(entproperty, ARG_2INT, ^(int prop, int amount) { int e = closestent(); if (e < 0) return; @@ -324,11 +326,9 @@ entproperty(int prop, int amount) ents[e].attr4 += amount; break; } -} +}) -void -delent() -{ +COMMAND(delent, ARG_NONE, ^{ int e = closestent(); if (e < 0) { conoutf(@"no more entities"); @@ -340,7 +340,7 @@ delent() addmsg(1, 10, SV_EDITENT, e, NOTUSED, 0, 0, 0, 0, 0, 0, 0); if (t == LIGHT) calclight(); -} +}) int findtype(OFString *what) @@ -397,9 +397,7 @@ newentity(int x, int y, int z, OFString *what, int v1, int v2, int v3, int v4) return e; } -void -clearents(OFString *name) -{ +COMMAND(clearents, ARG_1STR, ^(OFString *name) { int type = findtype(name); if (noteditmode() || multiplayer()) @@ -411,8 +409,7 @@ clearents(OFString *name) if (type == LIGHT) calclight(); -} -COMMAND(clearents, ARG_1STR) +}) static unsigned char scalecomp(unsigned char c, int intens) @@ -423,9 +420,7 @@ scalecomp(unsigned char c, int intens) return n; } -void -scalelights(int f, int intens) -{ +COMMAND(scalelights, ARG_2INT, ^(int f, int intens) { for (Entity *e in ents) { if (e.type != LIGHT) continue; @@ -444,8 +439,7 @@ scalelights(int f, int intens) } calclight(); -} -COMMAND(scalelights, ARG_2INT) +}) int findentity(int type, int index) @@ -551,20 +545,14 @@ empty_world(int factor, bool force) } } -void -mapenlarge() -{ +COMMAND(mapenlarge, ARG_NONE, ^{ empty_world(-1, false); -} +}) -void -newmap(int i) -{ +COMMAND(newmap, ARG_1INT, ^(int i) { empty_world(i, false); -} +}) -COMMAND(mapenlarge, ARG_NONE) -COMMAND(newmap, ARG_1INT) -COMMANDN(recalc, calclight, ARG_NONE) -COMMAND(delent, ARG_NONE) -COMMAND(entproperty, ARG_2INT) +COMMAND(recalc, ARG_NONE, ^{ + calclight(); +}) diff --git a/src/worldio.m b/src/worldio.m index 6e34ee3..61a6e96 100644 --- a/src/worldio.m +++ b/src/worldio.m @@ -2,6 +2,7 @@ #include "cube.h" +#import "Command.h" #import "Entity.h" struct persistent_entity { @@ -256,7 +257,10 @@ save_world(OFString *mname) conoutf(@"wrote map file %@", cgzname); settagareas(); } -COMMANDN(savemap, save_world, ARG_1STR) + +COMMAND(savemap, ARG_1STR, ^(OFString *mname) { + save_world(mname); +}) void load_world(OFString *mname) // still supports all map formats that have existed diff --git a/src/worldocull.m b/src/worldocull.m index c4c8b7f..3e0f6b9 100644 --- a/src/worldocull.m +++ b/src/worldocull.m @@ -2,6 +2,7 @@ #include "cube.h" +#import "Command.h" #import "DynamicEntity.h" #define NUMRAYS 512 @@ -10,12 +11,9 @@ float rdist[NUMRAYS]; bool ocull = true; float odist = 256; -void -toggleocull() -{ +COMMAND(toggleocull, ARG_NONE, ^{ ocull = !ocull; -} -COMMAND(toggleocull, ARG_NONE) +}) // constructs occlusion map: cast rays in all directions on the 2d plane and // record distance. done exactly once per frame.