Clean up identifiers, use blocks for commands
FossilOrigin-Name: d7661be1b1dc8fda8e4de50f9a9d75907f498e6e07530241fb04be015ca3d9ae
This commit is contained in:
parent
e995b95a84
commit
daa4c19312
25 changed files with 391 additions and 535 deletions
|
@ -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<OFString *> *)arguments isDown:(bool)isDown;
|
||||
@end
|
||||
|
||||
|
|
|
@ -20,23 +20,27 @@ padArguments(OFArray<OFString *> *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<OFString *> *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<OFString *> *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<OFString *> *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<OFString *> *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<OFString *> *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;
|
||||
|
|
16
src/Cube.m
16
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)
|
||||
})
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -1,6 +1,33 @@
|
|||
#import "Identifier.h"
|
||||
|
||||
// contains ALL vars/commands/aliases
|
||||
static OFMutableDictionary<OFString *, __kindof Identifier *> *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];
|
||||
|
|
|
@ -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)
|
||||
})
|
||||
|
|
|
@ -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);
|
||||
})
|
||||
|
|
|
@ -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()
|
||||
|
|
258
src/commands.m
258
src/commands.m
|
@ -9,9 +9,6 @@
|
|||
#import "OFString+Cube.h"
|
||||
#import "Variable.h"
|
||||
|
||||
// contains ALL vars/commands/aliases
|
||||
static OFMutableDictionary<OFString *, __kindof Identifier *> *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)
|
||||
})
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
#include <ctype.h>
|
||||
|
||||
#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<KeyMapping *> *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<OFString *> *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)
|
||||
|
|
|
@ -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() \
|
||||
|
|
142
src/editing.m
142
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]);
|
||||
})
|
||||
|
|
20
src/menus.m
20
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)
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
})
|
||||
|
|
|
@ -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()
|
||||
|
|
22
src/sound.m
22
src/sound.m
|
@ -1,5 +1,6 @@
|
|||
#include "cube.h"
|
||||
|
||||
#import "Command.h"
|
||||
#import "DynamicEntity.h"
|
||||
|
||||
#include <SDL_mixer.h>
|
||||
|
@ -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<OFString *> *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)
|
||||
})
|
||||
|
|
|
@ -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
|
||||
|
|
52
src/world.m
52
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();
|
||||
})
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue