Line data Source code
1 0 : /*
2 :
3 : OOJSGlobal.m
4 :
5 :
6 : Oolite
7 : Copyright (C) 2004-2013 Giles C Williams and contributors
8 :
9 : This program is free software; you can redistribute it and/or
10 : modify it under the terms of the GNU General Public License
11 : as published by the Free Software Foundation; either version 2
12 : of the License, or (at your option) any later version.
13 :
14 : This program is distributed in the hope that it will be useful,
15 : but WITHOUT ANY WARRANTY; without even the implied warranty of
16 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 : GNU General Public License for more details.
18 :
19 : You should have received a copy of the GNU General Public License
20 : along with this program; if not, write to the Free Software
21 : Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
22 : MA 02110-1301, USA.
23 :
24 : */
25 :
26 : #import "OOJSGlobal.h"
27 : #import "OOJavaScriptEngine.h"
28 :
29 : #import "OOJSPlayer.h"
30 : #import "PlayerEntityScriptMethods.h"
31 : #import "OOStringExpander.h"
32 : #import "OOConstToString.h"
33 : #import "OOConstToJSString.h"
34 : #import "OOCollectionExtractors.h"
35 : #import "OOTexture.h"
36 : #import "GuiDisplayGen.h"
37 : #import "MyOpenGLView.h"
38 : #import "ResourceManager.h"
39 : #import "OOSystemDescriptionManager.h"
40 : #import "NSFileManagerOOExtensions.h"
41 : #import "OOJSGuiScreenKeyDefinition.h"
42 :
43 : #if OOJSENGINE_MONITOR_SUPPORT
44 :
45 : @interface OOJavaScriptEngine (OOMonitorSupportInternal)
46 :
47 0 : - (void)sendMonitorLogMessage:(NSString *)message
48 : withMessageClass:(NSString *)messageClass
49 : inContext:(JSContext *)context;
50 :
51 : @end
52 :
53 : #endif
54 :
55 :
56 0 : static NSString * const kOOLogDebugMessage = @"script.debug.message";
57 :
58 :
59 : static JSBool GlobalGetProperty(JSContext *context, JSObject *this, jsid propID, jsval *value);
60 : #ifndef NDEBUG
61 : static JSBool GlobalSetProperty(JSContext *context, JSObject *this, jsid propID, JSBool strict, jsval *value);
62 : #endif
63 :
64 : static JSBool GlobalLog(JSContext *context, uintN argc, jsval *vp);
65 : static JSBool GlobalExpandDescription(JSContext *context, uintN argc, jsval *vp);
66 : static JSBool GlobalKeyBindingDescription(JSContext *context, uintN argc, jsval *vp);
67 : static JSBool GlobalExpandMissionText(JSContext *context, uintN argc, jsval *vp);
68 : static JSBool GlobalDisplayNameForCommodity(JSContext *context, uintN argc, jsval *vp);
69 : static JSBool GlobalRandomName(JSContext *context, uintN argc, jsval *vp);
70 : static JSBool GlobalRandomInhabitantsDescription(JSContext *context, uintN argc, jsval *vp);
71 : static JSBool GlobalSetScreenBackground(JSContext *context, uintN argc, jsval *vp);
72 : static JSBool GlobalSetScreenOverlay(JSContext *context, uintN argc, jsval *vp);
73 : static JSBool GlobalGetScreenBackgroundForKey(JSContext *context, uintN argc, jsval *vp);
74 : static JSBool GlobalSetScreenBackgroundForKey(JSContext *context, uintN argc, jsval *vp);
75 : static JSBool GlobalAutoAIForRole(JSContext *context, uintN argc, jsval *vp);
76 : static JSBool GlobalPauseGame(JSContext *context, uintN argc, jsval *vp);
77 : static JSBool GlobalGetGuiColorSettingForKey(JSContext *context, uintN argc, jsval *vp);
78 : static JSBool GlobalSetGuiColorSettingForKey(JSContext *context, uintN argc, jsval *vp);
79 : static JSBool GlobalSetExtraGuiScreenKeys(JSContext *context, uintN argc, jsval *vp);
80 : static JSBool GlobalClearExtraGuiScreenKeys(JSContext *context, uintN argc, jsval *vp);
81 : static JSBool GlobalGetColorSaturation(JSContext *context, uintN argc, jsval *vp);
82 : static JSBool GlobalSetColorSaturation(JSContext *context, uintN argc, jsval *vp);
83 :
84 : #ifndef NDEBUG
85 : static JSBool GlobalTakeSnapShot(JSContext *context, uintN argc, jsval *vp);
86 : #endif
87 :
88 :
89 0 : static JSClass sGlobalClass =
90 : {
91 : "Global",
92 : JSCLASS_GLOBAL_FLAGS,
93 :
94 : JS_PropertyStub,
95 : JS_PropertyStub,
96 : GlobalGetProperty,
97 : #ifndef NDEBUG
98 : GlobalSetProperty,
99 : #else
100 : // No writeable properties in non-debug builds
101 : JS_StrictPropertyStub,
102 : #endif
103 : JS_EnumerateStub,
104 : JS_ResolveStub,
105 : JS_ConvertStub,
106 : JS_FinalizeStub
107 : };
108 :
109 :
110 0 : enum
111 : {
112 : // Property IDs
113 : kGlobal_galaxyNumber, // galaxy number, integer, read-only
114 : kGlobal_global, // global.global.global.global, integer, read-only
115 : kGlobal_guiScreen, // current GUI screen, string, read-only
116 : kGlobal_postFX, // current post processing effect, integer, read/write
117 : #ifndef NDEBUG
118 : kGlobal_timeAccelerationFactor // time acceleration, float, read/write
119 : #endif
120 : };
121 :
122 :
123 0 : static JSPropertySpec sGlobalProperties[] =
124 : {
125 : // JS name ID flags
126 : { "galaxyNumber", kGlobal_galaxyNumber, OOJS_PROP_READONLY_CB },
127 : { "guiScreen", kGlobal_guiScreen, OOJS_PROP_READONLY_CB },
128 : { "postFX", kGlobal_postFX, OOJS_PROP_READWRITE_CB },
129 : #ifndef NDEBUG
130 : { "timeAccelerationFactor", kGlobal_timeAccelerationFactor, OOJS_PROP_READWRITE_CB },
131 : #endif
132 : { 0 }
133 : };
134 :
135 :
136 0 : static JSFunctionSpec sGlobalMethods[] =
137 : {
138 : // JS name Function min args
139 : { "log", GlobalLog, 1 },
140 : { "autoAIForRole", GlobalAutoAIForRole, 1 },
141 : { "expandDescription", GlobalExpandDescription, 1 },
142 : { "expandMissionText", GlobalExpandMissionText, 1 },
143 : { "displayNameForCommodity", GlobalDisplayNameForCommodity, 1 },
144 : { "randomName", GlobalRandomName, 0 },
145 : { "randomInhabitantsDescription", GlobalRandomInhabitantsDescription, 1 },
146 : { "setScreenBackground", GlobalSetScreenBackground, 1 },
147 : { "getScreenBackgroundForKey", GlobalGetScreenBackgroundForKey, 1 },
148 : { "setScreenBackgroundForKey", GlobalSetScreenBackgroundForKey, 2 },
149 : { "setScreenOverlay", GlobalSetScreenOverlay, 1 },
150 : { "getGuiColorSettingForKey", GlobalGetGuiColorSettingForKey, 1 },
151 : { "setGuiColorSettingForKey", GlobalSetGuiColorSettingForKey, 2 },
152 : { "keyBindingDescription", GlobalKeyBindingDescription, 1 },
153 : { "getColorSaturation", GlobalGetColorSaturation, 0 },
154 : { "setColorSaturation", GlobalSetColorSaturation, 1 },
155 : { "setExtraGuiScreenKeys", GlobalSetExtraGuiScreenKeys, 2 },
156 : { "clearExtraGuiScreenKeys", GlobalClearExtraGuiScreenKeys, 2 },
157 :
158 : #ifndef NDEBUG
159 : { "takeSnapShot", GlobalTakeSnapShot, 1 },
160 : #endif
161 : { "pauseGame", GlobalPauseGame, 0 },
162 : { 0 }
163 : };
164 :
165 :
166 0 : void CreateOOJSGlobal(JSContext *context, JSObject **outGlobal)
167 : {
168 : assert(outGlobal != NULL);
169 :
170 : *outGlobal = JS_NewCompartmentAndGlobalObject(context, &sGlobalClass, NULL);
171 :
172 : JS_SetGlobalObject(context, *outGlobal);
173 : JS_DefineProperty(context, *outGlobal, "global", OBJECT_TO_JSVAL(*outGlobal), NULL, NULL, OOJS_PROP_READONLY);
174 : }
175 :
176 :
177 0 : void SetUpOOJSGlobal(JSContext *context, JSObject *global)
178 : {
179 : JS_DefineProperties(context, global, sGlobalProperties);
180 : JS_DefineFunctions(context, global, sGlobalMethods);
181 : }
182 :
183 :
184 0 : static JSBool GlobalGetProperty(JSContext *context, JSObject *this, jsid propID, jsval *value)
185 : {
186 : if (!JSID_IS_INT(propID)) return YES;
187 :
188 : OOJS_NATIVE_ENTER(context)
189 :
190 : PlayerEntity *player = OOPlayerForScripting();
191 :
192 : switch (JSID_TO_INT(propID))
193 : {
194 : case kGlobal_galaxyNumber:
195 : *value = INT_TO_JSVAL([player currentGalaxyID]);
196 : return YES;
197 :
198 : case kGlobal_guiScreen:
199 : *value = OOJSValueFromGUIScreenID(context, [player guiScreen]);
200 : return YES;
201 :
202 : case kGlobal_postFX:
203 : *value = INT_TO_JSVAL([UNIVERSE currentPostFX]);
204 : return YES;
205 :
206 : #ifndef NDEBUG
207 : case kGlobal_timeAccelerationFactor:
208 : return JS_NewNumberValue(context, [UNIVERSE timeAccelerationFactor], value);
209 : #endif
210 :
211 : default:
212 : OOJSReportBadPropertySelector(context, this, propID, sGlobalProperties);
213 : return NO;
214 : }
215 :
216 : OOJS_NATIVE_EXIT
217 : }
218 :
219 :
220 : #ifndef NDEBUG
221 0 : static JSBool GlobalSetProperty(JSContext *context, JSObject *this, jsid propID, JSBool strict, jsval *value)
222 : {
223 : if (!JSID_IS_INT(propID)) return YES;
224 :
225 : OOJS_NATIVE_ENTER(context)
226 :
227 : jsdouble fValue;
228 : int32 iValue;
229 :
230 : switch (JSID_TO_INT(propID))
231 : {
232 : case kGlobal_postFX:
233 : if (JS_ValueToInt32(context, *value, &iValue))
234 : {
235 : iValue = MAX(iValue, 0);
236 : [UNIVERSE setCurrentPostFX:iValue];
237 : return YES;
238 : }
239 : break;
240 :
241 : case kGlobal_timeAccelerationFactor:
242 : if (JS_ValueToNumber(context, *value, &fValue))
243 : {
244 : [UNIVERSE setTimeAccelerationFactor:fValue];
245 : return YES;
246 : }
247 : break;
248 :
249 : default:
250 : OOJSReportBadPropertySelector(context, this, propID, sGlobalProperties);
251 : }
252 :
253 : OOJSReportBadPropertyValue(context, this, propID, sGlobalProperties, *value);
254 : return NO;
255 :
256 : OOJS_NATIVE_EXIT
257 : }
258 : #endif
259 :
260 :
261 : // *** Methods ***
262 :
263 : // log([messageClass : String,] message : string, ...)
264 0 : static JSBool GlobalLog(JSContext *context, uintN argc, jsval *vp)
265 : {
266 : OOJS_NATIVE_ENTER(context)
267 :
268 : NSString *message = nil;
269 : NSString *messageClass = nil;
270 :
271 : if (EXPECT_NOT(argc < 1))
272 : {
273 : OOJS_RETURN_VOID;
274 : }
275 : if (argc < 2)
276 : {
277 : messageClass = kOOLogDebugMessage;
278 : message = OOStringFromJSValue(context, OOJS_ARGV[0]);
279 : }
280 : else
281 : {
282 : messageClass = OOStringFromJSValueEvenIfNull(context, OOJS_ARGV[0]);
283 : if (!OOLogWillDisplayMessagesInClass(messageClass))
284 : {
285 : // Do nothing (and short-circuit) if message class is filtered out.
286 : OOJS_RETURN_VOID;
287 : }
288 :
289 : message = [NSString concatenationOfStringsFromJavaScriptValues:OOJS_ARGV + 1 count:argc - 1 separator:@", " inContext:context];
290 : }
291 :
292 : OOJS_BEGIN_FULL_NATIVE(context)
293 : OOLog(messageClass, @"%@", message);
294 :
295 : #if OOJSENGINE_MONITOR_SUPPORT
296 : [[OOJavaScriptEngine sharedEngine] sendMonitorLogMessage:message
297 : withMessageClass:nil
298 : inContext:context];
299 : #endif
300 : OOJS_END_FULL_NATIVE
301 :
302 : OOJS_RETURN_VOID;
303 :
304 : OOJS_NATIVE_EXIT
305 : }
306 :
307 :
308 : // expandDescription(description : String [, overrides : object (dictionary)]) : String
309 0 : static JSBool GlobalExpandDescription(JSContext *context, uintN argc, jsval *vp)
310 : {
311 : OOJS_NATIVE_ENTER(context)
312 :
313 : NSString *string = nil;
314 : NSDictionary *overrides = nil;
315 :
316 : if (argc > 0) string = OOStringFromJSValue(context, OOJS_ARGV[0]);
317 : if (string == nil)
318 : {
319 : OOJSReportBadArguments(context, nil, @"expandDescription", MIN(argc, 1U), OOJS_ARGV, nil, @"string");
320 : return NO;
321 : }
322 : if (argc > 1)
323 : {
324 : overrides = OOJSDictionaryFromStringTable(context, OOJS_ARGV[1]);
325 : }
326 :
327 : OOJS_BEGIN_FULL_NATIVE(context)
328 : string = OOExpandDescriptionString(kNilRandomSeed, string, overrides, nil, nil, kOOExpandForJavaScript | kOOExpandGoodRNG);
329 : OOJS_END_FULL_NATIVE
330 :
331 : OOJS_RETURN_OBJECT(string);
332 :
333 : OOJS_NATIVE_EXIT
334 : }
335 :
336 0 : static JSBool GlobalKeyBindingDescription(JSContext *context, uintN argc, jsval *vp)
337 : {
338 : OOJS_NATIVE_ENTER(context)
339 :
340 : NSString *string = nil;
341 : PlayerEntity *player = OOPlayerForScripting();
342 :
343 : if (argc > 0) string = OOStringFromJSValue(context, OOJS_ARGV[0]);
344 : if (string == nil)
345 : {
346 : OOJSReportBadArguments(context, nil, @"keyBindingDescription", MIN(argc, 1U), OOJS_ARGV, nil, @"string");
347 : return NO;
348 : }
349 :
350 : OOJS_BEGIN_FULL_NATIVE(context)
351 : string = [player keyBindingDescription2:string];
352 : OOJS_END_FULL_NATIVE
353 :
354 : OOJS_RETURN_OBJECT(string);
355 :
356 : OOJS_NATIVE_EXIT
357 : }
358 :
359 :
360 : // expandMissionText(textKey : String [, overrides : object (dictionary)]) : String
361 0 : static JSBool GlobalExpandMissionText(JSContext *context, uintN argc, jsval *vp)
362 : {
363 : OOJS_NATIVE_ENTER(context)
364 :
365 : NSString *string = nil;
366 : NSDictionary *overrides = nil;
367 :
368 : if (argc > 0) string = OOStringFromJSValue(context, OOJS_ARGV[0]);
369 : if (string == nil)
370 : {
371 : OOJSReportBadArguments(context, nil, @"expandMissionText", MIN(argc, 1U), OOJS_ARGV, nil, @"string");
372 : return NO;
373 : }
374 : if (argc > 1)
375 : {
376 : overrides = OOJSDictionaryFromStringTable(context, OOJS_ARGV[1]);
377 : }
378 :
379 : string = [[UNIVERSE missiontext] oo_stringForKey:string];
380 : string = OOExpandDescriptionString(kNilRandomSeed, string, overrides, nil, nil, kOOExpandForJavaScript | kOOExpandBackslashN | kOOExpandGoodRNG);
381 :
382 : OOJS_RETURN_OBJECT(string);
383 :
384 : OOJS_NATIVE_EXIT
385 : }
386 :
387 :
388 : // displayNameForCommodity(commodityName : String) : String
389 0 : static JSBool GlobalDisplayNameForCommodity(JSContext *context, uintN argc, jsval *vp)
390 : {
391 : OOJS_NATIVE_ENTER(context)
392 :
393 : NSString *string = nil;
394 :
395 : if (argc > 0) string = OOStringFromJSValue(context,OOJS_ARGV[0]);
396 : if (string == nil)
397 : {
398 : OOJSReportBadArguments(context, nil, @"displayNameForCommodity", MIN(argc, 1U), OOJS_ARGV, nil, @"string");
399 : return NO;
400 : }
401 : OOJS_RETURN_OBJECT(CommodityDisplayNameForSymbolicName(string));
402 :
403 : OOJS_NATIVE_EXIT
404 : }
405 :
406 :
407 : // randomName() : String
408 0 : static JSBool GlobalRandomName(JSContext *context, uintN argc, jsval *vp)
409 : {
410 : OOJS_NATIVE_ENTER(context)
411 :
412 : /* Temporarily set the system generation seed to a "really random" seed,
413 : so randomName() isn't repeatable.
414 : */
415 : RNG_Seed savedSeed = currentRandomSeed();
416 : setRandomSeed((RNG_Seed){ Ranrot(), Ranrot(), Ranrot(), Ranrot() });
417 :
418 : NSString *result = OOExpand(@"%N");
419 :
420 : // Restore seed.
421 : setRandomSeed(savedSeed);
422 :
423 : OOJS_RETURN_OBJECT(result);
424 :
425 : OOJS_NATIVE_EXIT
426 : }
427 :
428 :
429 : // randomInhabitantsDescription() : String
430 0 : static JSBool GlobalRandomInhabitantsDescription(JSContext *context, uintN argc, jsval *vp)
431 : {
432 : OOJS_NATIVE_ENTER(context)
433 :
434 : NSString *string = nil;
435 : Random_Seed aSeed;
436 : JSBool isPlural = YES;
437 :
438 : if (argc > 0 && !JS_ValueToBoolean(context, OOJS_ARGV[0], &isPlural))
439 : {
440 : OOJSReportBadArguments(context, nil, @"randomInhabitantsDescription", 1, OOJS_ARGV, nil, @"boolean");
441 : return NO;
442 : }
443 :
444 : make_pseudo_random_seed(&aSeed);
445 : string = [UNIVERSE getSystemInhabitants:Ranrot()%OO_SYSTEMS_PER_GALAXY plural:isPlural];
446 : OOJS_RETURN_OBJECT(string);
447 :
448 : OOJS_NATIVE_EXIT
449 : }
450 :
451 :
452 0 : static JSBool GlobalClearExtraGuiScreenKeys(JSContext *context, uintN argc, jsval *vp)
453 : {
454 : OOJS_NATIVE_ENTER(context)
455 :
456 : BOOL result = NO;
457 : PlayerEntity *player = OOPlayerForScripting();
458 :
459 : if (EXPECT_NOT(argc < 2))
460 : {
461 : OOJSReportBadArguments(context, nil, @"setExtraGuiScreenKeys", 0, OOJS_ARGV, nil, @"missing arguments");
462 : return NO;
463 : }
464 :
465 : NSString *key = OOStringFromJSValue(context, OOJS_ARGV[0]);
466 : if (EXPECT_NOT(key == nil || [key isEqualToString:@""]))
467 : {
468 : OOJSReportBadArguments(context, nil, @"clearExtraGuiScreenKeys", 1, OOJS_ARGV, nil, @"key");
469 : return NO;
470 : }
471 :
472 : OOGUIScreenID gui = OOGUIScreenIDFromJSValue(context, OOJS_ARGV[1]);
473 : if (!gui)
474 : {
475 : OOJSReportBadArguments(context, nil, @"clearExtraGuiScreenKeys", 0, OOJS_ARGV, nil, @"guiScreen invalid entry");
476 : return NO;
477 : }
478 :
479 : [player clearExtraGuiScreenKeys:gui key:key];
480 :
481 : result = YES;
482 : OOJS_RETURN_BOOL(result);
483 :
484 : OOJS_NATIVE_EXIT
485 : }
486 :
487 0 : static JSBool GlobalSetExtraGuiScreenKeys(JSContext *context, uintN argc, jsval *vp)
488 : {
489 : OOJS_NATIVE_ENTER(context)
490 :
491 : BOOL result = NO;
492 : jsval callback = JSVAL_NULL;
493 : JSObject *callbackThis = NULL;
494 : jsval value = JSVAL_NULL;
495 : NSString *key = nil;
496 : OOGUIScreenID gui;
497 : NSDictionary *keydefs = NULL;
498 : JSObject *params = NULL;
499 : PlayerEntity *player = OOPlayerForScripting();
500 :
501 : if (EXPECT_NOT(argc < 1))
502 : {
503 : OOJSReportBadArguments(context, nil, @"setExtraGuiScreenKeys", 0, OOJS_ARGV, nil, @"key, definition");
504 : return NO;
505 : }
506 : key = OOStringFromJSValue(context, OOJS_ARGV[0]);
507 :
508 : // Validate arguments.
509 : if (argc < 2 || !JS_ValueToObject(context, OOJS_ARGV[1], ¶ms))
510 : {
511 : OOJSReportBadArguments(context, @"global", @"setExtraGuiScreenKeys", 2, &OOJS_ARGV[1], nil, @"key, definition: definition is not a valid dictionary.");
512 : return NO;
513 : }
514 :
515 : if (JS_GetProperty(context, params, "guiScreen", &value) == JS_FALSE || JSVAL_IS_VOID(value))
516 : {
517 : OOJSReportBadArguments(context, @"global", @"setExtraGuiScreenKeys", 2, &OOJS_ARGV[1], nil, @"key, definition: must have a 'guiScreen' property.");
518 : return NO;
519 : }
520 :
521 : gui = OOGUIScreenIDFromJSValue(context, value);
522 : // gui will be 0 for invalid screen id's as well as GUI_SCREEN_MAIN
523 : if (gui == 0 || gui == GUI_SCREEN_LOAD || gui == GUI_SCREEN_SAVE || gui == GUI_SCREEN_STICKMAPPER || gui == GUI_SCREEN_OXZMANAGER ||
524 : gui == GUI_SCREEN_NEWGAME || gui == GUI_SCREEN_SAVE_OVERWRITE || gui == GUI_SCREEN_KEYBOARD || gui == GUI_SCREEN_STICKPROFILE || gui == GUI_SCREEN_KEYBOARD_CONFIRMCLEAR ||
525 : gui == GUI_SCREEN_KEYBOARD_CONFIG || gui == GUI_SCREEN_KEYBOARD_ENTRY || gui == GUI_SCREEN_KEYBOARD_LAYOUT)
526 : {
527 : OOJSReportBadArguments(context, @"global", @"setExtraGuiScreenKeys", 2, &OOJS_ARGV[1], nil, @"key, definition: 'guiScreen' property must be a permitted and valid GUI_SCREEN idenfifier.");
528 : return NO;
529 : }
530 :
531 : if (JS_GetProperty(context, params, "registerKeys", &value) == JS_FALSE || JSVAL_IS_VOID(value))
532 : {
533 : OOJSReportBadArguments(context, @"global", @"setExtraGuiScreenKeys", 2, &OOJS_ARGV[1], nil, @"key, definition: must have a 'registerKeys' property.");
534 : return NO;
535 : }
536 : if (!JSVAL_IS_NULL(value))
537 : {
538 : if (JSVAL_IS_OBJECT(value))
539 : {
540 : keydefs = OOJSNativeObjectFromJSObject(context, JSVAL_TO_OBJECT(value));
541 : }
542 : else
543 : {
544 : OOJSReportBadArguments(context, @"global", @"setExtraGuiScreenKeys", 2, &OOJS_ARGV[1], nil, @"key, definition: registerKeys is not a valid dictionary.");
545 : return NO;
546 : }
547 : }
548 :
549 : if (JS_GetProperty(context, params, "callback", &callback) == JS_FALSE || JSVAL_IS_VOID(callback))
550 : {
551 : OOJSReportBadArguments(context, @"global", @"setExtraGuiScreenKeys", 2, &OOJS_ARGV[1], NULL, @"key, definition; must have a 'callback' property.");
552 : return NO;
553 : }
554 : if (!OOJSValueIsFunction(context,callback))
555 : {
556 : OOJSReportBadArguments(context, @"global", @"setExtraGuiScreenKeys", 2, &OOJS_ARGV[1], NULL, @"key, definition; 'callback' property must be a function.");
557 : return NO;
558 : }
559 :
560 : OOJSGuiScreenKeyDefinition* definition = [[OOJSGuiScreenKeyDefinition alloc] init];
561 : [definition setName:key];
562 : [definition setRegisterKeys:keydefs];
563 : [definition setCallback:callback];
564 :
565 : // get callback 'this'
566 : if (JS_GetProperty(context, params, "cbThis", &value) == JS_TRUE && !JSVAL_IS_VOID(value))
567 : {
568 : JS_ValueToObject(context, value, &callbackThis);
569 : [definition setCallbackThis:callbackThis];
570 : // can do .bind(this) for callback instead
571 : }
572 :
573 : result = [player setExtraGuiScreenKeys:gui definition:definition];
574 : [definition release];
575 :
576 : OOJS_RETURN_BOOL(result);
577 :
578 : OOJS_NATIVE_EXIT
579 : }
580 :
581 :
582 : // setScreenBackground(descriptor : guiTextureDescriptor) : Boolean
583 0 : static JSBool GlobalSetScreenBackground(JSContext *context, uintN argc, jsval *vp)
584 : {
585 : OOJS_NATIVE_ENTER(context)
586 :
587 : BOOL result = NO;
588 : jsval value = (argc > 0) ? OOJS_ARGV[0] : JSVAL_NULL;
589 :
590 : if (EXPECT_NOT(argc == 0))
591 : {
592 : OOJSReportWarning(context, @"Usage error: %@() called with no arguments. Treating as %@(null). This call may fail in a future version of Oolite.", @"setScreenBackground", @"setScreenBackground");
593 : }
594 : else if (EXPECT_NOT(JSVAL_IS_VOID(value)))
595 : {
596 : OOJSReportBadArguments(context, nil, @"setScreenBackground", 1, &value, nil, @"GUI texture descriptor");
597 : return NO;
598 : }
599 :
600 : if ([UNIVERSE viewDirection] == VIEW_GUI_DISPLAY)
601 : {
602 : GuiDisplayGen *gui = [UNIVERSE gui];
603 : NSDictionary *descriptor = [gui textureDescriptorFromJSValue:value inContext:context callerDescription:@"setScreenBackground()"];
604 :
605 : result = [gui setBackgroundTextureDescriptor:descriptor];
606 :
607 : // add some permanence to the override if we're in the equip ship screen
608 : if (result && [PLAYER guiScreen] == GUI_SCREEN_EQUIP_SHIP) [PLAYER setEquipScreenBackgroundDescriptor:descriptor];
609 : }
610 :
611 : OOJS_RETURN_BOOL(result);
612 :
613 : OOJS_NATIVE_EXIT
614 : }
615 :
616 :
617 0 : static JSBool GlobalGetScreenBackgroundForKey(JSContext *context, uintN argc, jsval *vp)
618 : {
619 : OOJS_NATIVE_ENTER(context)
620 :
621 : if (EXPECT_NOT(argc == 0))
622 : {
623 : OOJSReportBadArguments(context, nil, @"getScreenBackgroundDefault", 0, OOJS_ARGV, nil, @"missing arguments");
624 : return NO;
625 : }
626 : NSString *key = OOStringFromJSValue(context, OOJS_ARGV[0]);
627 : if (EXPECT_NOT(key == nil || [key isEqualToString:@""]))
628 : {
629 : OOJSReportBadArguments(context, nil, @"getScreenBackgroundDefault", 0, OOJS_ARGV, nil, @"key");
630 : return NO;
631 : }
632 : NSDictionary *descriptor = [UNIVERSE screenTextureDescriptorForKey:key];
633 :
634 : OOJS_RETURN_OBJECT(descriptor);
635 :
636 : OOJS_NATIVE_EXIT
637 : }
638 :
639 : // setScreenBackgroundDefault (key : NSString, descriptor : guiTextureDescriptor) : boolean
640 0 : static JSBool GlobalSetScreenBackgroundForKey(JSContext *context, uintN argc, jsval *vp)
641 : {
642 : OOJS_NATIVE_ENTER(context)
643 :
644 : BOOL result = NO;
645 :
646 : if (EXPECT_NOT(argc < 2))
647 : {
648 : OOJSReportBadArguments(context, nil, @"setScreenBackgroundDefault", 0, OOJS_ARGV, nil, @"missing arguments");
649 : return NO;
650 : }
651 :
652 : NSString *key = OOStringFromJSValue(context, OOJS_ARGV[0]);
653 : jsval value = OOJS_ARGV[1];
654 : if (EXPECT_NOT(key == nil || [key isEqualToString:@""]))
655 : {
656 : OOJSReportBadArguments(context, nil, @"setScreenBackgroundDefault", 0, OOJS_ARGV, nil, @"key");
657 : return NO;
658 : }
659 :
660 : GuiDisplayGen *gui = [UNIVERSE gui];
661 : NSDictionary *descriptor = [gui textureDescriptorFromJSValue:value inContext:context callerDescription:@"setScreenBackgroundDefault()"];
662 :
663 : [UNIVERSE setScreenTextureDescriptorForKey:key descriptor:descriptor];
664 : result = YES;
665 :
666 : OOJS_RETURN_BOOL(result);
667 :
668 : OOJS_NATIVE_EXIT
669 : }
670 :
671 :
672 : // setScreenOverlay(descriptor : guiTextureDescriptor) : Boolean
673 0 : static JSBool GlobalSetScreenOverlay(JSContext *context, uintN argc, jsval *vp)
674 : {
675 : OOJS_NATIVE_ENTER(context)
676 :
677 : BOOL result = NO;
678 : jsval value = (argc > 0) ? OOJS_ARGV[0] : JSVAL_NULL;
679 :
680 : if (EXPECT_NOT(argc == 0))
681 : {
682 : OOJSReportWarning(context, @"Usage error: %@() called with no arguments. Treating as %@(null). This call may fail in a future version of Oolite.", @"setScreenOverlay", @"setScreenOverlay");
683 : }
684 : else if (EXPECT_NOT(JSVAL_IS_VOID(value)))
685 : {
686 : OOJSReportBadArguments(context, nil, @"setScreenOverlay", 1, &value, nil, @"GUI texture descriptor");
687 : return NO;
688 : }
689 :
690 : if ([UNIVERSE viewDirection] == VIEW_GUI_DISPLAY)
691 : {
692 : GuiDisplayGen *gui = [UNIVERSE gui];
693 : NSDictionary *descriptor = [gui textureDescriptorFromJSValue:value inContext:context callerDescription:@"setScreenOverlay()"];
694 :
695 : result = [gui setForegroundTextureDescriptor:descriptor];
696 : }
697 :
698 : OOJS_RETURN_BOOL(result);
699 :
700 : OOJS_NATIVE_EXIT
701 : }
702 :
703 :
704 0 : static JSBool GlobalGetGuiColorSettingForKey(JSContext *context, uintN argc, jsval *vp)
705 : {
706 : OOJS_NATIVE_ENTER(context)
707 :
708 : if (EXPECT_NOT(argc == 0))
709 : {
710 : OOJSReportBadArguments(context, nil, @"getGuiColorForKey", 0, OOJS_ARGV, nil, @"missing arguments");
711 : return NO;
712 : }
713 : NSString *key = OOStringFromJSValue(context, OOJS_ARGV[0]);
714 : if (EXPECT_NOT(key == nil || [key isEqualToString:@""]))
715 : {
716 : OOJSReportBadArguments(context, nil, @"getGuiColorForKey", 0, OOJS_ARGV, nil, @"key");
717 : return NO;
718 : }
719 : if ([key rangeOfString:@"color"].location == NSNotFound)
720 : {
721 : OOJSReportBadArguments(context, nil, @"getGuiColorForKey", 0, OOJS_ARGV, nil, @"valid color key setting");
722 : return NO;
723 : }
724 :
725 : GuiDisplayGen *gui = [UNIVERSE gui];
726 : OOColor *col = [gui colorFromSetting:key defaultValue:nil];
727 :
728 : OOJS_RETURN_OBJECT([col normalizedArray]);
729 :
730 : OOJS_NATIVE_EXIT
731 : }
732 :
733 :
734 : // setGuiColorForKey(descriptor : OOColor) : boolean
735 0 : static JSBool GlobalSetGuiColorSettingForKey(JSContext *context, uintN argc, jsval *vp)
736 : {
737 : OOJS_NATIVE_ENTER(context)
738 :
739 : BOOL result = NO;
740 : OOColor *col = nil;
741 :
742 : if (EXPECT_NOT(argc != 2))
743 : {
744 : OOJSReportBadArguments(context, nil, @"setGuiColorForKey", 0, OOJS_ARGV, nil, @"missing arguments");
745 : return NO;
746 : }
747 :
748 : NSString *key = OOStringFromJSValue(context, OOJS_ARGV[0]);
749 : jsval value = OOJS_ARGV[1];
750 : if (EXPECT_NOT(key == nil || [key isEqualToString:@""]))
751 : {
752 : OOJSReportBadArguments(context, nil, @"setGuiColorForKey", 0, OOJS_ARGV, nil, @"key");
753 : return NO;
754 : }
755 : if ([key rangeOfString:@"color"].location == NSNotFound)
756 : {
757 : OOJSReportBadArguments(context, nil, @"setGuiColorForKey", 0, OOJS_ARGV, nil, @"valid color key setting");
758 : return NO;
759 : }
760 :
761 : if (!JSVAL_IS_NULL(value))
762 : {
763 : col = [OOColor colorWithDescription:OOJSNativeObjectFromJSValue(context, value)];
764 : if (col == nil)
765 : {
766 : OOJSReportBadArguments(context, nil, @"setGuiColorForKey", 1, OOJS_ARGV, nil, @"color descriptor");
767 : return NO;
768 : }
769 : }
770 :
771 : GuiDisplayGen *gui = [UNIVERSE gui];
772 : [gui setGuiColorSettingFromKey:key color:col];
773 : result = YES;
774 :
775 : OOJS_RETURN_BOOL(result);
776 :
777 : OOJS_NATIVE_EXIT
778 : }
779 :
780 :
781 : // getColorSaturation()
782 0 : static JSBool GlobalGetColorSaturation(JSContext *context, uintN argc, jsval *vp)
783 : {
784 : OOJS_NATIVE_ENTER(context)
785 :
786 : OOJS_RETURN_OBJECT([NSNumber numberWithFloat:[[UNIVERSE gameView] colorSaturation]]);
787 :
788 : OOJS_NATIVE_EXIT
789 : }
790 :
791 :
792 : // setColorSaturation([desiredSaturation : Number])
793 0 : static JSBool GlobalSetColorSaturation(JSContext *context, uintN argc, jsval *vp)
794 : {
795 : OOJS_NATIVE_ENTER(context)
796 :
797 : jsdouble desiredColorSaturation = 0;
798 :
799 : if (argc < 1 || EXPECT_NOT(!JS_ValueToNumber(context, OOJS_ARGV[0], &desiredColorSaturation))) return NO;
800 :
801 : MyOpenGLView *gameView = [UNIVERSE gameView];
802 : float currentColorSaturation = [gameView colorSaturation];
803 : [gameView adjustColorSaturation:desiredColorSaturation - currentColorSaturation];
804 :
805 : OOJS_RETURN_VOID;
806 :
807 : OOJS_NATIVE_EXIT
808 : }
809 :
810 :
811 : #ifndef NDEBUG
812 : // takeSnapShot([name : alphanumeric String]) : Boolean
813 0 : static JSBool GlobalTakeSnapShot(JSContext *context, uintN argc, jsval *vp)
814 : {
815 : OOJS_NATIVE_ENTER(context)
816 :
817 : NSString *value = nil;
818 : NSMutableCharacterSet *allowedChars = (NSMutableCharacterSet *)[NSMutableCharacterSet alphanumericCharacterSet];
819 : BOOL result = NO;
820 :
821 : [allowedChars addCharactersInString:@"_-"];
822 :
823 : if (argc > 0)
824 : {
825 : value = OOStringFromJSValue(context, OOJS_ARGV[0]);
826 : if (EXPECT_NOT(value == nil || [value rangeOfCharacterFromSet:[allowedChars invertedSet]].location != NSNotFound))
827 : {
828 : OOJSReportBadArguments(context, nil, @"takeSnapShot", argc, OOJS_ARGV, nil, @"alphanumeric string");
829 : return NO;
830 : }
831 : }
832 :
833 : NSString *playerFileDirectory = [[NSFileManager defaultManager] defaultCommanderPath];
834 : NSDictionary *attr = [[NSFileManager defaultManager] oo_fileSystemAttributesAtPath:playerFileDirectory];
835 :
836 : if (attr != nil)
837 : {
838 : double freeSpace = [attr oo_doubleForKey:NSFileSystemFreeSize];
839 : if (freeSpace < 1073741824) // less than 1 GB free on disk?
840 : {
841 : OOJSReportWarning(context, @"takeSnapShot: function disabled when free disk space is less than 1GB.");
842 : OOJS_RETURN_BOOL(NO);
843 : }
844 : }
845 :
846 :
847 : OOJS_BEGIN_FULL_NATIVE(context)
848 : result = [[UNIVERSE gameView] snapShot:value];
849 : OOJS_END_FULL_NATIVE
850 :
851 : OOJS_RETURN_BOOL(result);
852 :
853 : OOJS_NATIVE_EXIT
854 : }
855 : #endif
856 :
857 : // autoAIForRole(role : String) : String
858 0 : static JSBool GlobalAutoAIForRole(JSContext *context, uintN argc, jsval *vp)
859 : {
860 : OOJS_NATIVE_ENTER(context)
861 :
862 : NSString *string = nil;
863 :
864 : if (argc > 0) string = OOStringFromJSValue(context,OOJS_ARGV[0]);
865 : if (string == nil)
866 : {
867 : OOJSReportBadArguments(context, nil, @"autoAIForRole", MIN(argc, 1U), OOJS_ARGV, nil, @"string");
868 : return NO;
869 : }
870 :
871 : NSDictionary *autoAIMap = [ResourceManager dictionaryFromFilesNamed:@"autoAImap.plist" inFolder:@"Config" andMerge:YES];
872 : NSString *autoAI = [autoAIMap oo_stringForKey:string];
873 :
874 : OOJS_RETURN_OBJECT(autoAI);
875 :
876 : OOJS_NATIVE_EXIT
877 : }
878 :
879 : // pauseGame() : Boolean
880 0 : static JSBool GlobalPauseGame(JSContext *context, uintN argc, jsval *vp)
881 : {
882 : OOJS_NATIVE_ENTER(context)
883 :
884 : BOOL result = NO;
885 : PlayerEntity *player = PLAYER;
886 :
887 : if (player)
888 : {
889 : OOGUIScreenID guiScreen = [player guiScreen];
890 :
891 : if (guiScreen != GUI_SCREEN_LONG_RANGE_CHART &&
892 : guiScreen != GUI_SCREEN_MISSION &&
893 : guiScreen != GUI_SCREEN_REPORT &&
894 : guiScreen != GUI_SCREEN_KEYBOARD_ENTRY &&
895 : guiScreen != GUI_SCREEN_SAVE)
896 : {
897 : [UNIVERSE pauseGame];
898 : result = YES;
899 : }
900 : }
901 :
902 : OOJS_RETURN_BOOL(result);
903 :
904 : OOJS_NATIVE_EXIT
905 : }
|