convert line ends
[canaan.git] / prj / cam / src / script / linkscpt.cpp
blobc53917840fd0527aaec2673e0833b2a43cb5ae83
1 /*
2 @Copyright Looking Glass Studios, Inc.
3 1996,1997,1998,1999,2000 Unpublished Work.
4 */
6 // $Header: r:/t2repos/thief2/src/script/linkscpt.cpp,v 1.17 1999/02/16 16:05:53 Justin Exp $
9 #include <comtools.h>
10 #include <appagg.h>
12 #include <scrptapi.h>
13 #include <scrptbas.h>
14 #include <scrptsrv.h>
16 #include <linkscpt.h>
18 #include <bintrait.h>
20 #include <linkbase.h>
21 #include <linkman.h>
22 #include <relation.h>
24 #include <sdesbase.h>
25 #include <sdestool.h>
26 #include <sdesparm.h>
28 #include <objlpars.h>
30 #include <dbmem.h>
32 ////////////////////////////////////////////////////////////
33 // LINK SCRIPT SERVICE
36 static ILinkManager* LinkMan()
38 static ILinkManager* da_man = NULL;
39 if (!da_man)
41 da_man = AppGetObj(ILinkManager);
43 return da_man;
46 static IStructDescTools* SdescTools()
48 static IStructDescTools* tools = NULL;
49 if (tools == NULL)
51 tools = AppGetObj(IStructDescTools);
53 return tools;
57 // Link Kind class
60 linkkind::linkkind(const char* name)
62 IRelation* rel = LinkMan()->GetRelationNamed(name);
63 id = rel->GetID();
65 AssertMsg1(id != RELID_NULL, "%s is not a link flavor", name);
66 SafeRelease(rel);
69 linkkind::operator string () const
71 cAutoIPtr<IRelation> rel ( LinkMan()->GetRelation(id) );
72 return rel->Describe()->name;
76 // Link class
79 object link::From() const
81 sLink link;
82 LinkMan()->Get(id,&link);
83 return link.source;
86 object link::To() const
88 sLink link;
89 LinkMan()->Get(id,&link);
90 return link.dest;
93 cMultiParm link::GetData(const char* field ) const
95 cAutoIPtr<IRelation> rel ( LinkMan()->GetRelation(LINKID_RELATION(id)) );
96 void* data = rel->GetData(id);
97 if (!data) return 0;
99 const sRelationDataDesc* ddesc = rel->DescribeData();
100 const sStructDesc* sdesc = SdescTools()->Lookup(ddesc->type);
101 if (!sdesc) return 0;
103 AssertMsg1(field != NULL || sdesc->nfields == 1,"%s links have more than one data field.", rel->Describe()->name);
105 const sFieldDesc* fdesc = NULL;
106 if (field)
108 fdesc = NULL;
109 for (int i = 0; i < sdesc->nfields; i++)
110 if (stricmp(field,sdesc->fields[i].name) == 0)
112 fdesc = &sdesc->fields[i];
113 break;
115 AssertMsg2(fdesc,"%s links have no data field named %s.",rel->Describe()->name,field);
117 else
118 fdesc = &sdesc->fields[0];
120 return GetParmFromField(fdesc,data);
124 void link::SetData(const char* field, const cMultiParm& value)
126 cAutoIPtr<IRelation> rel ( LinkMan()->GetRelation(LINKID_RELATION(id)) );
127 const sRelationDataDesc* ddesc = rel->DescribeData();
129 void* data = rel->GetData(id);
131 BOOL deldata = FALSE;
132 if (!data)
134 data = new char[ddesc->size];
135 deldata = TRUE;
138 const sStructDesc* sdesc = SdescTools()->Lookup(ddesc->type);
139 AssertMsg1(sdesc, "%s links have unknown data type.", rel->Describe()->name);
140 if (!sdesc) return ;
142 AssertMsg1(field != NULL || sdesc->nfields == 1,"Relation %s has more than one data field.", rel->Describe()->name);
144 const sFieldDesc* fdesc = NULL;
145 if (field)
147 fdesc = NULL;
148 for (int i = 0; i < sdesc->nfields; i++)
149 if (stricmp(field,sdesc->fields[i].name) == 0)
151 fdesc = &sdesc->fields[i];
152 break;
154 AssertMsg2(fdesc,"%s links have no field named %s.",rel->Describe()->name,field);
156 else
157 fdesc = &sdesc->fields[0];
159 SetFieldFromParm(fdesc,data,value);
160 rel->SetData(id,data);
162 if (deldata)
163 delete [] (char*)data;
167 // THE LINK SERVICE PROPER
170 DECLARE_SCRIPT_SERVICE_IMPL(cLinkSrv, Link)
172 STDMETHOD_(void, Init)()
176 STDMETHOD_(link,Create)(linkkind kind, object from, object to)
178 return LinkMan()->Add(ScriptObjID(from),ScriptObjID(to),kind);
181 STDMETHOD(Destroy)(link destroy_me)
183 return LinkMan()->Remove(destroy_me);
186 STDMETHOD_(boolean,AnyExist)(linkkind kind, object from, object to)
188 cAutoIPtr<ILinkQuery> q ( LinkMan()->Query(ScriptObjID(from),ScriptObjID(to),kind) );
189 return !q->Done();
193 // Get all the links that match a particular pattern
195 STDMETHOD_(linkset,GetAll)(linkkind kind, object from, object to)
197 cAutoIPtr<ILinkQuery> q ( LinkMan()->Query(ScriptObjID(from),ScriptObjID(to),kind) );
198 return linkset(q);
202 // Get just one link.
204 STDMETHOD_(link,GetOne)(linkkind kind, object from, object to)
206 cAutoIPtr<ILinkQuery> q ( LinkMan()->Query(ScriptObjID(from),ScriptObjID(to),kind) );
208 return (q->Done()) ? 0 : q->ID();
211 // @NOTE (justin 2/16/99): As of this writing, networking only supports
212 // ObjIDs as the type for linkdata. This will be fixed some time when
213 // I have time to properly network cMultiParms...
214 STDMETHOD(BroadcastOnAllLinks)(const object ref SelfObj,
215 const char *Message,
216 linkkind recipients,
217 const cMultiParm ref linkdata)
219 AutoAppIPtr(LinkManager);
220 AutoAppIPtr(ScriptMan);
222 ObjID self = ScriptObjID(SelfObj);
224 if (pLinkManager->AnyLinks(recipients,self,LINKOBJ_WILDCARD))
226 ILinkQuery *Controls = pLinkManager->Query(self,LINKOBJ_WILDCARD,recipients);
228 while (!Controls->Done())
230 // so maybe the linkdata should be interepreted in a questbit-specific way someday?
231 if (Controls->Data() == NULL || link(Controls->ID()).GetData() == linkdata)
233 sLink slink;
235 Controls->Link(&slink);
237 // Debug.MPrint(SelfObj," sending message ",Message," to ",thislink.To());
238 //pScriptMan->PostMessage2(SelfObj,slink.dest,Message,linkdata,NULL,NULL);
239 // We currently need to set up the message, to get the flag in:
240 sScrMsg * pMsg = new sScrMsg(self,
241 slink.dest,
242 Message,
243 linkdata);
244 pMsg->flags |= kSMF_MsgPostToOwner;
245 pScriptMan->PostMessage(pMsg);
246 pMsg->Release();
248 Controls->Next();
250 SafeRelease(Controls);
253 return(S_OK);
256 STDMETHOD(BroadcastOnAllLinks)(const object ref SelfObj,
257 const char *Message,
258 linkkind recipients)
260 AutoAppIPtr(LinkManager);
261 AutoAppIPtr(ScriptMan);
263 ObjID self = ScriptObjID(SelfObj);
265 if (pLinkManager->AnyLinks(recipients,self,LINKOBJ_WILDCARD))
267 ILinkQuery *Controls = pLinkManager->Query(self,LINKOBJ_WILDCARD,recipients);
269 while (!Controls->Done())
271 sLink slink;
272 Controls->Link(&slink);
274 //pScriptMan->PostMessage2(SelfObj,slink.dest,Message,NULL,NULL,NULL);
275 // We currently need to set up the message, to get the flag in:
276 sScrMsg * pMsg = new sScrMsg(self,
277 slink.dest,
278 Message,
279 NULL);
280 pMsg->flags |= kSMF_MsgPostToOwner;
281 pScriptMan->PostMessage(pMsg);
282 pMsg->Release();
283 Controls->Next();
285 SafeRelease(Controls);
288 return(S_OK);
292 // Create multiple links.
294 STDMETHOD(CreateMany)(linkkind kind, const string ref FromSet, const string ref ToSet)
296 cObjListParser parser;
297 cDynArray<ObjID> sources;
298 cDynArray<ObjID> destinations;
299 IRelation * pRelation = LinkMan()->GetRelation(kind);
301 if (!pRelation)
302 return E_FAIL;
304 parser.Parse(FromSet, &sources);
305 parser.Parse(ToSet, &destinations);
307 for (int i = 0; i < sources.Size(); i++)
308 for (int j = 0; j < destinations.Size(); j++)
309 pRelation->Add(sources[i], destinations[j]);
311 pRelation->Release();
312 return S_OK;
316 // Destroy multiple link
318 STDMETHOD(DestroyMany)(linkkind kind, const string ref FromSet, const string ref ToSet)
320 cObjListParser parser;
321 cDynArray<ObjID> sources;
322 cDynArray<ObjID> destinations;
323 IRelation * pRelation = LinkMan()->GetRelation(kind);
324 ILinkQuery * pQuery;
326 if (!pRelation)
327 return E_FAIL;
329 parser.Parse(FromSet, &sources);
330 parser.Parse(ToSet, &destinations);
332 for (int i = 0; i < sources.Size(); i++)
333 for (int j = 0; j < destinations.Size(); j++)
335 pQuery = pRelation->Query(sources[i], destinations[j]);
337 for (; !pQuery->Done(); pQuery->Next())
338 pRelation->Remove(pQuery->ID());
340 pQuery->Release();
343 pRelation->Release();
344 return S_OK;
347 STDMETHOD_(linkset,GetAllInherited)(linkkind kind, object from, object to)
349 cAutoIPtr<IRelation> rel = LinkMan()->GetRelation(kind);
350 cAutoIPtr<ILinkQuery> q = QueryInheritedLinksUncached(rel, from, to);
351 return linkset(q);
354 STDMETHOD_(linkset,GetAllInheritedSingle)(linkkind kind, object from, object to)
356 cAutoIPtr<IRelation> rel = LinkMan()->GetRelation(kind);
357 cAutoIPtr<ILinkQuery> q = QueryInheritedLinksSingleUncached(rel, from, to);
358 return linkset(q);
363 IMPLEMENT_SCRIPT_SERVICE_IMPL(cLinkSrv, Link);
366 DECLARE_SCRIPT_SERVICE_IMPL(cLinkToolsSrv, LinkTools)
368 STDMETHOD_(long, LinkKindNamed)(const char* name)
370 return linkkind(name);
373 STDMETHOD_(string, LinkKindName)(long id)
375 cAutoIPtr<IRelation> rel (LinkMan()->GetRelation(id) );
376 AssertMsg1(rel != 0,"A script referenced non-existent link kind %d",id);
377 return rel->Describe()->name;
380 STDMETHOD(LinkGet)(long id, sLink& link)
382 VerifyMsg1(LinkMan()->Get(id,&link),"A script tried to access non-existent link %d",id);
383 return S_OK;
386 STDMETHOD_(cMultiParm,LinkGetData)(long id, const char* field)
388 return link(id).GetData(field);
391 STDMETHOD(LinkSetData)(long id, const char* field, const cMultiParm ref val)
393 link(id).SetData(field,val);
394 return S_OK;
398 IMPLEMENT_SCRIPT_SERVICE_IMPL(cLinkToolsSrv, LinkTools);