Index: src/Alias.h ================================================================== --- src/Alias.h +++ src/Alias.h @@ -1,18 +1,19 @@ #import "Identifier.h" OF_ASSUME_NONNULL_BEGIN @interface Alias: Identifier -@property (copy, nonatomic) OFString *action; +@property (direct, copy, nonatomic) OFString *action; @property (readonly, nonatomic) bool persisted; + (instancetype)aliasWithName:(OFString *)name action:(OFString *)action - persisted:(bool)persisted; + persisted:(bool)persisted OF_DIRECT; - (instancetype)initWithName:(OFString *)name OF_UNAVAILABLE; - (instancetype)initWithName:(OFString *)name action:(OFString *)action - persisted:(bool)persisted; + persisted:(bool)persisted OF_DESIGNATED_INITIALIZER + OF_DIRECT; @end OF_ASSUME_NONNULL_END Index: src/Client.h ================================================================== --- src/Client.h +++ src/Client.h @@ -1,10 +1,11 @@ #import #import "cube.h" // server side version of "dynent" type +OF_DIRECT_MEMBERS @interface Client: OFObject @property (nonatomic) int type; @property (nonatomic) ENetPeer *peer; @property (copy, nonatomic) OFString *hostname; @property (copy, nonatomic) OFString *mapvote; Index: src/Command.h ================================================================== --- src/Command.h +++ src/Command.h @@ -11,19 +11,20 @@ argumentsTypes:nargs \ block:block_]; \ }); \ } +OF_DIRECT_MEMBERS @interface Command: Identifier @property (readonly, nonatomic) int argumentsTypes; + (instancetype)commandWithName:(OFString *)name argumentsTypes:(int)argumentsTypes block:(id)block; - (instancetype)initWithName:(OFString *)name OF_UNAVAILABLE; - (instancetype)initWithName:(OFString *)name argumentsTypes:(int)argumentsTypes - block:(id)block; + block:(id)block OF_DESIGNATED_INITIALIZER; - (int)callWithArguments:(OFArray *)arguments isDown:(bool)isDown; @end OF_ASSUME_NONNULL_END Index: src/ConsoleLine.h ================================================================== --- src/ConsoleLine.h +++ src/ConsoleLine.h @@ -1,7 +1,8 @@ #import +OF_DIRECT_MEMBERS @interface ConsoleLine: OFObject @property (readonly, copy) OFString *text; @property (readonly) int outtime; + (instancetype)lineWithText:(OFString *)text outtime:(int)outtime; Index: src/DynamicEntity.h ================================================================== --- src/DynamicEntity.h +++ src/DynamicEntity.h @@ -1,40 +1,39 @@ #import // players & monsters @interface DynamicEntity: OFObject -@property (class, readonly, nonatomic) size_t serializedSize; +@property (class, direct, readonly, nonatomic) size_t serializedSize; -@property (nonatomic) OFVector3D origin, velocity; +@property (direct, nonatomic) OFVector3D origin, velocity; // used as OFVector3D in one place -@property (nonatomic) float yaw, pitch, roll; +@property (direct, nonatomic) float yaw, pitch, roll; // cubes per second, 24 for player -@property (nonatomic) float maxSpeed; +@property (direct, nonatomic) float maxSpeed; // from his eyes -@property (nonatomic) bool outsideMap; -@property (nonatomic) bool inWater; -@property (nonatomic) bool onFloor, jumpNext; -@property (nonatomic) int move, strafe; +@property (direct, nonatomic) bool outsideMap; +@property (direct, nonatomic) bool inWater; +@property (direct, nonatomic) bool onFloor, jumpNext; +@property (direct, nonatomic) int move, strafe; // see input code -@property (nonatomic) bool k_left, k_right, k_up, k_down; +@property (direct, nonatomic) bool k_left, k_right, k_up, k_down; // used for fake gravity -@property (nonatomic) int timeInAir; +@property (direct, nonatomic) int timeInAir; // bounding box size -@property (nonatomic) float radius, eyeHeight, aboveEye; -@property (nonatomic) int lastUpdate, lag, ping; +@property (direct, nonatomic) float radius, eyeHeight, aboveEye; +@property (direct, nonatomic) int lastUpdate, lag, ping; // one of CS_* below -@property (nonatomic) int state; -@property (nonatomic) int health, armour, armourType, quadMillis; -@property (nonatomic) int gunSelect, gunWait; -@property (nonatomic) int lastAction, lastAttackGun, lastMove; -@property (readonly, nonatomic) int *ammo; -@property (nonatomic) bool attacking; +@property (direct, nonatomic) int state; +@property (direct, nonatomic) int health, armour, armourType, quadMillis; +@property (direct, nonatomic) int gunSelect, gunWait; +@property (direct, nonatomic) int lastAction, lastAttackGun, lastMove; +@property (direct, readonly, nonatomic) int *ammo; +@property (direct, nonatomic) bool attacking; // used by physics to signal ai -@property (nonatomic) bool blocked, moving; -@property (copy, nonatomic) OFString *name; +@property (direct, nonatomic) bool blocked, moving; +@property (direct, copy, nonatomic) OFString *name; -+ (instancetype)entity; - (OFData *)dataBySerializing; - (void)setFromSerializedData:(OFData *)data; - (void)resetMovement; // reset player state not persistent accross spawns - (void)resetToSpawnState; Index: src/Entity.h ================================================================== --- src/Entity.h +++ src/Entity.h @@ -1,8 +1,9 @@ #import // map entity +OF_DIRECT_MEMBERS @interface Entity: OFObject @property (nonatomic) short x, y, z; // cube aligned position @property (nonatomic) short attr1; @property (nonatomic) unsigned char type; // type is one of the above @property (nonatomic) unsigned char attr2, attr3, attr4; Index: src/Identifier.h ================================================================== --- src/Identifier.h +++ src/Identifier.h @@ -1,12 +1,12 @@ #import OF_ASSUME_NONNULL_BEGIN @interface Identifier: OFObject -@property (readonly, copy, nonatomic) OFString *name; -@property (class, readonly, nonatomic) +@property (direct, readonly, copy, nonatomic) OFString *name; +@property (class, direct, readonly, nonatomic) OFMutableDictionary *identifiers; - (instancetype)init OF_UNAVAILABLE; - (instancetype)initWithName:(OFString *)name; @end Index: src/KeyMapping.h ================================================================== --- src/KeyMapping.h +++ src/KeyMapping.h @@ -1,9 +1,10 @@ #import OF_ASSUME_NONNULL_BEGIN +OF_DIRECT_MEMBERS @interface KeyMapping: OFObject @property (readonly) int code; @property (readonly, nonatomic) OFString *name; @property (copy, nonatomic) OFString *action; Index: src/MD2.h ================================================================== --- src/MD2.h +++ src/MD2.h @@ -2,10 +2,11 @@ OF_ASSUME_NONNULL_BEGIN @class MapModelInfo; +OF_DIRECT_MEMBERS @interface MD2: OFObject @property (nonatomic) MapModelInfo *mmi; @property (copy, nonatomic) OFString *loadname; @property (nonatomic) int mdlnum; @property (nonatomic) bool loaded; Index: src/MapModelInfo.h ================================================================== --- src/MapModelInfo.h +++ src/MapModelInfo.h @@ -1,9 +1,10 @@ #import OF_ASSUME_NONNULL_BEGIN +OF_DIRECT_MEMBERS @interface MapModelInfo: OFObject @property (nonatomic) int rad, h, zoff, snap; @property (copy, nonatomic) OFString *name; + (instancetype)infoWithRad:(int)rad Index: src/Menu.h ================================================================== --- src/Menu.h +++ src/Menu.h @@ -2,10 +2,11 @@ OF_ASSUME_NONNULL_BEGIN @class MenuItem; +OF_DIRECT_MEMBERS @interface Menu: OFObject @property (readonly, nonatomic) OFString *name; @property (readonly) OFMutableArray *items; @property (nonatomic) int mwidth; @property (nonatomic) int menusel; Index: src/MenuItem.h ================================================================== --- src/MenuItem.h +++ src/MenuItem.h @@ -1,7 +1,8 @@ #import +OF_DIRECT_MEMBERS @interface MenuItem: OFObject @property (readonly, nonatomic) OFString *text, *action; + (instancetype)itemWithText:(OFString *)text action:(OFString *)action; - (instancetype)init OF_UNAVAILABLE; Index: src/Monster.h ================================================================== --- src/Monster.h +++ src/Monster.h @@ -1,7 +1,8 @@ #import "DynamicEntity.h" +OF_DIRECT_MEMBERS @interface Monster: DynamicEntity @property (class, readonly, nonatomic) OFMutableArray *monsters; // one of M_* @property (nonatomic) int monsterState; // see Monster.m Index: src/OFString+Cube.h ================================================================== --- src/OFString+Cube.h +++ src/OFString+Cube.h @@ -1,7 +1,8 @@ #import +OF_DIRECT_MEMBERS @interface OFString (Cube) @property (readonly, nonatomic) int cube_intValue; - (int)cube_intValueWithBase:(unsigned char)base; Index: src/Player.h ================================================================== --- src/Player.h +++ src/Player.h @@ -1,7 +1,8 @@ #import "DynamicEntity.h" +OF_DIRECT_MEMBERS @interface Player: DynamicEntity // special client ent that receives input and acts as camera @property (class, nonatomic) Player *player1; // sequence id for each respawn, used in damage test @property (nonatomic) int lifeSequence; Index: src/Projectile.h ================================================================== --- src/Projectile.h +++ src/Projectile.h @@ -1,9 +1,10 @@ #import @class DynamicEntity; +OF_DIRECT_MEMBERS @interface Projectile: OFObject @property (nonatomic) OFVector3D o, to; @property (nonatomic) float speed; @property (nonatomic) DynamicEntity *owner; @property (nonatomic) int gun; Index: src/ResolverResult.h ================================================================== --- src/ResolverResult.h +++ src/ResolverResult.h @@ -1,9 +1,10 @@ #import #import "cube.h" +OF_DIRECT_MEMBERS @interface ResolverResult: OFObject @property (readonly, nonatomic) OFString *query; @property (readonly, nonatomic) ENetAddress address; + (instancetype)resultWithQuery:(OFString *)query address:(ENetAddress)address; Index: src/ResolverThread.h ================================================================== --- src/ResolverThread.h +++ src/ResolverThread.h @@ -1,7 +1,8 @@ #import +OF_DIRECT_MEMBERS @interface ResolverThread: OFThread { volatile bool _stop; } Index: src/ServerEntity.h ================================================================== --- src/ServerEntity.h +++ src/ServerEntity.h @@ -1,8 +1,9 @@ #import // server side version of "entity" type +OF_DIRECT_MEMBERS @interface ServerEntity: OFObject @property (nonatomic) bool spawned; @property (nonatomic) int spawnsecs; + (instancetype)entity; Index: src/ServerInfo.h ================================================================== --- src/ServerInfo.h +++ src/ServerInfo.h @@ -1,9 +1,10 @@ #import #include +OF_DIRECT_MEMBERS @interface ServerInfo: OFObject @property (readonly, nonatomic) OFString *name; @property (copy, nonatomic) OFString *full; @property (copy, nonatomic) OFString *map; @property (copy, nonatomic) OFString *sdesc; Index: src/ServerInfo.m ================================================================== --- src/ServerInfo.m +++ src/ServerInfo.m @@ -25,18 +25,18 @@ _address.port = CUBE_SERVINFO_PORT; return self; } -- (OFComparisonResult)compare:(id)otherObject +- (OFComparisonResult)compare:(ServerInfo *)otherObject { if (![otherObject isKindOfClass:ServerInfo.class]) @throw [OFInvalidArgumentException exception]; - if (_ping > [otherObject ping]) + if (_ping > otherObject.ping) return OFOrderedDescending; - if (_ping < [otherObject ping]) + if (_ping < otherObject.ping) return OFOrderedAscending; - return [_name compare:[otherObject name]]; + return [_name compare:otherObject.name]; } @end Index: src/Variable.h ================================================================== --- src/Variable.h +++ src/Variable.h @@ -72,28 +72,29 @@ } \ \ static void var_##name() { body; } @interface Variable: Identifier -@property (readonly, nonatomic) int min, max; -@property (readonly, nonatomic) int *storage; -@property (readonly, nullable, nonatomic) void (*function)(); +@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; + (instancetype)variableWithName:(OFString *)name min:(int)min max:(int)max storage:(int *)storage function:(void (*_Nullable)())function - persisted:(bool)persisted; + persisted:(bool)persisted 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; -- (void)printValue; -- (void)setValue:(int)value; + persisted:(bool)persisted OF_DESIGNATED_INITIALIZER + OF_DIRECT; +- (void)printValue OF_DIRECT; +- (void)setValue:(int)value OF_DIRECT; @end OF_ASSUME_NONNULL_END Index: src/clientextras.m ================================================================== --- src/clientextras.m +++ src/clientextras.m @@ -84,17 +84,18 @@ extern int democlientnum; void renderclients() { - [players enumerateObjectsUsingBlock:^(id player, size_t i, bool *stop) { - if (player != [OFNull null] && - (!demoplayback || i != democlientnum)) - renderclient(player, - isteam(Player.player1.team, [player team]), - @"monster/ogro", false, 1.0f); - }]; + [players + enumerateObjectsUsingBlock:^(Player *player, size_t i, bool *stop) { + if ([player isKindOfClass:Player.class] && + (!demoplayback || i != democlientnum)) + renderclient(player, + isteam(Player.player1.team, [player team]), + @"monster/ogro", false, 1.0f); + }]; } // creation of scoreboard pseudo-menu bool scoreson = false; Index: src/clientgame.m ================================================================== --- src/clientgame.m +++ src/clientgame.m @@ -415,13 +415,13 @@ [Monster resetAll]; projreset(); spawncycle = -1; spawnplayer(Player.player1); Player.player1.frags = 0; - for (id player in players) - if (player != [OFNull null]) - [player setFrags:0]; + for (Player *player in players) + if ([player isKindOfClass:Player.class]) + player.frags = 0; resetspawns(); clientmap = name; if (editmode) toggleedit(); setvar(@"gamespeed", 100); Index: src/clients2c.m ================================================================== --- src/clients2c.m +++ src/clients2c.m @@ -277,11 +277,12 @@ d_.lifeSequence++; break; } case SV_FRAGS: - [players[cn] setFrags:getint(&p)]; + OFAssert([players[cn] isKindOfClass:Player.class]); + ((Player *)players[cn]).frags = getint(&p); break; case SV_ITEMPICKUP: setspawn(getint(&p), false); getint(&p); @@ -369,11 +370,12 @@ lastmillis - getint(&p)) / 6); break; case SV_CLIENTPING: - [players[cn] setPing:getint(&p)]; + OFAssert([players[cn] isKindOfClass:Player.class]); + ((Player *)players[cn]).ping = getint(&p); break; case SV_GAMEMODE: nextmode = getint(&p); break; Index: src/cube.h ================================================================== --- src/cube.h +++ src/cube.h @@ -10,10 +10,11 @@ @class DynamicEntity; @class Entity; @class Player; +OF_DIRECT_MEMBERS @interface Cube: OFObject @property (class, readonly, nonatomic) Cube *sharedInstance; @property (readonly, nonatomic) SDL_Window *window; @property (readonly, nonatomic) OFIRI *gameDataIRI, *userDataIRI; @property (nonatomic) bool repeatsKeys; Index: src/meson.build ================================================================== --- src/meson.build +++ src/meson.build @@ -68,10 +68,11 @@ win_subsystem: 'windows') executable('server', [ 'Client.m', + 'Entity.m', 'ServerEntity.m', 'server.m', 'serverms.m', 'serverutil.m', 'tools.m',