|
dvander@370
|
1 |
/** |
|
dvander@4067
|
2 |
* vim: set ts=4 sw=4 tw=99 noet : |
|
ds@1330
|
3 |
* ============================================================================= |
|
dvander@1231
|
4 |
* SourceMod |
|
ds@1947
|
5 |
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved. |
|
ds@1330
|
6 |
* ============================================================================= |
|
dvander@370
|
7 |
* |
|
ds@1330
|
8 |
* This program is free software; you can redistribute it and/or modify it under |
|
ds@1330
|
9 |
* the terms of the GNU General Public License, version 3.0, as published by the |
|
ds@1330
|
10 |
* Free Software Foundation. |
|
dvander@1231
|
11 |
* |
|
ds@1330
|
12 |
* This program is distributed in the hope that it will be useful, but WITHOUT |
|
ds@1330
|
13 |
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS |
|
ds@1330
|
14 |
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more |
|
ds@1330
|
15 |
* details. |
|
dvander@1231
|
16 |
* |
|
ds@1330
|
17 |
* You should have received a copy of the GNU General Public License along with |
|
ds@1330
|
18 |
* this program. If not, see <http://www.gnu.org/licenses/>. |
|
dvander@1231
|
19 |
* |
|
ds@1330
|
20 |
* As a special exception, AlliedModders LLC gives you permission to link the |
|
ds@1330
|
21 |
* code of this program (as well as its derivative works) to "Half-Life 2," the |
|
ds@1330
|
22 |
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software |
|
ds@1330
|
23 |
* by the Valve Corporation. You must obey the GNU General Public License in |
|
ds@1330
|
24 |
* all respects for all other code used. Additionally, AlliedModders LLC grants |
|
ds@1330
|
25 |
* this exception to all derivative works. AlliedModders LLC defines further |
|
ds@1330
|
26 |
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007), |
|
ds@1330
|
27 |
* or <http://www.sourcemod.net/license.php>. |
|
dvander@370
|
28 |
* |
|
dvander@370
|
29 |
* Version: $Id$ |
|
dvander@370
|
30 |
*/ |
|
dvander@370
|
31 |
|
|
dvander@229
|
32 |
#include "ShareSys.h" |
|
dvander@3872
|
33 |
#include "ExtensionSys.h" |
|
dvander@3872
|
34 |
#include <ILibrarySys.h> |
|
dvander@3872
|
35 |
#include "common_logic.h" |
|
dvander@3872
|
36 |
#include "PluginSys.h" |
|
dvander@229
|
37 |
#include "HandleSys.h" |
|
dvander@4106
|
38 |
#include <assert.h> |
|
dvander@229
|
39 |
|
|
dvander@4109
|
40 |
using namespace ke; |
|
dvander@4109
|
41 |
|
|
dvander@229
|
42 |
ShareSystem g_ShareSys; |
|
dvander@2086
|
43 |
static unsigned int g_mark_serial = 0; |
|
dvander@229
|
44 |
|
|
dvander@229
|
45 |
ShareSystem::ShareSystem() |
|
dvander@229
|
46 |
{ |
|
dvander@229
|
47 |
m_IdentRoot.ident = 0; |
|
dvander@229
|
48 |
m_TypeRoot = 0; |
|
dvander@229
|
49 |
m_IfaceType = 0; |
|
dvander@229
|
50 |
m_CoreType = 0; |
|
dvander@229
|
51 |
} |
|
dvander@229
|
52 |
|
|
dvander@229
|
53 |
IdentityToken_t *ShareSystem::CreateCoreIdentity() |
|
dvander@229
|
54 |
{ |
|
dvander@229
|
55 |
if (!m_CoreType) |
|
dvander@229
|
56 |
{ |
|
dvander@229
|
57 |
m_CoreType = CreateIdentType("CORE"); |
|
dvander@229
|
58 |
} |
|
dvander@229
|
59 |
|
|
dvander@868
|
60 |
return CreateIdentity(m_CoreType, this); |
|
dvander@229
|
61 |
} |
|
dvander@229
|
62 |
|
|
dvander@1770
|
63 |
void ShareSystem::Initialize() |
|
dvander@229
|
64 |
{ |
|
dvander@262
|
65 |
TypeAccess sec; |
|
dvander@229
|
66 |
|
|
dvander@3872
|
67 |
handlesys->InitAccessDefaults(&sec, NULL); |
|
dvander@262
|
68 |
sec.ident = GetIdentRoot(); |
|
dvander@262
|
69 |
|
|
dvander@3872
|
70 |
m_TypeRoot = handlesys->CreateType("Identity", this, 0, &sec, NULL, NULL, NULL); |
|
dvander@3872
|
71 |
m_IfaceType = handlesys->CreateType("Interface", this, 0, NULL, NULL, GetIdentRoot(), NULL); |
|
dvander@229
|
72 |
|
|
dvander@229
|
73 |
/* Initialize our static identity handle */ |
|
dvander@3872
|
74 |
m_IdentRoot.ident = handlesys->CreateHandle(m_TypeRoot, NULL, NULL, GetIdentRoot(), NULL); |
|
dvander@305
|
75 |
|
|
dvander@336
|
76 |
/* Add the Handle System and others... they are too innocent and pure to do it themselves */ |
|
dvander@3872
|
77 |
AddInterface(NULL, handlesys); |
|
dvander@3872
|
78 |
AddInterface(NULL, libsys); |
|
dvander@229
|
79 |
} |
|
dvander@229
|
80 |
|
|
dvander@229
|
81 |
void ShareSystem::OnSourceModShutdown() |
|
dvander@229
|
82 |
{ |
|
dvander@229
|
83 |
if (m_CoreType) |
|
dvander@229
|
84 |
{ |
|
dvander@3872
|
85 |
handlesys->RemoveType(m_CoreType, GetIdentRoot()); |
|
dvander@229
|
86 |
} |
|
dvander@229
|
87 |
|
|
dvander@3872
|
88 |
handlesys->RemoveType(m_IfaceType, GetIdentRoot()); |
|
dvander@3872
|
89 |
handlesys->RemoveType(m_TypeRoot, GetIdentRoot()); |
|
dvander@229
|
90 |
} |
|
dvander@229
|
91 |
|
|
dvander@229
|
92 |
IdentityType_t ShareSystem::FindIdentType(const char *name) |
|
dvander@229
|
93 |
{ |
|
dvander@229
|
94 |
HandleType_t type; |
|
dvander@229
|
95 |
|
|
dvander@3872
|
96 |
if (handlesys->FindHandleType(name, &type)) |
|
dvander@229
|
97 |
{ |
|
dvander@229
|
98 |
if (g_HandleSys.TypeCheck(type, m_TypeRoot)) |
|
dvander@229
|
99 |
{ |
|
dvander@229
|
100 |
return type; |
|
dvander@229
|
101 |
} |
|
dvander@229
|
102 |
} |
|
dvander@229
|
103 |
|
|
dvander@229
|
104 |
return 0; |
|
dvander@229
|
105 |
} |
|
dvander@229
|
106 |
|
|
dvander@229
|
107 |
IdentityType_t ShareSystem::CreateIdentType(const char *name) |
|
dvander@229
|
108 |
{ |
|
dvander@229
|
109 |
if (!m_TypeRoot) |
|
dvander@229
|
110 |
{ |
|
dvander@229
|
111 |
return 0; |
|
dvander@229
|
112 |
} |
|
dvander@229
|
113 |
|
|
dvander@3872
|
114 |
return handlesys->CreateType(name, this, m_TypeRoot, NULL, NULL, GetIdentRoot(), NULL); |
|
dvander@229
|
115 |
} |
|
dvander@229
|
116 |
|
|
dvander@229
|
117 |
void ShareSystem::OnHandleDestroy(HandleType_t type, void *object) |
|
dvander@229
|
118 |
{ |
|
dvander@283
|
119 |
/* THIS WILL NEVER BE CALLED FOR ANYTHING WITH THE IDENTITY TYPE */ |
|
dvander@229
|
120 |
} |
|
dvander@229
|
121 |
|
|
dvander@868
|
122 |
IdentityToken_t *ShareSystem::CreateIdentity(IdentityType_t type, void *ptr) |
|
dvander@229
|
123 |
{ |
|
dvander@229
|
124 |
if (!m_TypeRoot) |
|
dvander@229
|
125 |
{ |
|
dvander@229
|
126 |
return 0; |
|
dvander@229
|
127 |
} |
|
dvander@229
|
128 |
|
|
dvander@229
|
129 |
/* :TODO: Cache? */ |
|
dvander@229
|
130 |
IdentityToken_t *pToken = new IdentityToken_t; |
|
dvander@528
|
131 |
|
|
dvander@528
|
132 |
HandleSecurity sec; |
|
dvander@528
|
133 |
sec.pOwner = sec.pIdentity = GetIdentRoot(); |
|
dvander@528
|
134 |
|
|
dvander@528
|
135 |
pToken->ident = g_HandleSys.CreateHandleInt(type, NULL, &sec, NULL, NULL, true); |
|
dvander@868
|
136 |
pToken->ptr = ptr; |
|
dvander@868
|
137 |
pToken->type = type; |
|
dvander@229
|
138 |
|
|
dvander@229
|
139 |
return pToken; |
|
dvander@229
|
140 |
} |
|
dvander@229
|
141 |
|
|
dvander@304
|
142 |
bool ShareSystem::AddInterface(IExtension *myself, SMInterface *iface) |
|
dvander@229
|
143 |
{ |
|
dvander@229
|
144 |
if (!iface) |
|
dvander@229
|
145 |
{ |
|
dvander@229
|
146 |
return false; |
|
dvander@229
|
147 |
} |
|
dvander@229
|
148 |
|
|
dvander@229
|
149 |
IfaceInfo info; |
|
dvander@229
|
150 |
|
|
dvander@304
|
151 |
info.owner = myself; |
|
dvander@229
|
152 |
info.iface = iface; |
|
dvander@229
|
153 |
|
|
dvander@229
|
154 |
m_Interfaces.push_back(info); |
|
dvander@229
|
155 |
|
|
dvander@229
|
156 |
return true; |
|
dvander@229
|
157 |
} |
|
dvander@229
|
158 |
|
|
dvander@229
|
159 |
bool ShareSystem::RequestInterface(const char *iface_name, |
|
dvander@229
|
160 |
unsigned int iface_vers, |
|
dvander@311
|
161 |
IExtension *myself, |
|
dvander@229
|
162 |
SMInterface **pIface) |
|
dvander@229
|
163 |
{ |
|
dvander@229
|
164 |
/* See if the interface exists */ |
|
dvander@229
|
165 |
List<IfaceInfo>::iterator iter; |
|
dvander@229
|
166 |
SMInterface *iface; |
|
dvander@304
|
167 |
IExtension *iface_owner; |
|
dvander@229
|
168 |
bool found = false; |
|
dvander@229
|
169 |
for (iter=m_Interfaces.begin(); iter!=m_Interfaces.end(); iter++) |
|
dvander@229
|
170 |
{ |
|
dvander@229
|
171 |
IfaceInfo &info = (*iter); |
|
dvander@229
|
172 |
iface = info.iface; |
|
dvander@229
|
173 |
if (strcmp(iface->GetInterfaceName(), iface_name) == 0) |
|
dvander@229
|
174 |
{ |
|
dvander@229
|
175 |
if (iface->GetInterfaceVersion() == iface_vers |
|
dvander@229
|
176 |
|| iface->IsVersionCompatible(iface_vers)) |
|
dvander@229
|
177 |
{ |
|
dvander@304
|
178 |
iface_owner = info.owner; |
|
dvander@229
|
179 |
found = true; |
|
dvander@229
|
180 |
break; |
|
dvander@229
|
181 |
} |
|
dvander@229
|
182 |
} |
|
dvander@229
|
183 |
} |
|
dvander@229
|
184 |
|
|
dvander@229
|
185 |
if (!found) |
|
dvander@229
|
186 |
{ |
|
dvander@229
|
187 |
return false; |
|
dvander@229
|
188 |
} |
|
dvander@229
|
189 |
|
|
dvander@304
|
190 |
/* Add a dependency node */ |
|
dvander@229
|
191 |
if (iface_owner) |
|
dvander@229
|
192 |
{ |
|
dvander@304
|
193 |
IfaceInfo info; |
|
dvander@304
|
194 |
info.iface = iface; |
|
dvander@304
|
195 |
info.owner = iface_owner; |
|
dvander@311
|
196 |
g_Extensions.BindDependency(myself, &info); |
|
dvander@229
|
197 |
} |
|
dvander@229
|
198 |
|
|
dvander@304
|
199 |
if (pIface) |
|
dvander@304
|
200 |
{ |
|
dvander@304
|
201 |
*pIface = iface; |
|
dvander@304
|
202 |
} |
|
dvander@229
|
203 |
|
|
dvander@304
|
204 |
return true; |
|
dvander@229
|
205 |
} |
|
dvander@229
|
206 |
|
|
dvander@312
|
207 |
void ShareSystem::AddNatives(IExtension *myself, const sp_nativeinfo_t *natives) |
|
dvander@229
|
208 |
{ |
|
dvander@2086
|
209 |
CNativeOwner *pOwner; |
|
dvander@2086
|
210 |
|
|
dvander@2086
|
211 |
pOwner = g_Extensions.GetNativeOwner(myself); |
|
dvander@2086
|
212 |
|
|
dvander@2086
|
213 |
pOwner->AddNatives(natives); |
|
dvander@229
|
214 |
} |
|
dvander@229
|
215 |
|
|
dvander@229
|
216 |
void ShareSystem::DestroyIdentity(IdentityToken_t *identity) |
|
dvander@229
|
217 |
{ |
|
dvander@262
|
218 |
HandleSecurity sec; |
|
dvander@262
|
219 |
|
|
dvander@262
|
220 |
sec.pOwner = GetIdentRoot(); |
|
dvander@262
|
221 |
sec.pIdentity = GetIdentRoot(); |
|
dvander@262
|
222 |
|
|
dvander@3872
|
223 |
handlesys->FreeHandle(identity->ident, &sec); |
|
dvander@229
|
224 |
delete identity; |
|
dvander@229
|
225 |
} |
|
dvander@229
|
226 |
|
|
dvander@229
|
227 |
void ShareSystem::DestroyIdentType(IdentityType_t type) |
|
dvander@229
|
228 |
{ |
|
dvander@3872
|
229 |
handlesys->RemoveType(type, GetIdentRoot()); |
|
dvander@229
|
230 |
} |
|
dvander@229
|
231 |
|
|
dvander@304
|
232 |
void ShareSystem::RemoveInterfaces(IExtension *pExtension) |
|
dvander@304
|
233 |
{ |
|
dvander@304
|
234 |
List<IfaceInfo>::iterator iter = m_Interfaces.begin(); |
|
dvander@304
|
235 |
|
|
dvander@304
|
236 |
while (iter != m_Interfaces.end()) |
|
dvander@304
|
237 |
{ |
|
dvander@304
|
238 |
if ((*iter).owner == pExtension) |
|
dvander@304
|
239 |
{ |
|
dvander@304
|
240 |
iter = m_Interfaces.erase(iter); |
|
dvander@2086
|
241 |
} |
|
dvander@2086
|
242 |
else |
|
dvander@2086
|
243 |
{ |
|
dvander@304
|
244 |
iter++; |
|
dvander@304
|
245 |
} |
|
dvander@304
|
246 |
} |
|
dvander@304
|
247 |
} |
|
dvander@324
|
248 |
|
|
dvander@324
|
249 |
void ShareSystem::AddDependency(IExtension *myself, const char *filename, bool require, bool autoload) |
|
dvander@324
|
250 |
{ |
|
dvander@324
|
251 |
g_Extensions.AddDependency(myself, filename, require, autoload); |
|
dvander@324
|
252 |
} |
|
dvander@324
|
253 |
|
|
dvander@1572
|
254 |
void ShareSystem::RegisterLibrary(IExtension *myself, const char *name) |
|
dvander@1572
|
255 |
{ |
|
dvander@1572
|
256 |
g_Extensions.AddLibrary(myself, name); |
|
dvander@1572
|
257 |
} |
|
dvander@1689
|
258 |
|
|
dvander@1689
|
259 |
void ShareSystem::OverrideNatives(IExtension *myself, const sp_nativeinfo_t *natives) |
|
dvander@1689
|
260 |
{ |
|
dvander@4106
|
261 |
assert(false); |
|
dvander@2086
|
262 |
} |
|
dvander@2086
|
263 |
|
|
dvander@4109
|
264 |
PassRef<Native> ShareSystem::FindNative(const char *name) |
|
dvander@2086
|
265 |
{ |
|
dvander@4109
|
266 |
NativeCache::Result r = m_NtvCache.find(name); |
|
dvander@4109
|
267 |
if (!r.found()) |
|
dvander@2086
|
268 |
return NULL; |
|
dvander@4109
|
269 |
return *r; |
|
dvander@2086
|
270 |
} |
|
dvander@2086
|
271 |
|
|
dvander@2086
|
272 |
void ShareSystem::BindNativesToPlugin(CPlugin *pPlugin, bool bCoreOnly) |
|
dvander@2086
|
273 |
{ |
|
dvander@2086
|
274 |
sp_native_t *native; |
|
dvander@2086
|
275 |
uint32_t i, native_count; |
|
dvander@2086
|
276 |
IPluginContext *pContext; |
|
dvander@2086
|
277 |
|
|
dvander@2086
|
278 |
pContext = pPlugin->GetBaseContext(); |
|
dvander@2086
|
279 |
|
|
dvander@2086
|
280 |
/* Generate a new serial ID, mark our dependencies with it. */ |
|
dvander@2086
|
281 |
g_mark_serial++; |
|
dvander@3872
|
282 |
pPlugin->PropagateMarkSerial(g_mark_serial); |
|
dvander@2086
|
283 |
|
|
dvander@2086
|
284 |
native_count = pContext->GetNativesNum(); |
|
dvander@2086
|
285 |
for (i = 0; i < native_count; i++) |
|
dvander@2086
|
286 |
{ |
|
dvander@2086
|
287 |
if (pContext->GetNativeByIndex(i, &native) != SP_ERROR_NONE) |
|
dvander@2086
|
288 |
continue; |
|
dvander@2086
|
289 |
|
|
dvander@4106
|
290 |
// If we're already bound, no need to do anything else. |
|
dvander@2086
|
291 |
if (native->status == SP_NATIVE_BOUND) |
|
dvander@4106
|
292 |
continue; |
|
dvander@4106
|
293 |
|
|
dvander@2086
|
294 |
/* Otherwise, the native must be in our cache. */ |
|
dvander@4109
|
295 |
Ref<Native> pEntry = FindNative(native->name); |
|
dvander@4106
|
296 |
if (!pEntry) |
|
dvander@2086
|
297 |
continue; |
|
dvander@2086
|
298 |
|
|
dvander@3872
|
299 |
if (bCoreOnly && pEntry->owner != &g_CoreNatives) |
|
dvander@2086
|
300 |
continue; |
|
dvander@2086
|
301 |
|
|
dvander@2086
|
302 |
BindNativeToPlugin(pPlugin, native, i, pEntry); |
|
dvander@2086
|
303 |
} |
|
dvander@2086
|
304 |
} |
|
dvander@2086
|
305 |
|
|
dvander@4109
|
306 |
void ShareSystem::BindNativeToPlugin(CPlugin *pPlugin, const Ref<Native> &entry) |
|
dvander@2086
|
307 |
{ |
|
dvander@4109
|
308 |
if (!entry->owner) |
|
dvander@4109
|
309 |
return; |
|
dvander@2086
|
310 |
|
|
dvander@4109
|
311 |
IPluginContext *pContext = pPlugin->GetBaseContext(); |
|
dvander@2086
|
312 |
|
|
dvander@4109
|
313 |
uint32_t i; |
|
dvander@4109
|
314 |
if (pContext->FindNativeByName(entry->name(), &i) != SP_ERROR_NONE) |
|
dvander@2086
|
315 |
return; |
|
dvander@4109
|
316 |
|
|
dvander@4109
|
317 |
sp_native_t *native; |
|
dvander@2086
|
318 |
if (pContext->GetNativeByIndex(i, &native) != SP_ERROR_NONE) |
|
dvander@2086
|
319 |
return; |
|
dvander@2086
|
320 |
|
|
dvander@2086
|
321 |
if (native->status == SP_NATIVE_BOUND) |
|
dvander@2086
|
322 |
return; |
|
dvander@2086
|
323 |
|
|
dvander@4109
|
324 |
BindNativeToPlugin(pPlugin, native, i, entry); |
|
dvander@1689
|
325 |
} |
|
dvander@2086
|
326 |
|
|
dvander@4109
|
327 |
void ShareSystem::BindNativeToPlugin(CPlugin *pPlugin, sp_native_t *native, uint32_t index, |
|
dvander@4109
|
328 |
const Ref<Native> &pEntry) |
|
dvander@2086
|
329 |
{ |
|
dvander@2086
|
330 |
/* Mark as bound... we do the rest next. */ |
|
dvander@2086
|
331 |
native->status = SP_NATIVE_BOUND; |
|
dvander@4108
|
332 |
native->pfn = pEntry->func(); |
|
dvander@4106
|
333 |
|
|
kyle@4358
|
334 |
if (pEntry->fake) |
|
kyle@4358
|
335 |
{ |
|
kyle@4358
|
336 |
/* This native is not necessarily optional, but we don't guarantee |
|
kyle@4358
|
337 |
* that its address is long-lived. */ |
|
kyle@4358
|
338 |
native->flags |= SP_NTVFLAG_EPHEMERAL; |
|
kyle@4358
|
339 |
} |
|
kyle@4358
|
340 |
|
|
dvander@4106
|
341 |
/* We don't bother with dependency crap if the owner is Core. */ |
|
dvander@4106
|
342 |
if (pEntry->owner != &g_CoreNatives) |
|
dvander@2086
|
343 |
{ |
|
dvander@4106
|
344 |
/* The native is optional, this is a special case */ |
|
dvander@4106
|
345 |
if ((native->flags & SP_NTVFLAG_OPTIONAL) == SP_NTVFLAG_OPTIONAL) |
|
dvander@2086
|
346 |
{ |
|
dvander@4106
|
347 |
/* Only add if there is a valid owner. */ |
|
dvander@4109
|
348 |
if (pEntry->owner) |
|
dvander@4106
|
349 |
pEntry->owner->AddWeakRef(WeakNative(pPlugin, index)); |
|
dvander@2086
|
350 |
else |
|
dvander@4106
|
351 |
native->status = SP_NATIVE_UNBOUND; |
|
dvander@4106
|
352 |
} |
|
dvander@4106
|
353 |
/* Otherwise, we're a strong dependent and not a weak one */ |
|
dvander@4106
|
354 |
else |
|
dvander@4106
|
355 |
{ |
|
dvander@4106
|
356 |
/* See if this has already been marked as a dependent. |
|
dvander@4106
|
357 |
* If it has, it means this relationship has already occurred, |
|
dvander@4106
|
358 |
* and there is no reason to do it again. |
|
dvander@4106
|
359 |
*/ |
|
dvander@4106
|
360 |
if (pEntry->owner != pPlugin->ToNativeOwner() |
|
dvander@4106
|
361 |
&& pEntry->owner->GetMarkSerial() != g_mark_serial) |
|
dvander@4106
|
362 |
{ |
|
dvander@4106
|
363 |
/* This has not been marked as a dependency yet */ |
|
dvander@4106
|
364 |
//pPlugin->AddDependency(pEntry->owner); |
|
dvander@4106
|
365 |
pEntry->owner->AddDependent(pPlugin); |
|
dvander@4106
|
366 |
pEntry->owner->SetMarkSerial(g_mark_serial); |
|
dvander@2086
|
367 |
} |
|
dvander@2086
|
368 |
} |
|
dvander@2086
|
369 |
} |
|
dvander@2086
|
370 |
} |
|
dvander@2086
|
371 |
|
|
dvander@4109
|
372 |
PassRef<Native> ShareSystem::AddNativeToCache(CNativeOwner *pOwner, const sp_nativeinfo_t *ntv) |
|
dvander@2086
|
373 |
{ |
|
dvander@4109
|
374 |
NativeCache::Insert i = m_NtvCache.findForAdd(ntv->name); |
|
dvander@4109
|
375 |
if (i.found()) |
|
dvander@2086
|
376 |
return NULL; |
|
dvander@2086
|
377 |
|
|
dvander@4109
|
378 |
Ref<Native> entry = Newborn<Native>(new Native(pOwner, ntv)); |
|
dvander@4109
|
379 |
m_NtvCache.insert(ntv->name, entry); |
|
dvander@4109
|
380 |
return entry; |
|
dvander@4108
|
381 |
} |
|
dvander@2086
|
382 |
|
|
dvander@4108
|
383 |
FakeNative::~FakeNative() |
|
dvander@4108
|
384 |
{ |
|
dvander@4108
|
385 |
g_pSourcePawn2->DestroyFakeNative(gate); |
|
dvander@2086
|
386 |
} |
|
dvander@2086
|
387 |
|
|
dvander@2086
|
388 |
void ShareSystem::ClearNativeFromCache(CNativeOwner *pOwner, const char *name) |
|
dvander@2086
|
389 |
{ |
|
dvander@4109
|
390 |
NativeCache::Result r = m_NtvCache.find(name); |
|
dvander@4109
|
391 |
if (!r.found()) |
|
dvander@2086
|
392 |
return; |
|
dvander@2086
|
393 |
|
|
dvander@4109
|
394 |
Ref<Native> entry(*r); |
|
dvander@4109
|
395 |
if (entry->owner != pOwner) |
|
dvander@2086
|
396 |
return; |
|
dvander@2086
|
397 |
|
|
dvander@4109
|
398 |
// Clear out the owner bit as a sanity measure. |
|
dvander@4109
|
399 |
entry->owner = NULL; |
|
dvander@4109
|
400 |
|
|
dvander@4109
|
401 |
m_NtvCache.remove(r); |
|
dvander@2086
|
402 |
} |
|
dvander@2086
|
403 |
|
|
dvander@4109
|
404 |
PassRef<Native> ShareSystem::AddFakeNative(IPluginFunction *pFunc, const char *name, SPVM_FAKENATIVE_FUNC func) |
|
dvander@2086
|
405 |
{ |
|
dvander@4109
|
406 |
Ref<Native> entry(FindNative(name)); |
|
dvander@4109
|
407 |
if (entry) |
|
dvander@2086
|
408 |
return NULL; |
|
dvander@2086
|
409 |
|
|
dvander@4109
|
410 |
AutoPtr<FakeNative> fake(new FakeNative(name, pFunc)); |
|
dvander@2086
|
411 |
|
|
dvander@4108
|
412 |
fake->gate = g_pSourcePawn2->CreateFakeNative(func, fake); |
|
dvander@4108
|
413 |
if (!fake->gate) |
|
dvander@2086
|
414 |
return NULL; |
|
dvander@2086
|
415 |
|
|
dvander@4108
|
416 |
CNativeOwner *owner = g_PluginSys.GetPluginByCtx(fake->ctx->GetContext()); |
|
dvander@2086
|
417 |
|
|
dvander@4109
|
418 |
entry = Newborn<Native>(new Native(owner, fake.take())); |
|
dvander@4109
|
419 |
m_NtvCache.insert(name, entry); |
|
dvander@2086
|
420 |
|
|
dvander@4109
|
421 |
return entry; |
|
dvander@2086
|
422 |
} |
|
dvander@2841
|
423 |
|
|
dvander@2841
|
424 |
void ShareSystem::AddCapabilityProvider(IExtension *myself, IFeatureProvider *provider, |
|
dvander@2841
|
425 |
const char *name) |
|
dvander@2841
|
426 |
{ |
|
dvander@4067
|
427 |
if (m_caps.contains(name)) |
|
dvander@2841
|
428 |
return; |
|
dvander@2841
|
429 |
|
|
dvander@2841
|
430 |
Capability cap; |
|
dvander@2841
|
431 |
cap.ext = myself; |
|
dvander@2841
|
432 |
cap.provider = provider; |
|
dvander@2841
|
433 |
|
|
dvander@2841
|
434 |
m_caps.insert(name, cap); |
|
dvander@2841
|
435 |
} |
|
dvander@2841
|
436 |
|
|
dvander@2841
|
437 |
void ShareSystem::DropCapabilityProvider(IExtension *myself, IFeatureProvider *provider, |
|
dvander@2841
|
438 |
const char *name) |
|
dvander@2841
|
439 |
{ |
|
dvander@4067
|
440 |
StringHashMap<Capability>::Result r = m_caps.find(name); |
|
dvander@4067
|
441 |
if (!r.found()) |
|
dvander@4067
|
442 |
return; |
|
dvander@4067
|
443 |
if (r->value.ext != myself || r->value.provider != provider) |
|
dvander@2841
|
444 |
return; |
|
dvander@2841
|
445 |
|
|
dvander@4067
|
446 |
m_caps.remove(r); |
|
dvander@2841
|
447 |
} |
|
dvander@2841
|
448 |
|
|
dvander@2841
|
449 |
FeatureStatus ShareSystem::TestFeature(IPluginRuntime *pRuntime, FeatureType feature, |
|
dvander@2841
|
450 |
const char *name) |
|
dvander@2841
|
451 |
{ |
|
dvander@2841
|
452 |
switch (feature) |
|
dvander@2841
|
453 |
{ |
|
dvander@2841
|
454 |
case FeatureType_Native: |
|
dvander@2841
|
455 |
return TestNative(pRuntime, name); |
|
dvander@2841
|
456 |
case FeatureType_Capability: |
|
dvander@2841
|
457 |
return TestCap(name); |
|
dvander@2841
|
458 |
default: |
|
dvander@2841
|
459 |
break; |
|
dvander@2841
|
460 |
} |
|
dvander@2841
|
461 |
|
|
dvander@2841
|
462 |
return FeatureStatus_Unknown; |
|
dvander@2841
|
463 |
} |
|
dvander@2841
|
464 |
|
|
dvander@2841
|
465 |
FeatureStatus ShareSystem::TestNative(IPluginRuntime *pRuntime, const char *name) |
|
dvander@2841
|
466 |
{ |
|
dvander@2841
|
467 |
uint32_t index; |
|
dvander@2841
|
468 |
|
|
dvander@2841
|
469 |
if (pRuntime->FindNativeByName(name, &index) == SP_ERROR_NONE) |
|
dvander@2841
|
470 |
{ |
|
dvander@2841
|
471 |
sp_native_t *native; |
|
dvander@2841
|
472 |
if (pRuntime->GetNativeByIndex(index, &native) == SP_ERROR_NONE) |
|
dvander@2841
|
473 |
{ |
|
dvander@2841
|
474 |
if (native->status == SP_NATIVE_BOUND) |
|
dvander@2841
|
475 |
return FeatureStatus_Available; |
|
dvander@2841
|
476 |
else |
|
dvander@2841
|
477 |
return FeatureStatus_Unknown; |
|
dvander@2841
|
478 |
} |
|
dvander@2841
|
479 |
} |
|
dvander@2841
|
480 |
|
|
dvander@4109
|
481 |
Ref<Native> entry = FindNative(name); |
|
dvander@4106
|
482 |
if (!entry) |
|
dvander@2841
|
483 |
return FeatureStatus_Unknown; |
|
dvander@2841
|
484 |
|
|
dvander@4106
|
485 |
return FeatureStatus_Unavailable; |
|
dvander@2841
|
486 |
} |
|
dvander@2841
|
487 |
|
|
dvander@2841
|
488 |
FeatureStatus ShareSystem::TestCap(const char *name) |
|
dvander@2841
|
489 |
{ |
|
dvander@4067
|
490 |
StringHashMap<Capability>::Result r = m_caps.find(name); |
|
dvander@4067
|
491 |
if (!r.found()) |
|
dvander@2841
|
492 |
return FeatureStatus_Unknown; |
|
dvander@2841
|
493 |
|
|
dvander@4067
|
494 |
return r->value.provider->GetFeatureStatus(FeatureType_Capability, name); |
|
dvander@2841
|
495 |
} |