2 @Copyright Looking Glass Studios, Inc.
3 1996,1997,1998,1999,2000 Unpublished Work.
6 // $Header: r:/t2repos/thief2/src/script/linkscpt.cpp,v 1.17 1999/02/16 16:05:53 Justin Exp $
32 ////////////////////////////////////////////////////////////
33 // LINK SCRIPT SERVICE
36 static ILinkManager
* LinkMan()
38 static ILinkManager
* da_man
= NULL
;
41 da_man
= AppGetObj(ILinkManager
);
46 static IStructDescTools
* SdescTools()
48 static IStructDescTools
* tools
= NULL
;
51 tools
= AppGetObj(IStructDescTools
);
60 linkkind::linkkind(const char* name
)
62 IRelation
* rel
= LinkMan()->GetRelationNamed(name
);
65 AssertMsg1(id
!= RELID_NULL
, "%s is not a link flavor", name
);
69 linkkind::operator string () const
71 cAutoIPtr
<IRelation
> rel ( LinkMan()->GetRelation(id
) );
72 return rel
->Describe()->name
;
79 object
link::From() const
82 LinkMan()->Get(id
,&link
);
86 object
link::To() const
89 LinkMan()->Get(id
,&link
);
93 cMultiParm
link::GetData(const char* field
) const
95 cAutoIPtr
<IRelation
> rel ( LinkMan()->GetRelation(LINKID_RELATION(id
)) );
96 void* data
= rel
->GetData(id
);
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
;
109 for (int i
= 0; i
< sdesc
->nfields
; i
++)
110 if (stricmp(field
,sdesc
->fields
[i
].name
) == 0)
112 fdesc
= &sdesc
->fields
[i
];
115 AssertMsg2(fdesc
,"%s links have no data field named %s.",rel
->Describe()->name
,field
);
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
;
134 data
= new char[ddesc
->size
];
138 const sStructDesc
* sdesc
= SdescTools()->Lookup(ddesc
->type
);
139 AssertMsg1(sdesc
, "%s links have unknown data type.", rel
->Describe()->name
);
142 AssertMsg1(field
!= NULL
|| sdesc
->nfields
== 1,"Relation %s has more than one data field.", rel
->Describe()->name
);
144 const sFieldDesc
* 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
];
154 AssertMsg2(fdesc
,"%s links have no field named %s.",rel
->Describe()->name
,field
);
157 fdesc
= &sdesc
->fields
[0];
159 SetFieldFromParm(fdesc
,data
,value
);
160 rel
->SetData(id
,data
);
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
) );
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
) );
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
,
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
)
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
,
244 pMsg
->flags
|= kSMF_MsgPostToOwner
;
245 pScriptMan
->PostMessage(pMsg
);
250 SafeRelease(Controls
);
256 STDMETHOD(BroadcastOnAllLinks
)(const object ref SelfObj
,
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())
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
,
280 pMsg
->flags
|= kSMF_MsgPostToOwner
;
281 pScriptMan
->PostMessage(pMsg
);
285 SafeRelease(Controls
);
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
);
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();
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
);
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());
343 pRelation
->Release();
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
);
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
);
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
);
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
);
398 IMPLEMENT_SCRIPT_SERVICE_IMPL(cLinkToolsSrv
, LinkTools
);