Cube  Check-in [7a98b92af9]

Overview
Comment:Make use of OF_DIRECT
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: 7a98b92af94db34093428fc95da00435311c270d74135e69aa94bca16871a023
User & Date: js on 2025-03-25 23:52:50.704
Other Links: manifest | tags
Context
2025-03-26
21:44
Remove OF_DIRECT_MEMBERS from category check-in: 5bca00e8e2 user: js tags: trunk
2025-03-25
23:52
Make use of OF_DIRECT check-in: 7a98b92af9 user: js tags: trunk
23:38
Clean up Variable check-in: 0ee94739ce user: js tags: trunk
Changes
1
2
3
4
5
6

7
8
9
10
11

12
13
14
15


16
17
18
1
2
3
4
5

6
7
8
9
10

11
12
13
14

15
16
17
18
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
1
2
3
4
5

6
7
8
9
10
11
12
1
2
3
4
5
6
7
8
9
10
11
12
13





+







#import <ObjFW/ObjFW.h>

#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;
@property (copy, nonatomic) OFString *name;
@property (nonatomic) int modevote;
9
10
11
12
13
14
15

16
17
18
19
20
21
22
23
24
25

26
27
28
29
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

26
27
28
29
30







+









-
+




			Identifier.identifiers[@ #name] =     \
			    [Command commandWithName:@ #name  \
			              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<OFString *> *)arguments isDown:(bool)isDown;
@end

OF_ASSUME_NONNULL_END
1
2

3
4
5
6
7
8
9
1
2
3
4
5
6
7
8
9
10


+







#import <ObjFW/ObjFW.h>

OF_DIRECT_MEMBERS
@interface ConsoleLine: OFObject
@property (readonly, copy) OFString *text;
@property (readonly) int outtime;

+ (instancetype)lineWithText:(OFString *)text outtime:(int)outtime;
- (instancetype)initWithText:(OFString *)text outtime:(int)outtime;
@end
1
2
3
4
5

6
7

8
9

10
11

12
13
14
15
16




17
18

19
20

21
22
23


24
25
26
27
28
29
30






31
32
33


34
35
36
37
38
39
40
41
1
2
3
4

5
6

7
8

9
10

11
12




13
14
15
16
17

18
19

20
21


22
23
24






25
26
27
28
29
30
31


32
33
34

35
36
37
38
39
40




-
+

-
+

-
+

-
+

-
-
-
-
+
+
+
+

-
+

-
+

-
-
+
+

-
-
-
-
-
-
+
+
+
+
+
+

-
-
+
+

-






#import <ObjFW/ObjFW.h>

// players & monsters
@interface DynamicEntity: OFObject <OFCopying>
@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;
@end
1
2
3

4
5
6
7
8
9
10
1
2
3
4
5
6
7
8
9
10
11



+







#import <ObjFW/ObjFW.h>

// 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;
@property (nonatomic) bool spawned;

1
2
3
4
5
6
7


8
9
10
11
12
13
14
1
2
3
4
5


6
7
8
9
10
11
12
13
14





-
-
+
+







#import <ObjFW/ObjFW.h>

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<OFString *, __kindof Identifier *> *identifiers;

- (instancetype)init OF_UNAVAILABLE;
- (instancetype)initWithName:(OFString *)name;
@end

OF_ASSUME_NONNULL_END
1
2
3
4

5
6
7
8
9
10
11
1
2
3
4
5
6
7
8
9
10
11
12




+







#import <ObjFW/ObjFW.h>

OF_ASSUME_NONNULL_BEGIN

OF_DIRECT_MEMBERS
@interface KeyMapping: OFObject
@property (readonly) int code;
@property (readonly, nonatomic) OFString *name;
@property (copy, nonatomic) OFString *action;

+ (instancetype)mappingWithCode:(int)code name:(OFString *)name;
- (instancetype)init OF_UNAVAILABLE;
Modified src/MD2.h from [56302384a5] to [738081230a].
1
2
3
4
5
6

7
8
9
10
11
12
13
1
2
3
4
5
6
7
8
9
10
11
12
13
14






+







#import <ObjFW/ObjFW.h>

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;

+ (instancetype)md2;
1
2
3
4

5
6
7
8
9
10
11
1
2
3
4
5
6
7
8
9
10
11
12




+







#import <ObjFW/ObjFW.h>

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
                          h:(int)h
                       zoff:(int)zoff
1
2
3
4
5
6

7
8
9
10
11
12
13
1
2
3
4
5
6
7
8
9
10
11
12
13
14






+







#import <ObjFW/ObjFW.h>

OF_ASSUME_NONNULL_BEGIN

@class MenuItem;

OF_DIRECT_MEMBERS
@interface Menu: OFObject
@property (readonly, nonatomic) OFString *name;
@property (readonly) OFMutableArray<MenuItem *> *items;
@property (nonatomic) int mwidth;
@property (nonatomic) int menusel;

+ (instancetype)menuWithName:(OFString *)name;
1
2

3
4
5
6
7
8
9
1
2
3
4
5
6
7
8
9
10


+







#import <ObjFW/ObjFW.h>

OF_DIRECT_MEMBERS
@interface MenuItem: OFObject
@property (readonly, nonatomic) OFString *text, *action;

+ (instancetype)itemWithText:(OFString *)text action:(OFString *)action;
- (instancetype)init OF_UNAVAILABLE;
- (instancetype)initWithText:(OFString *)text action:(OFString *)action;
@end
1
2

3
4
5
6
7
8
9
1
2
3
4
5
6
7
8
9
10


+







#import "DynamicEntity.h"

OF_DIRECT_MEMBERS
@interface Monster: DynamicEntity
@property (class, readonly, nonatomic) OFMutableArray<Monster *> *monsters;
// one of M_*
@property (nonatomic) int monsterState;
// see Monster.m
@property (nonatomic) int monsterType;
// monster wants to kill this entity
1
2

3
4
5
6
7
8
1
2
3
4
5
6
7
8
9


+






#import <ObjFW/ObjFW.h>

OF_DIRECT_MEMBERS
@interface
OFString (Cube)
@property (readonly, nonatomic) int cube_intValue;

- (int)cube_intValueWithBase:(unsigned char)base;
@end
1
2

3
4
5
6
7
8
9
1
2
3
4
5
6
7
8
9
10


+







#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;
@property (nonatomic) int frags;
@property (copy, nonatomic) OFString *team;
1
2
3
4

5
6
7
8
9
10
11
1
2
3
4
5
6
7
8
9
10
11
12




+







#import <ObjFW/ObjFW.h>

@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;
@property (nonatomic) bool inuse, local;

1
2
3
4

5
6
7
8
9
10
11
1
2
3
4
5
6
7
8
9
10
11
12




+







#import <ObjFW/ObjFW.h>

#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;
- (instancetype)init OF_UNAVAILABLE;
- (instancetype)initWithQuery:(OFString *)query address:(ENetAddress)address;
1
2

3
4
5
6
7
8
9
1
2
3
4
5
6
7
8
9
10


+







#import <ObjFW/ObjFW.h>

OF_DIRECT_MEMBERS
@interface ResolverThread: OFThread
{
	volatile bool _stop;
}

@property (copy, nonatomic) OFString *query;
@property (nonatomic) int starttime;
1
2
3

4
5
6
7
8
9
1
2
3
4
5
6
7
8
9
10



+






#import <ObjFW/ObjFW.h>

// server side version of "entity" type
OF_DIRECT_MEMBERS
@interface ServerEntity: OFObject
@property (nonatomic) bool spawned;
@property (nonatomic) int spawnsecs;

+ (instancetype)entity;
@end
1
2
3
4

5
6
7
8
9
10
11
1
2
3
4
5
6
7
8
9
10
11
12




+







#import <ObjFW/ObjFW.h>

#include <enet/enet.h>

OF_DIRECT_MEMBERS
@interface ServerInfo: OFObject <OFComparing>
@property (readonly, nonatomic) OFString *name;
@property (copy, nonatomic) OFString *full;
@property (copy, nonatomic) OFString *map;
@property (copy, nonatomic) OFString *sdesc;
@property (nonatomic) int mode, numplayers, ping, protocol, minremain;
@property (nonatomic) ENetAddress address;
23
24
25
26
27
28
29
30

31
32
33
34
35

36
37

38
39
40

41
42
23
24
25
26
27
28
29

30
31
32
33
34

35
36

37
38
39

40
41
42







-
+




-
+

-
+


-
+


	_sdesc = @"";
	_address.host = ENET_HOST_ANY;
	_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
70
71
72
73
74
75
76
77
78
79



80
81
82
83
84
85
86
87

88
89
90
91
92
93
94
95
96




97
98
99
70
71
72
73
74
75
76



77
78
79
80
81
82
83
84
85
86

87
88
89
90
91
92
93



94
95
96
97
98
99
100







-
-
-
+
+
+







-
+






-
-
-
+
+
+
+



			Identifier.identifiers[@ #name] = variable; \
		});                                                 \
	}                                                           \
                                                                    \
	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
82
83
84
85
86
87
88

89
90
91
92
93
94
95







96
97
98
99
100
101
102
82
83
84
85
86
87
88
89







90
91
92
93
94
95
96
97
98
99
100
101
102
103







+
-
-
-
-
-
-
-
+
+
+
+
+
+
+







}

extern int democlientnum;

void
renderclients()
{
	[players
	[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);
	}];
	    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;

void
413
414
415
416
417
418
419
420
421
422



423
424
425
426
427
428
429
413
414
415
416
417
418
419



420
421
422
423
424
425
426
427
428
429







-
-
-
+
+
+







	}
	sleepwait = 0;
	[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);
	setvar(@"fog", 180);
	setvar(@"fogcolour", 0x8099B3);
275
276
277
278
279
280
281
282


283
284
285
286
287
288
289
275
276
277
278
279
280
281

282
283
284
285
286
287
288
289
290







-
+
+







			OFVector3D loc = d_.origin;
			playsound(S_DIE1 + rnd(2), &loc);
			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);
			break;

367
368
369
370
371
372
373
374


375
376
377
378
379
380
381
368
369
370
371
372
373
374

375
376
377
378
379
380
381
382
383







-
+
+







			addmsg(0, 2, SV_CLIENTPING,
			    Player.player1.ping = (Player.player1.ping * 5 +
			                              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;

		case SV_TIMEUP:
8
9
10
11
12
13
14

15
16
17
18
19
20
21
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22







+








#define _MAXDEFSTR 260

@class DynamicEntity;
@class Entity;
@class Player;

OF_DIRECT_MEMBERS
@interface Cube: OFObject <OFApplicationDelegate>
@property (class, readonly, nonatomic) Cube *sharedInstance;
@property (readonly, nonatomic) SDL_Window *window;
@property (readonly, nonatomic) OFIRI *gameDataIRI, *userDataIRI;
@property (nonatomic) bool repeatsKeys;
@property (nonatomic) int framesInMap;
@end
66
67
68
69
70
71
72

73
74
75
76
77
78
79
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80







+







  link_args: client_link_args,
  link_with: [enet],
  win_subsystem: 'windows')

executable('server',
  [
    'Client.m',
    'Entity.m',
    'ServerEntity.m',
    'server.m',
    'serverms.m',
    'serverutil.m',
    'tools.m',
  ],
  objc_args: ['-DSTANDALONE'],