Oolite 1.91.0.7646-241128-10e222e
Loading...
Searching...
No Matches
OOJSEntity.m
Go to the documentation of this file.
1/*
2
3OOJSEntity.m
4
5Oolite
6Copyright (C) 2004-2013 Giles C Williams and contributors
7
8This program is free software; you can redistribute it and/or
9modify it under the terms of the GNU General Public License
10as published by the Free Software Foundation; either version 2
11of the License, or (at your option) any later version.
12
13This program is distributed in the hope that it will be useful,
14but WITHOUT ANY WARRANTY; without even the implied warranty of
15MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16GNU General Public License for more details.
17
18You should have received a copy of the GNU General Public License
19along with this program; if not, write to the Free Software
20Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
21MA 02110-1301, USA.
22
23*/
24
25#import "OOJSEntity.h"
26#import "OOJSVector.h"
27#import "OOJSQuaternion.h"
29#import "OOConstToJSString.h"
31#import "OOJSCall.h"
32
33#import "OOJSPlayer.h"
34#import "PlayerEntity.h"
35#import "ShipEntity.h"
36
37
39
40
41static JSBool EntityGetProperty(JSContext *context, JSObject *this, jsid propID, jsval *value);
42static JSBool EntitySetProperty(JSContext *context, JSObject *this, jsid propID, JSBool strict, jsval *value);
43#ifndef NDEBUG
44static JSBool EntityDumpState(JSContext *context, uintN argc, jsval *vp);
45#endif
46
47
49{
50 "Entity",
51 JSCLASS_HAS_PRIVATE,
52
53 JS_PropertyStub, // addProperty
54 JS_PropertyStub, // delProperty
55 EntityGetProperty, // getProperty
56 EntitySetProperty, // setProperty
57 JS_EnumerateStub, // enumerate
58 JS_ResolveStub, // resolve
59 JS_ConvertStub, // convert
61 JSCLASS_NO_OPTIONAL_MEMBERS
62};
63
64
65enum
66{
67 // Property IDs
68 kEntity_collisionRadius, // collision radius, double, read-only.
69 kEntity_distanceTravelled, // distance travelled, double, read-only.
70 kEntity_energy, // energy, double, read-write.
71 kEntity_heading, // heading, vector, read-only (like orientation but ignoring twist angle)
72 kEntity_mass, // mass, double, read-only
73 kEntity_maxEnergy, // maxEnergy, double, read-only.
74 kEntity_orientation, // orientation, quaternion, read/write
75 kEntity_owner, // owner, Entity, read-only. (Parent ship for subentities, station for defense ships, launching ship for missiles etc)
76 kEntity_position, // position in system space, Vector, read/write
77 kEntity_scanClass, // scan class, string, read-only
78 kEntity_spawnTime, // spawn time, double, read-only.
79 kEntity_status, // entity status, string, read-only
80 kEntity_isPlanet, // is planet, boolean, read-only.
81 kEntity_isPlayer, // is player, boolean, read-only.
82 kEntity_isShip, // is ship, boolean, read-only.
83 kEntity_isStation, // is station, boolean, read-only.
84 kEntity_isDock, // is dock, boolean, read-only.
85 kEntity_isSubEntity, // is subentity, boolean, read-only.
86 kEntity_isSun, // is sun, boolean, read-only.
87 kEntity_isSunlit, // is sunlit, boolean, read-only.
88 kEntity_isValid, // is not stale, boolean, read-only.
89 kEntity_isInSpace, // is in space, boolean, read-only.
90 kEntity_isVisible, // is within drawing distance, boolean, read-only.
91 kEntity_isVisualEffect, // is visual effect, boolean, read-only.
92 kEntity_isWormhole, // is visual effect, boolean, read-only.
93};
94
95
96static JSPropertySpec sEntityProperties[] =
97{
98 // JS name ID flags
99 { "collisionRadius", kEntity_collisionRadius, OOJS_PROP_READONLY_CB },
100 { "distanceTravelled", kEntity_distanceTravelled, OOJS_PROP_READONLY_CB },
116 { "isSubEntity", kEntity_isSubEntity, OOJS_PROP_READONLY_CB },
122 { "isVisualEffect", kEntity_isVisualEffect, OOJS_PROP_READONLY_CB },
123 { "isWormhole", kEntity_isWormhole, OOJS_PROP_READONLY_CB },
124 { 0 }
125};
126
127
128static JSFunctionSpec sEntityMethods[] =
129{
130 // JS name Function min args
131 { "toString", OOJSObjectWrapperToString, 0 },
132#ifndef NDEBUG
133 { "dumpState", EntityDumpState, 0 },
134#endif
135 { 0 }
136};
137
138
139void InitOOJSEntity(JSContext *context, JSObject *global)
140{
141 gOOEntityJSPrototype = JS_InitClass(context, global, NULL, &gOOEntityJSClass, OOJSUnconstructableConstruct, 0, sEntityProperties, sEntityMethods, NULL, NULL);
143}
144
145
146BOOL JSValueToEntity(JSContext *context, jsval value, Entity **outEntity)
147{
148 if (JSVAL_IS_OBJECT(value))
149 {
150 return OOJSEntityGetEntity(context, JSVAL_TO_OBJECT(value), outEntity);
151 }
152
153 return NO;
154}
155
156
157BOOL EntityFromArgumentList(JSContext *context, NSString *scriptClass, NSString *function, uintN argc, jsval *argv, Entity **outEntity, uintN *outConsumed)
158{
160
161 // Sanity checks.
162 if (outConsumed != NULL) *outConsumed = 0;
163 if (EXPECT_NOT(argc == 0 || argv == NULL || outEntity == NULL))
164 {
166 return NO;
167 }
168
169 // Get value, if possible.
170 if (EXPECT_NOT(!JSValueToEntity(context, argv[0], outEntity)))
171 {
172 // Failed; report bad parameters, if given a class and function.
173 if (scriptClass != nil && function != nil)
174 {
175 OOJSReportWarning(context, @"%@.%@(): expected entity, got %@.", scriptClass, function, [NSString stringWithJavaScriptParameters:argv count:1 inContext:context]);
176 return NO;
177 }
178 }
179
180 // Success.
181 if (outConsumed != NULL) *outConsumed = 1;
182 return YES;
183
185}
186
187
188static JSBool EntityGetProperty(JSContext *context, JSObject *this, jsid propID, jsval *value)
189{
190 if (!JSID_IS_INT(propID)) return YES;
191
192 OOJS_NATIVE_ENTER(context)
193
194 Entity *entity = nil;
195 id result = nil;
196
197 if (EXPECT_NOT(!OOJSEntityGetEntity(context, this, &entity))) return NO;
198 if (OOIsStaleEntity(entity))
199 {
200 if (JSID_TO_INT(propID) == kEntity_isValid) *value = JSVAL_FALSE;
201 else { *value = JSVAL_VOID; }
202 return YES;
203 }
204
205 switch (JSID_TO_INT(propID))
206 {
208 return JS_NewNumberValue(context, [entity collisionRadius], value);
209
210 case kEntity_position:
211 return HPVectorToJSValue(context, [entity position], value);
212
214 return QuaternionToJSValue(context, [entity normalOrientation], value);
215
216 case kEntity_heading:
217 return VectorToJSValue(context, vector_forward_from_quaternion([entity normalOrientation]), value);
218
219 case kEntity_status:
220 *value = OOJSValueFromEntityStatus(context, [entity status]);
221 return YES;
222
224 *value = OOJSValueFromScanClass(context, [entity scanClass]);
225 return YES;
226
227 case kEntity_mass:
228 return JS_NewNumberValue(context, [entity mass], value);
229
230 case kEntity_owner:
231 result = [entity owner];
232 if (result == entity) result = nil;
233 break;
234
235 case kEntity_energy:
236 return JS_NewNumberValue(context, [entity energy], value);
237
239 return JS_NewNumberValue(context, [entity maxEnergy], value);
240
241 case kEntity_isValid:
242 *value = [entity status] == STATUS_DEAD ? JSVAL_FALSE : JSVAL_TRUE;
243 return YES;
244
246 *value = OOJSValueFromBOOL([entity isInSpace]);
247 return YES;
248
249 case kEntity_isShip:
250 *value = OOJSValueFromBOOL([entity isShip]);
251 return YES;
252
254 *value = OOJSValueFromBOOL([entity isStation]);
255 return YES;
256
257 case kEntity_isDock:
258 *value = OOJSValueFromBOOL([entity isDock]);
259 return YES;
260
262 *value = OOJSValueFromBOOL([entity isSubEntity]);
263 return YES;
264
265 case kEntity_isPlayer:
266 *value = OOJSValueFromBOOL([entity isPlayer]);
267 return YES;
268
269 case kEntity_isPlanet:
270 *value = OOJSValueFromBOOL([entity isPlanet]);
271 return YES;
272
273 case kEntity_isSun:
274 *value = OOJSValueFromBOOL([entity isSun]);
275 return YES;
276
277 case kEntity_isSunlit:
278 *value = OOJSValueFromBOOL([entity isSunlit]);
279 return YES;
280
282 *value = OOJSValueFromBOOL([entity isVisible]);
283 return YES;
284
286 *value = OOJSValueFromBOOL([entity isVisualEffect]);
287 return YES;
288
290 *value = OOJSValueFromBOOL([entity isWormhole]);
291 return YES;
292
294 return JS_NewNumberValue(context, [entity distanceTravelled], value);
295
297 return JS_NewNumberValue(context, [entity spawnTime], value);
298
299 default:
300 OOJSReportBadPropertySelector(context, this, propID, sEntityProperties);
301 }
302
303 *value = OOJSValueFromNativeObject(context, result);
304 return YES;
305
307}
308
309
310static JSBool EntitySetProperty(JSContext *context, JSObject *this, jsid propID, JSBool strict, jsval *value)
311{
312 if (!JSID_IS_INT(propID)) return YES;
313
314 OOJS_NATIVE_ENTER(context)
315
316 Entity *entity = nil;
317 double fValue;
318 HPVector hpvValue;
319 Quaternion qValue;
320
321 if (EXPECT_NOT(!OOJSEntityGetEntity(context, this, &entity))) return NO;
322 if (OOIsStaleEntity(entity)) return YES;
323
324 switch (JSID_TO_INT(propID))
325 {
326 case kEntity_position:
327 if (JSValueToHPVector(context, *value, &hpvValue))
328 {
329 [entity setPosition:hpvValue];
330 if ([entity isShip])
331 {
332 [(ShipEntity *)entity resetExhaustPlumes];
333 [(ShipEntity *)entity forceAegisCheck];
334 }
335 return YES;
336 }
337 break;
338
340 if (JSValueToQuaternion(context, *value, &qValue))
341 {
342 [entity setNormalOrientation:qValue];
343 return YES;
344 }
345 break;
346
347 case kEntity_energy:
348 if (JS_ValueToNumber(context, *value, &fValue))
349 {
350 fValue = OOClamp_0_max_d(fValue, [entity maxEnergy]);
351 [entity setEnergy:fValue];
352 return YES;
353 }
354 break;
355
357 if (JS_ValueToNumber(context, *value, &fValue))
358 {
359 if (fValue <= 0.0)
360 {
361 OOJSReportError(context, @"entity.maxEnergy must be positive.");
362 return NO;
363 }
364 [entity setMaxEnergy:fValue];
365 return YES;
366 }
367 break;
368
369
371 if ([entity isShip] && ![entity isPlayer])
372 {
373 OOScanClass newClass = OOScanClassFromJSValue(context, *value);
374 if (newClass == CLASS_NOT_SET || newClass == CLASS_NO_DRAW || newClass == CLASS_TARGET || newClass == CLASS_WORMHOLE || newClass == CLASS_PLAYER || newClass == CLASS_VISUAL_EFFECT)
375 {
376 OOJSReportError(context, @"entity.scanClass cannot be set to that value.");
377 return NO;
378 }
379 [entity setScanClass:newClass];
380 return YES;
381 }
382 else
383 {
384 OOJSReportError(context, @"entity.scanClass is read-only except on NPC ships.");
385 return NO;
386 }
387 default:
388 OOJSReportBadPropertySelector(context, this, propID, sEntityProperties);
389 return NO;
390 }
391
392 OOJSReportBadPropertyValue(context, this, propID, sEntityProperties, *value);
393 return NO;
394
396}
397
398
399#ifndef NDEBUG
400static JSBool EntityDumpState(JSContext *context, uintN argc, jsval *vp)
401{
403
404 Entity *thisEnt = nil;
405 OOJSEntityGetEntity(context, OOJS_THIS, &thisEnt);
406 [thisEnt dumpState];
407
409
411}
412#endif
OOScanClass
Definition Entity.h:71
OOINLINE jsval OOJSValueFromScanClass(JSContext *context, OOScanClass value)
OOINLINE jsval OOJSValueFromEntityStatus(JSContext *context, OOEntityStatus value)
OOINLINE OOScanClass OOScanClassFromJSValue(JSContext *context, jsval value)
#define EXPECT_NOT(x)
#define OOJS_PROFILE_EXIT
#define OOJS_NATIVE_ENTER(cx)
#define OOJS_NATIVE_EXIT
#define OOJS_PROFILE_ENTER
OOINLINE BOOL OOIsStaleEntity(Entity *entity)
Definition OOJSEntity.h:71
static JSBool EntityDumpState(JSContext *context, uintN argc, jsval *vp)
Definition OOJSEntity.m:400
JSClass gOOEntityJSClass
Definition OOJSEntity.m:48
static JSBool EntitySetProperty(JSContext *context, JSObject *this, jsid propID, JSBool strict, jsval *value)
Definition OOJSEntity.m:310
BOOL JSValueToEntity(JSContext *context, jsval value, Entity **outEntity)
Definition OOJSEntity.m:146
static JSBool EntityGetProperty(JSContext *context, JSObject *this, jsid propID, jsval *value)
Definition OOJSEntity.m:188
BOOL EntityFromArgumentList(JSContext *context, NSString *scriptClass, NSString *function, uintN argc, jsval *argv, Entity **outEntity, uintN *outConsumed)
Definition OOJSEntity.m:157
@ kEntity_owner
Definition OOJSEntity.m:75
@ kEntity_distanceTravelled
Definition OOJSEntity.m:69
@ kEntity_scanClass
Definition OOJSEntity.m:77
@ kEntity_isVisible
Definition OOJSEntity.m:90
@ kEntity_isDock
Definition OOJSEntity.m:84
@ kEntity_isInSpace
Definition OOJSEntity.m:89
@ kEntity_status
Definition OOJSEntity.m:79
@ kEntity_orientation
Definition OOJSEntity.m:74
@ kEntity_isStation
Definition OOJSEntity.m:83
@ kEntity_isSunlit
Definition OOJSEntity.m:87
@ kEntity_mass
Definition OOJSEntity.m:72
@ kEntity_isValid
Definition OOJSEntity.m:88
@ kEntity_collisionRadius
Definition OOJSEntity.m:68
@ kEntity_isVisualEffect
Definition OOJSEntity.m:91
@ kEntity_isWormhole
Definition OOJSEntity.m:92
@ kEntity_isSubEntity
Definition OOJSEntity.m:85
@ kEntity_energy
Definition OOJSEntity.m:70
@ kEntity_position
Definition OOJSEntity.m:76
@ kEntity_heading
Definition OOJSEntity.m:71
@ kEntity_isShip
Definition OOJSEntity.m:82
@ kEntity_maxEnergy
Definition OOJSEntity.m:73
@ kEntity_isPlanet
Definition OOJSEntity.m:80
@ kEntity_isPlayer
Definition OOJSEntity.m:81
@ kEntity_isSun
Definition OOJSEntity.m:86
@ kEntity_spawnTime
Definition OOJSEntity.m:78
JSObject * gOOEntityJSPrototype
Definition OOJSEntity.m:38
static JSFunctionSpec sEntityMethods[]
Definition OOJSEntity.m:128
static JSPropertySpec sEntityProperties[]
Definition OOJSEntity.m:96
void InitOOJSEntity(JSContext *context, JSObject *global)
Definition OOJSEntity.m:139
BOOL JSValueToQuaternion(JSContext *context, jsval value, Quaternion *outQuaternion) NONNULL_FUNC
BOOL QuaternionToJSValue(JSContext *context, Quaternion quaternion, jsval *outValue) NONNULL_FUNC
BOOL HPVectorToJSValue(JSContext *context, HPVector vector, jsval *outValue) NONNULL_FUNC
Definition OOJSVector.m:228
BOOL JSValueToHPVector(JSContext *context, jsval value, HPVector *outVector) NONNULL_FUNC
Definition OOJSVector.m:252
BOOL VectorToJSValue(JSContext *context, Vector vector, jsval *outValue) NONNULL_FUNC
Definition OOJSVector.m:185
void OOJSReportWarning(JSContext *context, NSString *format,...)
#define OOJS_THIS
JSBool OOJSObjectWrapperToString(JSContext *context, uintN argc, jsval *vp)
#define OOJS_PROP_READWRITE_CB
void OOJSRegisterObjectConverter(JSClass *theClass, OOJSClassConverterCallback converter)
OOINLINE jsval OOJSValueFromNativeObject(JSContext *context, id object)
void OOJSObjectWrapperFinalize(JSContext *context, JSObject *this)
void OOJSReportBadPropertySelector(JSContext *context, JSObject *thisObj, jsid propID, JSPropertySpec *propertySpec)
JSBool OOJSUnconstructableConstruct(JSContext *context, uintN argc, jsval *vp)
void OOJSReportError(JSContext *context, NSString *format,...)
OOINLINE jsval OOJSValueFromBOOL(int b) INLINE_CONST_FUNC
void OOJSReportBadPropertyValue(JSContext *context, JSObject *thisObj, jsid propID, JSPropertySpec *propertySpec, jsval value)
id OOJSBasicPrivateObjectConverter(JSContext *context, JSObject *object)
#define OOJS_PROP_READONLY_CB
#define OOJS_RETURN_VOID
#define OOLogGenericParameterError()
Definition OOLogging.h:125
unsigned count
return nil
Vector vector_forward_from_quaternion(Quaternion quat)
void setMaxEnergy:(GLfloat amount)
Definition Entity.m:823
void setNormalOrientation:(Quaternion quat)
Definition Entity.m:744
void setScanClass:(OOScanClass sClass)
Definition Entity.m:799
OOEntityStatus status()
Definition Entity.m:793
void setEnergy:(GLfloat amount)
Definition Entity.m:811
id owner()
Definition Entity.m:583
void setPosition:(HPVector posn)
Definition Entity.m:647