Oolite 1.91.0.7644-241112-7f5034b
Loading...
Searching...
No Matches
OOJSShipGroup.m
Go to the documentation of this file.
1/*
2
3OOShipGroup.m
4
5
6Oolite
7Copyright (C) 2004-2013 Giles C Williams and contributors
8
9This program is free software; you can redistribute it and/or
10modify it under the terms of the GNU General Public License
11as published by the Free Software Foundation; either version 2
12of the License, or (at your option) any later version.
13
14This program is distributed in the hope that it will be useful,
15but WITHOUT ANY WARRANTY; without even the implied warranty of
16MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17GNU General Public License for more details.
18
19You should have received a copy of the GNU General Public License
20along with this program; if not, write to the Free Software
21Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
22MA 02110-1301, USA.
23
24*/
25
26#import "OOShipGroup.h"
28#import "OOShipGroup.h"
29#import "Universe.h"
30
31
32static JSObject *sShipGroupPrototype;
33
34
35static JSBool ShipGroupGetProperty(JSContext *context, JSObject *this, jsid propID, jsval *value);
36static JSBool ShipGroupSetProperty(JSContext *context, JSObject *this, jsid propID, JSBool strict, jsval *value);
37static JSBool ShipGroupConstruct(JSContext *context, uintN argc, jsval *vp);
38
39// Methods
40static JSBool ShipGroupAddShip(JSContext *context, uintN argc, jsval *vp);
41static JSBool ShipGroupRemoveShip(JSContext *context, uintN argc, jsval *vp);
42static JSBool ShipGroupContainsShip(JSContext *context, uintN argc, jsval *vp);
43
44
45static JSClass sShipGroupClass =
46{
47 "ShipGroup",
48 JSCLASS_HAS_PRIVATE,
49
50 JS_PropertyStub, // addProperty
51 JS_PropertyStub, // delProperty
52 ShipGroupGetProperty, // getProperty
53 ShipGroupSetProperty, // setProperty
54 JS_EnumerateStub, // enumerate
55 JS_ResolveStub, // resolve
56 JS_ConvertStub, // convert
58 JSCLASS_NO_OPTIONAL_MEMBERS
59};
60
61
62enum
63{
64 // Property IDs
65 kShipGroup_ships, // array of ships, double, read-only
66 kShipGroup_leader, // leader, Ship, read/write
67 kShipGroup_name, // name, string, read/write
68 kShipGroup_count, // number of ships, integer, read-only
69};
70
71
72static JSPropertySpec sShipGroupProperties[] =
73{
74 // JS name ID flags
79 { 0 }
80};
81
82
83static JSFunctionSpec sShipGroupMethods[] =
84{
85 // JS name Function min args
86 { "toString", OOJSObjectWrapperToString, 0 },
87 { "addShip", ShipGroupAddShip, 1 },
88 { "containsShip", ShipGroupContainsShip, 1 },
89 { "removeShip", ShipGroupRemoveShip, 1 },
90 { 0 }
91};
92
93
95
96
97void InitOOJSShipGroup(JSContext *context, JSObject *global)
98{
99 sShipGroupPrototype = JS_InitClass(context, global, NULL, &sShipGroupClass, ShipGroupConstruct, 0, sShipGroupProperties, sShipGroupMethods, NULL, NULL);
101}
102
103
104static JSBool ShipGroupGetProperty(JSContext *context, JSObject *this, jsid propID, jsval *value)
105{
106 if (!JSID_IS_INT(propID)) return YES;
107
108 OOJS_NATIVE_ENTER(context)
109
110 OOShipGroup *group = nil;
111 id result = nil;
112
113 if (EXPECT_NOT(!JSShipGroupGetShipGroup(context, this, &group))) return NO;
114
115 switch (JSID_TO_INT(propID))
116 {
117 case kShipGroup_ships:
118 result = [group memberArray];
119 if (result == nil) result = [NSArray array];
120 break;
121
123 result = [group leader];
124 break;
125
126 case kShipGroup_name:
127 result = [group name];
128 if (result == nil) result = [NSNull null];
129 break;
130
131 case kShipGroup_count:
132 return JS_NewNumberValue(context, [group count], value);
133
134 default:
136 return NO;
137 }
138
139 *value = OOJSValueFromNativeObject(context, result);
140 return YES;
141
143}
144
145
146static JSBool ShipGroupSetProperty(JSContext *context, JSObject *this, jsid propID, JSBool strict, jsval *value)
147{
148 if (!JSID_IS_INT(propID)) return YES;
149
150 OOJS_NATIVE_ENTER(context)
151
152 OOShipGroup *group = nil;
153 ShipEntity *shipValue = nil;
154
155 if (EXPECT_NOT(!JSShipGroupGetShipGroup(context, this, &group))) return NO;
156
157 switch (JSID_TO_INT(propID))
158 {
160 shipValue = OOJSNativeObjectOfClassFromJSValue(context, *value, [ShipEntity class]);
161 if (shipValue != nil || JSVAL_IS_NULL(*value))
162 {
163 [group setLeader:shipValue];
164 return YES;
165 }
166 break;
167
168 case kShipGroup_name:
169 [group setName:OOStringFromJSValueEvenIfNull(context, *value)];
170 return YES;
171 break;
172
173 default:
175 return NO;
176 }
177
178 OOJSReportBadPropertyValue(context, this, propID, sShipGroupProperties, *value);
179 return NO;
180
182}
183
184
185// new ShipGroup([name : String [, leader : Ship]]) : ShipGroup
186static JSBool ShipGroupConstruct(JSContext *context, uintN argc, jsval *vp)
187{
188 OOJS_NATIVE_ENTER(context)
189
190 if (EXPECT_NOT(!JS_IsConstructing(context, vp)))
191 {
192 OOJSReportError(context, @"ShipGroup() cannot be called as a function, it must be used as a constructor (as in new ShipGroup(...)).");
193 return NO;
194 }
195
196 NSString *name = nil;
197 ShipEntity *leader = nil;
198
199 if (argc >= 1)
200 {
201 if (!JSVAL_IS_STRING(OOJS_ARGV[0]))
202 {
203 OOJSReportBadArguments(context, nil, @"ShipGroup()", 1, OOJS_ARGV, @"Could not create ShipGroup", @"group name");
204 return NO;
205 }
206 name = OOStringFromJSValue(context, OOJS_ARGV[0]);
207 }
208
209 if (argc >= 2)
210 {
211 leader = OOJSNativeObjectOfClassFromJSValue(context, OOJS_ARGV[1], [ShipEntity class]);
212 if (leader == nil && !JSVAL_IS_NULL(OOJS_ARGV[1]))
213 {
214 OOJSReportBadArguments(context, nil, @"ShipGroup()", 1, OOJS_ARGV + 1, @"Could not create ShipGroup", @"ship");
215 return NO;
216 }
217 }
218
219 OOJS_RETURN_OBJECT([OOShipGroup groupWithName:name leader:leader]);
220
222}
223
224
225@implementation OOShipGroup (OOJavaScriptExtensions)
226
227- (jsval) oo_jsValueInContext:(JSContext *)context
228{
229 jsval result = JSVAL_NULL;
230
231 if (_jsSelf == NULL)
232 {
233 _jsSelf = JS_NewObject(context, &sShipGroupClass, sShipGroupPrototype, NULL);
234 if (_jsSelf != NULL)
235 {
236 if (!JS_SetPrivate(context, _jsSelf, [self retain])) _jsSelf = NULL;
237 }
238 }
239
240 if (_jsSelf != NULL) result = OBJECT_TO_JSVAL(_jsSelf);
241
242 return result;
243}
244
245
246- (void) oo_clearJSSelf:(JSObject *)selfVal
247{
248 if (_jsSelf == selfVal) _jsSelf = NULL;
249}
250
251@end
252
253
254
255// *** Methods ***
256
257// addShip(ship : Ship)
258static JSBool ShipGroupAddShip(JSContext *context, uintN argc, jsval *vp)
259{
260 OOJS_NATIVE_ENTER(context)
261
262 OOShipGroup *thisGroup = nil;
263 ShipEntity *ship = nil;
264 BOOL OK = YES;
265
266 if (EXPECT_NOT(!JSShipGroupGetShipGroup(context, OOJS_THIS, &thisGroup))) return NO;
267
268 if (argc > 0) ship = OOJSNativeObjectOfClassFromJSValue(context, OOJS_ARGV[0], [ShipEntity class]);
269 if (ship == nil)
270 {
271 if (argc > 0 && JSVAL_IS_NULL(OOJS_ARGV[0])) OOJS_RETURN_VOID; // OK, do nothing for null ship.
272
273 OOJSReportBadArguments(context, @"ShipGroup", @"addShip", MIN(argc, 1U), OOJS_ARGV, nil, @"ship");
274 return NO;
275 }
276
277 if ([thisGroup containsShip:ship])
278 {
279 // nothing to do...
281 }
282 else
283 {
284 ShipEntity *thisGroupLeader = [thisGroup leader];
285
286 if ([thisGroupLeader escortGroup] == thisGroup) // escort group!
287 {
288 if ([thisGroup count] > 1) // already with some escorts
289 {
290 OOShipGroup *thatGroup = [ship group];
291 if ([thatGroup count] > 1 && [[thatGroup leader] escortGroup] == thatGroup) // new escort already escorting!
292 {
293 OOJSReportWarningForCaller(context, @"ShipGroup", @"addShip", @"Ship %@ cannot be assigned to two escort groups, ignoring.", ship);
294 OK = NO;
295 }
296 else
297 {
298 OK = [thisGroupLeader acceptAsEscort:ship];
299 }
300 }
301 else // [thisGroup count] == 1, default unescorted ship?
302 {
303 if ([thisGroupLeader escortGroup] == [thisGroupLeader group])
304 {
305 // Default unescorted, unescortable, ship. Create new group and use that instead.
306 [thisGroupLeader setGroup:[[OOShipGroup alloc] initWithName:@"ship group"]];
307 thisGroup = [thisGroupLeader group];
308 }
309 else
310 {
311 // Unescorted ship with custom group. See if it accepts escorts.
312 OK = [thisGroupLeader acceptAsEscort:ship];
313 }
314 }
315 }
316 if (OK)
317 {
318 OOJS_RETURN_BOOL([thisGroup addShip:ship]); // if ship is there already, noop & YES
319 }
320 else OOJS_RETURN_BOOL(NO);
321 }
322
324}
325
326
327// removeShip(ship : Ship)
328static JSBool ShipGroupRemoveShip(JSContext *context, uintN argc, jsval *vp)
329{
330 OOJS_NATIVE_ENTER(context)
331
332 OOShipGroup *thisGroup = nil;
333 ShipEntity *ship = nil;
334
335 if (EXPECT_NOT(!JSShipGroupGetShipGroup(context, OOJS_THIS, &thisGroup))) return NO;
336
337 if (argc > 0) ship = OOJSNativeObjectOfClassFromJSValue(context, OOJS_ARGV[0], [ShipEntity class]);
338 if (ship == nil)
339 {
340 if (argc > 0 && JSVAL_IS_NULL(OOJS_ARGV[0])) OOJS_RETURN_VOID; // OK, do nothing for null ship.
341
342 OOJSReportBadArguments(context, @"ShipGroup", @"removeShip", MIN(argc, 1U), OOJS_ARGV, nil, @"ship");
343 return NO;
344 }
345
346 OOJS_RETURN_BOOL([thisGroup removeShip:ship]);
347
349}
350
351
352// containsShip(ship : Ship) : Boolean
353static JSBool ShipGroupContainsShip(JSContext *context, uintN argc, jsval *vp)
354{
355 OOJS_NATIVE_ENTER(context)
356
357 OOShipGroup *thisGroup = nil;
358 ShipEntity *ship = nil;
359
360 if (EXPECT_NOT(!JSShipGroupGetShipGroup(context, OOJS_THIS, &thisGroup))) return NO;
361
362 if (argc > 0) ship = OOJSNativeObjectOfClassFromJSValue(context, OOJS_ARGV[0], [ShipEntity class]);
363 if (ship == nil)
364 {
365 if (argc > 0 && JSVAL_IS_NULL(OOJS_ARGV[0])) OOJS_RETURN_BOOL(NO); // OK, return false for null ship.
366
367 OOJSReportBadArguments(context, @"ShipGroup", @"containsShip", MIN(argc, 1U), OOJS_ARGV, nil, @"ship");
368 return NO;
369 }
370
371 OOJS_RETURN_BOOL([thisGroup containsShip:ship]);
372
374}
#define EXPECT_NOT(x)
#define OOJS_NATIVE_ENTER(cx)
#define OOJS_NATIVE_EXIT
static JSPropertySpec sShipGroupProperties[]
static JSObject * sShipGroupPrototype
static JSBool ShipGroupAddShip(JSContext *context, uintN argc, jsval *vp)
static JSBool ShipGroupGetProperty(JSContext *context, JSObject *this, jsid propID, jsval *value)
@ kShipGroup_count
@ kShipGroup_leader
@ kShipGroup_ships
@ kShipGroup_name
static JSBool ShipGroupContainsShip(JSContext *context, uintN argc, jsval *vp)
static JSBool ShipGroupConstruct(JSContext *context, uintN argc, jsval *vp)
static JSBool ShipGroupSetProperty(JSContext *context, JSObject *this, jsid propID, JSBool strict, jsval *value)
static JSBool ShipGroupRemoveShip(JSContext *context, uintN argc, jsval *vp)
void InitOOJSShipGroup(JSContext *context, JSObject *global)
static JSFunctionSpec sShipGroupMethods[]
static JSClass sShipGroupClass
#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)
#define DEFINE_JS_OBJECT_GETTER(NAME, JSCLASS, JSPROTO, OBJCCLASSNAME)
void OOJSObjectWrapperFinalize(JSContext *context, JSObject *this)
#define OOJS_RETURN_OBJECT(o)
void OOJSReportBadPropertySelector(JSContext *context, JSObject *thisObj, jsid propID, JSPropertySpec *propertySpec)
void OOJSReportWarningForCaller(JSContext *context, NSString *scriptClass, NSString *function, NSString *format,...)
#define OOJS_RETURN_BOOL(v)
id OOJSNativeObjectOfClassFromJSValue(JSContext *context, jsval value, Class requiredClass)
NSString * OOStringFromJSValue(JSContext *context, jsval value)
void OOJSReportError(JSContext *context, NSString *format,...)
#define OOJS_ARGV
void OOJSReportBadPropertyValue(JSContext *context, JSObject *thisObj, jsid propID, JSPropertySpec *propertySpec, jsval value)
id OOJSBasicPrivateObjectConverter(JSContext *context, JSObject *object)
void OOJSReportBadArguments(JSContext *context, NSString *scriptClass, NSString *function, uintN argc, jsval *argv, NSString *message, NSString *expectedArgsDescription)
#define OOJS_PROP_READONLY_CB
#define OOJS_RETURN_VOID
#define MIN(A, B)
Definition OOMaths.h:111
unsigned count
return nil
void setName:(NSString *name)
void setLeader:(ShipEntity *leader)
NSString * name()
ShipEntity * leader()
NSArray * memberArray()
BOOL acceptAsEscort:(ShipEntity *other_ship)
void setGroup:(OOShipGroup *group)
OOShipGroup * group()