Cube  Check-in [d2f07d884a]

Overview
Comment:Be more tolerant of invalid arguments
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: d2f07d884a4f4319ff687e085c3233e210ee05b46a2675ecd757a261e6f19e6e
User & Date: js on 2025-03-12 00:16:05
Other Links: manifest | tags
Context
2025-03-12
22:35
Add files forgotten in last commit check-in: e208417f95 user: js tags: trunk
00:16
Be more tolerant of invalid arguments check-in: d2f07d884a user: js tags: trunk
2025-03-11
01:20
Make use of the new -[OFString intValue] check-in: 09eb96f339 user: js tags: trunk
Changes

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

1

2
3
4
5
6
7
8
#import "Command.h"


#include <cube.h>

static OFArray<OFString *> *
padArguments(OFArray<OFString *> *arguments, size_t count)
{
	OFMutableArray<OFString *> *copy;

>







1
2
3
4
5
6
7
8
9
#import "Command.h"
#import "OFString+Cube.h"

#include <cube.h>

static OFArray<OFString *> *
padArguments(OFArray<OFString *> *arguments, size_t count)
{
	OFMutableArray<OFString *> *copy;
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
- (int)callWithArguments:(OFArray<OFString *> *)arguments isDown:(bool)isDown
{
	switch (_argumentsTypes) {
	case ARG_1INT:
		if (isDown) {
			arguments = padArguments(arguments, 2);
			((void(__cdecl *)(int))_function)(
			    [arguments[1] intValueWithBase:0]);
		}
		break;
	case ARG_2INT:
		if (isDown) {
			arguments = padArguments(arguments, 3);
			((void(__cdecl *)(int, int))_function)(
			    [arguments[1] intValueWithBase:0],
			    [arguments[2] intValueWithBase:0]);
		}
		break;
	case ARG_3INT:
		if (isDown) {
			arguments = padArguments(arguments, 4);
			((void(__cdecl *)(int, int, int))_function)(
			    [arguments[1] intValueWithBase:0],
			    [arguments[2] intValueWithBase:0],
			    [arguments[3] intValueWithBase:0]);
		}
		break;
	case ARG_4INT:
		if (isDown) {
			arguments = padArguments(arguments, 5);
			((void(__cdecl *)(int, int, int, int))_function)(
			    [arguments[1] intValueWithBase:0],
			    [arguments[2] intValueWithBase:0],
			    [arguments[3] intValueWithBase:0],
			    [arguments[4] intValueWithBase:0]);
		}
		break;
	case ARG_NONE:
		if (isDown)
			((void(__cdecl *)())_function)();
		break;
	case ARG_1STR:







|






|
|






|
|
|






|
|
|
|







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
- (int)callWithArguments:(OFArray<OFString *> *)arguments isDown:(bool)isDown
{
	switch (_argumentsTypes) {
	case ARG_1INT:
		if (isDown) {
			arguments = padArguments(arguments, 2);
			((void(__cdecl *)(int))_function)(
			    [arguments[1] cube_intValueWithBase:0]);
		}
		break;
	case ARG_2INT:
		if (isDown) {
			arguments = padArguments(arguments, 3);
			((void(__cdecl *)(int, int))_function)(
			    [arguments[1] cube_intValueWithBase:0],
			    [arguments[2] cube_intValueWithBase:0]);
		}
		break;
	case ARG_3INT:
		if (isDown) {
			arguments = padArguments(arguments, 4);
			((void(__cdecl *)(int, int, int))_function)(
			    [arguments[1] cube_intValueWithBase:0],
			    [arguments[2] cube_intValueWithBase:0],
			    [arguments[3] cube_intValueWithBase:0]);
		}
		break;
	case ARG_4INT:
		if (isDown) {
			arguments = padArguments(arguments, 5);
			((void(__cdecl *)(int, int, int, int))_function)(
			    [arguments[1] cube_intValueWithBase:0],
			    [arguments[2] cube_intValueWithBase:0],
			    [arguments[3] cube_intValueWithBase:0],
			    [arguments[4] cube_intValueWithBase:0]);
		}
		break;
	case ARG_NONE:
		if (isDown)
			((void(__cdecl *)())_function)();
		break;
	case ARG_1STR:

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

19
20
21
22
23
24
25


26
27

28
29
30


31
32
33
34
35
36
37
		@throw [OFInvalidArgumentException exception];

	int x, y;
	@try {
		x = _text.intValue;
	} @catch (OFInvalidFormatException *e) {
		x = 0;


	}


	@try {
		y = otherItem.text.intValue;
	} @catch (OFInvalidFormatException *e) {


		y = 0;
	}

	if (x > y)
		return OFOrderedAscending;
	if (x < y)
		return OFOrderedDescending;







>
>


>
|


>
>







19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
		@throw [OFInvalidArgumentException exception];

	int x, y;
	@try {
		x = _text.intValue;
	} @catch (OFInvalidFormatException *e) {
		x = 0;
	} @catch (OFOutOfRangeException *e) {
		x = 0;
	}

	@
	try {
		y = otherItem.text.intValue;
	} @catch (OFInvalidFormatException *e) {
		y = 0;
	} @catch (OFOutOfRangeException *e) {
		y = 0;
	}

	if (x > y)
		return OFOrderedAscending;
	if (x < y)
		return OFOrderedDescending;

Modified src/clientgame.mm from [c71213128a] to [ec0093549c].

1
2
3
4
5

6
7
8
9
10
11
12
// clientgame.cpp: core game related stuff

#include "cube.h"

#import "DynamicEntity.h"


int nextmode = 0; // nextmode becomes gamemode after next map load
VAR(gamemode, 1, 0, 0);

void
mode(int n)
{





>







1
2
3
4
5
6
7
8
9
10
11
12
13
// clientgame.cpp: core game related stuff

#include "cube.h"

#import "DynamicEntity.h"
#import "OFString+Cube.h"

int nextmode = 0; // nextmode becomes gamemode after next map load
VAR(gamemode, 1, 0, 0);

void
mode(int n)
{
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
}

int sleepwait = 0;
static OFString *sleepcmd = nil;
void
sleepf(OFString *msec, OFString *cmd)
{
	sleepwait = msec.intValue + lastmillis;
	sleepcmd = cmd;
}
COMMANDN(sleep, sleepf, ARG_2STR)

void
updateworld(int millis) // main game update loop
{







|







235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
}

int sleepwait = 0;
static OFString *sleepcmd = nil;
void
sleepf(OFString *msec, OFString *cmd)
{
	sleepwait = msec.cube_intValue + lastmillis;
	sleepcmd = cmd;
}
COMMANDN(sleep, sleepf, ARG_2STR)

void
updateworld(int millis) // main game update loop
{

Modified src/commands.mm from [69ee305979] to [e9b116439f].

1
2
3
4
5
6
7
8
9
10

11
12
13
14
15
16
17
// command.cpp: implements the parsing and execution of a tiny script language
// which is largely backwards compatible with the quake console language.

#include "cube.h"

#include <memory>

#import "Alias.h"
#import "Command.h"
#import "Identifier.h"

#import "Variable.h"

// contains ALL vars/commands/aliases
static OFMutableDictionary<OFString *, __kindof Identifier *> *identifiers;

void
alias(OFString *name, OFString *action)










>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// command.cpp: implements the parsing and execution of a tiny script language
// which is largely backwards compatible with the quake console language.

#include "cube.h"

#include <memory>

#import "Alias.h"
#import "Command.h"
#import "Identifier.h"
#import "OFString+Cube.h"
#import "Variable.h"

// contains ALL vars/commands/aliases
static OFMutableDictionary<OFString *, __kindof Identifier *> *identifiers;

void
alias(OFString *name, OFString *action)
176
177
178
179
180
181
182
















































183
184
185
186
187
188
189
		} else if ([identifier isKindOfClass:Alias.class])
			return [identifier action];
	}

	conoutf(@"unknown alias lookup: %@", [n substringFromIndex:1]);
	return n;
}

















































// all evaluation happens here, recursively
int
execute(OFString *string, bool isDown)
{
	@autoreleasepool {
		std::unique_ptr<char> copy(strdup(string.UTF8String));







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
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
		} else if ([identifier isKindOfClass:Alias.class])
			return [identifier action];
	}

	conoutf(@"unknown alias lookup: %@", [n substringFromIndex:1]);
	return n;
}

int
executeIdentifier(__kindof Identifier *identifier,
    OFArray<OFString *> *arguments, bool isDown)
{
	if (identifier == nil) {
		@try {
			return [arguments[0] intValueWithBase:0];
		} @catch (OFInvalidFormatException *e) {
			conoutf(@"unknown command: %@", arguments[0]);
			return 0;
		} @catch (OFOutOfRangeException *e) {
			conoutf(@"invalid value: %@", arguments[0]);
			return 0;
		}
	}

	if ([identifier isKindOfClass:Command.class])
		// game defined commands use very ad-hoc function signature,
		// and just call it
		return [identifier callWithArguments:arguments isDown:isDown];

	if ([identifier isKindOfClass:Variable.class]) {
		if (!isDown)
			return 0;

		// game defined variables
		if (arguments.count < 2 || arguments[1].length == 0)
			[identifier printValue];
		else
			[identifier
			    setValue:[arguments[1] cube_intValueWithBase:0]];
	}

	if ([identifier isKindOfClass:Alias.class]) {
		// alias, also used as functions and (global) variables
		for (int i = 1; i < arguments.count; i++) {
			// set any arguments as (global) arg values so
			// functions can access them
			OFString *t = [OFString stringWithFormat:@"arg%d", i];
			alias(t, arguments[i]);
		}

		return execute([identifier action], isDown);
	}

	return 0;
}

// all evaluation happens here, recursively
int
execute(OFString *string, bool isDown)
{
	@autoreleasepool {
		std::unique_ptr<char> copy(strdup(string.UTF8String));
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
				c = [c substringFromIndex:1];
				w[0] = c;
			}
			// empty statement
			if (c.length == 0)
				continue;

			__kindof Identifier *identifier = identifiers[c];
			if (identifier == nil) {
				@try {
					val = [c intValueWithBase:0];
				} @catch (OFInvalidFormatException *e) {
					conoutf(@"unknown command: %@", c);
				}
			} else {
				if ([identifier isKindOfClass:Command.class]) {
					// game defined commands use very
					// ad-hoc function signature, and just
					// call it
					OFArray<OFString *> *arguments =
					    [[OFArray alloc]
					        initWithObjects:w
					                  count:numargs];
					val = [identifier
					    callWithArguments:arguments
					               isDown:isDown];
				} else if ([identifier
				               isKindOfClass:Variable.class]) {
					// game defined variables
					if (isDown) {
						if (w[1].length == 0)
							[identifier printValue];
						else
							[identifier
							    setValue:
							        [w[1]
							            intValueWithBase:
							                0]];
					}
				} else if ([identifier
				               isKindOfClass:Alias.class]) {
					// alias, also used as functions and
					// (global) variables
					for (int i = 1; i < numargs; i++) {
						// set any arguments as
						// (global) arg values so
						// functions can access them
						OFString *t = [OFString
						    stringWithFormat:@"arg%d",
						    i];
						alias(t, w[i]);
					}
					val = execute(
					    [identifier action], isDown);
				}
			}
		}

		return val;
	}
}

// tab-completion of all identifiers







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
|
<
<







275
276
277
278
279
280
281













































282
283


284
285
286
287
288
289
290
				c = [c substringFromIndex:1];
				w[0] = c;
			}
			// empty statement
			if (c.length == 0)
				continue;














































			val = executeIdentifier(identifiers[c],
			    [OFArray arrayWithObjects:w count:numargs], isDown);


		}

		return val;
	}
}

// tab-completion of all identifiers
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
		    IRIByAppendingPathComponent:@"config.cfg"];
		stream = [[OFIRIHandler handlerForIRI:IRI] openItemAtIRI:IRI
		                                                    mode:@"w"];
	} @catch (id e) {
		return;
	}

	[stream writeString:
	            @"// automatically written on exit, do not modify\n"
	            @"// delete this file to have defaults.cfg overwrite these "
	            @"settings\n"
	            @"// modify settings in game, or put settings in "
	            @"autoexec.cfg to override anything\n"
	            @"\n"];
	writeclientinfo(stream);
	[stream writeString:@"\n"];

	[identifiers enumerateKeysAndObjectsUsingBlock:^(
	    OFString *name, __kindof Identifier *identifier, bool *stop) {
		if (![identifier isKindOfClass:Variable.class] ||
		    ![identifier persisted])







<
|
|
|
|
|
|







376
377
378
379
380
381
382

383
384
385
386
387
388
389
390
391
392
393
394
395
		    IRIByAppendingPathComponent:@"config.cfg"];
		stream = [[OFIRIHandler handlerForIRI:IRI] openItemAtIRI:IRI
		                                                    mode:@"w"];
	} @catch (id e) {
		return;
	}


	[stream writeString:@"// automatically written on exit, do not modify\n"
	                    @"// delete this file to have defaults.cfg "
	                    @"overwrite these settings\n"
	                    @"// modify settings in game, or put settings in "
	                    @"autoexec.cfg to override anything\n"
	                    @"\n"];
	writeclientinfo(stream);
	[stream writeString:@"\n"];

	[identifiers enumerateKeysAndObjectsUsingBlock:^(
	    OFString *name, __kindof Identifier *identifier, bool *stop) {
		if (![identifier isKindOfClass:Variable.class] ||
		    ![identifier persisted])
414
415
416
417
418
419
420
421
422

423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449

	[stream close];
}

COMMAND(writecfg, ARG_NONE)

// below the commands that implement a small imperative language. thanks to the
// semantics of
// () and [] expressions, any control construct can be defined trivially.


void
intset(OFString *name, int v)
{
	@autoreleasepool {
		alias(name, [OFString stringWithFormat:@"%d", v]);
	}
}

void
ifthen(OFString *cond, OFString *thenp, OFString *elsep)
{
	execute((![cond hasPrefix:@"0"] ? thenp : elsep));
}

void
loopa(OFString *times, OFString *body)
{
	@autoreleasepool {
		int t = times.intValue;

		loopi(t)
		{
			intset(@"i", i);
			execute(body);
		}
	}







<
|
>



















|







415
416
417
418
419
420
421

422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450

	[stream close];
}

COMMAND(writecfg, ARG_NONE)

// below the commands that implement a small imperative language. thanks to the

// semantics of () and [] expressions, any control construct can be defined
// trivially.

void
intset(OFString *name, int v)
{
	@autoreleasepool {
		alias(name, [OFString stringWithFormat:@"%d", v]);
	}
}

void
ifthen(OFString *cond, OFString *thenp, OFString *elsep)
{
	execute((![cond hasPrefix:@"0"] ? thenp : elsep));
}

void
loopa(OFString *times, OFString *body)
{
	@autoreleasepool {
		int t = times.cube_intValue;

		loopi(t)
		{
			intset(@"i", i);
			execute(body);
		}
	}
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
	}
}

void
at(OFString *s_, OFString *pos)
{
	@autoreleasepool {
		int n = pos.intValue;
		std::unique_ptr<char> copy(strdup(s_.UTF8String));
		char *s = copy.get();

		loopi(n) s += strspn(s += strcspn(s, " \0"), " ");
		s[strcspn(s, " \0")] = 0;
		concat(@(s));
	}
}

COMMANDN(loop, loopa, ARG_2STR)







|


<







494
495
496
497
498
499
500
501
502
503

504
505
506
507
508
509
510
	}
}

void
at(OFString *s_, OFString *pos)
{
	@autoreleasepool {
		int n = pos.cube_intValue;
		std::unique_ptr<char> copy(strdup(s_.UTF8String));
		char *s = copy.get();

		loopi(n) s += strspn(s += strcspn(s, " \0"), " ");
		s[strcspn(s, " \0")] = 0;
		concat(@(s));
	}
}

COMMANDN(loop, loopa, ARG_2STR)

Modified src/console.mm from [1408af0279] to [40d6223ddd].

1
2
3
4
5
6
7

8
9
10
11
12
13
14
// console.cpp: the console buffer, its display, and command line control

#include "cube.h"

#include <ctype.h>

#import "KeyMapping.h"


struct cline {
	char *cref;
	int outtime;
};
vector<cline> conlines;








>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// console.cpp: the console buffer, its display, and command line control

#include "cube.h"

#include <ctype.h>

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

struct cline {
	char *cref;
	int outtime;
};
vector<cline> conlines;

102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117

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

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

void
bindkey(OFString *key, OFString *action)







|
|







103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118

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];
	mapping.action = action;
	[keyMappings addObject:mapping];
}
COMMAND(keymap, ARG_3STR)

void
bindkey(OFString *key, OFString *action)

Modified src/editing.mm from [b565167d7b] to [76cc8ec718].

1
2
3
4
5
6

7
8
9
10
11
12
13
// editing.cpp: most map editing commands go here, entity editing commands are
// in world.cpp

#include "cube.h"

#import "DynamicEntity.h"


bool editmode = false;

// the current selection, used by almost all editing commands
// invariant: all code assumes that these are kept inside MINBORD distance of
// the edge of the map







>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
// editing.cpp: most map editing commands go here, entity editing commands are
// in world.cpp

#include "cube.h"

#import "DynamicEntity.h"
#import "OFString+Cube.h"

bool editmode = false;

// the current selection, used by almost all editing commands
// invariant: all code assumes that these are kept inside MINBORD distance of
// the edge of the map

601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616

void
newent(OFString *what, OFString *a1, OFString *a2, OFString *a3, OFString *a4)
{
	EDITSEL;
	@autoreleasepool {
		newentity(sel.x, sel.y, (int)player1.o.z, what,
		    [a1 intValueWithBase:0], [a2 intValueWithBase:0],
		    [a3 intValueWithBase:0], [a4 intValueWithBase:0]);
	}
}

COMMANDN(select, selectpos, ARG_4INT)
COMMAND(edittag, ARG_1INT)
COMMAND(replace, ARG_NONE)
COMMAND(archvertex, ARG_3INT)







|
|







602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617

void
newent(OFString *what, OFString *a1, OFString *a2, OFString *a3, OFString *a4)
{
	EDITSEL;
	@autoreleasepool {
		newentity(sel.x, sel.y, (int)player1.o.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)

Modified src/meson.build from [ff6b55de94] to [db6c55f2bb].

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

13
14
15
16
17
18
19
executable('client',
  [
    'Alias.m',
    'Command.mm',
    'Cube.mm',
    'DynamicEntity.mm',
    'Identifier.m',
    'KeyMapping.m',
    'MD2.mm',
    'MapModelInfo.m',
    'Menu.m',
    'MenuItem.m',

    'Projectile.m',
    'ServerInfo.mm',
    'Variable.mm',
    'client.mm',
    'clientextras.mm',
    'clientgame.mm',
    'clients2c.mm',












>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
executable('client',
  [
    'Alias.m',
    'Command.mm',
    'Cube.mm',
    'DynamicEntity.mm',
    'Identifier.m',
    'KeyMapping.m',
    'MD2.mm',
    'MapModelInfo.m',
    'Menu.m',
    'MenuItem.m',
    'OFString+Cube.mm',
    'Projectile.m',
    'ServerInfo.mm',
    'Variable.mm',
    'client.mm',
    'clientextras.mm',
    'clientgame.mm',
    'clients2c.mm',

Modified src/renderextras.mm from [3c937d7f40] to [5d964620ef].

202
203
204
205
206
207
208



209
210
211
212
213
214
215

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




		if ([lastsky isEqual:basename])
			return;

		static const OFString *side[] = { @"ft", @"bk", @"lf", @"rt",
			@"dn", @"up" };
		int texnum = 14;
		loopi(6)







>
>
>







202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218

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

		basename = [basename stringByReplacingOccurrencesOfString:@"\\"
		                                               withString:@"/"];

		if ([lastsky isEqual:basename])
			return;

		static const OFString *side[] = { @"ft", @"bk", @"lf", @"rt",
			@"dn", @"up" };
		int texnum = 14;
		loopi(6)

Modified src/rendergl.mm from [4da3c2483c] to [e315f901d3].

1
2
3
4
5

6
7
8
9
10
11
12
// rendergl.cpp: core opengl rendering stuff

#include "cube.h"

#import "DynamicEntity.h"


#ifdef DARWIN
# define GL_COMBINE_EXT GL_COMBINE_ARB
# define GL_COMBINE_RGB_EXT GL_COMBINE_RGB_ARB
# define GL_SOURCE0_RBG_EXT GL_SOURCE0_RGB_ARB
# define GL_SOURCE1_RBG_EXT GL_SOURCE1_RGB_ARB
# define GL_RGB_SCALE_EXT GL_RGB_SCALE_ARB





>







1
2
3
4
5
6
7
8
9
10
11
12
13
// rendergl.cpp: core opengl rendering stuff

#include "cube.h"

#import "DynamicEntity.h"
#import "OFString+Cube.h"

#ifdef DARWIN
# define GL_COMBINE_EXT GL_COMBINE_ARB
# define GL_COMBINE_RGB_EXT GL_COMBINE_RGB_ARB
# define GL_SOURCE0_RBG_EXT GL_SOURCE0_RGB_ARB
# define GL_SOURCE1_RBG_EXT GL_SOURCE1_RGB_ARB
# define GL_RGB_SCALE_EXT GL_RGB_SCALE_ARB
193
194
195
196
197
198
199
200

201
202

203
204


205
206
207
208
209
210
211
}
COMMAND(texturereset, ARG_NONE)

void
texture(OFString *aframe, OFString *name)
{
	@autoreleasepool {
		int num = curtexnum++, frame = aframe.intValue;

		if (num < 0 || num >= 256 || frame < 0 || frame >= MAXFRAMES)
			return;

		mapping[num][frame] = 1;
		mapname[num][frame] = name;


	}
}
COMMAND(texture, ARG_2STR)

int
lookuptexture(int tex, int *xs, int *ys)
{







|
>


>

|
>
>







194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
}
COMMAND(texturereset, ARG_NONE)

void
texture(OFString *aframe, OFString *name)
{
	@autoreleasepool {
		int num = curtexnum++, frame = aframe.cube_intValue;

		if (num < 0 || num >= 256 || frame < 0 || frame >= MAXFRAMES)
			return;

		mapping[num][frame] = 1;
		mapname[num][frame] =
		    [name stringByReplacingOccurrencesOfString:@"\\"
		                                    withString:@"/"];
	}
}
COMMAND(texture, ARG_2STR)

int
lookuptexture(int tex, int *xs, int *ys)
{

Modified src/rendermd2.mm from [53ddda709f] to [08d6b30ba2].

1
2
3
4
5
6
7

8
9
10
11
12
13
14
// rendermd2.cpp: loader code adapted from a nehe tutorial

#include "cube.h"

#import "DynamicEntity.h"
#import "MD2.h"
#import "MapModelInfo.h"


static OFMutableDictionary<OFString *, MD2 *> *mdllookup = nil;
static OFMutableArray<MD2 *> *mapmodels = nil;

static const int FIRSTMDL = 20;

void







>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// rendermd2.cpp: loader code adapted from a nehe tutorial

#include "cube.h"

#import "DynamicEntity.h"
#import "MD2.h"
#import "MapModelInfo.h"
#import "OFString+Cube.h"

static OFMutableDictionary<OFString *, MD2 *> *mdllookup = nil;
static OFMutableArray<MD2 *> *mapmodels = nil;

static const int FIRSTMDL = 20;

void
63
64
65
66
67
68
69
70

71
72
73
74
75
76
77
78
79
80
81
	}
}

void
mapmodel(
    OFString *rad, OFString *h, OFString *zoff, OFString *snap, OFString *name)
{
	MD2 *m = loadmodel(name);

	m.mmi = [[MapModelInfo alloc] initWithRad:rad.intValue
	                                        h:h.intValue
	                                     zoff:zoff.intValue
	                                     snap:snap.intValue
	                                     name:m.loadname];

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

	[mapmodels addObject:m];
}







|
>
|
|
|
|







64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
	}
}

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

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

	[mapmodels addObject:m];
}

Modified src/sound.mm from [f6d08d4aed] to [7cef1841c0].

84
85
86
87
88
89
90


91
92
93
94
95
96
97
music(OFString *name)
{
	if (nosound)
		return;
	stopsound();
	if (soundvol && musicvol) {
		@autoreleasepool {


			OFString *path =
			    [OFString stringWithFormat:@"packages/%@", name];
			OFIRI *IRI = [Cube.sharedInstance.gameDataIRI
			    IRIByAppendingPathComponent:path];

#ifdef USE_MIXER
			if ((mod = Mix_LoadMUS(







>
>







84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
music(OFString *name)
{
	if (nosound)
		return;
	stopsound();
	if (soundvol && musicvol) {
		@autoreleasepool {
			name = [name stringByReplacingOccurrencesOfString:@"\\"
			                                       withString:@"/"];
			OFString *path =
			    [OFString stringWithFormat:@"packages/%@", name];
			OFIRI *IRI = [Cube.sharedInstance.gameDataIRI
			    IRIByAppendingPathComponent:path];

#ifdef USE_MIXER
			if ((mod = Mix_LoadMUS(
144
145
146
147
148
149
150
151

152
153
154
155
156
157
158

		i++;
	}

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

	[snames addObject:name];

	samples.add(NULL);

	return samples.length() - 1;
}
COMMAND(registersound, ARG_1EST)

void







|
>







146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161

		i++;
	}

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

	[snames addObject:[name stringByReplacingOccurrencesOfString:@"\\"
	                                                  withString:@"/"]];
	samples.add(NULL);

	return samples.length() - 1;
}
COMMAND(registersound, ARG_1EST)

void

Modified src/weapon.mm from [1d3f50a464] to [a4e8e0ad47].

1
2
3
4
5

6
7
8
9
10
11
12
// weapon.cpp: all shooting and effects code

#include "cube.h"

#import "DynamicEntity.h"

#import "Projectile.h"

static const int MONSTERDAMAGEFACTOR = 4;
static const int SGRAYS = 20;
static const float SGSPREAD = 2;
static OFVector3D sg[SGRAYS];






>







1
2
3
4
5
6
7
8
9
10
11
12
13
// weapon.cpp: all shooting and effects code

#include "cube.h"

#import "DynamicEntity.h"
#import "OFString+Cube.h"
#import "Projectile.h"

static const int MONSTERDAMAGEFACTOR = 4;
static const int SGRAYS = 20;
static const float SGSPREAD = 2;
static OFVector3D sg[SGRAYS];

59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
{
	return guns[gun].attackdelay;
}

void
weapon(OFString *a1, OFString *a2, OFString *a3)
{
	selectgun((a1.length > 0 ? a1.intValue : -1),
	    (a2.length > 0 ? a2.intValue : -1),
	    (a3.length > 0 ? a3.intValue : -1));
}
COMMAND(weapon, ARG_3STR)

void
createrays(OFVector3D &from,
    OFVector3D &to) // create random spread of rays for the shotgun
{







|
|
|







60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
{
	return guns[gun].attackdelay;
}

void
weapon(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)

void
createrays(OFVector3D &from,
    OFVector3D &to) // create random spread of rays for the shotgun
{