Index: src/Cube.m ================================================================== --- src/Cube.m +++ src/Cube.m @@ -6,12 +6,19 @@ #import "Player.h" #import "Variable.h" OF_APPLICATION_DELEGATE(Cube) -VARF(gamespeed, 10, 100, 1000, if (multiplayer()) gamespeed = 100); -VARP(minmillis, 0, 5, 1000); +static int gamespeed = 100; +VARB(gamespeed, 10, 1000, ^ { return gamespeed; }, ^ (int value) { + if (multiplayer()) + gamespeed = 100; + else + gamespeed = value; +}) + +VARP(minmillis, 0, 5, 1000) @implementation Cube { int _width, _height; } Index: src/Monster.m ================================================================== --- src/Monster.m +++ src/Monster.m @@ -33,11 +33,15 @@ state: state trigger: trigger move: move]; } -VARF(skill, 1, 3, 10, conoutf(@"skill is now %d", skill)); +static int skill = 3; +VARB(skill, 1, 10, ^ { return skill; }, ^ (int value) { + skill = value; + conoutf(@"skill is now %d", skill); +}) // for savegames + (void)restoreAll { for (Monster *monster in monsters) Index: src/OFColor+Cube.h ================================================================== --- src/OFColor+Cube.h +++ src/OFColor+Cube.h @@ -1,5 +1,7 @@ #import @interface OFColor (Cube) - (void)cube_setAsGLColor; +- (void)cube_setAsGLClearColor; +- (void)cube_setAsGLFogColor; @end Index: src/OFColor+Cube.m ================================================================== --- src/OFColor+Cube.m +++ src/OFColor+Cube.m @@ -4,9 +4,32 @@ @implementation OFColor (Cube) - (void)cube_setAsGLColor { float red, green, blue, alpha; + [self getRed: &red green: &green blue: &blue alpha: &alpha]; + glColor4f(red, green, blue, alpha); } + +- (void)cube_setAsGLClearColor +{ + float red, green, blue, alpha; + + [self getRed: &red green: &green blue: &blue alpha: &alpha]; + + glClearColor(red, green, blue, alpha); +} + +- (void)cube_setAsGLFogColor +{ + float color[4]; + + [self getRed: &color[0] + green: &color[1] + blue: &color[2] + alpha: &color[3]]; + + glFogfv(GL_FOG_COLOR, color); +} @end Index: src/Variable.h ================================================================== --- src/Variable.h +++ src/Variable.h @@ -1,25 +1,9 @@ #import "Identifier.h" OF_ASSUME_NONNULL_BEGIN -#define VARP(name, min_, cur, max_) \ - int name = cur; \ - \ - OF_CONSTRUCTOR() \ - { \ - enqueueInit(^ { \ - Variable *variable = [Variable \ - variableWithName: @#name \ - min: min_ \ - max: max_ \ - storage: &name \ - function: NULL \ - persisted: true]; \ - Identifier.identifiers[@#name] = variable; \ - }); \ - } #define VAR(name, min_, cur, max_) \ int name = cur; \ \ OF_CONSTRUCTOR() \ { \ @@ -27,82 +11,86 @@ Variable *variable = [Variable \ variableWithName: @#name \ min: min_ \ max: max_ \ storage: &name \ - function: NULL \ - persisted: false]; \ + persisted: false \ + getter: NULL \ + setter: NULL]; \ Identifier.identifiers[@#name] = variable; \ }); \ } -#define VARF(name, min_, cur, max_, body) \ - static void var_##name(void); \ - static int name = cur; \ +#define VARP(name, min_, cur, max_) \ + int name = cur; \ \ OF_CONSTRUCTOR() \ { \ enqueueInit(^ { \ Variable *variable = [Variable \ variableWithName: @#name \ min: min_ \ max: max_ \ storage: &name \ - function: var_##name \ - persisted: false]; \ + persisted: true \ + getter: NULL \ + setter: NULL]; \ + Identifier.identifiers[@#name] = variable; \ + }); \ + } +#define VARB(name, min_, max_, getter_, setter_) \ + OF_CONSTRUCTOR() \ + { \ + enqueueInit(^ { \ + Variable *variable = [Variable \ + variableWithName: @#name \ + min: min_ \ + max: max_ \ + storage: NULL \ + persisted: false \ + getter: getter_ \ + setter: setter_]; \ Identifier.identifiers[@#name] = variable; \ }); \ - } \ - \ - static void \ - var_##name(void) \ - { \ - body; \ - } -#define VARFP(name, min_, cur, max_, body) \ - static void var_##name(void); \ - static int name = cur; \ - \ + } +#define VARBP(name, min_, max_, getter_, setter_) \ OF_CONSTRUCTOR() \ { \ enqueueInit(^ { \ Variable *variable = [Variable \ - variableWithName: @#name \ - min: min_ \ - max: max_ \ - storage: &name \ - function: var_##name \ - persisted: true]; \ + variableWithName: @#name \ + min: min_ \ + max: max_ \ + storage: NULL \ + persisted: true \ + getter: getter_ \ + setter: setter_]; \ Identifier.identifiers[@#name] = variable; \ }); \ - } \ - \ - static void \ - var_##name(void) \ - { \ - body; \ } @interface Variable: Identifier @property (direct, readonly, nonatomic) int min, max; -@property (direct, readonly, nonatomic) int *storage; -@property (direct, readonly, nullable, nonatomic) void (*function)(); @property (readonly, nonatomic) bool persisted; +@property (direct, readonly, nullable, nonatomic) int (^getter)(void); +@property (direct, readonly, nullable, nonatomic) void (^setter)(int); +@property (direct, nonatomic) int value; + (instancetype)variableWithName: (OFString *)name min: (int)min max: (int)max - storage: (int *)storage - function: (void (*_Nullable)())function - persisted: (bool)persisted OF_DIRECT; + storage: (nullable int *)storage + persisted: (bool)persisted + getter: (int (^_Nullable)(void))getter + setter: (void (^_Nullable)(int))setter OF_DIRECT; - (instancetype)initWithName: (OFString *)name OF_UNAVAILABLE; - (instancetype)initWithName: (OFString *)name min: (int)min max: (int)max - storage: (int *)storage - function: (void (*_Nullable)())function - persisted: (bool)persisted OF_DESIGNATED_INITIALIZER - OF_DIRECT; + storage: (nullable int *)storage + persisted: (bool)persisted + getter: (int (^_Nullable)(void))getter + setter: (void (^_Nullable)(int))setter + OF_DESIGNATED_INITIALIZER OF_DIRECT; - (void)printValue OF_DIRECT; -- (void)setValue: (int)value OF_DIRECT; @end OF_ASSUME_NONNULL_END Index: src/Variable.m ================================================================== --- src/Variable.m +++ src/Variable.m @@ -1,46 +1,54 @@ #import "Variable.h" #include "cube.h" @implementation Variable +{ + int *_storage; +} + + (instancetype)variableWithName: (OFString *)name min: (int)min max: (int)max storage: (int *)storage - function: (void (*__cdecl)())function persisted: (bool)persisted + getter: (int (^)(void))getter + setter: (void (^)(int))setter { return [[self alloc] initWithName: name min: min max: max storage: storage - function: function - persisted: persisted]; + persisted: persisted + getter: getter + setter: setter]; } - (instancetype)initWithName: (OFString *)name min: (int)min max: (int)max storage: (int *)storage - function: (void (*__cdecl)())function persisted: (bool)persisted + getter: (int (^)(void))getter + setter: (void (^)(int))setter { self = [super initWithName: name]; _min = min; _max = max; _storage = storage; - _function = function; _persisted = persisted; + _getter = [getter copy]; + _setter = [setter copy]; return self; } - (void)printValue { - conoutf(@"%@ = %d", self.name, *_storage); + conoutf(@"%@ = %d", self.name, self.value); } - (void)setValue: (int)value { bool outOfRange = false; @@ -58,15 +66,24 @@ if (value > _max) { value = _max; outOfRange = true; } - if (outOfRange) + if (outOfRange) { conoutf(@"valid range for %@ is %d..%d", self.name, _min, _max); + return; + } - *_storage = value; + if (_setter != NULL) + _setter(value); + else + *_storage = value; +} - if (_function != NULL) - // call trigger function if available - _function(); +- (int)value +{ + if (_getter != NULL) + return _getter(); + else + return *_storage; } @end Index: src/clients.m ================================================================== --- src/clients.m +++ src/clients.m @@ -40,29 +40,46 @@ conoutf(@"editing in multiplayer requires coopedit mode (1)"); return allow; } -VARF(rate, 0, 0, 25000, +static int rate = 0; +VARB(rate, 0, 25000, ^ { return rate; }, ^ (int value) { + rate = value; + if (clienthost && (!rate || rate > 1000)) - enet_host_bandwidth_limit(clienthost, rate, rate)); - -void throttle(); - -VARF(throttle_interval, 0, 5, 30, throttle()); -VARF(throttle_accel, 0, 2, 32, throttle()); -VARF(throttle_decel, 0, 2, 32, throttle()); - -void -throttle() + enet_host_bandwidth_limit(clienthost, rate, rate); +}) + +static int throttle_interval = 5; +static int throttle_accel = 2; +static int throttle_decel = 2; + +static void +throttle(void) { if (!clienthost || connecting) return; + assert(ENET_PEER_PACKET_THROTTLE_SCALE == 32); + enet_peer_throttle_configure(clienthost->peers, throttle_interval * 1000, throttle_accel, throttle_decel); } + +VARB(throttle_interval, 0, 30, ^ { return throttle_interval; }, ^ (int value) { + throttle_interval = value; + throttle(); +}) +VARB(throttle_accel, 0, 32, ^ { return throttle_accel; }, ^ (int value) { + throttle_accel = value; + throttle(); +}) +VARB(throttle_decel, 0, 32, ^ { return throttle_decel; }, ^ (int value) { + throttle_decel = value; + throttle(); +}) static void newname(OFString *name) { c2sinit = false; Index: src/commands.m ================================================================== --- src/commands.m +++ src/commands.m @@ -41,20 +41,20 @@ setvar(OFString *name, int i) { Variable *variable = Identifier.identifiers[name]; if ([variable isKindOfClass: Variable.class]) - *variable.storage = i; + variable.value = i; } int getvar(OFString *name) { Variable *variable = Identifier.identifiers[name]; if ([variable isKindOfClass: Variable.class]) - return *variable.storage; + return variable.value; return 0; } bool @@ -142,11 +142,11 @@ __kindof Identifier *identifier = Identifier.identifiers[[n substringFromIndex: 1]]; if ([identifier isKindOfClass: Variable.class]) { return [OFString stringWithFormat: - @"%d", *[identifier storage]]; + @"%d", [identifier value]]; } else if ([identifier isKindOfClass: Alias.class]) return [identifier action]; conoutf(@"unknown alias lookup: %@", [n substringFromIndex: 1]); return n; @@ -348,17 +348,16 @@ @"\n"]; writeclientinfo(stream); [stream writeString: @"\n"]; [Identifier.identifiers enumerateKeysAndObjectsUsingBlock: - ^ (OFString *name, __kindof Identifier *identifier, bool *stop) { - if (![identifier isKindOfClass: Variable.class] || - ![identifier persisted]) + ^ (OFString *name, Variable *variable, bool *stop) { + if (![variable isKindOfClass: Variable.class] || + !variable.persisted) return; - [stream writeFormat: - @"%@ %d\n", identifier.name, *[identifier storage]]; + [stream writeFormat: @"%@ %d\n", variable.name, variable.value]; }]; [stream writeString: @"\n"]; writebinds(stream); [stream writeString: @"\n"]; Index: src/editing.m ================================================================== --- src/editing.m +++ src/editing.m @@ -22,21 +22,26 @@ { enqueueInit(^ { static const struct { OFString *name; int *storage; - } vars[4] = { { @"selx", &sel.x }, { @"sely", &sel.y }, - { @"selxs", &sel.xs }, { @"selys", &sel.ys } }; + } vars[4] = { + { @"selx", &sel.x }, + { @"sely", &sel.y }, + { @"selxs", &sel.xs }, + { @"selys", &sel.ys } + }; for (size_t i = 0; i < 4; i++) { Variable *variable = [Variable variableWithName: vars[i].name min: 0 max: 4096 storage: vars[i].storage - function: NULL - persisted: false]; + persisted: false + getter: NULL + setter: NULL]; Identifier.identifiers[vars[i].name] = variable; } }); } @@ -632,17 +637,20 @@ sel.xs--; sel.ys--; }) -VARF( - fullbright, 0, 0, 1, if (fullbright) { - if (noteditmode()) - return; - for (int i = 0; i < mipsize; i++) - world[i].r = world[i].g = world[i].b = 176; - }); +static int fullbright = 0; +VARB(fullbright, 0, 1, ^ { return fullbright; }, ^ (int value) { + if (fullbright) { + if (noteditmode()) + return; + + for (int i = 0; i < mipsize; i++) + world[i].r = world[i].g = world[i].b = 176; + } +}); COMMAND(edittag, ARG_1INT, ^ (int tag) { EDITSELMP; struct block *sel_ = &sel; Index: src/rendercubes.m ================================================================== --- src/rendercubes.m +++ src/rendercubes.m @@ -318,12 +318,15 @@ } int wx1, wy1, wx2, wy2; VAR(watersubdiv, 1, 4, 64); -VARF(waterlevel, -128, -128, 127, - if (!noteditmode()) hdr.waterlevel = waterlevel); + +VARB(waterlevel, -128, 127, ^ { return hdr.waterlevel; }, ^ (int value) { + if (!noteditmode()) + hdr.waterlevel = value; +}) static inline void vertw(int v1, float v2, int v3, struct sqr *c, float t1, float t2, float t) { vertcheck(); Index: src/rendergl.m ================================================================== --- src/rendergl.m +++ src/rendergl.m @@ -325,18 +325,21 @@ [strips addItem: &s]; } #undef gamma -VARFP(gamma, 30, 100, 300, { - float f = gamma / 100.0f; +static int gamma = 100; +VARBP(gamma, 30, 300, ^ { return gamma; }, ^ (int value) { + float f = value / 100.0f; Uint16 ramp[256]; SDL_CalculateGammaRamp(f, ramp); if (SDL_SetWindowGammaRamp(Cube.sharedInstance.window, - ramp, ramp, ramp) == -1) { + ramp, ramp, ramp) != -1) + gamma = value; + else { conoutf( @"Could not set gamma (card/driver doesn't support it?)"); conoutf(@"sdl: %s", SDL_GetError()); } }) @@ -360,11 +363,33 @@ VARP(fov, 10, 105, 120); int xtraverts; VAR(fog, 64, 180, 1024); -VAR(fogcolour, 0, 0x8099B3, 0xFFFFFF); + +static OFColor *fogColor; +VARB(fogcolour, 0, 0xFFFFFF, (^ { + float red, green, blue; + + if (fogColor == nil) + return 0x8099B3; + + [fogColor getRed: &red green: &green blue: &blue alpha: NULL]; + + return ((unsigned char)(red * 255.0f) << 16) | + ((unsigned char)(green * 255.0f) << 8) | + (unsigned char)(blue * 255.0f); +}), ^ (int value) { + unsigned char red = (value >> 16) & 0xFF; + unsigned char green = (value >> 8) & 0xFF; + unsigned char blue = value & 0xFF; + + fogColor = [OFColor colorWithRed: red / 255.0f + green: green / 255.0f + blue: blue / 255.0f + alpha: 1.f]; +}) VARP(hudgun, 0, 1, 1); OFString *hudgunnames[] = { @"hudguns/fist", @"hudguns/shotg", @"hudguns/chaing", @"hudguns/rocket", @"hudguns/rifle" }; @@ -420,15 +445,12 @@ float aspect = w / (float)h; bool underwater = (player1.origin.z < hf); glFogi(GL_FOG_START, (fog + 64) / 8); glFogi(GL_FOG_END, fog); - float fogc[4] = { (fogcolour >> 16) / 256.0f, - ((fogcolour >> 8) & 255) / 256.0f, (fogcolour & 255) / 256.0f, - 1.0f }; - glFogfv(GL_FOG_COLOR, fogc); - glClearColor(fogc[0], fogc[1], fogc[2], 1.0f); + [fogColor cube_setAsGLFogColor]; + [fogColor cube_setAsGLClearColor]; if (underwater) { fovy += (float)sin(lastmillis / 1000.0) * 2.0f; aspect += (float)sin(lastmillis / 1000.0 + PI) * 0.1f; glFogi(GL_FOG_START, 0); Index: src/renderparticles.m ================================================================== --- src/renderparticles.m +++ src/renderparticles.m @@ -1,9 +1,10 @@ // renderparticles.cpp #include "cube.h" +#import "OFColor+Cube.h" #import "Player.h" #import "Variable.h" #define MAXPARTICLES 10500 const int NUMPARTCUTOFF = 20; @@ -64,23 +65,55 @@ glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_SRC_ALPHA); glDisable(GL_FOG); struct parttype { - float r, g, b; + OFColor *color; int gr, tex; float sz; } parttypes[] = { - { 0.7f, 0.6f, 0.3f, 2, 3, 0.06f }, // yellow: sparks - { 0.5f, 0.5f, 0.5f, 20, 7, 0.15f }, // grey: small smoke - { 0.2f, 0.2f, 1.0f, 20, 3, 0.08f }, // blue: edit mode entities - { 1.0f, 0.1f, 0.1f, 1, 7, 0.06f }, // red: blood spats - { 1.0f, 0.8f, 0.8f, 20, 6, 1.2f }, // yellow: fireball1 - { 0.5f, 0.5f, 0.5f, 20, 7, 0.6f }, // grey: big smoke - { 1.0f, 1.0f, 1.0f, 20, 8, 1.2f }, // blue: fireball2 - { 1.0f, 1.0f, 1.0f, 20, 9, 1.2f }, // green: fireball3 - { 1.0f, 0.1f, 0.1f, 0, 7, 0.2f }, // red: demotrack + /* + * Note: Some comments don't match the color. This was already + * the case in the original. + */ + + // yellow: sparks + { [OFColor colorWithRed: 0.7f + green: 0.6f + blue: 0.3f + alpha: 1.0f], 2, 3, 0.06f }, + // grey: small smoke + { OFColor.gray, 20, 7, 0.15f }, + // blue: edit mode entities + { [OFColor colorWithRed: 0.2f + green: 0.2f + blue: 1.0f + alpha: 1.0f], 20, 3, 0.08f }, + // red: blood spats + { [OFColor colorWithRed: 1.0f + green: 0.1f + blue: 0.1f + alpha: 1.0f], 1, 7, 0.06f }, + // yellow: fireball1 + { [OFColor colorWithRed: 1.0f + green: 0.8f + blue: 0.8f + alpha: 1.0f], 20, 6, 1.2f }, + // grey: big smoke + { [OFColor colorWithRed: 0.5f + green: 0.5f + blue: 0.5f + alpha: 1.0f], 20, 7, 0.6f }, + // blue: fireball2 + { OFColor.white, 20, 8, 1.2f }, + // green: fireball3 + { OFColor.white, 20, 9, 1.2f }, + // red: demotrack + { [OFColor colorWithRed: 1.0f + green: 0.1f + blue: 0.1f + alpha: 1.0f], 0, 7, 0.2f } }; int numrender = 0; for (struct particle *p, **pp = &parlist; (p = *pp) != NULL;) { @@ -87,11 +120,11 @@ struct parttype *pt = &parttypes[p->type]; glBindTexture(GL_TEXTURE_2D, pt->tex); glBegin(GL_QUADS); - glColor3d(pt->r, pt->g, pt->b); + [pt->color cube_setAsGLColor]; float sz = pt->sz * particlesize / 100.0f; // perf varray? glTexCoord2f(0.0, 1.0); glVertex3d(p->o.x + (-right.x + up.x) * sz, p->o.z + (-right.y + up.y) * sz,