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