Cube  Check-in [89fbd7a152]

Overview
Comment:Make more use of convenience methods
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: 89fbd7a1520ecb65809b4c1bd10006ce9bb3a662cb7e7804abaf85d1ee1da63a
User & Date: js on 2025-03-20 13:21:56
Other Links: manifest | tags
Context
2025-03-20
16:04
Convert entity to a class check-in: 4b002822f9 user: js tags: trunk
13:21
Make more use of convenience methods check-in: 89fbd7a152 user: js tags: trunk
11:03
Use enumerateObjectsUsingBlock: where appropriate check-in: fd4460c7b6 user: js tags: trunk
Changes

Modified src/Alias.h from [6c97091132] to [12efdce9a2].

1
2
3
4
5
6
7
8



9
10
11
12
13
14
15
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18








+
+
+







#import "Identifier.h"

OF_ASSUME_NONNULL_BEGIN

@interface Alias: Identifier
@property (copy, nonatomic) OFString *action;
@property (readonly, nonatomic) bool persisted;

+ (instancetype)aliasWithName:(OFString *)name
                       action:(OFString *)action
                    persisted:(bool)persisted;
- (instancetype)initWithName:(OFString *)name OF_UNAVAILABLE;
- (instancetype)initWithName:(OFString *)name
                      action:(OFString *)action
                   persisted:(bool)persisted;
@end

OF_ASSUME_NONNULL_END

Modified src/Alias.m from [2901519ebd] to [dce3b067a2].

1
2
3









4
5
6
7
8
9
10
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19



+
+
+
+
+
+
+
+
+







#import "Alias.h"

@implementation Alias
+ (instancetype)aliasWithName:(OFString *)name
                       action:(OFString *)action
                    persisted:(bool)persisted;
{
	return [[self alloc] initWithName:name
	                           action:action
	                        persisted:persisted];
}

- (instancetype)initWithName:(OFString *)name
                      action:(OFString *)action
                   persisted:(bool)persisted
{
	self = [super initWithName:name];

	_action = [action copy];

Added src/Client.h version [3002aefde8].

Added src/Client.mm version [432ce6fc62].

Modified src/Command.h from [e066e0d794] to [e984d89122].

1
2
3
4
5
6
7
8



9
10
11
12
13
14
15
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18








+
+
+







#import "Identifier.h"

OF_ASSUME_NONNULL_BEGIN

@interface Command: Identifier
@property (readonly, nonatomic) void (*function)();
@property (readonly, nonatomic) int argumentsTypes;

+ (instancetype)commandWithName:(OFString *)name
                       function:(void (*)())function
                 argumentsTypes:(int)argumentsTypes;
- (instancetype)initWithName:(OFString *)name OF_UNAVAILABLE;
- (instancetype)initWithName:(OFString *)name
                    function:(void (*)())function
              argumentsTypes:(int)argumentsTypes;
- (int)callWithArguments:(OFArray<OFString *> *)arguments isDown:(bool)isDown;
@end

Modified src/Command.mm from [16592a90b0] to [ca8bd2ebde].

16
17
18
19
20
21
22









23
24
25
26
27
28
29
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38







+
+
+
+
+
+
+
+
+







		[copy addObject:@""];

	[copy makeImmutable];
	return copy;
}

@implementation Command
+ (instancetype)commandWithName:(OFString *)name
                       function:(void (*)())function
                 argumentsTypes:(int)argumentsTypes
{
	return [[self alloc] initWithName:name
	                         function:function
	                   argumentsTypes:argumentsTypes];
}

- (instancetype)initWithName:(OFString *)name
                    function:(void (*)())function
              argumentsTypes:(int)argumentsTypes
{
	self = [super initWithName:name];

	_function = function;

Added src/ConsoleLine.h version [a5636ed577].

Added src/ConsoleLine.m version [8c83ebcd46].

Modified src/KeyMapping.h from [995386e6ec] to [4403af7dfe].

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
15









+
+




#import <ObjFW/ObjFW.h>

OF_ASSUME_NONNULL_BEGIN

@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;
- (instancetype)initWithCode:(int)code name:(OFString *)name;
@end

OF_ASSUME_NONNULL_END

Modified src/KeyMapping.m from [c90f999690] to [49eed66821].

1
2
3





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



+
+
+
+
+







#import "KeyMapping.h"

@implementation KeyMapping
+ (instancetype)mappingWithCode:(int)code name:(OFString *)name
{
	return [[self alloc] initWithCode:code name:name];
}

- (instancetype)initWithCode:(int)code name:(OFString *)name
{
	self = [super init];

	_code = code;
	_name = [name copy];

Modified src/MD2.h from [3eecbab1e8] to [abc59220a9].

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
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












+




-
+
-
-







#import <ObjFW/ObjFW.h>

OF_ASSUME_NONNULL_BEGIN

@class MapModelInfo;

@interface MD2: OFObject
@property (nonatomic) MapModelInfo *mmi;
@property (copy, nonatomic) OFString *loadname;
@property (nonatomic) int mdlnum;
@property (nonatomic) bool loaded;

+ (instancetype)md2;
- (bool)loadWithIRI:(OFIRI *)IRI;
- (void)renderWithLight:(OFVector3D)light
                  frame:(int)frame
                  range:(int)range
                      x:(float)x
               position:(OFVector3D)position
                      y:(float)y
                      z:(float)z
                    yaw:(float)yaw
                  pitch:(float)pitch
                  scale:(float)scale
                  speed:(float)speed
                   snap:(int)snap
               basetime:(int)basetime;
- (void)scaleWithFrame:(int)frame scale:(float)scale snap:(int)snap;

Modified src/MD2.mm from [4b55922953] to [3c502ddbf2].

39
40
41
42
43
44
45





46
47
48
49
50
51
52
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57







+
+
+
+
+







	int _numFrames;
	int _numVerts;
	char *_frames;
	OFVector3D **_mverts;
	int _displaylist;
	int _displaylistverts;
}

+ (instancetype)md2
{
	return [[self alloc] init];
}

- (void)dealloc
{
	if (_glCommands)
		delete[] _glCommands;
	if (_frames)
		delete[] _frames;
122
123
124
125
126
127
128
129

130
131
132
133
134
135
136
137
138
139
140
141
142
143
144

145
146
147
148
149
150
151
127
128
129
130
131
132
133

134


135
136
137
138
139
140
141
142
143
144
145
146

147
148
149
150
151
152
153
154







-
+
-
-












-
+







		v->z = (snap(sn, cv[2] * cf->scale[2]) + cf->translate[2]) / sc;
	}
}

- (void)renderWithLight:(OFVector3D)light
                  frame:(int)frame
                  range:(int)range
                      x:(float)x
               position:(OFVector3D)position
                      y:(float)y
                      z:(float)z
                    yaw:(float)yaw
                  pitch:(float)pitch
                  scale:(float)sc
                  speed:(float)speed
                   snap:(int)sn
               basetime:(int)basetime
{
	loopi(range) if (!_mverts[frame + i])[self scaleWithFrame:frame + i
	                                                    scale:sc
	                                                     snap:sn];

	glPushMatrix();
	glTranslatef(x, y, z);
	glTranslatef(position.x, position.y, position.z);
	glRotatef(yaw + 180, 0, -1, 0);
	glRotatef(pitch, 0, 0, 1);

	glColor3fv((float *)&light);

	if (_displaylist && frame == 0 && range == 1) {
		glCallList(_displaylist);

Modified src/MapModelInfo.h from [5ed60ec67c] to [2be3bcf086].

1
2
3
4
5
6
7
8






9
10
11
12
13
14
15
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21








+
+
+
+
+
+







#import <ObjFW/ObjFW.h>

OF_ASSUME_NONNULL_BEGIN

@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
                       snap:(int)snap
                       name:(OFString *)name;
- (instancetype)init OF_UNAVAILABLE;
- (instancetype)initWithRad:(int)rad
                          h:(int)h
                       zoff:(int)zoff
                       snap:(int)snap
                       name:(OFString *)name;
@end

Modified src/MapModelInfo.m from [a1a57242f0] to [d506409929].

1
2
3









4
5
6
7
8
9
10
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19



+
+
+
+
+
+
+
+
+







#import "MapModelInfo.h"

@implementation MapModelInfo
+ (instancetype)infoWithRad:(int)rad
                          h:(int)h
                       zoff:(int)zoff
                       snap:(int)snap
                       name:(OFString *)name
{
	return [[self alloc] initWithRad:rad h:h zoff:zoff snap:snap name:name];
}

- (instancetype)initWithRad:(int)rad
                          h:(int)h
                       zoff:(int)zoff
                       snap:(int)snap
                       name:(OFString *)name
{
	self = [super init];

Modified src/Menu.h from [5fa014f8d6] to [d8e35c6745].

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


13
14
15
16
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18












+
+




#import <ObjFW/ObjFW.h>

OF_ASSUME_NONNULL_BEGIN

@class MenuItem;

@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;
- (instancetype)init OF_UNAVAILABLE;
- (instancetype)initWithName:(OFString *)name;
@end

OF_ASSUME_NONNULL_END

Modified src/Menu.m from [bdc2f1f706] to [e5fbce3936].

1
2
3





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



+
+
+
+
+







#import "Menu.h"

@implementation Menu
+ (instancetype)menuWithName:(OFString *)name
{
	return [[self alloc] initWithName:name];
}

- (instancetype)initWithName:(OFString *)name
{
	self = [super init];

	_name = [name copy];
	_items = [[OFMutableArray alloc] init];

Modified src/MenuItem.h from [3f56310839] to [237d14ade3].

1
2
3
4
5


6
7
1
2
3
4
5
6
7
8
9





+
+


#import <ObjFW/ObjFW.h>

@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

Modified src/MenuItem.m from [2a6ad46c6d] to [5ee318d452].

1
2
3





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



+
+
+
+
+







#import "MenuItem.h"

@implementation MenuItem
+ (instancetype)itemWithText:(OFString *)text action:(OFString *)action
{
	return [[self alloc] initWithText:text action:action];
}

- (instancetype)initWithText:(OFString *)text action:(OFString *)action
{
	self = [super init];

	_text = [text copy];
	_action = [action copy];

Modified src/Projectile.h from [f3375dc858] to [03669c69fe].

1
2
3
4
5
6
7
8
9
10


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










+
+

#import <ObjFW/ObjFW.h>

@class DynamicEntity;

@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;

+ (instancetype)projectile;
@end

Modified src/Projectile.m from [902fed7b64] to [f2a969a0fa].

1
2
3




4
1
2
3
4
5
6
7
8



+
+
+
+

#import "Projectile.h"

@implementation Projectile
+ (instancetype)projectile
{
	return [[self alloc] init];
}
@end

Added src/ResolverResult.h version [7ec5a5a420].

Added src/ResolverResult.mm version [36dcd5aa96].

Added src/ResolverThread.h version [648d3b8e86].

Added src/ResolverThread.mm version [5a480794ce].

Modified src/ServerInfo.h from [fa8f02f977] to [3ffaecefa4].

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

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












+



#import <ObjFW/ObjFW.h>

#include <enet/enet.h>

@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;

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

Modified src/ServerInfo.mm from [4b142ee758] to [d173cecbd6].

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
14
15
16
17





+
+
+
+
+







#import "ServerInfo.h"

#include "cube.h"

@implementation ServerInfo
+ (instancetype)infoWithName:(OFString *)name;
{
	return [[self alloc] initWithName:name];
}

- (instancetype)initWithName:(OFString *)name
{
	self = [super init];

	_name = [name copy];
	_full = @"";
	_mode = 0;

Modified src/Variable.h from [82779ddfda] to [1fe61b3c20].

1
2
3
4
5
6
7
8
9
10






11
12
13
14
15
16
17
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23










+
+
+
+
+
+







#import "Identifier.h"

OF_ASSUME_NONNULL_BEGIN

@interface Variable: Identifier
@property (readonly, nonatomic) int min, max;
@property (readonly, nonatomic) int *storage;
@property (readonly, nonatomic) void (*__cdecl function)();
@property (readonly, nonatomic) bool persisted;

+ (instancetype)variableWithName:(OFString *)name
                             min:(int)min
                             max:(int)max
                         storage:(int *)storage
                        function:(void (*__cdecl)())function
                       persisted:(bool)persisted;
- (instancetype)initWithName:(OFString *)name OF_UNAVAILABLE;
- (instancetype)initWithName:(OFString *)name
                         min:(int)min
                         max:(int)max
                     storage:(int *)storage
                    function:(void (*__cdecl)())function
                   persisted:(bool)persisted;

Modified src/Variable.mm from [a7099f1853] to [eb5893de54].

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
14
15
16
17
18
19
20
21
22
23
24
25
26
27





+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







#import "Variable.h"

#include "cube.h"

@implementation Variable
+ (instancetype)variableWithName:(OFString *)name
                             min:(int)min
                             max:(int)max
                         storage:(int *)storage
                        function:(void (*__cdecl)())function
                       persisted:(bool)persisted
{
	return [[self alloc] initWithName:name
	                              min:min
	                              max:max
	                          storage:storage
	                         function:function
	                        persisted:persisted];
}

- (instancetype)initWithName:(OFString *)name
                         min:(int)min
                         max:(int)max
                     storage:(int *)storage
                    function:(void (*__cdecl)())function
                   persisted:(bool)persisted
{

Modified src/clientextras.mm from [d40925e827] to [6b3acabfcd].

67
68
69
70
71
72
73
74
75



76
77
78
79
80
81
82
67
68
69
70
71
72
73


74
75
76
77
78
79
80
81
82
83







-
-
+
+
+







			speed = 300 / d.maxspeed;
	}
	if (hellpig) {
		n++;
		scale *= 32;
		mz -= 1.9f;
	}
	rendermodel(mdlname, frame[n], range[n], 0, 1.5f, d.o.x, mz, d.o.y,
	    d.yaw + 90, d.pitch / 2, team, scale, speed, 0, basetime);
	rendermodel(mdlname, frame[n], range[n], 0, 1.5f,
	    OFMakeVector3D(d.o.x, mz, d.o.y), d.yaw + 90, d.pitch / 2, team,
	    scale, speed, 0, basetime);
}

extern int democlientnum;

void
renderclients()
{
157
158
159
160
161
162
163
164

165
166
167
168
169
170
171
158
159
160
161
162
163
164

165
166
167
168
169
170
171
172







-
+







	if (m_teammode) {
		teamsUsed = 0;
		for (id player in players)
			if (player != [OFNull null])
				addteamscore(player);
		if (!demoplayback)
			addteamscore(player1);
		OFMutableString *teamScores = [[OFMutableString alloc] init];
		OFMutableString *teamScores = [OFMutableString string];
		for (size_t j = 0; j < teamsUsed; j++)
			[teamScores appendFormat:@"[ %@: %d ]", teamName[j],
			            teamScore[j]];
		menumanual(0, scoreLines.count, @"");
		menumanual(0, scoreLines.count + 1, teamScores);
	}
}

Modified src/clientgame.mm from [75ba298a0a] to [bec4825c49].

467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
467
468
469
470
471
472
473


474
475
476
477
478
479
480
481
482
483
484


485
486
487
488
489
490
491







-
-











-
-







DynamicEntity *
getclient(int cn) // ensure valid entity
{
	if (cn < 0 || cn >= MAXCLIENTS) {
		neterr(@"clientnum");
		return nil;
	}
	if (players == nil)
		players = [[OFMutableArray alloc] init];
	while (cn >= players.count)
		[players addObject:[OFNull null]];
	return (players[cn] != [OFNull null] ? players[cn]
	                                     : (players[cn] = newdynent()));
}

void
setclient(int cn, id client)
{
	if (cn < 0 || cn >= MAXCLIENTS)
		neterr(@"clientnum");
	if (players == nil)
		players = [[OFMutableArray alloc] init];
	while (cn >= players.count)
		[players addObject:[OFNull null]];
	players[cn] = client;
}

void
initclient()

Name change from src/client.mm to src/clients.mm.

Modified src/commands.mm from [8783bcd63b] to [586613b4e5].

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
42
43
44
45
46
47
48
49
50






51
52
53
54
55
56
57
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
42






43
44
45
46
47
48
49
50
51
52
53
54
55







-
-
-
+



















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








void
alias(OFString *name, OFString *action)
{
	Alias *alias = identifiers[name];

	if (alias == nil) {
		alias = [[Alias alloc] initWithName:name
		                             action:action
		                          persisted:true];
		alias = [Alias aliasWithName:name action:action persisted:true];

		if (identifiers == nil)
			identifiers = [[OFMutableDictionary alloc] init];

		identifiers[name] = alias;
	} else {
		if ([alias isKindOfClass:Alias.class])
			alias.action = action;
		else
			conoutf(
			    @"cannot redefine builtin %@ with an alias", name);
	}
}
COMMAND(alias, ARG_2STR)

int
variable(OFString *name, int min, int cur, int max, int *storage,
    void (*function)(), bool persisted)
{
	Variable *variable = [[Variable alloc] initWithName:name
	                                                min:min
	                                                max:max
	                                            storage:storage
	                                           function:function
	                                          persisted: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;

	return cur;
85
86
87
88
89
90
91
92
93
94



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



90
91
92
93
94
95
96
97
98
99







-
-
-
+
+
+








	return nil;
}

bool
addcommand(OFString *name, void (*function)(), int argumentsTypes)
{
	Command *command = [[Command alloc] initWithName:name
	                                        function:function
	                                  argumentsTypes:argumentsTypes];
	Command *command = [Command commandWithName:name
	                                   function:function
	                             argumentsTypes:argumentsTypes];

	if (identifiers == nil)
		identifiers = [[OFMutableDictionary alloc] init];

	identifiers[name] = command;

	return false;

Modified src/console.mm from [c4ec2131b8] to [555c5a6eb3].

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
42
1
2
3
4
5
6
7
8
9
10







11
12

















13
14
15
16
17
18
19






+



-
-
-
-
-
-
-


-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-







// console.cpp: the console buffer, its display, and command line control

#include "cube.h"

#include <ctype.h>

#import "ConsoleLine.h"
#import "KeyMapping.h"
#import "OFString+Cube.h"

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

- (instancetype)initWithText:(OFString *)text outtime:(int)outtime;
@end

static OFMutableArray<ConsoleLine *> *conlines;

@implementation ConsoleLine
- (instancetype)initWithText:(OFString *)text outtime:(int)outtime
{
	self = [super init];

	_text = [text copy];
	_outtime = outtime;

	return self;
}

- (OFString *)description
{
	return _text;
}
@end

const int ndraw = 5;
const int WORDWRAP = 80;
int conskip = 0;

bool saycommandon = false;
static OFMutableString *commandbuf;

55
56
57
58
59
60
61
62

63
64
65
66
67
68
69
70
71
72
73
74


75
76
77
78
79
80
81
32
33
34
35
36
37
38

39
40
41
42
43
44
45
46
47
48
49


50
51
52
53
54
55
56
57
58







-
+










-
-
+
+







	OFMutableString *text;

	// constrain the buffer size
	if (conlines.count > 100) {
		text = [conlines.lastObject.text mutableCopy];
		[conlines removeLastObject];
	} else
		text = [[OFMutableString alloc] init];
		text = [OFMutableString string];

	if (highlight)
		// show line in a different colour, for chat etc.
		[text appendString:@"\f"];

	[text appendString:sf];

	if (conlines == nil)
		conlines = [[OFMutableArray alloc] init];

	[conlines insertObject:[[ConsoleLine alloc] initWithText:text
	                                                 outtime:lastmillis]
	[conlines insertObject:[ConsoleLine lineWithText:text
	                                         outtime:lastmillis]
	               atIndex:0];

	puts(text.UTF8String);
#ifndef OF_WINDOWS
	fflush(stdout);
#endif
}
131
132
133
134
135
136
137
138
139


140
141
142
143
144
145
146
108
109
110
111
112
113
114


115
116
117
118
119
120
121
122
123







-
-
+
+








void
keymap(OFString *code, OFString *key, OFString *action)
{
	if (keyMappings == nil)
		keyMappings = [[OFMutableArray alloc] init];

	KeyMapping *mapping =
	    [[KeyMapping alloc] initWithCode:code.cube_intValue name:key];
	KeyMapping *mapping = [KeyMapping mappingWithCode:code.cube_intValue
	                                             name:key];
	mapping.action = action;
	[keyMappings addObject:mapping];
}
COMMAND(keymap, ARG_3STR)

void
bindkey(OFString *key, OFString *action)

Modified src/entities.mm from [58180dec4d] to [c332d89e7c].

22
23
24
25
26
27
28
29
30



31
32
33
34
35
36
37
38
39
40
41
42
43
44
45

46
47



48
49
50
51
52
53
54
22
23
24
25
26
27
28


29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47


48
49
50
51
52
53
54
55
56
57







-
-
+
+
+















+
-
-
+
+
+








int triggertime = 0;

void
renderent(entity &e, OFString *mdlname, float z, float yaw, int frame = 0,
    int numf = 1, int basetime = 0, float speed = 10.0f)
{
	rendermodel(mdlname, frame, numf, 0, 1.1f, e.x, z + S(e.x, e.y)->floor,
	    e.y, yaw, 0, false, 1.0f, speed, 0, basetime);
	rendermodel(mdlname, frame, numf, 0, 1.1f,
	    OFMakeVector3D(e.x, z + S(e.x, e.y)->floor, e.y), yaw, 0, false,
	    1.0f, speed, 0, basetime);
}

void
renderentities()
{
	if (lastmillis > triggertime + 1000)
		triggertime = 0;
	loopv(ents)
	{
		entity &e = ents[i];
		if (e.type == MAPMODEL) {
			MapModelInfo *mmi = getmminfo(e.attr2);
			if (mmi == nil)
				continue;
			rendermodel(mmi.name, 0, 1, e.attr4, (float)mmi.rad,
			    OFMakeVector3D(e.x,
			    e.x, (float)S(e.x, e.y)->floor + mmi.zoff + e.attr3,
			    e.y, (float)((e.attr1 + 7) - (e.attr1 + 7) % 15), 0,
			        (float)S(e.x, e.y)->floor + mmi.zoff + e.attr3,
			        e.y),
			    (float)((e.attr1 + 7) - (e.attr1 + 7) % 15), 0,
			    false, 1.0f, 10.0f, mmi.snap);
		} else {
			if (OUTBORD(e.x, e.y))
				continue;
			if (e.type != CARROT) {
				if (!e.spawned && e.type != TELEPORT)
					continue;

Modified src/menus.mm from [e754271834] to [bd623c6a87].

91
92
93
94
95
96
97
98

99
100
101
102
103
104
105
106
107
108

109
110
111
112
113
114
115
116
117
118
119


120
121
122
123
124
125
126
91
92
93
94
95
96
97

98
99
100
101
102
103
104
105
106
107

108
109
110
111
112
113
114
115
116
117


118
119
120
121
122
123
124
125
126







-
+









-
+









-
-
+
+








void
newmenu(OFString *name)
{
	if (menus == nil)
		menus = [[OFMutableArray alloc] init];

	[menus addObject:[[Menu alloc] initWithName:name]];
	[menus addObject:[Menu menuWithName:name]];
}
COMMAND(newmenu, ARG_1STR)

void
menumanual(int m, int n, OFString *text)
{
	if (n == 0)
		[menus[m].items removeAllObjects];

	MenuItem *item = [[MenuItem alloc] initWithText:text action:@""];
	MenuItem *item = [MenuItem itemWithText:text action:@""];
	[menus[m].items addObject:item];
}

void
menuitem(OFString *text, OFString *action)
{
	Menu *menu = menus.lastObject;

	MenuItem *item =
	    [[MenuItem alloc] initWithText:text
	                            action:(action.length > 0 ? action : text)];
	    [MenuItem itemWithText:text
	                    action:(action.length > 0 ? action : text)];
	[menu.items addObject:item];
}
COMMAND(menuitem, ARG_2STR)

bool
menukey(int code, bool isdown)
{

Modified src/meson.build from [db6c55f2bb] to [7a5be72f65].

1
2
3

4

5
6
7
8
9
10
11
12
13
14


15
16
17

18
19
20
21
22
23
24
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



+

+










+
+


-
+







executable('client',
  [
    'Alias.m',
    'Client.mm',
    'Command.mm',
    'ConsoleLine.m',
    'Cube.mm',
    'DynamicEntity.mm',
    'Identifier.m',
    'KeyMapping.m',
    'MD2.mm',
    'MapModelInfo.m',
    'Menu.m',
    'MenuItem.m',
    'OFString+Cube.mm',
    'Projectile.m',
    'ResolverResult.mm',
    'ResolverThread.mm',
    'ServerInfo.mm',
    'Variable.mm',
    'client.mm',
    'clients.mm',
    'clientextras.mm',
    'clientgame.mm',
    'clients2c.mm',
    'commands.mm',
    'console.mm',
    'editing.mm',
    'entities.mm',
58
59
60
61
62
63
64

65
66
67
68
69
70
71
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76







+







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

executable('server',
  [
    'Client.mm',
    'server.mm',
    'serverms.mm',
    'serverutil.mm',
    'tools.mm',
  ],
  objcpp_args: ['-DSTANDALONE'],
  dependencies: [

Modified src/protos.h from [2b4f29b604] to [ca691ec5c9].

206
207
208
209
210
211
212
213
214


215
216
217
218
219
220
221
206
207
208
209
210
211
212


213
214
215
216
217
218
219
220
221







-
-
+
+







extern void playsound(int n, const OFVector3D *loc = NULL);
extern void playsoundc(int n);
extern void initsound();
extern void cleansound();

// rendermd2
extern void rendermodel(OFString *mdl, int frame, int range, int tex, float rad,
    float x, float y, float z, float yaw, float pitch, bool teammate,
    float scale, float speed, int snap = 0, int basetime = 0);
    OFVector3D position, float yaw, float pitch, bool teammate, float scale,
    float speed, int snap = 0, int basetime = 0);
@class MapModelInfo;
extern MapModelInfo *getmminfo(int i);

// server
extern void initserver(bool dedicated, int uprate, OFString *sdesc,
    OFString *ip, OFString *master, OFString *passwd, int maxcl);
extern void cleanupserver();

Modified src/renderextras.mm from [87f5ac882b] to [0275a674d6].

188
189
190
191
192
193
194
195
196
197
198
199





200
201
202
203
204
205
206
188
189
190
191
192
193
194





195
196
197
198
199
200
201
202
203
204
205
206







-
-
-
-
-
+
+
+
+
+







			continue;
		OFVector3D v = OFMakeVector3D(e.x, e.y, e.z);
		particle_splash(2, 2, 40, v);
	}
	int e = closestent();
	if (e >= 0) {
		entity &c = ents[e];
		closeent = [[OFString alloc]
		    initWithFormat:@"closest entity = %@ (%d, %d, %d, %d), "
		                   @"selection = (%d, %d)",
		    entnames[c.type], c.attr1, c.attr2, c.attr3, c.attr4,
		    getvar(@"selxs"), getvar(@"selys")];
		closeent =
		    [OFString stringWithFormat:@"closest entity = %@ (%d, %d, "
		                               @"%d, %d), selection = (%d, %d)",
		              entnames[c.type], c.attr1, c.attr2, c.attr3,
		              c.attr4, getvar(@"selxs"), getvar(@"selys")];
	}
}

void
loadsky(OFString *basename)
{
	static OFString *lastsky = @"";

Modified src/rendergl.mm from [6d1422bea1] to [81f69c07bf].

355
356
357
358
359
360
361
362
363


364
365
366
367
368
369
370
355
356
357
358
359
360
361


362
363
364
365
366
367
368
369
370







-
-
+
+







OFString *hudgunnames[] = { @"hudguns/fist", @"hudguns/shotg",
	@"hudguns/chaing", @"hudguns/rocket", @"hudguns/rifle" };

void
drawhudmodel(int start, int end, float speed, int base)
{
	rendermodel(hudgunnames[player1.gunselect], start, end, 0, 1.0f,
	    player1.o.x, player1.o.z, player1.o.y, player1.yaw + 90,
	    player1.pitch, false, 1.0f, speed, 0, base);
	    OFMakeVector3D(player1.o.x, player1.o.z, player1.o.y),
	    player1.yaw + 90, player1.pitch, false, 1.0f, speed, 0, base);
}

void
drawhudgun(float fovy, float aspect, int farplane)
{
	if (!hudgun /*|| !player1.gunselect*/)
		return;

Modified src/rendermd2.mm from [9b0441a720] to [72886c2cec].

37
38
39
40
41
42
43
44

45
46

47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67





68
69
70
71
72
73
74
37
38
39
40
41
42
43

44
45

46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62





63
64
65
66
67
68
69
70
71
72
73
74







-
+

-
+
















-
-
-
-
-
+
+
+
+
+







{
	static int modelnum = 0;

	MD2 *m = mdllookup[name];
	if (m != nil)
		return m;

	m = [[MD2 alloc] init];
	m = [MD2 md2];
	m.mdlnum = modelnum++;
	m.mmi = [[MapModelInfo alloc] initWithRad:2 h:2 zoff:0 snap:0 name:@""];
	m.mmi = [MapModelInfo infoWithRad:2 h:2 zoff:0 snap:0 name:@""];
	m.loadname = name;

	if (mdllookup == nil)
		mdllookup = [[OFMutableDictionary alloc] init];

	mdllookup[name] = m;

	return m;
}

void
mapmodel(
    OFString *rad, OFString *h, OFString *zoff, OFString *snap, OFString *name)
{
	MD2 *m = loadmodel([name stringByReplacingOccurrencesOfString:@"\\"
	                                                   withString:@"/"]);
	m.mmi = [[MapModelInfo alloc] initWithRad:rad.cube_intValue
	                                        h:h.cube_intValue
	                                     zoff:zoff.cube_intValue
	                                     snap:snap.cube_intValue
	                                     name:m.loadname];
	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];

	[mapmodels addObject:m];
}
COMMAND(mapmodel, ARG_5STR)
83
84
85
86
87
88
89
90
91


92
93
94
95
96


97
98
99
100
101
102
103
104
105
106


107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127

128
129
130
131
132
133
134
135
136
83
84
85
86
87
88
89


90
91
92
93
94
95

96
97
98
99
100
101
102
103
104
105


106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127

128


129
130
131
132
133
134
135







-
-
+
+




-
+
+








-
-
+
+




















-
+
-
-







MapModelInfo *
getmminfo(int i)
{
	return i < mapmodels.count ? mapmodels[i].mmi : nil;
}

void
rendermodel(OFString *mdl, int frame, int range, int tex, float rad, float x,
    float y, float z, float yaw, float pitch, bool teammate, float scale,
rendermodel(OFString *mdl, int frame, int range, int tex, float rad,
    OFVector3D position, float yaw, float pitch, bool teammate, float scale,
    float speed, int snap, int basetime)
{
	MD2 *m = loadmodel(mdl);

	if (isoccluded(player1.o.x, player1.o.y, x - rad, z - rad, rad * 2))
	if (isoccluded(player1.o.x, player1.o.y, position.x - rad,
	        position.z - rad, rad * 2))
		return;

	delayedload(m);

	int xs, ys;
	glBindTexture(GL_TEXTURE_2D,
	    tex ? lookuptexture(tex, &xs, &ys) : FIRSTMDL + m.mdlnum);

	int ix = (int)x;
	int iy = (int)z;
	int ix = (int)position.x;
	int iy = (int)position.z;
	OFVector3D light = OFMakeVector3D(1, 1, 1);

	if (!OUTBORD(ix, iy)) {
		sqr *s = S(ix, iy);
		float ll = 256.0f; // 0.96f;
		float of = 0.0f;   // 0.1f;
		light.x = s->r / ll + of;
		light.y = s->g / ll + of;
		light.z = s->b / ll + of;
	}

	if (teammate) {
		light.x *= 0.6f;
		light.y *= 0.7f;
		light.z *= 1.2f;
	}

	[m renderWithLight:light
	             frame:frame
	             range:range
	                 x:x
	          position:position
	                 y:y
	                 z:z
	               yaw:yaw
	             pitch:pitch
	             scale:scale
	             speed:speed
	              snap:snap
	          basetime:basetime];
}

Modified src/server.mm from [f99720b385] to [1804a617a4].

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
1
2
3
4
5
6
7
8
9













10
11
12
13
14
15
16




+
+



-
-
-
-
-
-
-
-
-
-
-
-
-







// server.cpp: little more than enhanced multicaster
// runs dedicated or as client coroutine

#include "cube.h"

#import "Client.h"

enum { ST_EMPTY, ST_LOCAL, ST_TCPIP };

// server side version of "dynent" type
@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;
@end

@implementation Client
@end

static OFMutableArray<Client *> *clients;

int maxclients = 8;
static OFString *smapname;

// server side version of "entity" type
struct server_entity {
355
356
357
358
359
360
361
362

363
364
365
366
367
368
369
344
345
346
347
348
349
350

351
352
353
354
355
356
357
358







-
+







Client *
addclient()
{
	for (Client *client in clients)
		if (client.type == ST_EMPTY)
			return client;

	Client *client = [[Client alloc] init];
	Client *client = [Client client];

	if (clients == nil)
		clients = [[OFMutableArray alloc] init];

	[clients addObject:client];

	return client;

Modified src/serverbrowser.mm from [7409dbfc1c] to [40331e8345].

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
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
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
101
102
103
104
105
106
107

108
109
110
111
112
113
114
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
42

43
44
45
46
47
48
49
50






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

-
-
-
-
-
-
-
-

-
-
-
+
+
+


-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-










-
+















-
+







// serverbrowser.cpp: eihrul's concurrent resolver, and server browser window
// management

#include "SDL_thread.h"
#include "cube.h"

#import "ServerInfo.h"
#import "ResolverResult.h"

@interface ResolverThread: OFThread
#import "ResolverThread.h"
{
	volatile bool _stop;
}

#import "ServerInfo.h"
@property (copy, nonatomic) OFString *query;
@property (nonatomic) int starttime;
@end

@interface ResolverResult: OFObject
@property (readonly, nonatomic) OFString *query;
@property (readonly, nonatomic) ENetAddress address;

- (instancetype)init OF_UNAVAILABLE;
- (instancetype)initWithQuery:(OFString *)query address:(ENetAddress)address;
@end

static OFMutableArray<ResolverThread *> *resolverthreads;
static OFMutableArray<OFString *> *resolverqueries;
static OFMutableArray<ResolverResult *> *resolverresults;
static SDL_sem *resolversem;
OFMutableArray<OFString *> *resolverqueries;
OFMutableArray<ResolverResult *> *resolverresults;
SDL_sem *resolversem;
static int resolverlimit = 1000;

@implementation ResolverThread
- (id)main
{
	while (!_stop) {
		SDL_SemWait(resolversem);

		@synchronized(ResolverThread.class) {
			if (resolverqueries.count == 0)
				continue;

			_query = resolverqueries.lastObject;
			[resolverqueries removeLastObject];
			_starttime = lastmillis;
		}

		ENetAddress address = { ENET_HOST_ANY, CUBE_SERVINFO_PORT };
		enet_address_set_host(&address, _query.UTF8String);

		@synchronized(ResolverThread.class) {
			[resolverresults addObject:[[ResolverResult alloc]
			                               initWithQuery:_query
			                                     address:address]];

			_query = NULL;
			_starttime = 0;
		}
	}

	return nil;
}

- (void)stop
{
	_stop = true;
}
@end

@implementation ResolverResult
- (instancetype)initWithQuery:(OFString *)query address:(ENetAddress)address
{
	self = [super init];

	_query = query;
	_address = address;

	return self;
}
@end

void
resolverinit(int threads, int limit)
{
	resolverthreads = [[OFMutableArray alloc] init];
	resolverqueries = [[OFMutableArray alloc] init];
	resolverresults = [[OFMutableArray alloc] init];
	resolverlimit = limit;
	resolversem = SDL_CreateSemaphore(0);

	while (threads > 0) {
		ResolverThread *rt = [[ResolverThread alloc] init];
		ResolverThread *rt = [ResolverThread thread];
		rt.name = @"resolverthread";
		[resolverthreads addObject:rt];
		[rt start];
		--threads;
	}
}

void
resolverstop(size_t i, bool restart)
{
	@synchronized(ResolverThread.class) {
		ResolverThread *rt = resolverthreads[i];
		[rt stop];

		if (restart) {
			rt = [[ResolverThread alloc] init];
			rt = [ResolverThread thread];
			rt.name = @"resolverthread";

			resolverthreads[i] = rt;

			[rt start];
		} else
			[resolverthreads removeObjectAtIndex:i];
183
184
185
186
187
188
189
190

191
192
193
194
195
196
197
119
120
121
122
123
124
125

126
127
128
129
130
131
132
133







-
+







	for (ServerInfo *si in servers)
		if ([si.name isEqual:servername])
			return;

	if (servers == nil)
		servers = [[OFMutableArray alloc] init];

	[servers addObject:[[ServerInfo alloc] initWithName:servername]];
	[servers addObject:[ServerInfo infoWithName:servername]];
}

void
pingservers()
{
	ENetBuffer buf;
	uchar ping[MAXTRANS];
276
277
278
279
280
281
282
283
284


285
286
287
288
289


290
291
292
293
294
295


296
297
298
299
300
301
302
212
213
214
215
216
217
218


219
220
221
222
223


224
225
226
227
228
229


230
231
232
233
234
235
236
237
238







-
-
+
+



-
-
+
+




-
-
+
+







	[servers sort];

	__block int maxmenu = 16;
	[servers enumerateObjectsUsingBlock:^(
	    ServerInfo *si, size_t i, bool *stop) {
		if (si.address.host != ENET_HOST_ANY && si.ping != 9999) {
			if (si.protocol != PROTOCOL_VERSION)
				si.full = [[OFString alloc]
				    initWithFormat:
				si.full = [OFString
				    stringWithFormat:
				        @"%@ [different cube protocol]",
				    si.name];
			else
				si.full = [[OFString alloc]
				    initWithFormat:@"%d\t%d\t%@, %@: %@ %@",
				si.full = [OFString
				    stringWithFormat:@"%d\t%d\t%@, %@: %@ %@",
				    si.ping, si.numplayers,
				    si.map.length > 0 ? si.map : @"[unknown]",
				    modestr(si.mode), si.name, si.sdesc];
		} else
			si.full = [[OFString alloc]
			    initWithFormat:
			si.full = [OFString
			    stringWithFormat:
			        (si.address.host != ENET_HOST_ANY
			                ? @"%@ [waiting for server response]"
			                : @"%@ [unknown host]\t"),
			    si.name];

		// cut off too long server descriptions
		if (si.full.length > 50)

Modified src/serverms.mm from [4bb1ac1ee8] to [0e5451e8b8].

154
155
156
157
158
159
160
161
162

163
164
165
166
167
168
169
154
155
156
157
158
159
160


161
162
163
164
165
166
167
168







-
-
+







servermsinit(OFString *master_, OFString *sdesc, bool listen)
{
	const char *master = master_.UTF8String;
	const char *mid = strstr(master, "/");
	if (!mid)
		mid = master;
	masterpath = @(mid);
	masterbase = [[OFString alloc] initWithUTF8String:master
	                                           length:mid - master];
	masterbase = [OFString stringWithUTF8String:master length:mid - master];
	serverdesc = sdesc;

	if (listen) {
		ENetAddress address = { ENET_HOST_ANY, CUBE_SERVINFO_PORT };
		pongsock =
		    enet_socket_create(ENET_SOCKET_TYPE_DATAGRAM, &address);
		if (pongsock == ENET_SOCKET_NULL)

Modified src/weapon.mm from [5796e07781] to [ec6a711714].

144
145
146
147
148
149
150
151

152
153

154
155
156
157
158
159
160
161
144
145
146
147
148
149
150

151


152

153
154
155
156
157
158
159







-
+
-
-
+
-







void
newprojectile(OFVector3D &from, OFVector3D &to, float speed, bool local,
    DynamicEntity *owner, int gun)
{
	for (size_t i = 0; i < MAXPROJ; i++) {
		Projectile *p = projs[i];

		if (p == nil) {
		if (p == nil)
			p = [[Projectile alloc] init];
			projs[i] = p;
			projs[i] = p = [Projectile projectile];
		}

		if (p.inuse)
			continue;

		p.inuse = true;
		p.o = from;
		p.to = to;
350
351
352
353
354
355
356
357
358


359
360
361
362
363
364
365
348
349
350
351
352
353
354


355
356
357
358
359
360
361
362
363







-
-
+
+







	hit(target, damage, d, at);
	vdist(dist, v, from, to);
	vmul(v, damage / dist / 50);
	vadd(d.vel, v);
}

void
raydamage(
    DynamicEntity *o, const OFVector3D &from, const OFVector3D &to, DynamicEntity *d, int i)
raydamage(DynamicEntity *o, const OFVector3D &from, const OFVector3D &to,
    DynamicEntity *d, int i)
{
	if (o.state != CS_ALIVE)
		return;
	int qdam = guns[d.gunselect].damage;
	if (d.quadmillis)
		qdam *= 4;
	if (d.monsterstate)