Line data Source code
1 0 : /*
2 :
3 : OOJSSystemInfo.m
4 :
5 : Oolite
6 : Copyright (C) 2004-2013 Giles C Williams and contributors
7 :
8 : This program is free software; you can redistribute it and/or
9 : modify it under the terms of the GNU General Public License
10 : as published by the Free Software Foundation; either version 2
11 : of the License, or (at your option) any later version.
12 :
13 : This program is distributed in the hope that it will be useful,
14 : but WITHOUT ANY WARRANTY; without even the implied warranty of
15 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 : GNU General Public License for more details.
17 :
18 : You should have received a copy of the GNU General Public License
19 : along with this program; if not, write to the Free Software
20 : Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
21 : MA 02110-1301, USA.
22 :
23 : */
24 :
25 : #import "OOJSSystemInfo.h"
26 : #import "OOJavaScriptEngine.h"
27 : #import "PlayerEntityScriptMethods.h"
28 : #import "Universe.h"
29 : #import "OOJSVector.h"
30 : #import "OOIsNumberLiteral.h"
31 : #import "OOConstToString.h"
32 : #import "OOSystemDescriptionManager.h"
33 : #import "OOJSScript.h"
34 :
35 :
36 0 : static JSObject *sSystemInfoPrototype;
37 0 : static JSObject *sCachedSystemInfo;
38 0 : static OOGalaxyID sCachedGalaxy;
39 0 : static OOSystemID sCachedSystem;
40 :
41 :
42 : static JSBool SystemInfoDeleteProperty(JSContext *context, JSObject *this, jsid propID, jsval *value);
43 : static JSBool SystemInfoGetProperty(JSContext *context, JSObject *this, jsid propID, jsval *value);
44 : static JSBool SystemInfoSetProperty(JSContext *context, JSObject *this, jsid propID, JSBool strict, jsval *value);
45 : static void SystemInfoFinalize(JSContext *context, JSObject *this);
46 : static JSBool SystemInfoEnumerate(JSContext *context, JSObject *this, JSIterateOp enumOp, jsval *state, jsid *idp);
47 :
48 : static JSBool SystemInfoDistanceToSystem(JSContext *context, uintN argc, jsval *vp);
49 : static JSBool SystemInfoRouteToSystem(JSContext *context, uintN argc, jsval *vp);
50 : static JSBool SystemInfoSamplePrice(JSContext *context, uintN argc, jsval *vp);
51 : static JSBool SystemInfoSetPropertyMethod(JSContext *context, uintN argc, jsval *vp);
52 :
53 : static JSBool SystemInfoStaticSetInterstellarProperty(JSContext *context, uintN argc, jsval *vp);
54 : static JSBool SystemInfoStaticFilteredSystems(JSContext *context, uintN argc, jsval *vp);
55 :
56 :
57 0 : static JSClass sSystemInfoClass =
58 : {
59 : "SystemInfo",
60 : JSCLASS_HAS_PRIVATE | JSCLASS_NEW_ENUMERATE,
61 :
62 : JS_PropertyStub,
63 : SystemInfoDeleteProperty,
64 : SystemInfoGetProperty,
65 : SystemInfoSetProperty,
66 : (JSEnumerateOp)SystemInfoEnumerate,
67 : JS_ResolveStub,
68 : JS_ConvertStub,
69 : SystemInfoFinalize,
70 : JSCLASS_NO_OPTIONAL_MEMBERS
71 : };
72 :
73 :
74 0 : enum
75 : {
76 : // Property IDs
77 : kSystemInfo_coordinates, // system coordinates (in LY), Vector3D (with z = 0), read-only
78 : kSystemInfo_internalCoordinates, // system coordinates (unscaled), Vector3D (with z = 0), read-only
79 : kSystemInfo_galaxyID, // galaxy number, integer, read-only
80 : kSystemInfo_systemID // system number, integer, read-only
81 : };
82 :
83 :
84 0 : static JSPropertySpec sSystemInfoProperties[] =
85 : {
86 : // JS name ID flags
87 : { "coordinates", kSystemInfo_coordinates, OOJS_PROP_READONLY_CB },
88 : { "internalCoordinates", kSystemInfo_internalCoordinates, OOJS_PROP_READONLY_CB },
89 : { "galaxyID", kSystemInfo_galaxyID, OOJS_PROP_READONLY_CB },
90 : { "systemID", kSystemInfo_systemID, OOJS_PROP_READONLY_CB },
91 : { 0 }
92 : };
93 :
94 :
95 0 : static JSFunctionSpec sSystemInfoMethods[] =
96 : {
97 : // JS name Function min args
98 : { "toString", OOJSObjectWrapperToString, 0 },
99 : { "distanceToSystem", SystemInfoDistanceToSystem, 1 },
100 : { "routeToSystem", SystemInfoRouteToSystem, 1 },
101 : { "samplePrice", SystemInfoSamplePrice, 1 },
102 : { "setProperty", SystemInfoSetPropertyMethod, 3 },
103 : { 0 }
104 : };
105 :
106 :
107 0 : static JSFunctionSpec sSystemInfoStaticMethods[] =
108 : {
109 : // JS name Function min args
110 : { "filteredSystems", SystemInfoStaticFilteredSystems, 2 },
111 : { "setInterstellarProperty",SystemInfoStaticSetInterstellarProperty, 4 },
112 : { 0 }
113 : };
114 :
115 :
116 : // Helper class wrapped by JS SystemInfo objects
117 0 : @interface OOSystemInfo: NSObject
118 : {
119 : @private
120 0 : OOGalaxyID _galaxy;
121 0 : OOSystemID _system;
122 0 : NSString *_planetKey;
123 : }
124 :
125 0 : - (id) initWithGalaxy:(OOGalaxyID)galaxy system:(OOSystemID)system;
126 :
127 0 : - (id) valueForKey:(NSString *)key;
128 0 : - (void) setValue:(id)value forKey:(NSString *)key;
129 :
130 0 : - (NSArray *) allKeys;
131 :
132 0 : - (OOGalaxyID) galaxy;
133 0 : - (OOSystemID) system;
134 : //- (Random_Seed) systemSeed;
135 :
136 : @end
137 :
138 :
139 0 : DEFINE_JS_OBJECT_GETTER(JSSystemInfoGetSystemInfo, &sSystemInfoClass, sSystemInfoPrototype, OOSystemInfo);
140 :
141 :
142 : @implementation OOSystemInfo
143 :
144 0 : - (id) init
145 : {
146 : [self release];
147 : return nil;
148 : }
149 :
150 :
151 : - (id) initWithGalaxy:(OOGalaxyID)galaxy system:(OOSystemID)system
152 : {
153 : if (galaxy > kOOMaximumGalaxyID || system > kOOMaximumSystemID || system < kOOMinimumSystemID)
154 : {
155 : [self release];
156 : return nil;
157 : }
158 :
159 : if ((self = [super init]))
160 : {
161 : _galaxy = galaxy;
162 : _system = system;
163 : _planetKey = [[NSString stringWithFormat:@"%u %i", galaxy, system] retain];
164 : }
165 : return self;
166 : }
167 :
168 :
169 0 : - (void) dealloc
170 : {
171 : [_planetKey release];
172 :
173 : [super dealloc];
174 : }
175 :
176 :
177 0 : - (NSString *) descriptionComponents
178 : {
179 : return [NSString stringWithFormat:@"galaxy %u, system %i", _galaxy, _system];
180 : }
181 :
182 :
183 0 : - (NSString *) shortDescriptionComponents
184 : {
185 : return _planetKey;
186 : }
187 :
188 :
189 0 : - (NSString *) oo_jsClassName
190 : {
191 : return @"SystemInfo";
192 : }
193 :
194 :
195 0 : - (BOOL) isEqual:(id)other
196 : {
197 : return other == self ||
198 : ([other isKindOfClass:[OOSystemInfo class]] &&
199 : [other galaxy] == _galaxy &&
200 : [other system] == _system);
201 :
202 : }
203 :
204 :
205 0 : - (NSUInteger) hash
206 : {
207 : NSUInteger hash = _galaxy;
208 : hash <<= 16;
209 : hash |= (uint16_t)_system;
210 : return hash;
211 : }
212 :
213 :
214 : - (id) valueForKey:(NSString *)key
215 : {
216 : if ([UNIVERSE inInterstellarSpace] && _system == -1)
217 : {
218 : return [[UNIVERSE currentSystemData] objectForKey:key];
219 : }
220 : return [UNIVERSE systemDataForGalaxy:_galaxy planet:_system key:key];
221 : }
222 :
223 :
224 : - (void) setValue:(id)value forKey:(NSString *)key
225 : {
226 : NSString *manifest = [[OOJSScript currentlyRunningScript] propertyNamed:kLocalManifestProperty];
227 :
228 : [UNIVERSE setSystemDataForGalaxy:_galaxy planet:_system key:key value:value fromManifest:manifest forLayer:OO_LAYER_OXP_DYNAMIC];
229 : }
230 :
231 :
232 : - (NSArray *) allKeys
233 : {
234 : if ([UNIVERSE inInterstellarSpace] && _system == -1)
235 : {
236 : return [[UNIVERSE currentSystemData] allKeys];
237 : }
238 : return [UNIVERSE systemDataKeysForGalaxy:_galaxy planet:_system];
239 : }
240 :
241 :
242 : - (OOGalaxyID) galaxy
243 : {
244 : return _galaxy;
245 : }
246 :
247 :
248 : - (OOSystemID) system
249 : {
250 : return _system;
251 : }
252 :
253 :
254 : /*- (Random_Seed) systemSeed
255 : {
256 : NSAssert([PLAYER currentGalaxyID] == _galaxy, @"Attempt to use -[OOSystemInfo systemSeed] from a different galaxy.");
257 : return [UNIVERSE systemSeedForSystemNumber:_system];
258 : }*/
259 :
260 :
261 0 : - (NSPoint) coordinates
262 : {
263 : if ([UNIVERSE inInterstellarSpace] && _system == -1)
264 : {
265 : return [PLAYER galaxy_coordinates];
266 : }
267 : return [UNIVERSE coordinatesForSystem:_system];
268 : }
269 :
270 :
271 0 : - (jsval) oo_jsValueInContext:(JSContext *)context
272 : {
273 : JSObject *jsSelf = NULL;
274 : jsval result = JSVAL_NULL;
275 :
276 : jsSelf = JS_NewObject(context, &sSystemInfoClass, sSystemInfoPrototype, NULL);
277 : if (jsSelf != NULL)
278 : {
279 : if (!JS_SetPrivate(context, jsSelf, [self retain])) jsSelf = NULL;
280 : }
281 : if (jsSelf != NULL) result = OBJECT_TO_JSVAL(jsSelf);
282 :
283 : return result;
284 : }
285 :
286 : @end
287 :
288 :
289 :
290 0 : void InitOOJSSystemInfo(JSContext *context, JSObject *global)
291 : {
292 : sSystemInfoPrototype = JS_InitClass(context, global, NULL, &sSystemInfoClass, OOJSUnconstructableConstruct, 0, sSystemInfoProperties, sSystemInfoMethods, NULL, sSystemInfoStaticMethods);
293 : OOJSRegisterObjectConverter(&sSystemInfoClass, OOJSBasicPrivateObjectConverter);
294 : }
295 :
296 :
297 0 : jsval GetJSSystemInfoForSystem(JSContext *context, OOGalaxyID galaxy, OOSystemID system)
298 : {
299 : OOJS_PROFILE_ENTER
300 :
301 : // Use cached object if possible.
302 : if (sCachedSystemInfo != NULL &&
303 : sCachedGalaxy == galaxy &&
304 : sCachedSystem == system)
305 : {
306 : return OBJECT_TO_JSVAL(sCachedSystemInfo);
307 : }
308 :
309 : // If not, create a new one.
310 : OOSystemInfo *info = nil;
311 : jsval result;
312 : OOJS_BEGIN_FULL_NATIVE(context)
313 : info = [[[OOSystemInfo alloc] initWithGalaxy:galaxy system:system] autorelease];
314 : OOJS_END_FULL_NATIVE
315 :
316 : if (EXPECT_NOT(info == nil))
317 : {
318 : OOJSReportWarning(context, @"Could not create system info object for galaxy %u, system %i.", galaxy, system);
319 : }
320 :
321 : result = OOJSValueFromNativeObject(context, info);
322 :
323 : // Cache is not a root; we clear it in finalize if necessary.
324 : sCachedSystemInfo = JSVAL_TO_OBJECT(result);
325 : sCachedGalaxy = galaxy;
326 : sCachedSystem = system;
327 :
328 : return result;
329 :
330 : OOJS_PROFILE_EXIT_JSVAL
331 : }
332 :
333 :
334 0 : static void SystemInfoFinalize(JSContext *context, JSObject *this)
335 : {
336 : OOJS_PROFILE_ENTER
337 :
338 : [(id)JS_GetPrivate(context, this) release];
339 : JS_SetPrivate(context, this, nil);
340 :
341 : // Clear now-stale cache entry if appropriate.
342 : if (sCachedSystemInfo == this) sCachedSystemInfo = NULL;
343 :
344 : OOJS_PROFILE_EXIT_VOID
345 : }
346 :
347 :
348 0 : static JSBool SystemInfoEnumerate(JSContext *context, JSObject *this, JSIterateOp enumOp, jsval *state, jsid *idp)
349 : {
350 : OOJS_NATIVE_ENTER(context)
351 :
352 : NSEnumerator *enumerator = nil;
353 :
354 : switch (enumOp)
355 : {
356 : case JSENUMERATE_INIT:
357 : case JSENUMERATE_INIT_ALL: // For ES5 Object.getOwnPropertyNames(). Since we have no non-enumerable properties, this is the same as _INIT.
358 : {
359 : OOSystemInfo *info = JS_GetPrivate(context, this);
360 : NSArray *keys = [info allKeys];
361 : enumerator = [[keys objectEnumerator] retain];
362 : *state = PRIVATE_TO_JSVAL(enumerator);
363 :
364 : NSUInteger count = [keys count];
365 : assert(count <= INT32_MAX);
366 : if (idp != NULL) *idp = INT_TO_JSID((int32_t)count);
367 : return YES;
368 : }
369 :
370 : case JSENUMERATE_NEXT:
371 : {
372 : enumerator = JSVAL_TO_PRIVATE(*state);
373 : NSString *next = [enumerator nextObject];
374 : if (next != nil)
375 : {
376 : jsval val = [next oo_jsValueInContext:context];
377 : return JS_ValueToId(context, val, idp);
378 : }
379 : // else:
380 : *state = JSVAL_NULL;
381 : // Fall through.
382 : }
383 :
384 : case JSENUMERATE_DESTROY:
385 : {
386 : if (enumerator == nil && JSVAL_IS_DOUBLE(*state))
387 : {
388 : enumerator = JSVAL_TO_PRIVATE(*state);
389 : }
390 : [enumerator release];
391 :
392 : if (idp != NULL) *idp = JSID_VOID;
393 : return YES;
394 : }
395 : }
396 :
397 :
398 :
399 : OOJS_NATIVE_EXIT
400 : }
401 :
402 :
403 0 : static JSBool SystemInfoDeleteProperty(JSContext *context, JSObject *this, jsid propID, jsval *value)
404 : {
405 : OOJS_PROFILE_ENTER // Any exception will be converted in SystemInfoSetProperty()
406 :
407 : jsval v = JSVAL_VOID;
408 : return SystemInfoSetProperty(context, this, propID, NO, &v);
409 :
410 : OOJS_PROFILE_EXIT
411 : }
412 :
413 :
414 0 : static JSBool SystemInfoGetProperty(JSContext *context, JSObject *this, jsid propID, jsval *value)
415 : {
416 : OOJS_NATIVE_ENTER(context)
417 :
418 : if (this == sSystemInfoPrototype)
419 : {
420 : // Let SpiderMonkey handle access to the prototype object (where info will be nil).
421 : return YES;
422 : }
423 :
424 : OOSystemInfo *info = OOJSNativeObjectOfClassFromJSObject(context, this, [OOSystemInfo class]);
425 : // What if we're trying to access a saved witchspace systemInfo object?
426 : BOOL savedInterstellarInfo = ![UNIVERSE inInterstellarSpace] && [info system] == -1;
427 : BOOL sameGalaxy = [PLAYER currentGalaxyID] == [info galaxy];
428 :
429 :
430 : if (JSID_IS_INT(propID))
431 : {
432 : switch (JSID_TO_INT(propID))
433 : {
434 : case kSystemInfo_coordinates:
435 : if (sameGalaxy && !savedInterstellarInfo)
436 : {
437 : return VectorToJSValue(context, OOGalacticCoordinatesFromInternal([info coordinates]), value);
438 : }
439 : else
440 : {
441 : OOJSReportError(context, @"Cannot read systemInfo values for %@.", savedInterstellarInfo ? @"invalid interstellar space reference" : @"other galaxies");
442 : return NO;
443 : }
444 : break;
445 :
446 : case kSystemInfo_internalCoordinates:
447 : if (sameGalaxy && !savedInterstellarInfo)
448 : {
449 : return NSPointToVectorJSValue(context, [info coordinates], value);
450 : }
451 : else
452 : {
453 : OOJSReportError(context, @"Cannot read systemInfo values for %@.", savedInterstellarInfo ? @"invalid interstellar space reference" : @"other galaxies");
454 : return NO;
455 : }
456 : break;
457 :
458 : case kSystemInfo_galaxyID:
459 : *value = INT_TO_JSVAL([info galaxy]);
460 : return YES;
461 :
462 : case kSystemInfo_systemID:
463 : *value = INT_TO_JSVAL([info system]);
464 : return YES;
465 :
466 : default:
467 : OOJSReportBadPropertySelector(context, this, propID, sSystemInfoProperties);
468 : return NO;
469 : }
470 : }
471 : else if (JSID_IS_STRING(propID))
472 : {
473 : NSString *key = OOStringFromJSString(context, JSID_TO_STRING(propID));
474 :
475 : OOSystemDescriptionManager *systemManager = [UNIVERSE systemManager];
476 : id propValue = nil;
477 : // interstellar space needs more work at this stage
478 : if ([info system] != -1)
479 : {
480 : propValue = [systemManager getProperty:key forSystem:[info system] inGalaxy:[info galaxy]];
481 : } else {
482 : propValue = [info valueForKey:key];
483 : }
484 :
485 : if (propValue != nil)
486 : {
487 : if ([propValue isKindOfClass:[NSNumber class]] || OOIsNumberLiteral([propValue description], YES))
488 : {
489 : BOOL OK = JS_NewNumberValue(context, [propValue doubleValue], value);
490 : if (!OK)
491 : {
492 : *value = JSVAL_VOID;
493 : return NO;
494 : }
495 : }
496 : else
497 : {
498 : *value = [propValue oo_jsValueInContext:context];
499 : }
500 : }
501 : }
502 : return YES;
503 :
504 : OOJS_NATIVE_EXIT
505 : }
506 :
507 :
508 0 : static JSBool SystemInfoSetProperty(JSContext *context, JSObject *this, jsid propID, JSBool strict, jsval *value)
509 : {
510 : if (EXPECT_NOT(this == sSystemInfoPrototype))
511 : {
512 : // Let SpiderMonkey handle access to the prototype object (where info will be nil).
513 : return YES;
514 : }
515 :
516 : OOJS_NATIVE_ENTER(context);
517 :
518 : if (JSID_IS_STRING(propID))
519 : {
520 : NSString *key = OOStringFromJSString(context, JSID_TO_STRING(propID));
521 : OOSystemInfo *info = OOJSNativeObjectOfClassFromJSObject(context, this, [OOSystemInfo class]);
522 :
523 : [info setValue:OOStringFromJSValue(context, *value) forKey:key];
524 : }
525 : return YES;
526 :
527 : OOJS_NATIVE_EXIT
528 : }
529 :
530 :
531 : // distanceToSystem(sys : SystemInfo) : Number
532 0 : static JSBool SystemInfoDistanceToSystem(JSContext *context, uintN argc, jsval *vp)
533 : {
534 : OOJS_NATIVE_ENTER(context)
535 :
536 : OOSystemInfo *thisInfo = nil;
537 : JSObject *otherObj = NULL;
538 : OOSystemInfo *otherInfo = nil;
539 :
540 : if (!JSSystemInfoGetSystemInfo(context, OOJS_THIS, &thisInfo)) return NO;
541 : if (argc < 1 || !JS_ValueToObject(context, OOJS_ARGV[0], &otherObj) || !JSSystemInfoGetSystemInfo(context, otherObj, &otherInfo))
542 : {
543 : OOJSReportBadArguments(context, @"SystemInfo", @"distanceToSystem", MIN(argc, 1U), OOJS_ARGV, nil, @"system info");
544 : return NO;
545 : }
546 :
547 : BOOL sameGalaxy = ([thisInfo galaxy] == [otherInfo galaxy]);
548 : if (!sameGalaxy)
549 : {
550 : OOJSReportErrorForCaller(context, @"SystemInfo", @"distanceToSystem", @"Cannot calculate distance for systems in other galaxies.");
551 : return NO;
552 : }
553 :
554 : NSPoint thisCoord = [thisInfo coordinates];
555 : NSPoint otherCoord = [otherInfo coordinates];
556 :
557 : OOJS_RETURN_DOUBLE(distanceBetweenPlanetPositions(thisCoord.x, thisCoord.y, otherCoord.x, otherCoord.y));
558 :
559 : OOJS_NATIVE_EXIT
560 : }
561 :
562 :
563 : // routeToSystem(sys : SystemInfo [, optimizedBy : String]) : Object
564 0 : static JSBool SystemInfoRouteToSystem(JSContext *context, uintN argc, jsval *vp)
565 : {
566 : OOJS_NATIVE_ENTER(context)
567 :
568 : OOSystemInfo *thisInfo = nil;
569 : JSObject *otherObj = NULL;
570 : OOSystemInfo *otherInfo = nil;
571 : NSDictionary *result = nil;
572 : OORouteType routeType = OPTIMIZED_BY_JUMPS;
573 :
574 : if (!JSSystemInfoGetSystemInfo(context, OOJS_THIS, &thisInfo)) return NO;
575 : if (argc < 1 || !JS_ValueToObject(context, OOJS_ARGV[0], &otherObj) || !JSSystemInfoGetSystemInfo(context, otherObj, &otherInfo))
576 : {
577 : OOJSReportBadArguments(context, @"SystemInfo", @"routeToSystem", MIN(argc, 1U), OOJS_ARGV, nil, @"system info");
578 : return NO;
579 : }
580 :
581 : BOOL sameGalaxy = ([thisInfo galaxy] == [otherInfo galaxy]);
582 : if (!sameGalaxy)
583 : {
584 : OOJSReportErrorForCaller(context, @"SystemInfo", @"routeToSystem", @"Cannot calculate route for destinations in other galaxies.");
585 : return NO;
586 : }
587 :
588 : if (argc >= 2)
589 : {
590 : routeType = StringToRouteType(OOStringFromJSValue(context, OOJS_ARGV[1]));
591 : }
592 :
593 : OOJS_BEGIN_FULL_NATIVE(context)
594 : result = [UNIVERSE routeFromSystem:[thisInfo system] toSystem:[otherInfo system] optimizedBy:routeType];
595 : OOJS_END_FULL_NATIVE
596 :
597 : OOJS_RETURN_OBJECT(result);
598 :
599 : OOJS_NATIVE_EXIT
600 : }
601 :
602 :
603 : // samplePrice(commodity)
604 0 : static JSBool SystemInfoSamplePrice(JSContext *context, uintN argc, jsval *vp)
605 : {
606 : OOJS_NATIVE_ENTER(context)
607 :
608 : OOSystemInfo *thisInfo = nil;
609 :
610 : if (!JSSystemInfoGetSystemInfo(context, OOJS_THIS, &thisInfo)) return NO;
611 : OOCommodityType commodity = OOStringFromJSValue(context, OOJS_ARGV[0]);
612 : if (EXPECT_NOT(![[UNIVERSE commodities] goodDefined:commodity]))
613 : {
614 : OOJSReportBadArguments(context, @"SystemInfo", @"samplePrice", MIN(argc, 1U), OOJS_ARGV, NULL, @"Unrecognised commodity type");
615 : return NO;
616 : }
617 :
618 : BOOL sameGalaxy = ([thisInfo galaxy] == [PLAYER galaxyNumber]);
619 : if (!sameGalaxy)
620 : {
621 : OOJSReportErrorForCaller(context, @"SystemInfo", @"samplePrice", @"Cannot calculate sample price for destinations in other galaxies.");
622 : return NO;
623 : }
624 :
625 : OOCreditsQuantity price = [[UNIVERSE commodities] samplePriceForCommodity:commodity inEconomy:[[thisInfo valueForKey:@"economy"] intValue] withScript:[thisInfo valueForKey:@"commodity_script"] inSystem:[thisInfo system]];
626 :
627 : return JS_NewNumberValue(context, price, &OOJS_RVAL);
628 :
629 : OOJS_NATIVE_EXIT
630 : }
631 :
632 :
633 0 : static JSBool SystemInfoSetPropertyMethod(JSContext *context, uintN argc, jsval *vp)
634 : {
635 : OOJS_NATIVE_ENTER(context)
636 :
637 : OOSystemInfo *thisInfo = nil;
638 :
639 : if (!JSSystemInfoGetSystemInfo(context, OOJS_THIS, &thisInfo)) return NO;
640 :
641 : NSString *property = nil;
642 : id value = nil;
643 : NSString *manifest = nil;
644 :
645 : int32 iValue;
646 :
647 : if (argc < 3)
648 : {
649 : OOJSReportBadArguments(context, @"SystemInfo", @"setProperty", MIN(argc, 3U), OOJS_ARGV, NULL, @"setProperty(layer, property, value [,manifest])");
650 : return NO;
651 : }
652 : if (!JS_ValueToInt32(context, OOJS_ARGV[0], &iValue))
653 : {
654 : OOJSReportBadArguments(context, @"SystemInfo", @"setProperty", MIN(argc, 3U), OOJS_ARGV, NULL, @"setProperty(layer, property, value [,manifest])");
655 : return NO;
656 : }
657 : if (iValue < 0 || iValue >= OO_SYSTEM_LAYERS)
658 : {
659 : OOJSReportBadArguments(context, @"SystemInfo", @"setProperty", MIN(argc, 3U), OOJS_ARGV, NULL, @"layer must be 0, 1, 2 or 3");
660 : return NO;
661 : }
662 : OOSystemLayer layer = (OOSystemLayer)iValue;
663 :
664 : property = OOStringFromJSValue(context, OOJS_ARGV[1]);
665 : if (!JSVAL_IS_NULL(OOJS_ARGV[2]))
666 : {
667 : value = OOJSNativeObjectFromJSValue(context, OOJS_ARGV[2]);
668 : }
669 : if (argc >= 4)
670 : {
671 : manifest = OOStringFromJSValue(context, OOJS_ARGV[3]);
672 : }
673 : else
674 : {
675 : manifest = [[OOJSScript currentlyRunningScript] propertyNamed:kLocalManifestProperty];
676 : }
677 :
678 : [UNIVERSE setSystemDataForGalaxy:[thisInfo galaxy] planet:[thisInfo system] key:property value:value fromManifest:manifest forLayer:layer];
679 :
680 : OOJS_RETURN_VOID;
681 :
682 : OOJS_NATIVE_EXIT
683 : }
684 :
685 :
686 : // filteredSystems(this : Object, predicate : Function) : Array
687 0 : static JSBool SystemInfoStaticFilteredSystems(JSContext *context, uintN argc, jsval *vp)
688 : {
689 : OOJS_NATIVE_ENTER(context)
690 :
691 : JSObject *jsThis = NULL;
692 :
693 : // Get this and predicate arguments
694 : if (argc < 2 || !OOJSValueIsFunction(context, OOJS_ARGV[1]) || !JS_ValueToObject(context, OOJS_ARGV[0], &jsThis))
695 : {
696 : OOJSReportBadArguments(context, @"SystemInfo", @"filteredSystems", argc, OOJS_ARGV, nil, @"this and predicate function");
697 : return NO;
698 : }
699 : jsval predicate = OOJS_ARGV[1];
700 :
701 : NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
702 : NSMutableArray *result = [NSMutableArray arrayWithCapacity:256];
703 :
704 : // Not OOJS_BEGIN_FULL_NATIVE() - we use JSAPI while paused.
705 : OOJSPauseTimeLimiter();
706 :
707 : // Iterate over systems.
708 : BOOL OK = result != nil;
709 : OOGalaxyID galaxy = [PLAYER currentGalaxyID];
710 : OOSystemID system;
711 : for (system = 0; system <= kOOMaximumSystemID; system++)
712 : {
713 : // NOTE: this deliberately bypasses the cache, since iteration is inherently unfriendly to a single-item cache.
714 : OOSystemInfo *info = [[[OOSystemInfo alloc] initWithGalaxy:galaxy system:system] autorelease];
715 : jsval args[1] = { OOJSValueFromNativeObject(context, info) };
716 :
717 : jsval rval = JSVAL_VOID;
718 : OOJSResumeTimeLimiter();
719 : OK = JS_CallFunctionValue(context, jsThis, predicate, 1, args, &rval);
720 : OOJSPauseTimeLimiter();
721 :
722 : if (OK)
723 : {
724 : if (JS_IsExceptionPending(context))
725 : {
726 : JS_ReportPendingException(context);
727 : OK = NO;
728 : }
729 : }
730 :
731 : if (OK)
732 : {
733 : JSBool boolVal;
734 : if (JS_ValueToBoolean(context, rval, &boolVal) && boolVal)
735 : {
736 : [result addObject:info];
737 : }
738 : }
739 :
740 : if (!OK) break;
741 : }
742 :
743 : if (OK)
744 : {
745 : OOJS_SET_RVAL([result oo_jsValueInContext:context]);
746 : }
747 : else
748 : {
749 : OOJS_SET_RVAL(JSVAL_VOID);
750 : }
751 :
752 : [pool release];
753 :
754 : OOJSResumeTimeLimiter();
755 : return OK;
756 :
757 : OOJS_NATIVE_EXIT
758 : }
759 :
760 :
761 0 : static JSBool SystemInfoStaticSetInterstellarProperty(JSContext *context, uintN argc, jsval *vp)
762 : {
763 : OOJS_NATIVE_ENTER(context)
764 :
765 : NSString *property = nil;
766 : id value = nil;
767 : NSString *manifest = nil;
768 :
769 : int32 iValue;
770 : OOGalaxyID g;
771 : OOSystemID s1,s2;
772 :
773 : if (argc < 6)
774 : {
775 : OOJSReportBadArguments(context, @"SystemInfo", @"setInterstellarProperty", MIN(argc, 3U), OOJS_ARGV, NULL, @"setProperty(galaxy, fromsystem, tosystem, layer, property, value [,manifest])");
776 : return NO;
777 : }
778 : if (!JS_ValueToInt32(context, OOJS_ARGV[0], &iValue))
779 : {
780 : OOJSReportBadArguments(context, @"SystemInfo", @"setInterstellarProperty", MIN(argc, 3U), OOJS_ARGV, NULL, @"setProperty(galaxy, fromsystem, tosystem, layer, property, value [,manifest])");
781 : return NO;
782 : }
783 : if (iValue < 0 || iValue > kOOMaximumGalaxyID)
784 : {
785 : OOJSReportBadArguments(context, @"SystemInfo", @"setInterstellarProperty", MIN(argc, 3U), OOJS_ARGV, NULL, @"galaxy out of range");
786 : return NO;
787 : }
788 : else
789 : {
790 : g = (OOGalaxyID)iValue;
791 : }
792 :
793 : if (!JS_ValueToInt32(context, OOJS_ARGV[1], &iValue))
794 : {
795 : OOJSReportBadArguments(context, @"SystemInfo", @"setInterstellarProperty", MIN(argc, 3U), OOJS_ARGV, NULL, @"setProperty(galaxy, fromsystem, tosystem, layer, property, value [,manifest])");
796 : return NO;
797 : }
798 : if (iValue < 0 || iValue > kOOMaximumSystemID)
799 : {
800 : OOJSReportBadArguments(context, @"SystemInfo", @"setInterstellarProperty", MIN(argc, 3U), OOJS_ARGV, NULL, @"fromsystem out of range");
801 : return NO;
802 : }
803 : else
804 : {
805 : s1 = (OOSystemID)iValue;
806 : }
807 :
808 : if (!JS_ValueToInt32(context, OOJS_ARGV[2], &iValue))
809 : {
810 : OOJSReportBadArguments(context, @"SystemInfo", @"setInterstellarProperty", MIN(argc, 3U), OOJS_ARGV, NULL, @"setProperty(galaxy, fromsystem, tosystem, layer, property, value [,manifest])");
811 : return NO;
812 : }
813 : if (iValue < 0 || iValue > kOOMaximumSystemID)
814 : {
815 : OOJSReportBadArguments(context, @"SystemInfo", @"setInterstellarProperty", MIN(argc, 3U), OOJS_ARGV, NULL, @"tosystem out of range");
816 : return NO;
817 : }
818 : else
819 : {
820 : s2 = (OOSystemID)iValue;
821 : }
822 :
823 : if (!JS_ValueToInt32(context, OOJS_ARGV[3], &iValue))
824 : {
825 : OOJSReportBadArguments(context, @"SystemInfo", @"setInterstellarProperty", MIN(argc, 3U), OOJS_ARGV, NULL, @"setProperty(galaxy, fromsystem, tosystem, layer, property, value [,manifest])");
826 : return NO;
827 : }
828 : if (iValue < 0 || iValue >= OO_SYSTEM_LAYERS)
829 : {
830 : OOJSReportBadArguments(context, @"SystemInfo", @"setInterstellarProperty", MIN(argc, 3U), OOJS_ARGV, NULL, @"layer must be 0, 1, 2 or 3");
831 : return NO;
832 : }
833 : OOSystemLayer layer = (OOSystemLayer)iValue;
834 :
835 : property = OOStringFromJSValue(context, OOJS_ARGV[4]);
836 : if (!JSVAL_IS_NULL(OOJS_ARGV[5]))
837 : {
838 : value = OOJSNativeObjectFromJSValue(context, OOJS_ARGV[5]);
839 : }
840 : if (argc >= 7)
841 : {
842 : manifest = OOStringFromJSValue(context, OOJS_ARGV[6]);
843 : }
844 : else
845 : {
846 : manifest = [[OOJSScript currentlyRunningScript] propertyNamed:kLocalManifestProperty];
847 : }
848 :
849 : NSString *key = [NSString stringWithFormat:@"interstellar: %u %u %u",g,s1,s2];
850 :
851 : [[UNIVERSE systemManager] setProperty:property forSystemKey:key andLayer:layer toValue:value fromManifest:manifest];
852 :
853 : OOJS_RETURN_VOID;
854 :
855 : OOJS_NATIVE_EXIT
856 : }
|