├── GPLv3.txt ├── LICENSE.txt ├── plugins ├── disabled │ ├── dynamic-classexample.smx │ ├── dynamic-example.smx │ └── dynamic-test.smx ├── dynamic.smx └── dynamic │ └── dynamic.smx └── scripting ├── dynamic-test.sp ├── dynamic.sp ├── dynamic ├── examples │ ├── 001-the_dynamic_lifecycle │ │ └── dynamic-example.sp │ ├── 002-accessing_dynamic_members │ │ └── dynamic-example.sp │ ├── 003-type_conversion │ │ └── dynamic-example.sp │ ├── 999-old │ │ ├── basics.sp │ │ ├── collections │ │ │ ├── collection.sp │ │ │ ├── people.inc │ │ │ └── person.inc │ │ ├── dynamic-classexample.sp │ │ ├── dynamic-example.sp │ │ └── keyvalues │ │ │ └── using_read_hook.sp │ └── wiki_resources │ │ ├── a_basic_methodmap.sp │ │ └── accessing_members.sp └── system │ ├── benchmark │ └── output.txt │ ├── commands.sp │ ├── datatypes │ ├── bool.sp │ ├── dynamic.sp │ ├── float.sp │ ├── function.sp │ ├── handle.sp │ ├── int.sp │ ├── string.sp │ └── vector.sp │ ├── flatconfigs.sp │ ├── handleusage.sp │ ├── hooks.sp │ ├── keyvalues.sp │ ├── methodmaps │ └── dynamicobject.sp │ ├── natives.sp │ ├── plugins.sp │ ├── preparedquery.sp │ └── selftest.sp └── include ├── dynamic-example.inc ├── dynamic.inc └── dynamic ├── methodmaps ├── basic.inc ├── collection.inc ├── dynamic.inc ├── dynamicoffset.inc └── preparedquery.inc └── natives.inc /LICENSE.txt: -------------------------------------------------------------------------------- 1 | /** 2 | * ============================================================================= 3 | * Dynamic for SourceMod (C)2016 Matthew J Dunn. All rights reserved. 4 | * ============================================================================= 5 | * 6 | * This program is free software; you can redistribute it and/or modify it under 7 | * the terms of the GNU General Public License, version 3.0, as published by the 8 | * Free Software Foundation. 9 | * 10 | * This program is distributed in the hope that it will be useful, but WITHOUT 11 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 12 | * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more 13 | * details. 14 | * 15 | * You should have received a copy of the GNU General Public License along with 16 | * this program. If not, see . 17 | * 18 | */ 19 | -------------------------------------------------------------------------------- /plugins/disabled/dynamic-classexample.smx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ntoxin66/Dynamic/ddecdaae44a2c0f43486a3952a2a0bd45ae915a3/plugins/disabled/dynamic-classexample.smx -------------------------------------------------------------------------------- /plugins/disabled/dynamic-example.smx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ntoxin66/Dynamic/ddecdaae44a2c0f43486a3952a2a0bd45ae915a3/plugins/disabled/dynamic-example.smx -------------------------------------------------------------------------------- /plugins/disabled/dynamic-test.smx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ntoxin66/Dynamic/ddecdaae44a2c0f43486a3952a2a0bd45ae915a3/plugins/disabled/dynamic-test.smx -------------------------------------------------------------------------------- /plugins/dynamic.smx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ntoxin66/Dynamic/ddecdaae44a2c0f43486a3952a2a0bd45ae915a3/plugins/dynamic.smx -------------------------------------------------------------------------------- /plugins/dynamic/dynamic.smx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ntoxin66/Dynamic/ddecdaae44a2c0f43486a3952a2a0bd45ae915a3/plugins/dynamic/dynamic.smx -------------------------------------------------------------------------------- /scripting/dynamic-test.sp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | public Plugin myinfo = 5 | { 6 | name = "Dynamic Test", 7 | author = "Neuro Toxin", 8 | description = "Benchmarks and Tests all Dynamic Object aspects", 9 | version = "1.0.2", 10 | url = "https://forums.alliedmods.net/showthread.php?t=270519" 11 | } 12 | 13 | public void OnPluginStart() 14 | { 15 | BenchmarkTest(); 16 | } 17 | 18 | stock void BenchmarkTest() 19 | { 20 | int objectcount = 1000; 21 | int membercount = 100; // must be a multiple of 5 22 | 23 | PrintToServer("[SM] Preparing benchmark Test..."); 24 | Dynamic someobject; 25 | char membernames[100][DYNAMIC_MEMBERNAME_MAXLEN]; 26 | DynamicOffset memberoffsets[100]; 27 | char buffer[DYNAMIC_MEMBERNAME_MAXLEN]; 28 | int ival; float fval; char sval[DYNAMIC_MEMBERNAME_MAXLEN]; float vector[3]; 29 | DynamicOffset offset; 30 | Dynamic objects[1000]; 31 | 32 | // Make member names 33 | for (int x = 0; x < membercount; x++) 34 | { 35 | Format(membernames[x], DYNAMIC_MEMBERNAME_MAXLEN, "m_Field_%d", x); 36 | } 37 | PrintToServer("[SM] Starting Benchmark Tests..."); 38 | 39 | // Create objectcount objects with 100 fields in each 40 | float start = GetEngineTime(); 41 | for (int i=0; i({1.0, 2.0, 3.0})); 74 | x++; 75 | } 76 | else if (p==5) 77 | { 78 | memberoffsets[x] = someobject.SetString(membernames[x], "Some nice string that has some data", 128); 79 | } 80 | } 81 | } 82 | } 83 | PrintToServer("Created %d dynamic member(s) in %f second(s)", objectcount * membercount, GetEngineTime() - start); 84 | 85 | start = GetEngineTime(); 86 | for (int i=0; i({2.0, 3.0, 4.0})); 259 | x++; 260 | } 261 | else if (p==5) 262 | { 263 | someobject.SetString(membernames[x], "123Some nice string that has some data123"); 264 | } 265 | } 266 | } 267 | } 268 | PrintToServer("Updated %d dynamic member(s) in %f second(s)", objectcount * membercount, GetEngineTime() - start); 269 | 270 | start = GetEngineTime(); 271 | for (int i=0; iobj.%s = %d", offset, member, obj.GetIntByOffset(offset)); 361 | } 362 | case DynamicType_Float: 363 | { 364 | PrintToServer("[%d] obj.%s = %f", offset, member, obj.GetFloatByOffset(offset)); 365 | } 366 | case DynamicType_String: 367 | { 368 | char somestring[64]; 369 | obj.GetStringByOffset(offset, somestring, sizeof(somestring)); 370 | PrintToServer("[%d] obj.%s = '%s'", offset, member, somestring); 371 | } 372 | } 373 | } -------------------------------------------------------------------------------- /scripting/dynamic.sp: -------------------------------------------------------------------------------- 1 | /** 2 | * ============================================================================= 3 | * Dynamic for SourceMod (C)2016 Matthew J Dunn. All rights reserved. 4 | * ============================================================================= 5 | * 6 | * This program is free software; you can redistribute it and/or modify it under 7 | * the terms of the GNU General Public License, version 3.0, as published by the 8 | * Free Software Foundation. 9 | * 10 | * This program is distributed in the hope that it will be useful, but WITHOUT 11 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 12 | * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more 13 | * details. 14 | * 15 | * You should have received a copy of the GNU General Public License along with 16 | * this program. If not, see . 17 | * 18 | */ 19 | #define dynamic_use_local_methodmap 1 20 | #include 21 | #include 22 | #undef INVALID_DYNAMIC_OBJECT 23 | #define INVALID_DYNAMIC_OBJECT view_as(-1) 24 | #pragma newdecls required 25 | #pragma semicolon 1 26 | 27 | // Public data 28 | int s_CollectionSize = 0; 29 | Handle s_FreeIndicies = null; 30 | StringMap s_tObjectNames = null; 31 | Handle g_sRegex_Vector = null; 32 | int g_iDynamic_MemberLookup_Offset; 33 | ArrayList g_aPlugins = null; 34 | 35 | // Dynamics internal methodmaps 36 | #include "dynamic/system/methodmaps/dynamicobject.sp" 37 | 38 | // Dynamic datatypes 39 | #include "dynamic/system/datatypes/bool.sp" 40 | #include "dynamic/system/datatypes/dynamic.sp" 41 | #include "dynamic/system/datatypes/float.sp" 42 | #include "dynamic/system/datatypes/handle.sp" 43 | #include "dynamic/system/datatypes/int.sp" 44 | #include "dynamic/system/datatypes/string.sp" 45 | #include "dynamic/system/datatypes/vector.sp" 46 | #include "dynamic/system/datatypes/function.sp" 47 | 48 | // Other features 49 | #include "dynamic/system/commands.sp" 50 | #include "dynamic/system/flatconfigs.sp" 51 | #include "dynamic/system/handleusage.sp" 52 | #include "dynamic/system/hooks.sp" 53 | #include "dynamic/system/keyvalues.sp" 54 | #include "dynamic/system/natives.sp" 55 | #include "dynamic/system/plugins.sp" 56 | #include "dynamic/system/selftest.sp" 57 | #include "dynamic/system/preparedquery.sp" 58 | 59 | public Plugin myinfo = 60 | { 61 | name = "Dynamic", 62 | author = "Neuro Toxin", 63 | description = "Shared Dynamic Objects for Sourcepawn", 64 | version = "0.0.32", 65 | url = "https://forums.alliedmods.net/showthread.php?t=270519" 66 | } 67 | 68 | public APLRes AskPluginLoad2(Handle myself, bool late, char[] error, int err_max) 69 | { 70 | // Initialise static plugin data 71 | s_Collection = CreateArray(Dynamic_Field_Count); 72 | s_CollectionSize = 0; 73 | s_FreeIndicies = CreateStack(); 74 | s_tObjectNames = new StringMap(); 75 | g_iDynamic_MemberLookup_Offset = ByteCountToCells(DYNAMIC_MEMBERNAME_MAXLEN)+1; 76 | g_aPlugins = CreateArray(2); 77 | 78 | // Reserve first object index for global settings 79 | DynamicObject settings = DynamicObject(); 80 | settings.Initialise(null); 81 | 82 | // Ensure settings is assigned index 0 83 | if (view_as(settings) != 0) 84 | SetFailState("Serious error encountered assigning server settings index!"); 85 | 86 | // Reserve first object indicies for player objects 87 | for (int client = 1; client < MAXPLAYERS; client++) 88 | { 89 | settings = DynamicObject(); 90 | settings.Initialise(null); 91 | 92 | // This is a check to ensure the index matches the client 93 | if (view_as(settings) != client) 94 | SetFailState("Serious error encountered assigning player settings indicies!"); 95 | } 96 | 97 | // Create natives 98 | CreateNatives(); 99 | 100 | // Register commands 101 | RegisterCommands(); 102 | 103 | // Register library 104 | RegPluginLibrary("dynamic"); 105 | return APLRes_Success; 106 | } 107 | 108 | public void OnLibraryRemoved(const char[] name) 109 | { 110 | _Dynamic_CollectGarbage(); 111 | } 112 | 113 | public void OnPluginEnd() 114 | { 115 | // Dispose of all objects in the collection pool 116 | while (s_CollectionSize > 0) 117 | { 118 | _Dynamic_Dispose(view_as(s_CollectionSize - 1), false, _, _, false); 119 | } 120 | } 121 | 122 | public void OnMapStart() 123 | { 124 | _Dynamic_CollectGarbage(); 125 | } 126 | 127 | stock void OnClientDisconnect_Post(int client) 128 | { 129 | _Dynamic_ResetObject(client); 130 | } 131 | 132 | stock int _Dynamic_Initialise(Handle plugin, int blocksize=64, int startsize=0, bool persistent=false) 133 | { 134 | int index = -1; 135 | DynamicObject member; 136 | 137 | // Always try to reuse a previously disposed index 138 | while (PopStackCell(s_FreeIndicies, index)) 139 | { 140 | if (index < s_CollectionSize) 141 | { 142 | member = view_as(index); 143 | break; 144 | } 145 | index = -1; 146 | } 147 | 148 | // Create a new index if required 149 | if (index == -1) 150 | member = DynamicObject(); 151 | 152 | // Initial 153 | member.Initialise(plugin, blocksize, startsize, persistent); 154 | 155 | // Return the index 156 | return member.Index; 157 | } 158 | 159 | stock bool _Dynamic_Dispose(DynamicObject dynamic, bool disposemembers, bool reuse=false, int startsize=0, bool fromnative=true) 160 | { 161 | if (!_Dynamic_IsValid(dynamic.Index, false, fromnative)) 162 | return false; 163 | 164 | int blocksize = dynamic.BlockSize; 165 | 166 | // Dispose of child members if disposemembers is set 167 | if (disposemembers) 168 | { 169 | ArrayList data = dynamic.Data; 170 | int count = dynamic.MemberCount; 171 | DynamicOffset offset; 172 | DynamicObject disposableobject; 173 | Handle disposablehandle; 174 | 175 | Dynamic_MemberType membertype; 176 | 177 | for (int i = 0; i < count; i++) 178 | { 179 | offset = _Dynamic_GetMemberOffsetByIndex(dynamic, i); 180 | membertype = _Dynamic_GetMemberDataType(data, offset.Index, offset.Cell, blocksize); 181 | 182 | if (membertype == DynamicType_Dynamic) 183 | { 184 | disposableobject = view_as(_Dynamic_GetMemberDataInt(data, offset.Index, offset.Cell, blocksize)); 185 | if (!disposableobject.IsValid(false)) 186 | continue; 187 | 188 | // Check if member hasnt been referenced to another object 189 | if (disposableobject.Parent == dynamic) 190 | _Dynamic_Dispose(disposableobject, true); 191 | } 192 | else if (membertype == DynamicType_Handle) 193 | { 194 | disposablehandle = view_as(_Dynamic_GetMemberDataInt(data, offset.Index, offset.Cell, blocksize)); 195 | _Dynamic_SetMemberDataInt(data, offset.Index, offset.Cell, blocksize, 0); 196 | CloseHandle(disposablehandle); 197 | } 198 | } 199 | } 200 | 201 | // Close dynamic object array handles 202 | dynamic.Dispose(reuse); 203 | 204 | if (reuse) 205 | { 206 | // Reset the dynamic object so it can be used straight 207 | dynamic.Reset(); 208 | return true; 209 | } 210 | 211 | // Remove all indicies from the end of the array which are empty (trimend array) 212 | int index = dynamic.Index; 213 | if (index + 1 == s_CollectionSize) 214 | { 215 | RemoveFromArray(s_Collection, index); 216 | s_CollectionSize--; 217 | 218 | for (int i = index - 1; i >= 0; i--) 219 | { 220 | if (s_Collection.Get(i, Dynamic_Index) != Invalid_Dynamic_Object) 221 | break; 222 | 223 | RemoveFromArray(s_Collection, i); 224 | s_CollectionSize--; 225 | } 226 | } 227 | else 228 | { 229 | // Mark the index as diposed and report the free index for reusage 230 | PushStackCell(s_FreeIndicies, dynamic); 231 | } 232 | return true; 233 | } 234 | 235 | stock void _Dynamic_CollectGarbage() 236 | { 237 | // Dispose all objects owned by terminated plugins 238 | DynamicObject dynamic; 239 | for (int i = MAXPLAYERS; i < s_CollectionSize; i++) 240 | { 241 | dynamic = view_as(i); 242 | 243 | // Skip disposed objects 244 | if (!dynamic.IsValid(false)) 245 | continue; 246 | 247 | // Skip persistent objects 248 | if (dynamic.Persistent) 249 | continue; 250 | 251 | // Validate owner plugin is still loaded 252 | if (!_Dynamic_Plugins_IsLoaded(dynamic.OwnerPlugin)) 253 | { 254 | dynamic.Dispose(false); 255 | continue; 256 | } 257 | 258 | switch(GetPluginStatus(dynamic.OwnerPluginHandle)) 259 | { 260 | case Plugin_Error, Plugin_Failed: 261 | { 262 | dynamic.Dispose(false); 263 | } 264 | } 265 | } 266 | } 267 | 268 | stock bool _Dynamic_ResetObject(DynamicObject dynamic, bool disposemembers, int blocksize=0, int startsize=0) 269 | { 270 | if (!dynamic.IsValid(true)) 271 | return false; 272 | 273 | if (blocksize == 0) 274 | blocksize = dynamic.BlockSize; 275 | 276 | return _Dynamic_Dispose(dynamic, disposemembers, true, startsize); 277 | } 278 | 279 | stock Handle _Dynamic_GetOwnerPlugin(DynamicObject dynamic) 280 | { 281 | if (!dynamic.IsValid(true)) 282 | return null; 283 | 284 | return dynamic.OwnerPluginHandle; 285 | } 286 | 287 | stock bool _Dynamic_SetName(DynamicObject dynamic, const char[] objectname, bool replace) 288 | { 289 | if (!dynamic.IsValid(true)) 290 | return false; 291 | 292 | return s_tObjectNames.SetValue(objectname, dynamic, replace); 293 | } 294 | 295 | stock DynamicObject _Dynamic_FindByName(const char[] objectname) 296 | { 297 | // Find name in object names trie 298 | DynamicObject dynamic; 299 | if (!s_tObjectNames.GetValue(objectname, dynamic)) 300 | return INVALID_DYNAMIC_OBJECT; 301 | 302 | // Check object is still valid 303 | if (!dynamic.IsValid(true)) 304 | return INVALID_DYNAMIC_OBJECT; 305 | 306 | // Return object index 307 | return dynamic; 308 | } 309 | 310 | stock DynamicObject _Dynamic_GetParent(DynamicObject dynamic) 311 | { 312 | if (!dynamic.IsValid(true)) 313 | return INVALID_DYNAMIC_OBJECT; 314 | 315 | return dynamic.Parent; 316 | } 317 | 318 | stock bool _Dynamic_GetName(DynamicObject dynamic, char[] buffer, int length) 319 | { 320 | if (!dynamic.IsValid(true)) 321 | return false; 322 | 323 | DynamicObject parent = dynamic.Parent; 324 | if (!parent.IsValid(false)) 325 | return false; 326 | 327 | DynamicOffset offset = dynamic.ParentOffset; 328 | if (offset == INVALID_DYNAMIC_OFFSET) 329 | return false; 330 | 331 | _Dynamic_GetMemberNameByOffset(parent, offset, buffer, length); 332 | return true; 333 | } 334 | 335 | stock bool _Dynamic_GetPersistence(DynamicObject dynamic) 336 | { 337 | if (!dynamic.IsValid(true)) 338 | return false; 339 | 340 | return dynamic.Persistent; 341 | } 342 | 343 | stock bool _Dynamic_SetPersistence(DynamicObject dynamic, bool value) 344 | { 345 | if (!dynamic.IsValid(true)) 346 | return false; 347 | 348 | dynamic.Persistent = value; 349 | return true; 350 | } 351 | 352 | stock bool _Dynamic_IsValid(int index, bool throwerror=false, bool fromnative=true) 353 | { 354 | // Check if object index is valid 355 | if (index < 0 || index >= s_CollectionSize) 356 | { 357 | if (throwerror) 358 | { 359 | if (fromnative) 360 | ThrowNativeError(SP_ERROR_NATIVE, "Unable to access dynamic handle %d", index); 361 | else 362 | ThrowError("Unable to access dynamic handle %d", index); 363 | } 364 | return false; 365 | } 366 | 367 | if (s_Collection.Get(index, Dynamic_Index) == -1) 368 | { 369 | if (throwerror) 370 | { 371 | if (fromnative) 372 | ThrowNativeError(SP_ERROR_NATIVE, "Tried to access disposed dynamic handle %d", index); 373 | else 374 | ThrowError("Tried to access disposed dynamic handle %d", index); 375 | } 376 | return false; 377 | } 378 | 379 | return true; 380 | } 381 | 382 | stock DynamicOffset _Dynamic_GetMemberOffset(DynamicObject dynamic, const char[] membername) 383 | { 384 | if (!dynamic.IsValid(true)) 385 | return INVALID_DYNAMIC_OFFSET; 386 | 387 | // Find and return offset for member 388 | StringMap offsets = dynamic.Offsets; 389 | DynamicOffset offset; 390 | if (GetTrieValue(offsets, membername, offset)) 391 | return offset; 392 | 393 | // No offset found 394 | return INVALID_DYNAMIC_OFFSET; 395 | } 396 | 397 | stock bool _Dynamic_GetMemberDataOffset(DynamicObject dynamic, const char[] membername, bool create, DynamicOffset &offset, Dynamic_MemberType type, int stringlength=0) 398 | { 399 | // Find and return member offset 400 | if (dynamic.Offsets.GetValue(membername, offset)) 401 | return true; 402 | 403 | // Return false if offset was not found 404 | if (!create) 405 | return false; 406 | 407 | // We need to create a new member 408 | _Dynamic_CreateMemberOffset(dynamic, offset, membername, type, stringlength); 409 | return true; 410 | } 411 | 412 | stock int _Dynamic_CreateMemberOffset(DynamicObject dynamic, DynamicOffset &offset, const char[] membername, Dynamic_MemberType type, int stringlength=0, StringMap offsets=null) 413 | { 414 | int memberindex; 415 | ArrayList membernames = dynamic.MemberNames; 416 | 417 | // Increment member count 418 | dynamic.MemberCount++; 419 | 420 | // Get offsets if required 421 | if (offsets == null) 422 | offsets = dynamic.Offsets; 423 | 424 | offset = dynamic.NextOffset; 425 | offsets.SetValue(membername, offset); 426 | memberindex = membernames.PushString(membername); 427 | membernames.Set(memberindex, offset, g_iDynamic_MemberLookup_Offset); 428 | ArrayList data = dynamic.Data; 429 | int blocksize = dynamic.BlockSize; 430 | 431 | if (type == DynamicType_String) 432 | { 433 | if (stringlength == 0) 434 | { 435 | ThrowNativeError(SP_ERROR_NATIVE, "You must set a strings length when you initialise it"); 436 | return false; 437 | } 438 | 439 | _Dynamic_ExpandIfRequired(data, offset, blocksize, ByteCountToCells(stringlength)); 440 | _Dynamic_SetMemberDataType(data, offset, blocksize, type); 441 | _Dynamic_SetMemberStringLength(data, offset, blocksize, stringlength); 442 | dynamic.NextOffset = offset.Clone(blocksize, 3 + ByteCountToCells(stringlength)); 443 | return memberindex; 444 | } 445 | else if (type == DynamicType_Vector) 446 | { 447 | _Dynamic_ExpandIfRequired(data, offset, blocksize, 3); 448 | _Dynamic_SetMemberDataType(data, offset, blocksize, type); 449 | dynamic.NextOffset = offset.Clone(blocksize, 4); 450 | return memberindex; 451 | } 452 | else 453 | { 454 | _Dynamic_ExpandIfRequired(data, offset, blocksize, 1); 455 | _Dynamic_SetMemberDataType(data, offset, blocksize, type); 456 | dynamic.NextOffset = offset.Clone(blocksize, 2); 457 | return memberindex; 458 | } 459 | } 460 | 461 | stock bool _Dynamic_RecalculateOffset(int &position, int &offset, int blocksize, bool aschar=false) 462 | { 463 | // Calculate offset into internal array index and cell position 464 | if (aschar) 465 | blocksize *= 4; 466 | 467 | while (offset < 0) 468 | { 469 | offset+=blocksize; 470 | position--; 471 | } 472 | while (offset >= blocksize) 473 | { 474 | offset-=blocksize; 475 | position++; 476 | } 477 | return true; 478 | } 479 | 480 | stock void _Dynamic_ExpandIfRequired(ArrayList data, DynamicOffset offset, int blocksize, int length=1) 481 | { 482 | // Used to expand internal object arrays by the _Dynamic_GetMemberDataOffset method 483 | int index = offset.Index; 484 | int cell = offset.Cell + length + 1; 485 | _Dynamic_RecalculateOffset(index, cell, blocksize); 486 | 487 | // Expand array if offset is outside of array bounds 488 | // Performance: Get array size should be replaced with an size counter 489 | // The above needs a really good think!! 490 | int size = GetArraySize(data); 491 | while (size <= index) 492 | { 493 | // -1 is the default value of unused memory to allow parenting via Set/PushObject 494 | int val = PushArrayCell(data, INVALID_DYNAMIC_OBJECT); 495 | size++; 496 | 497 | // This was added to ensure all memory is set to -1 for a parent resetting 498 | // -> this might impact performance and potentially cause parent resetting to be redone 499 | for (int block = 1; block < blocksize; block++) 500 | { 501 | SetArrayCell(data, val, INVALID_DYNAMIC_OBJECT, block); 502 | } 503 | } 504 | } 505 | 506 | stock Dynamic_MemberType _Dynamic_GetMemberDataType(ArrayList data, int position, int offset, int blocksize) 507 | { 508 | return data.Get(position, offset); 509 | } 510 | 511 | stock void _Dynamic_SetMemberDataType(ArrayList data, DynamicOffset offset, int blocksize, Dynamic_MemberType type) 512 | { 513 | // Set member type 514 | SetArrayCell(data, offset.Index, type, offset.Cell); 515 | } 516 | 517 | stock int _Dynamic_GetCollectionSize() 518 | { 519 | return s_CollectionSize; 520 | } 521 | 522 | stock int _Dynamic_GetMemberCount(DynamicObject dynamic) 523 | { 524 | if (!dynamic.IsValid(true)) 525 | return 0; 526 | 527 | return dynamic.MemberCount; 528 | } 529 | 530 | stock DynamicOffset _Dynamic_GetMemberOffsetByIndex(DynamicObject dynamic, int memberindex) 531 | { 532 | if (!dynamic.IsValid(true)) 533 | return INVALID_DYNAMIC_OFFSET; 534 | 535 | return dynamic.MemberNames.Get(memberindex, g_iDynamic_MemberLookup_Offset); 536 | } 537 | 538 | stock Dynamic_MemberType _Dynamic_GetMemberType(DynamicObject dynamic, const char[] membername) 539 | { 540 | if (!dynamic.IsValid(true)) 541 | return DynamicType_Unknown; 542 | 543 | DynamicOffset offset; 544 | if (!_Dynamic_GetMemberDataOffset(dynamic, membername, false, offset, DynamicType_Unknown)) 545 | return DynamicType_Unknown; 546 | 547 | return _Dynamic_GetMemberDataType(dynamic.Data, offset.Index, offset.Cell, dynamic.BlockSize); 548 | } 549 | 550 | stock Dynamic_MemberType _Dynamic_GetMemberTypeByOffset(DynamicObject dynamic, DynamicOffset offset) 551 | { 552 | if (!dynamic.IsValid(true)) 553 | return DynamicType_Unknown; 554 | 555 | return _Dynamic_GetMemberDataType(dynamic.Data, offset.Index, offset.Cell, dynamic.BlockSize); 556 | } 557 | 558 | stock bool _Dynamic_GetMemberNameByIndex(DynamicObject dynamic, int memberindex, char[] buffer, int length) 559 | { 560 | if (!dynamic.IsValid(true)) 561 | return false; 562 | 563 | if (memberindex >= dynamic.MemberCount) 564 | { 565 | buffer[0] = '\0'; 566 | return false; 567 | } 568 | 569 | GetArrayString(dynamic.MemberNames, memberindex, buffer, length); 570 | return true; 571 | } 572 | 573 | stock bool _Dynamic_GetMemberNameByOffset(DynamicObject dynamic, DynamicOffset offset, char[] buffer, int length) 574 | { 575 | if (!dynamic.IsValid(true)) 576 | return false; 577 | 578 | ArrayList membernames = dynamic.MemberNames; 579 | int membercount = membernames.Length; 580 | 581 | for (int i = 0; i < membercount; i++) 582 | { 583 | if (membernames.Get(i, g_iDynamic_MemberLookup_Offset) == offset) 584 | { 585 | membernames.GetString(i, buffer, length); 586 | return true; 587 | } 588 | } 589 | return false; 590 | } 591 | 592 | stock bool _Dynamic_SortMembers(DynamicObject dynamic, SortOrder order) 593 | { 594 | if (!dynamic.IsValid(true)) 595 | return false; 596 | 597 | int count = dynamic.MemberCount; 598 | if (count == 0) 599 | return false; 600 | 601 | // Dont bother sorting if there are no members 602 | ArrayList members = dynamic.MemberNames; 603 | StringMap offets = dynamic.Offsets; 604 | char[][] membernames = new char[count][DYNAMIC_MEMBERNAME_MAXLEN]; 605 | DynamicOffset offset; 606 | 607 | // Get each membername into a string array 608 | for (int memberindex = 0; memberindex < count; memberindex++) 609 | GetArrayString(members, memberindex, membernames[memberindex], DYNAMIC_MEMBERNAME_MAXLEN); 610 | 611 | // Sort member names 612 | SortStrings(membernames, count, order); 613 | 614 | // Clear current member index lookup arrays 615 | ClearArray(members); 616 | 617 | // Rebuild member lookup arrays based on sorted membernames 618 | for (int memberindex = 0; memberindex < count; memberindex++) 619 | { 620 | if (!offets.GetValue(membernames[memberindex], offset)) 621 | continue; 622 | 623 | memberindex = PushArrayString(members, membernames[memberindex]); 624 | SetArrayCell(members, memberindex, offset, g_iDynamic_MemberLookup_Offset); 625 | } 626 | return true; 627 | } 628 | 629 | stock Collection _Dynamic_FindByMemberValue(DynamicObject dynamic, DynamicObject params) 630 | { 631 | if (!dynamic.IsValid(true)) 632 | return null; 633 | 634 | // Iterate through child dynamic objects 635 | int membercount = dynamic.MemberCount; 636 | if (membercount == 0) 637 | return null; 638 | 639 | // All the required stuff 640 | Collection results = new Collection(); 641 | DynamicObject member; 642 | int paramcount = params.MemberCount; 643 | bool matched = true; 644 | int resultcount = 0; 645 | DynamicOffset memberoffset; 646 | 647 | // Compile params 648 | char[][] param_name = new char[paramcount][DYNAMIC_MEMBERNAME_MAXLEN]; 649 | Dynamic_MemberType[] param_type = new Dynamic_MemberType[paramcount]; 650 | DynamicObject[] param_object = new DynamicObject[paramcount]; 651 | DynamicOffset[] param_offset = new DynamicOffset[paramcount]; 652 | int[] param_length = new int[paramcount]; 653 | int[] param_operator = new int[paramcount]; 654 | int param_maxlength; 655 | DynamicObject paramater; 656 | for (int i=0; i param_maxlength) 669 | param_maxlength = param_length[i]; 670 | } 671 | } 672 | char[] paramvalue = new char[param_maxlength]; 673 | 674 | // Loop members in object 675 | for (int i = 0; i < membercount; i++) 676 | { 677 | // Get member offset and check its a dynamic object 678 | memberoffset = _Dynamic_GetMemberOffsetByIndex(dynamic, i); 679 | if (_Dynamic_GetMemberTypeByOffset(dynamic, memberoffset) != DynamicType_Dynamic) 680 | continue; 681 | 682 | // Get member and check its valid 683 | member = _Dynamic_GetDynamicByOffset(dynamic, memberoffset); 684 | if (!member.IsValid(false)) 685 | continue; 686 | 687 | // Iterate through each param and check for matches 688 | matched = true; 689 | for (int param=0; param < paramcount; param++) 690 | { 691 | switch (param_type[param]) 692 | { 693 | case DynamicType_String: 694 | { 695 | _Dynamic_GetStringByOffset(param_object[param], param_offset[param], paramvalue, param_length[param]); 696 | memberoffset = _Dynamic_GetMemberOffset(member, param_name[param]); 697 | 698 | switch(param_operator[param]) 699 | { 700 | case DynamicOperator_Equals: 701 | { 702 | if (!_Dynamic_CompareStringByOffset(member, memberoffset, paramvalue, true)) 703 | { 704 | matched = false; 705 | break; 706 | } 707 | } 708 | case DynamicOperator_NotEquals: 709 | { 710 | if (_Dynamic_CompareStringByOffset(member, memberoffset, paramvalue, true)) 711 | { 712 | matched = false; 713 | break; 714 | } 715 | } 716 | default: 717 | { 718 | ThrowError("DynamicOperator %d is not yet supported", param_operator[param]); 719 | return null; 720 | } 721 | } 722 | } 723 | default: 724 | { 725 | ThrowError("Dynamic_MemberType %d is not yet supported", param_type[param]); 726 | return null; 727 | } 728 | } 729 | } 730 | 731 | // Check result 732 | if (!matched) 733 | continue; 734 | 735 | results.Push(member); 736 | resultcount++; 737 | } 738 | 739 | if (resultcount == 0) 740 | { 741 | delete results; 742 | return null; 743 | } 744 | 745 | return results; 746 | } -------------------------------------------------------------------------------- /scripting/dynamic/examples/001-the_dynamic_lifecycle/dynamic-example.sp: -------------------------------------------------------------------------------- 1 | #include 2 | #pragma newdecls required 3 | #pragma semicolon 1 4 | 5 | public void OnPluginStart() 6 | { 7 | // Creating a dynamic object 8 | Dynamic dynamic = Dynamic(); 9 | 10 | // You must dispose of your dynamic objects! 11 | dynamic.Dispose(); 12 | 13 | // You may want to set your reference to invalid 14 | dynamic = INVALID_DYNAMIC_OBJECT; 15 | 16 | // Sometimes you need to check if an object is still valid 17 | if (!dynamic.IsValid) 18 | dynamic = Dynamic(); 19 | 20 | // What if you want to reset an object and keep the reference 21 | dynamic.Reset(); 22 | 23 | // Dont forget to dispose! 24 | dynamic.Dispose(); 25 | } -------------------------------------------------------------------------------- /scripting/dynamic/examples/002-accessing_dynamic_members/dynamic-example.sp: -------------------------------------------------------------------------------- 1 | #include 2 | #pragma newdecls required 3 | #pragma semicolon 1 4 | 5 | bool bvalue = false; 6 | Dynamic dvalue = INVALID_DYNAMIC_OBJECT; 7 | float fvalue = 0.0; 8 | Handle hvalue = null; 9 | int ivalue = 0; 10 | char svalue[16] = ""; 11 | float vvalue[3] = {0.0, 0.0, 0.0}; 12 | 13 | public void OnPluginStart() 14 | { 15 | Dynamic dynamic = Dynamic(); 16 | 17 | dynamic.SetBool("Bool", false); 18 | dynamic.SetDynamic("Dynamic", INVALID_DYNAMIC_OBJECT); 19 | dynamic.SetFloat("Float", 0.0); 20 | dynamic.SetHandle("Handle", null); 21 | dynamic.SetInt("Int", 0); 22 | dynamic.SetString("String", ""); 23 | dynamic.SetVector("Vector", NULL_VECTOR); 24 | 25 | bvalue = dynamic.GetBool("Bool"); 26 | dvalue = dynamic.GetDynamic("Dynamic"); 27 | fvalue = dynamic.GetFloat("Float"); 28 | hvalue = dynamic.GetHandle("Handle"); 29 | ivalue = dynamic.GetInt("Int"); 30 | dynamic.GetString("String", svalue, sizeof(svalue)); 31 | dynamic.GetVector("Vector", vvalue); 32 | 33 | bvalue = dynamic.GetBool("Bool", bvalue); 34 | fvalue = dynamic.GetFloat("Float", fvalue); 35 | ivalue = dynamic.GetInt("Int", ivalue); 36 | 37 | dynamic.Dispose(); 38 | } -------------------------------------------------------------------------------- /scripting/dynamic/examples/003-type_conversion/dynamic-example.sp: -------------------------------------------------------------------------------- 1 | #include 2 | #pragma newdecls required 3 | #pragma semicolon 1 4 | 5 | public void OnPluginStart() 6 | { 7 | // Creating a dynamic object 8 | Dynamic dynamic = Dynamic(); 9 | 10 | // Dynamic will convert member types automatically based on 11 | // the type used when they were first set. 12 | 13 | // Lets show each types setter 14 | dynamic.SetBool("Bool", false); 15 | dynamic.SetDynamic("Dynamic", INVALID_DYNAMIC_OBJECT); 16 | dynamic.SetFloat("Float", 77.7); 17 | dynamic.SetHandle("Handle", null); 18 | dynamic.SetInt("Int", 66); 19 | dynamic.SetString("String", "Hello!"); 20 | dynamic.SetVector("Vector", NULL_VECTOR); 21 | 22 | // Each member above has it's type set because the first setter 23 | // determines the members lifetime type. 24 | 25 | // Lets give some examples 26 | dynamic.SetString("Bool", "True"); // Bool == bool:true 27 | dynamic.GetFloat("Int"); // returns float:66.0 28 | dynamic.GetInt("Float"); // returns int:78 (rounds to closest whole number) 29 | 30 | // Bool, Float, Int and String can all be all freely type 31 | // converted between eachother. 32 | 33 | // Dynamic and Int are convertable with eachother 34 | 35 | // Handle is not convertable with any other type 36 | 37 | // Vector and String are convertable with eachother 38 | 39 | // Any unconvertable types will receive an 40 | // `Unsupported member datatype` error 41 | 42 | // Dont forget to dispose! 43 | dynamic.Dispose(); 44 | } -------------------------------------------------------------------------------- /scripting/dynamic/examples/999-old/basics.sp: -------------------------------------------------------------------------------- 1 | #include 2 | #pragma newdecls required 3 | #pragma semicolon 1 4 | 5 | public void OnPluginStart() 6 | { 7 | // Creating dynamic objects is straight foward 8 | Dynamic someobj = Dynamic(); 9 | 10 | // Setting integers, floats and booleans also 11 | someobj.SetInt("someint", 1); 12 | someobj.SetFloat("somefloat", 512.7); 13 | someobj.SetBool("somebool", true); 14 | 15 | // When dealing with strings... 16 | // you want to set an appropriate length if the value will change 17 | someobj.SetString("somestring", "What did you say?", 64); 18 | 19 | // If the value of a string will never change you might as well 20 | someobj.SetString("our_planets_name", "Earth"); 21 | 22 | // Getting integers, floats and booleans is also straight foward 23 | int someint = someobj.GetInt("someint"); 24 | float somefloat = someobj.GetFloat("somefloat"); 25 | bool somebool = someobj.GetBool("somebool"); 26 | 27 | // You can also include default values in case a member doesn't exist 28 | someint = someobj.GetInt("someint1", -1); 29 | somefloat = someobj.GetFloat("somefloat2", 7.25); 30 | somebool = someobj.GetBool("somebool2", false); 31 | 32 | // And the normal "extra" stuff to get a string in sourcespawn 33 | char somestring[64]; 34 | someobj.GetString("somestring", somestring, sizeof(somestring)); 35 | 36 | // You can also get an exact string by size 37 | int length = someobj.GetStringLength("our_planets_name"); 38 | char[] our_planets_name = new char[length]; 39 | someobj.GetString("our_planets_name", our_planets_name, length); 40 | 41 | // Dynamic supports type conversion!!!!!!!!!!! 42 | someint = someobj.GetInt("somefloat"); // rounds to floor 43 | somefloat = someobj.GetFloat("someint"); 44 | someobj.GetString("somefloat", somestring, sizeof(somestring)); 45 | someobj.GetString("somebool", somestring, sizeof(somestring)); 46 | 47 | // You can even set dynamic objects within themselves 48 | Dynamic anotherobj = Dynamic(); 49 | anotherobj.SetInt("someint", 128); 50 | someobj.SetObject("anotherobj", anotherobj); 51 | 52 | // You can also get and set Handles 53 | someobj.SetHandle("somehandle", CreateArray()); 54 | Handle somehandle = someobj.GetHandle("somehandle"); 55 | PushArrayCell(somehandle, 1); 56 | 57 | // Vectors are also supported like so 58 | float somevec[3] = {1.0, 2.0, 3.0}; 59 | someobj.SetVector("somevec", NULL_VECTOR); 60 | someobj.SetVector("somevec", somevec); 61 | someobj.GetVector("somevec", somevec); 62 | 63 | // You can name a dynamic object 64 | someobj.SetName("someobj"); 65 | 66 | // So another plugin can access it like so 67 | someobj = Dynamic.FindByName("someobj"); 68 | 69 | // You can also sort members within a dynamic object by name 70 | someobj.SortMembers(Sort_Ascending); 71 | 72 | // Dynamic assigns player settings which can be accessed like so 73 | int client = 1; 74 | Dynamic settings = Dynamic.GetPlayerSettings(client); 75 | 76 | // You can also access dynamic player settings like this 77 | settings = view_as(client); 78 | 79 | // Dynamic also provides a global settings object 80 | settings = Dynamic.GetSettings(); 81 | 82 | // You can also access the global settings object like this 83 | settings = view_as(0); 84 | 85 | // This is to a stop compilation warning 86 | settings.SetInt("someint", 1); 87 | 88 | // Sometimes you might want to iterate through members to accomplish stuff 89 | int count = someobj.MemberCount; 90 | int memberoffset; 91 | char membername[DYNAMIC_MEMBERNAME_MAXLEN]; 92 | 93 | PrintToServer("GETTING ALL DYNAMIC OBJECT MEMBERS"); 94 | PrintToServer(" > someobj.MemberCount=%d", someobj.MemberCount); 95 | for (int i = 0; i < count; i++) 96 | { 97 | memberoffset = someobj.GetMemberOffsetByIndex(i); 98 | someobj.GetMemberNameByIndex(i, membername, sizeof(membername)); 99 | 100 | switch (someobj.GetMemberType(memberoffset)) 101 | { 102 | case DynamicType_Int: 103 | { 104 | someint = someobj.GetIntByOffset(memberoffset); 105 | PrintToServer("[%d] someobj.%s = %d", memberoffset, membername, someint); 106 | } 107 | case DynamicType_Bool: 108 | { 109 | somebool = someobj.GetBoolByOffset(memberoffset); 110 | PrintToServer("[%d] someobj.%s = %d", memberoffset, membername, somebool); 111 | } 112 | case DynamicType_Float: 113 | { 114 | somefloat = someobj.GetFloatByOffset(memberoffset); 115 | PrintToServer("[%d] someobj.%s = %f", memberoffset, membername, somefloat); 116 | } 117 | case DynamicType_String: 118 | { 119 | someobj.GetStringByOffset(memberoffset, somestring, sizeof(somestring)); 120 | PrintToServer("[%d] someobj.%s = '%s'", memberoffset, membername, somestring); 121 | } 122 | case DynamicType_Object: 123 | { 124 | anotherobj = someobj.GetObjectByOffset(memberoffset); 125 | someint = anotherobj.GetInt("someint"); 126 | PrintToServer("[%d] .someobj.%s.someint = %d", memberoffset, membername, someint); 127 | } 128 | case DynamicType_Handle: 129 | { 130 | somehandle = someobj.GetHandleByOffset(memberoffset); 131 | PrintToServer("[%d] .someobj.%s = %d", memberoffset, membername, somehandle); 132 | } 133 | case DynamicType_Vector: 134 | { 135 | someobj.GetVectorByOffset(memberoffset, somevec); 136 | PrintToServer("[%d] .someobj.%s = {%f, %f, %f}", memberoffset, membername, somevec[0], somevec[1], somevec[2]); 137 | } 138 | } 139 | } 140 | 141 | // Sometimes you may want to listen to member changes within a callback 142 | PrintToServer("CALLBACK TESTING MESSAGES"); 143 | someobj.HookChanges(OnDynamicMemberChanged); 144 | someobj.SetInt("someint", 256); 145 | someobj.SetFloat("somefloat", -12.04); 146 | someobj.SetBool("somebool", false); 147 | someobj.SetString("somestring", "ye sure moite"); 148 | someobj.SetVector("somevec", view_as({2.0, 3.0, 4.0})); 149 | 150 | // You MUST! dispose your dynamic objects when your done. 151 | anotherobj.Dispose(); 152 | 153 | // You can also dispose of any disposable members like this 154 | // -> This includes auto closure of Handle datatypes 155 | someobj.Dispose(true); 156 | } 157 | 158 | public void OnDynamicMemberChanged(Dynamic obj, int offset, const char[] member, Dynamic_MemberType type) 159 | { 160 | switch (type) 161 | { 162 | case DynamicType_Int: 163 | { 164 | PrintToServer("[%d] obj.%s = %d", offset, member, obj.GetIntByOffset(offset)); 165 | } 166 | case DynamicType_Float: 167 | { 168 | PrintToServer("[%d] obj.%s = %f", offset, member, obj.GetFloatByOffset(offset)); 169 | } 170 | case DynamicType_Bool: 171 | { 172 | PrintToServer("[%d] obj.%s = %d", offset, member, obj.GetBoolByOffset(offset)); 173 | } 174 | case DynamicType_String: 175 | { 176 | char somestring[64]; 177 | obj.GetStringByOffset(offset, somestring, sizeof(somestring)); 178 | PrintToServer("[%d] obj.%s = '%s'", offset, member, somestring); 179 | } 180 | case DynamicType_Vector: 181 | { 182 | char somestring[64]; 183 | obj.GetStringByOffset(offset, somestring, sizeof(somestring)); 184 | PrintToServer("[%d] obj.%s = %s", offset, member, somestring); 185 | } 186 | } 187 | } -------------------------------------------------------------------------------- /scripting/dynamic/examples/999-old/collections/collection.sp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "person.inc" 3 | #include "people.inc" 4 | #pragma newdecls required 5 | #pragma semicolon 1 6 | 7 | public void OnPluginStart() 8 | { 9 | // New people collection as defined in `people.inc` 10 | People people = new People(); 11 | 12 | // New person as defined in `person.inc` 13 | Person person = Person(); 14 | person.SetName("Neuro Toxin"); 15 | person.Age = 32; 16 | person.Height = 6.4; 17 | person.IsAlive = true; 18 | 19 | // Add person to people 20 | people.AddItem(person); 21 | 22 | // Lets add another person 23 | person = Person(); 24 | person.SetName("Nouse"); 25 | person.Age = 21; 26 | person.Height = 5.7; 27 | person.IsAlive = true; 28 | people.AddItem(person); 29 | 30 | // Iterating people in the collection 31 | for (int index = 0; index < people.Count; index++) 32 | { 33 | person = people.Items(index); 34 | if (!person.IsValid) 35 | continue; 36 | 37 | char name[1024]; 38 | person.GetName(name, sizeof(name)); 39 | 40 | PrintToServer("Found Person {Name:'%s', Age:%d, Height:%f, IsAlive:%d}", 41 | name, person.Age, person.Height, person.IsAlive); 42 | } 43 | 44 | // Always clean up when your done 45 | people.Dispose(); 46 | } 47 | -------------------------------------------------------------------------------- /scripting/dynamic/examples/999-old/collections/people.inc: -------------------------------------------------------------------------------- 1 | #if defined _dynamic_collection_people 2 | #endinput 3 | #endif 4 | #define _dynamic_collection_people 5 | 6 | /* 7 | This example demonstrates how to easily create a collection 8 | methodmap by inheriting Dynamic. 9 | */ 10 | 11 | // We inherit Dynamic's collection methodmap 12 | methodmap People < Collection 13 | { 14 | public People() 15 | { 16 | // Return a new Dynamic Collection 17 | return view_as(new Collection()); 18 | } 19 | 20 | // Override Items method to return type Person 21 | public Person Items(int index) 22 | { 23 | return view_as(this.Items(index)); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /scripting/dynamic/examples/999-old/collections/person.inc: -------------------------------------------------------------------------------- 1 | #if defined _dynamic_methodmap_person 2 | #endinput 3 | #endif 4 | #define _dynamic_methodmap_person 5 | 6 | /* 7 | This example demonstrates how to easily store data for your 8 | own methodmaps by inherting Dynamic 9 | */ 10 | 11 | methodmap Person < Dynamic 12 | { 13 | public Person() 14 | { 15 | Dynamic person = Dynamic(); 16 | return view_as(person); 17 | } 18 | 19 | property int Age 20 | { 21 | public get() 22 | { 23 | return this.GetInt("Age", 0); 24 | } 25 | public set(int value) 26 | { 27 | this.SetInt("Age", value); 28 | } 29 | } 30 | 31 | property float Height 32 | { 33 | public get() 34 | { 35 | return this.GetFloat("Height", 0.0); 36 | } 37 | public set(float value) 38 | { 39 | this.SetFloat("Height", value); 40 | } 41 | } 42 | 43 | property bool IsAlive 44 | { 45 | public get() 46 | { 47 | return this.GetBool("IsAlive", false); 48 | } 49 | public set(bool value) 50 | { 51 | this.SetBool("IsAlive", value); 52 | } 53 | } 54 | 55 | public bool GetName(char[] buffer, int length) 56 | { 57 | return this.GetString("Name", buffer, length); 58 | } 59 | 60 | public void SetName(const char[] buffer) 61 | { 62 | this.SetString("Name", buffer, 1024); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /scripting/dynamic/examples/999-old/dynamic-classexample.sp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #pragma newdecls required 4 | #pragma semicolon 1 5 | 6 | public void OnPluginStart() 7 | { 8 | // You can also use Dynamic to back Methodmap properties. 9 | // This is another step towards sourcepawn feeling a bit more OO 10 | // -> Find the methodmap in 'include/dynamic-example.sp' 11 | // -> This class was generated @ 'http://console.aus-tg.com/index.php?page=createdynamicclass' 12 | 13 | // Creating dynamic classes is straight foward 14 | MyClass someobj = MyClass(); 15 | 16 | // Setting integers, floats and booleans also 17 | someobj.SomeInt = 1; 18 | someobj.SomeFloat = 512.7; 19 | someobj.SomeBool = true; 20 | 21 | // The strings length is now defined within the class initialiser code 22 | someobj.SetSomeString("What did you say?"); 23 | 24 | // Getting integers, floats and booleans is also straight foward 25 | int someint = someobj.SomeInt; 26 | float somefloat = someobj.SomeFloat; 27 | bool somebool = someobj.SomeBool; 28 | 29 | // And the normal "extra" stuff to get a string in sourcespawn 30 | char somestring[64]; 31 | someobj.GetSomeString(somestring, 64); 32 | 33 | // You can also get an exact string by size 34 | int length = someobj.GetStringLength("SomeString"); 35 | someobj.GetSomeString(somestring, length); 36 | 37 | // Dynamic supports type conversion!!!!!!!!!!! 38 | // -> Type conversion is not possible inside of classes 39 | //someint = someobj.GetInt("somefloat"); // rounds to floor 40 | //somefloat = someobj.GetFloat("someint"); 41 | //someobj.GetString("somefloat", somestring, sizeof(somestring)); 42 | //someobj.GetString("somebool", somestring, sizeof(somestring)); 43 | 44 | // You can even set dynamic objects within themselves 45 | Dynamic anotherobj = Dynamic(); 46 | anotherobj.SetInt("someint", 128); 47 | someobj.SomeObject = anotherobj; 48 | 49 | // You can also get and set Handles 50 | someobj.SomeHandle = CreateArray(); 51 | Handle somehandle = someobj.SomeHandle; 52 | PushArrayCell(somehandle, 1); 53 | 54 | // Vectors are also supported like so 55 | float somevec[3] = {1.0, 2.0, 3.0}; 56 | someobj.SetSomeVector(NULL_VECTOR); 57 | someobj.SetSomeVector(somevec); 58 | someobj.GetSomeVector(somevec); 59 | 60 | // You can name a dynamic object 61 | someobj.SetName("someobj"); 62 | 63 | // So another plugin can access it like so 64 | someobj = view_as(Dynamic.FindByName("someobj")); 65 | 66 | // You can also sort members within a dynamic object by name 67 | someobj.SortMembers(Sort_Ascending); 68 | 69 | // Sometimes you might want to iterate through members to accomplish stuff 70 | int count = someobj.MemberCount; 71 | int memberoffset; 72 | char membername[DYNAMIC_MEMBERNAME_MAXLEN]; 73 | 74 | PrintToServer("GETTING ALL DYNAMIC OBJECT MEMBERS"); 75 | for (int i = 0; i < count; i++) 76 | { 77 | memberoffset = someobj.GetMemberOffsetByIndex(i); 78 | someobj.GetMemberNameByIndex(i, membername, sizeof(membername)); 79 | 80 | switch (someobj.GetMemberType(memberoffset)) 81 | { 82 | case DynamicType_Int: 83 | { 84 | someint = someobj.GetIntByOffset(memberoffset); 85 | PrintToServer("[%d] someobj.%s = %d", memberoffset, membername, someint); 86 | } 87 | case DynamicType_Bool: 88 | { 89 | somebool = someobj.GetBoolByOffset(memberoffset); 90 | PrintToServer("[%d] someobj.%s = %d", memberoffset, membername, somebool); 91 | } 92 | case DynamicType_Float: 93 | { 94 | somefloat = someobj.GetFloatByOffset(memberoffset); 95 | PrintToServer("[%d] someobj.%s = %f", memberoffset, membername, somefloat); 96 | } 97 | case DynamicType_String: 98 | { 99 | someobj.GetStringByOffset(memberoffset, somestring, sizeof(somestring)); 100 | PrintToServer("[%d] someobj.%s = '%s'", memberoffset, membername, somestring); 101 | } 102 | case DynamicType_Object: 103 | { 104 | anotherobj = someobj.GetObjectByOffset(memberoffset); 105 | someint = anotherobj.GetInt("someint"); 106 | PrintToServer("[%d] .someobj.%s.someint = %d", memberoffset, membername, someint); 107 | } 108 | case DynamicType_Handle: 109 | { 110 | somehandle = someobj.GetHandleByOffset(memberoffset); 111 | PrintToServer("[%d] .someobj.%s = %d", memberoffset, membername, somehandle); 112 | } 113 | case DynamicType_Vector: 114 | { 115 | someobj.GetVectorByOffset(memberoffset, somevec); 116 | PrintToServer("[%d] .someobj.%s = {%f, %f, %f}", memberoffset, membername, somevec[0], somevec[1], somevec[2]); 117 | } 118 | } 119 | } 120 | 121 | // Sometimes you may want to listen to member changes within a callback 122 | PrintToServer("CALLBACK TESTING MESSAGES"); 123 | someobj.HookChanges(OnDynamicMemberChanged); 124 | someobj.SetInt("someint", 256); 125 | someobj.SetFloat("somefloat", -12.04); 126 | someobj.SetBool("somebool", false); 127 | someobj.SetString("somestring", "ye sure moite"); 128 | someobj.SetVector("somevec", view_as({2.0, 3.0, 4.0})); 129 | 130 | // You MUST! dispose your dynamic objects when your done. 131 | anotherobj.Dispose(); 132 | 133 | // You can also dispose of any disposable members like this 134 | // -> This includes auto closure of Handle datatypes 135 | someobj.Dispose(true); 136 | } 137 | 138 | public void OnDynamicMemberChanged(Dynamic obj, int offset, const char[] member, Dynamic_MemberType type) 139 | { 140 | switch (type) 141 | { 142 | case DynamicType_Int: 143 | { 144 | PrintToServer("[%d] obj.%s = %d", offset, member, obj.GetIntByOffset(offset)); 145 | } 146 | case DynamicType_Float: 147 | { 148 | PrintToServer("[%d] obj.%s = %f", offset, member, obj.GetFloatByOffset(offset)); 149 | } 150 | case DynamicType_Bool: 151 | { 152 | PrintToServer("[%d] obj.%s = %d", offset, member, obj.GetBoolByOffset(offset)); 153 | } 154 | case DynamicType_String: 155 | { 156 | char somestring[64]; 157 | obj.GetStringByOffset(offset, somestring, sizeof(somestring)); 158 | PrintToServer("[%d] obj.%s = '%s'", offset, member, somestring); 159 | } 160 | case DynamicType_Vector: 161 | { 162 | char somestring[64]; 163 | obj.GetStringByOffset(offset, somestring, sizeof(somestring)); 164 | PrintToServer("[%d] obj.%s = %s", offset, member, somestring); 165 | } 166 | } 167 | } 168 | -------------------------------------------------------------------------------- /scripting/dynamic/examples/999-old/dynamic-example.sp: -------------------------------------------------------------------------------- 1 | #include 2 | #pragma newdecls required 3 | #pragma semicolon 1 4 | 5 | public void OnPluginStart() 6 | { 7 | // Creating dynamic objects is straight foward 8 | Dynamic someobj = Dynamic(); 9 | 10 | // Setting integers, floats and booleans also 11 | someobj.SetInt("someint", 1); 12 | someobj.SetFloat("somefloat", 512.7); 13 | someobj.SetBool("somebool", true); 14 | 15 | // When dealing with strings... 16 | // you want to set an appropriate length if the value will change 17 | someobj.SetString("somestring", "What did you say?", 64); 18 | 19 | // If the value of a string will never change you might as well 20 | someobj.SetString("our_planets_name", "Earth"); 21 | 22 | // Getting integers, floats and booleans is also straight foward 23 | int someint = someobj.GetInt("someint"); 24 | float somefloat = someobj.GetFloat("somefloat"); 25 | bool somebool = someobj.GetBool("somebool"); 26 | 27 | // You can also include default values in case a member doesn't exist 28 | someint = someobj.GetInt("someint1", -1); 29 | somefloat = someobj.GetFloat("somefloat2", 7.25); 30 | somebool = someobj.GetBool("somebool2", false); 31 | 32 | // And the normal "extra" stuff to get a string in sourcespawn 33 | char somestring[64]; 34 | someobj.GetString("somestring", somestring, sizeof(somestring)); 35 | 36 | // You can also get an exact string by size 37 | int length = someobj.GetStringLength("our_planets_name"); 38 | char[] our_planets_name = new char[length]; 39 | someobj.GetString("our_planets_name", our_planets_name, length); 40 | 41 | // Dynamic supports type conversion!!!!!!!!!!! 42 | someint = someobj.GetInt("somefloat"); // rounds to floor 43 | somefloat = someobj.GetFloat("someint"); 44 | someobj.GetString("somefloat", somestring, sizeof(somestring)); 45 | someobj.GetString("somebool", somestring, sizeof(somestring)); 46 | 47 | // You can even set dynamic objects within themselves 48 | Dynamic anotherobj = Dynamic(); 49 | anotherobj.SetInt("someint", 128); 50 | someobj.SetObject("anotherobj", anotherobj); 51 | 52 | // You can also get and set Handles 53 | someobj.SetHandle("somehandle", CreateArray()); 54 | Handle somehandle = someobj.GetHandle("somehandle"); 55 | PushArrayCell(somehandle, 1); 56 | 57 | // Vectors are also supported like so 58 | float somevec[3] = {1.0, 2.0, 3.0}; 59 | someobj.SetVector("somevec", NULL_VECTOR); 60 | someobj.SetVector("somevec", somevec); 61 | someobj.GetVector("somevec", somevec); 62 | 63 | // You can name a dynamic object 64 | someobj.SetName("someobj"); 65 | 66 | // So another plugin can access it like so 67 | someobj = Dynamic.FindByName("someobj"); 68 | 69 | // You can also sort members within a dynamic object by name 70 | someobj.SortMembers(Sort_Ascending); 71 | 72 | // Dynamic assigns player settings which can be accessed like so 73 | int client = 1; 74 | Dynamic settings = Dynamic.GetPlayerSettings(client); 75 | 76 | // You can also access dynamic player settings like this 77 | settings = view_as(client); 78 | 79 | // Dynamic also provides a global settings object 80 | settings = Dynamic.GetSettings(); 81 | 82 | // You can also access the global settings object like this 83 | settings = view_as(0); 84 | 85 | // This is to a stop compilation warning 86 | settings.SetInt("someint", 1); 87 | 88 | // Sometimes you might want to iterate through members to accomplish stuff 89 | int count = someobj.MemberCount; 90 | int memberoffset; 91 | char membername[DYNAMIC_MEMBERNAME_MAXLEN]; 92 | 93 | PrintToServer("GETTING ALL DYNAMIC OBJECT MEMBERS"); 94 | for (int i = 0; i < count; i++) 95 | { 96 | memberoffset = someobj.GetMemberOffsetByIndex(i); 97 | someobj.GetMemberNameByIndex(i, membername, sizeof(membername)); 98 | 99 | switch (someobj.GetMemberType(memberoffset)) 100 | { 101 | case DynamicType_Int: 102 | { 103 | someint = someobj.GetIntByOffset(memberoffset); 104 | PrintToServer("[%d] someobj.%s = %d", memberoffset, membername, someint); 105 | } 106 | case DynamicType_Bool: 107 | { 108 | somebool = someobj.GetBoolByOffset(memberoffset); 109 | PrintToServer("[%d] someobj.%s = %d", memberoffset, membername, somebool); 110 | } 111 | case DynamicType_Float: 112 | { 113 | somefloat = someobj.GetFloatByOffset(memberoffset); 114 | PrintToServer("[%d] someobj.%s = %f", memberoffset, membername, somefloat); 115 | } 116 | case DynamicType_String: 117 | { 118 | someobj.GetStringByOffset(memberoffset, somestring, sizeof(somestring)); 119 | PrintToServer("[%d] someobj.%s = '%s'", memberoffset, membername, somestring); 120 | } 121 | case DynamicType_Object: 122 | { 123 | anotherobj = someobj.GetObjectByOffset(memberoffset); 124 | someint = anotherobj.GetInt("someint"); 125 | PrintToServer("[%d] .someobj.%s.someint = %d", memberoffset, membername, someint); 126 | } 127 | case DynamicType_Handle: 128 | { 129 | somehandle = someobj.GetHandleByOffset(memberoffset); 130 | PrintToServer("[%d] .someobj.%s = %d", memberoffset, membername, somehandle); 131 | } 132 | case DynamicType_Vector: 133 | { 134 | someobj.GetVectorByOffset(memberoffset, somevec); 135 | PrintToServer("[%d] .someobj.%s = {%f, %f, %f}", memberoffset, membername, somevec[0], somevec[1], somevec[2]); 136 | } 137 | } 138 | } 139 | 140 | // Sometimes you may want to listen to member changes within a callback 141 | PrintToServer("CALLBACK TESTING MESSAGES"); 142 | someobj.HookChanges(OnDynamicMemberChanged); 143 | someobj.SetInt("someint", 256); 144 | someobj.SetFloat("somefloat", -12.04); 145 | someobj.SetBool("somebool", false); 146 | someobj.SetString("somestring", "ye sure moite"); 147 | someobj.SetVector("somevec", view_as({2.0, 3.0, 4.0})); 148 | 149 | // You MUST! dispose your dynamic objects when your done. 150 | anotherobj.Dispose(); 151 | 152 | // You can also dispose of any disposable members like this 153 | // -> This includes auto closure of Handle datatypes 154 | someobj.Dispose(true); 155 | } 156 | 157 | public void OnDynamicMemberChanged(Dynamic obj, int offset, const char[] member, Dynamic_MemberType type) 158 | { 159 | switch (type) 160 | { 161 | case DynamicType_Int: 162 | { 163 | PrintToServer("[%d] obj.%s = %d", offset, member, obj.GetIntByOffset(offset)); 164 | } 165 | case DynamicType_Float: 166 | { 167 | PrintToServer("[%d] obj.%s = %f", offset, member, obj.GetFloatByOffset(offset)); 168 | } 169 | case DynamicType_Bool: 170 | { 171 | PrintToServer("[%d] obj.%s = %d", offset, member, obj.GetBoolByOffset(offset)); 172 | } 173 | case DynamicType_String: 174 | { 175 | char somestring[64]; 176 | obj.GetStringByOffset(offset, somestring, sizeof(somestring)); 177 | PrintToServer("[%d] obj.%s = '%s'", offset, member, somestring); 178 | } 179 | case DynamicType_Vector: 180 | { 181 | char somestring[64]; 182 | obj.GetStringByOffset(offset, somestring, sizeof(somestring)); 183 | PrintToServer("[%d] obj.%s = %s", offset, member, somestring); 184 | } 185 | } 186 | } 187 | -------------------------------------------------------------------------------- /scripting/dynamic/examples/999-old/keyvalues/using_read_hook.sp: -------------------------------------------------------------------------------- 1 | /* 2 | In this example, you will see how Dynamic can parse a KeyValues file while using a hook 3 | to select the keys you would like to load. 4 | */ 5 | 6 | #include 7 | #pragma newdecls required 8 | #pragma semicolon 1 9 | 10 | public void OnPluginStart() 11 | { 12 | // The normal old begining for Dynamic 13 | Dynamic items_game = Dynamic(); 14 | 15 | // Lets load `items_game.txt` and parse our hook callback 16 | items_game.ReadKeyValues("scripts/items/items_game.txt", 1024, PK_ReadDynamicKeyValue); 17 | 18 | // The hook has now done it's work and we are left with only a couple of subkeys 19 | Dynamic game_info = items_game.GetObject("game_info"); 20 | Dynamic prefabs = items_game.GetObject("prefabs"); 21 | Dynamic items = items_game.GetObject("items"); 22 | Dynamic attributes = items_game.GetObject("attributes"); 23 | 24 | // Lets make a new version of `items_game.txt` 25 | items_game.WriteKeyValues("scripts/items/items_game_dynamic.txt"); 26 | 27 | // That's all folks, better clean up my trash! 28 | items_game.Dispose(true); 29 | } 30 | 31 | public Action PK_ReadDynamicKeyValue(Dynamic obj, const char[] member, int depth) 32 | { 33 | // Allow the basekey (depth=0) to be loaded 34 | if (depth == 0) 35 | return Plugin_Continue; 36 | 37 | // Check all subkeys (depth=1) within the basekey (depth=0) 38 | if (depth == 1) 39 | { 40 | // Allow these subkeys (depth=1) in the basekey (depth=0) to load 41 | if (StrEqual(member, "game_info")) 42 | return Plugin_Continue; 43 | if (StrEqual(member, "prefabs")) 44 | return Plugin_Continue; 45 | if (StrEqual(member, "items")) 46 | return Plugin_Continue; 47 | if (StrEqual(member, "attributes")) 48 | return Plugin_Continue; 49 | else 50 | { 51 | // Block all other subkeys (depth=1) 52 | return Plugin_Stop; 53 | } 54 | } 55 | 56 | // Let all subkeys in higher depths load (depth>1) 57 | return Plugin_Continue; 58 | } -------------------------------------------------------------------------------- /scripting/dynamic/examples/wiki_resources/a_basic_methodmap.sp: -------------------------------------------------------------------------------- 1 | #include 2 | #pragma newdecls required 3 | #pragma semicolon 1 4 | 5 | methodmap MyPluginPlayerInfo < Dynamic 6 | { 7 | public MyPluginPlayerInfo() 8 | { 9 | Dynamic playerinfo = Dynamic(); 10 | return view_as(playerinfo); 11 | } 12 | 13 | property int Points 14 | { 15 | public get() 16 | { 17 | return this.GetInt("Points"); 18 | } 19 | public set(int value) 20 | { 21 | this.SetInt("Points", value); 22 | } 23 | } 24 | 25 | property float KDR 26 | { 27 | public get() 28 | { 29 | return this.GetFloat("KDR"); 30 | } 31 | public set(float value) 32 | { 33 | this.SetFloat("KDR", value); 34 | } 35 | } 36 | 37 | property int Rank 38 | { 39 | public get() 40 | { 41 | return this.GetInt("Rank"); 42 | } 43 | public set(int value) 44 | { 45 | this.SetInt("Rank", value); 46 | } 47 | } 48 | } 49 | 50 | public void OnClientConnected(int client) 51 | { 52 | MyPluginPlayerInfo playerinfo = MyPluginPlayerInfo(); 53 | playerinfo.Points = 2217; 54 | playerinfo.KDR = 2.69; 55 | playerinfo.Rank = 1; 56 | } -------------------------------------------------------------------------------- /scripting/dynamic/examples/wiki_resources/accessing_members.sp: -------------------------------------------------------------------------------- 1 | #include 2 | #pragma newdecls required 3 | #pragma semicolon 1 4 | 5 | bool bvalue = false; 6 | Dynamic dvalue = INVALID_DYNAMIC_OBJECT; 7 | float fvalue = 0.0; 8 | Handle hvalue = null; 9 | int ivalue = 0; 10 | char svalue[16] = ""; 11 | float vvalue[3] = {0.0, 0.0, 0.0}; 12 | 13 | public void OnPluginStart() 14 | { 15 | Dynamic dynamic = Dynamic(); 16 | 17 | dynamic.SetBool("Bool", false); 18 | dynamic.SetDynamic("Dynamic", INVALID_DYNAMIC_OBJECT); 19 | dynamic.SetFloat("Float", 0.0); 20 | dynamic.SetHandle("Handle", null); 21 | dynamic.SetInt("Int", 0); 22 | dynamic.SetString("String", ""); 23 | dynamic.SetVector("Vector", NULL_VECTOR); 24 | 25 | bvalue = dynamic.GetBool("Bool"); 26 | dvalue = dynamic.GetDynamic("Dynamic"); 27 | fvalue = dynamic.GetFloat("Float"); 28 | hvalue = dynamic.GetHandle("Handle"); 29 | ivalue = dynamic.GetInt("Int"); 30 | dynamic.GetString("String", svalue, sizeof(svalue)); 31 | dynamic.GetVector("Vector", vvalue); 32 | 33 | bvalue = dynamic.GetBool("Bool", bvalue); 34 | fvalue = dynamic.GetFloat("Float", fvalue); 35 | ivalue = dynamic.GetInt("Int", ivalue); 36 | 37 | dynamic.Dispose(); 38 | } -------------------------------------------------------------------------------- /scripting/dynamic/system/benchmark/output.txt: -------------------------------------------------------------------------------- 1 | [SM] Preparing benchmark Test... 2 | [SM] Starting Benchmark Tests... 3 | Created 1000 dynamic object(s) in 0.000000 second(s) 4 | Created 100000 dynamic member(s) in 0.164062 second(s) 5 | Read 100000 dynamic member(s) in 0.070312 second(s) 6 | Read 100000 dynamic member(s) using offsets in 0.054687 second(s) 7 | Verified 100000 dynamic member(s) in 0.222656 second(s) 8 | Updated 100000 dynamic member(s) in 0.078125 second(s) 9 | Offset verification with 100000 dynamic member(s) in 0.203125 second(s) 10 | Disposed 1000 dynamic object(s) in 0.023437 second(s) 11 | 12 | [SM] Preparing benchmark Test... 13 | [SM] Starting Benchmark Tests... 14 | Created 1000 dynamic object(s) in 0.000000 second(s) 15 | Created 100000 dynamic member(s) in 0.160156 second(s) 16 | Read 100000 dynamic member(s) in 0.070312 second(s) 17 | Read 100000 dynamic member(s) using offsets in 0.054687 second(s) 18 | Verified 100000 dynamic member(s) in 0.218750 second(s) 19 | Updated 100000 dynamic member(s) in 0.078125 second(s) 20 | Offset verification with 100000 dynamic member(s) in 0.207031 second(s) 21 | Disposed 1000 dynamic object(s) in 0.019531 second(s) 22 | 23 | [SM] Preparing benchmark Test... 24 | [SM] Starting Benchmark Tests... 25 | Created 1000 dynamic object(s) in 0.000000 second(s) 26 | Created 100000 dynamic member(s) in 0.164062 second(s) 27 | Read 100000 dynamic member(s) in 0.070312 second(s) 28 | Read 100000 dynamic member(s) using offsets in 0.054687 second(s) 29 | Verified 100000 dynamic member(s) in 0.222656 second(s) 30 | Updated 100000 dynamic member(s) in 0.078125 second(s) 31 | Offset verification with 100000 dynamic member(s) in 0.203125 second(s) 32 | Disposed 1000 dynamic object(s) in 0.023437 second(s) -------------------------------------------------------------------------------- /scripting/dynamic/system/commands.sp: -------------------------------------------------------------------------------- 1 | /** 2 | * ============================================================================= 3 | * Dynamic for SourceMod (C)2016 Matthew J Dunn. All rights reserved. 4 | * ============================================================================= 5 | * 6 | * This program is free software; you can redistribute it and/or modify it under 7 | * the terms of the GNU General Public License, version 3.0, as published by the 8 | * Free Software Foundation. 9 | * 10 | * This program is distributed in the hope that it will be useful, but WITHOUT 11 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 12 | * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more 13 | * details. 14 | * 15 | * You should have received a copy of the GNU General Public License along with 16 | * this program. If not, see . 17 | * 18 | */ 19 | 20 | #if defined _dynamic_system_commands 21 | #endinput 22 | #endif 23 | #define _dynamic_system_commands 24 | 25 | stock void RegisterCommands() 26 | { 27 | RegAdminCmd("sm_dynamic_selftest", OnDynamicSelfTestCommand, ADMFLAG_RCON, "performs a Dynamic SelfTest to verify Dynamic is running properly"); 28 | RegAdminCmd("sm_dynamic_handles", OnDynamicHandlesCommand, ADMFLAG_RCON, "displays a Dynamic Handle usage report per plugin"); 29 | RegAdminCmd("sm_dynamic_collectgarbage", OnDynamicCollectGarbageCommand, ADMFLAG_RCON, "runs Dynamic's garbage collector"); 30 | } 31 | 32 | public Action OnDynamicSelfTestCommand(int client, int args) 33 | { 34 | ReplyToCommand(client, "Dynamic is running a SelfTest..."); 35 | RequestFrame(_Dynamic_SelfTest, (client > 0 ? GetClientUserId(client) : 0)); 36 | return Plugin_Handled; 37 | } 38 | 39 | public Action OnDynamicHandlesCommand(int client, int args) 40 | { 41 | PrintToConsole(client, "Dynamic is running a HandleUsage report..."); 42 | RequestFrame(_Dynamic_HandleUsage, (client > 0 ? GetClientUserId(client) : 0)); 43 | return Plugin_Handled; 44 | } 45 | 46 | public Action OnDynamicCollectGarbageCommand(int client, int args) 47 | { 48 | PrintToConsole(client, "Dynamic is starting it's garbage collector..."); 49 | _Dynamic_CollectGarbage(); 50 | return Plugin_Handled; 51 | } 52 | -------------------------------------------------------------------------------- /scripting/dynamic/system/datatypes/bool.sp: -------------------------------------------------------------------------------- 1 | /** 2 | * ============================================================================= 3 | * Dynamic for SourceMod (C)2016 Matthew J Dunn. All rights reserved. 4 | * ============================================================================= 5 | * 6 | * This program is free software; you can redistribute it and/or modify it under 7 | * the terms of the GNU General Public License, version 3.0, as published by the 8 | * Free Software Foundation. 9 | * 10 | * This program is distributed in the hope that it will be useful, but WITHOUT 11 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 12 | * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more 13 | * details. 14 | * 15 | * You should have received a copy of the GNU General Public License along with 16 | * this program. If not, see . 17 | * 18 | */ 19 | 20 | #if defined _dynamic_system_datatypes_bool 21 | #endinput 22 | #endif 23 | #define _dynamic_system_datatypes_bool 24 | 25 | stock bool _GetBool(ArrayList data, int position, int offset, int blocksize, bool defaultvalue) 26 | { 27 | Dynamic_MemberType type = _Dynamic_GetMemberDataType(data, position, offset, blocksize); 28 | if (type == DynamicType_Bool) 29 | return view_as(_Dynamic_GetMemberDataInt(data, position, offset, blocksize)); 30 | else if (type == DynamicType_Int) 31 | return (_Dynamic_GetMemberDataInt(data, position, offset, blocksize) == 0 ? false : true); 32 | else if (type == DynamicType_Float) 33 | return (_Dynamic_GetMemberDataFloat(data, position, offset, blocksize) == 0.0 ? false : true); 34 | else if (type == DynamicType_String) 35 | { 36 | int length = _Dynamic_GetMemberStringLength(data, position, offset, blocksize); 37 | char[] buffer = new char[length]; 38 | _Dynamic_GetMemberDataString(data, position, offset, blocksize, buffer, length); 39 | if (StrEqual(buffer, "false", false)) 40 | return false; 41 | else if (StrEqual(buffer, "0")) 42 | return false; 43 | 44 | return true; 45 | } 46 | else if (type == DynamicType_Dynamic) 47 | { 48 | DynamicObject value = view_as(_Dynamic_GetMemberDataInt(data, position, offset, blocksize)); 49 | if (!value.IsValid(false)) 50 | return false; 51 | return true; 52 | } 53 | else 54 | { 55 | ThrowNativeError(SP_ERROR_NATIVE, "Unsupported member datatype (%d)", type); 56 | return defaultvalue; 57 | } 58 | } 59 | 60 | stock Dynamic_MemberType _SetBool(ArrayList data, int position, int offset, int blocksize, bool value) 61 | { 62 | Dynamic_MemberType type = _Dynamic_GetMemberDataType(data, position, offset, blocksize); 63 | if (type == DynamicType_Bool) 64 | { 65 | _Dynamic_SetMemberDataInt(data, position, offset, blocksize, value); 66 | return DynamicType_Bool; 67 | } 68 | else if (type == DynamicType_Int) 69 | { 70 | _Dynamic_SetMemberDataInt(data, position, offset, blocksize, value); 71 | return DynamicType_Int; 72 | } 73 | else if (type == DynamicType_Float) 74 | { 75 | _Dynamic_SetMemberDataFloat(data, position, offset, blocksize, float(value)); 76 | return DynamicType_Float; 77 | } 78 | else if (type == DynamicType_String) 79 | { 80 | int length = _Dynamic_GetMemberStringLength(data, position, offset, blocksize); 81 | char[] buffer = new char[length]; 82 | if (value) 83 | strcopy(buffer, length, "True"); 84 | else 85 | strcopy(buffer, length, "False"); 86 | _Dynamic_SetMemberDataString(data, position, offset, blocksize, buffer); 87 | return DynamicType_String; 88 | } 89 | else 90 | { 91 | ThrowNativeError(SP_ERROR_NATIVE, "Unsupported member datatype (%d)", type); 92 | return DynamicType_Unknown; 93 | } 94 | } 95 | 96 | stock bool _Dynamic_GetBool(DynamicObject dynamic, const char[] membername, bool defaultvalue=false) 97 | { 98 | if (!dynamic.IsValid(true)) 99 | return defaultvalue; 100 | 101 | DynamicOffset offset; 102 | if (!_Dynamic_GetMemberDataOffset(dynamic, membername, false, offset, DynamicType_Bool)) 103 | return defaultvalue; 104 | 105 | return _GetBool(dynamic.Data, offset.Index, offset.Cell, dynamic.BlockSize, defaultvalue); 106 | } 107 | 108 | stock DynamicOffset _Dynamic_SetBool(DynamicObject dynamic, const char[] membername, bool value) 109 | { 110 | if (!dynamic.IsValid(true)) 111 | return INVALID_DYNAMIC_OFFSET; 112 | 113 | DynamicOffset offset; 114 | if (!_Dynamic_GetMemberDataOffset(dynamic, membername, true, offset, DynamicType_Bool)) 115 | return INVALID_DYNAMIC_OFFSET; 116 | 117 | Dynamic_MemberType type = _SetBool(dynamic.Data, offset.Index, offset.Cell, dynamic.BlockSize, value); 118 | _Dynamic_CallOnChangedForward(dynamic, offset, membername, type); 119 | return offset; 120 | } 121 | 122 | stock bool _Dynamic_GetBoolByOffset(DynamicObject dynamic, DynamicOffset offset, bool defaultvalue=false) 123 | { 124 | if (!dynamic.IsValid(true)) 125 | return defaultvalue; 126 | 127 | return _GetBool(dynamic.Data, offset.Index, offset.Cell, dynamic.BlockSize, defaultvalue); 128 | } 129 | 130 | stock bool _Dynamic_SetBoolByOffset(DynamicObject dynamic, DynamicOffset offset, bool value) 131 | { 132 | if (!dynamic.IsValid(true)) 133 | return false; 134 | 135 | Dynamic_MemberType type = _SetBool(dynamic.Data, offset.Index, offset.Cell, dynamic.BlockSize, value); 136 | _Dynamic_CallOnChangedForwardByOffset(dynamic, offset, type); 137 | return true; 138 | } 139 | 140 | stock int _Dynamic_PushBool(DynamicObject dynamic, bool value, const char[] name="") 141 | { 142 | if (!dynamic.IsValid(true)) 143 | return INVALID_DYNAMIC_INDEX; 144 | 145 | DynamicOffset offset; 146 | int memberindex = _Dynamic_CreateMemberOffset(dynamic, offset, name, DynamicType_Bool); 147 | _Dynamic_SetMemberDataInt(dynamic.Data, offset.Index, offset.Cell, dynamic.BlockSize, value); 148 | _Dynamic_CallOnChangedForward(dynamic, offset, name, DynamicType_Bool); 149 | return memberindex; 150 | } 151 | 152 | stock bool _Dynamic_GetBoolByIndex(DynamicObject dynamic, int memberindex, bool defaultvalue=false) 153 | { 154 | if (!dynamic.IsValid(true)) 155 | return false; 156 | 157 | DynamicOffset offset = _Dynamic_GetMemberOffsetByIndex(dynamic, memberindex); 158 | if (offset == INVALID_DYNAMIC_OFFSET) 159 | return defaultvalue; 160 | 161 | return _Dynamic_GetBoolByOffset(dynamic, offset, defaultvalue); 162 | } -------------------------------------------------------------------------------- /scripting/dynamic/system/datatypes/dynamic.sp: -------------------------------------------------------------------------------- 1 | /** 2 | * ============================================================================= 3 | * Dynamic for SourceMod (C)2016 Matthew J Dunn. All rights reserved. 4 | * ============================================================================= 5 | * 6 | * This program is free software; you can redistribute it and/or modify it under 7 | * the terms of the GNU General Public License, version 3.0, as published by the 8 | * Free Software Foundation. 9 | * 10 | * This program is distributed in the hope that it will be useful, but WITHOUT 11 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 12 | * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more 13 | * details. 14 | * 15 | * You should have received a copy of the GNU General Public License along with 16 | * this program. If not, see . 17 | * 18 | */ 19 | 20 | #if defined _dynamic_system_datatypes_dynamic 21 | #endinput 22 | #endif 23 | #define _dynamic_system_datatypes_dynamic 24 | 25 | stock DynamicObject _GetDynamic(ArrayList data, int position, int offset, int blocksize) 26 | { 27 | Dynamic_MemberType type = _Dynamic_GetMemberDataType(data, position, offset, blocksize); 28 | if (type == DynamicType_Dynamic) 29 | return view_as(_Dynamic_GetMemberDataInt(data, position, offset, blocksize)); 30 | else 31 | { 32 | ThrowNativeError(SP_ERROR_NATIVE, "Unsupported member datatype (%d)", type); 33 | return INVALID_DYNAMIC_OBJECT; 34 | } 35 | } 36 | 37 | stock Dynamic_MemberType _SetDynamic(DynamicObject dynamic, ArrayList data, int position, int offset, int blocksize, DynamicObject value, const char[] membername="") 38 | { 39 | Dynamic_MemberType type = _Dynamic_GetMemberDataType(data, position, offset, blocksize); 40 | if (type == DynamicType_Dynamic) 41 | { 42 | // remove parent from current value 43 | DynamicObject currentvalue = view_as(_Dynamic_GetMemberDataInt(data, position, offset, blocksize)); 44 | if (currentvalue != INVALID_DYNAMIC_OBJECT) 45 | { 46 | currentvalue.Parent = INVALID_DYNAMIC_OBJECT; 47 | currentvalue.ParentOffset = INVALID_DYNAMIC_OFFSET; 48 | } 49 | 50 | // set value and name 51 | _Dynamic_SetMemberDataInt(data, position, offset, blocksize, value.Index); 52 | 53 | // set parent 54 | if (value != INVALID_DYNAMIC_OBJECT) 55 | { 56 | value.Parent = dynamic; 57 | value.ParentOffset = DynamicOffset(position, offset); 58 | } 59 | return DynamicType_Dynamic; 60 | } 61 | else 62 | { 63 | ThrowNativeError(SP_ERROR_NATIVE, "Unsupported member datatype (%d)", type); 64 | return DynamicType_Unknown; 65 | } 66 | } 67 | 68 | stock DynamicObject _Dynamic_GetDynamic(DynamicObject dynamic, const char[] membername) 69 | { 70 | if (!dynamic.IsValid(true)) 71 | return INVALID_DYNAMIC_OBJECT; 72 | 73 | DynamicOffset offset; 74 | if (!_Dynamic_GetMemberDataOffset(dynamic, membername, false, offset, DynamicType_Dynamic)) 75 | return INVALID_DYNAMIC_OBJECT; 76 | 77 | return _GetDynamic(dynamic.Data, offset.Index, offset.Cell, dynamic.BlockSize); 78 | } 79 | 80 | stock DynamicOffset _Dynamic_SetDynamic(DynamicObject dynamic, const char[] membername, DynamicObject value) 81 | { 82 | if (!dynamic.IsValid(true)) 83 | return INVALID_DYNAMIC_OFFSET; 84 | 85 | DynamicOffset offset; 86 | if (!_Dynamic_GetMemberDataOffset(dynamic, membername, true, offset, DynamicType_Dynamic)) 87 | return INVALID_DYNAMIC_OFFSET; 88 | 89 | Dynamic_MemberType type = _SetDynamic(dynamic, dynamic.Data, offset.Index, offset.Cell, dynamic.BlockSize, value, membername); 90 | _Dynamic_CallOnChangedForward(dynamic, offset, membername, type); 91 | return offset; 92 | } 93 | 94 | stock DynamicObject _Dynamic_GetDynamicByOffset(DynamicObject dynamic, DynamicOffset offset) 95 | { 96 | if (!dynamic.IsValid(true)) 97 | return INVALID_DYNAMIC_OBJECT; 98 | 99 | return _GetDynamic(dynamic.Data, offset.Index, offset.Cell, dynamic.BlockSize); 100 | } 101 | 102 | stock bool _Dynamic_SetDynamicByOffset(DynamicObject dynamic, DynamicOffset offset, DynamicObject value) 103 | { 104 | if (!dynamic.IsValid(true)) 105 | return false; 106 | 107 | Dynamic_MemberType type = _SetDynamic(dynamic, dynamic.Data, offset.Index, offset.Cell, dynamic.BlockSize, value); 108 | _Dynamic_CallOnChangedForwardByOffset(dynamic, offset, type); 109 | return true; 110 | } 111 | 112 | stock int _Dynamic_PushDynamic(DynamicObject dynamic, DynamicObject value, const char[] name="") 113 | { 114 | if (!dynamic.IsValid(true)) 115 | return INVALID_DYNAMIC_INDEX; 116 | 117 | DynamicOffset offset; 118 | int memberindex = _Dynamic_CreateMemberOffset(dynamic, offset, name, DynamicType_Dynamic); 119 | _Dynamic_SetMemberDataInt(dynamic.Data, offset.Index, offset.Cell, dynamic.BlockSize, value.Index); 120 | 121 | // set parent 122 | if (value != INVALID_DYNAMIC_OBJECT) 123 | { 124 | value.Parent = dynamic; 125 | value.ParentOffset = offset; 126 | } 127 | 128 | _Dynamic_CallOnChangedForward(dynamic, offset, name, DynamicType_Dynamic); 129 | return memberindex; 130 | } 131 | 132 | stock DynamicObject _Dynamic_GetDynamicByIndex(DynamicObject dynamic, int memberindex) 133 | { 134 | if (!dynamic.IsValid(true)) 135 | return INVALID_DYNAMIC_OBJECT; 136 | 137 | DynamicOffset offset = _Dynamic_GetMemberOffsetByIndex(dynamic, memberindex); 138 | if (offset == INVALID_DYNAMIC_OFFSET) 139 | return INVALID_DYNAMIC_OBJECT; 140 | 141 | return _Dynamic_GetDynamicByOffset(dynamic, offset); 142 | } 143 | 144 | stock bool _Dynamic_SetDynamicByIndex(DynamicObject dynamic, int memberindex, DynamicObject value) 145 | { 146 | if (!dynamic.IsValid(true)) 147 | return false; 148 | 149 | DynamicOffset offset = _Dynamic_GetMemberOffsetByIndex(dynamic, memberindex); 150 | if (offset == INVALID_DYNAMIC_OFFSET) 151 | return false; 152 | 153 | return _Dynamic_SetDynamicByOffset(dynamic, offset, value); 154 | } -------------------------------------------------------------------------------- /scripting/dynamic/system/datatypes/float.sp: -------------------------------------------------------------------------------- 1 | /** 2 | * ============================================================================= 3 | * Dynamic for SourceMod (C)2016 Matthew J Dunn. All rights reserved. 4 | * ============================================================================= 5 | * 6 | * This program is free software; you can redistribute it and/or modify it under 7 | * the terms of the GNU General Public License, version 3.0, as published by the 8 | * Free Software Foundation. 9 | * 10 | * This program is distributed in the hope that it will be useful, but WITHOUT 11 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 12 | * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more 13 | * details. 14 | * 15 | * You should have received a copy of the GNU General Public License along with 16 | * this program. If not, see . 17 | * 18 | */ 19 | 20 | #if defined _dynamic_system_datatypes_float 21 | #endinput 22 | #endif 23 | #define _dynamic_system_datatypes_float 24 | 25 | stock float _GetFloat(ArrayList data, int position, int offset, int blocksize, float defaultvalue) 26 | { 27 | Dynamic_MemberType type = _Dynamic_GetMemberDataType(data, position, offset, blocksize); 28 | if (type == DynamicType_Float) 29 | return _Dynamic_GetMemberDataFloat(data, position, offset, blocksize); 30 | else if (type == DynamicType_Int || type == DynamicType_Bool) 31 | return float(_Dynamic_GetMemberDataInt(data, position, offset, blocksize)); 32 | else if (type == DynamicType_String) 33 | { 34 | int length = _Dynamic_GetMemberStringLength(data, position, offset, blocksize); 35 | char[] buffer = new char[length]; 36 | _Dynamic_GetMemberDataString(data, position, offset, blocksize, buffer, length); 37 | return StringToFloat(buffer); 38 | } 39 | else 40 | { 41 | ThrowNativeError(SP_ERROR_NATIVE, "Unsupported member datatype (%d)", type); 42 | return defaultvalue; 43 | } 44 | } 45 | 46 | stock Dynamic_MemberType _SetFloat(ArrayList data, int position, int offset, int blocksize, float value) 47 | { 48 | Dynamic_MemberType type = _Dynamic_GetMemberDataType(data, position, offset, blocksize); 49 | if (type == DynamicType_Float) 50 | { 51 | _Dynamic_SetMemberDataFloat(data, position, offset, blocksize, value); 52 | return DynamicType_Float; 53 | } 54 | else if (type == DynamicType_Int) 55 | { 56 | _Dynamic_SetMemberDataInt(data, position, offset, blocksize, RoundFloat(value)); 57 | return DynamicType_Int; 58 | } 59 | else if (type == DynamicType_Bool) 60 | { 61 | _Dynamic_SetMemberDataInt(data, position, offset, blocksize, RoundFloat(value)); 62 | return DynamicType_Bool; 63 | } 64 | else if (type == DynamicType_String) 65 | { 66 | int length = _Dynamic_GetMemberStringLength(data, position, offset, blocksize); 67 | char[] buffer = new char[length]; 68 | FloatToString(value, buffer, length); 69 | _Dynamic_SetMemberDataString(data, position, offset, blocksize, buffer); 70 | return DynamicType_String; 71 | } 72 | else 73 | { 74 | ThrowNativeError(SP_ERROR_NATIVE, "Unsupported member datatype (%d)", type); 75 | return DynamicType_Unknown; 76 | } 77 | } 78 | 79 | stock float _Dynamic_GetFloat(DynamicObject dynamic, const char[] membername, float defaultvalue=-1.0) 80 | { 81 | if (!dynamic.IsValid(true)) 82 | return defaultvalue; 83 | 84 | DynamicOffset offset; 85 | if (!_Dynamic_GetMemberDataOffset(dynamic, membername, false, offset, DynamicType_Float)) 86 | return defaultvalue; 87 | 88 | return _GetFloat(dynamic.Data, offset.Index, offset.Cell, dynamic.BlockSize, defaultvalue); 89 | } 90 | 91 | stock DynamicOffset _Dynamic_SetFloat(DynamicObject dynamic, const char[] membername, float value) 92 | { 93 | if (!dynamic.IsValid(true)) 94 | return INVALID_DYNAMIC_OFFSET; 95 | 96 | DynamicOffset offset; 97 | if (!_Dynamic_GetMemberDataOffset(dynamic, membername, true, offset, DynamicType_Float)) 98 | return INVALID_DYNAMIC_OFFSET; 99 | 100 | Dynamic_MemberType type = _SetFloat(dynamic.Data, offset.Index, offset.Cell, dynamic.BlockSize, value); 101 | _Dynamic_CallOnChangedForward(dynamic, offset, membername, type); 102 | return offset; 103 | } 104 | 105 | stock float _Dynamic_GetFloatByOffset(DynamicObject dynamic, DynamicOffset offset, float defaultvalue=-1.0) 106 | { 107 | if (!dynamic.IsValid(true)) 108 | return defaultvalue; 109 | 110 | return _GetFloat(dynamic.Data, offset.Index, offset.Cell, dynamic.BlockSize, defaultvalue); 111 | } 112 | 113 | stock bool _Dynamic_SetFloatByOffset(DynamicObject dynamic, DynamicOffset offset, float value) 114 | { 115 | if (!dynamic.IsValid(true)) 116 | return false; 117 | 118 | Dynamic_MemberType type = _SetFloat(dynamic.Data, offset.Index, offset.Cell, dynamic.BlockSize, value); 119 | _Dynamic_CallOnChangedForwardByOffset(dynamic, offset, type); 120 | return true; 121 | } 122 | 123 | stock int _Dynamic_PushFloat(DynamicObject dynamic, float value, const char[] name="") 124 | { 125 | if (!dynamic.IsValid(true)) 126 | return INVALID_DYNAMIC_INDEX; 127 | 128 | DynamicOffset offset; 129 | int memberindex = _Dynamic_CreateMemberOffset(dynamic, offset, name, DynamicType_Float); 130 | _Dynamic_SetMemberDataFloat(dynamic.Data, offset.Index, offset.Cell, dynamic.BlockSize, value); 131 | _Dynamic_CallOnChangedForward(dynamic, offset, name, DynamicType_Float); 132 | return memberindex; 133 | } 134 | 135 | stock float _Dynamic_GetFloatByIndex(DynamicObject dynamic, int memberindex, float defaultvalue=-1.0) 136 | { 137 | if (!dynamic.IsValid(true)) 138 | return defaultvalue; 139 | 140 | DynamicOffset offset = _Dynamic_GetMemberOffsetByIndex(dynamic, memberindex); 141 | if (offset == INVALID_DYNAMIC_OFFSET) 142 | return defaultvalue; 143 | 144 | return _Dynamic_GetFloatByOffset(dynamic, offset, defaultvalue); 145 | } 146 | 147 | stock float _Dynamic_GetMemberDataFloat(ArrayList data, int position, int offset, int blocksize) 148 | { 149 | // Move the offset forward by one cell as this is where the value is stored 150 | offset++; 151 | 152 | // Calculate internal data array index and cell position 153 | _Dynamic_RecalculateOffset(position, offset, blocksize); 154 | 155 | // Return value 156 | return data.Get(position, offset); 157 | } 158 | 159 | stock void _Dynamic_SetMemberDataFloat(ArrayList data, int position, int offset, int blocksize, float value) 160 | { 161 | // Move the offset forward by one cell as this is where the value is stored 162 | offset++; 163 | 164 | // Calculate internal data array index and cell position 165 | _Dynamic_RecalculateOffset(position, offset, blocksize); 166 | 167 | // Set the value 168 | SetArrayCell(data, position, value, offset); 169 | } 170 | -------------------------------------------------------------------------------- /scripting/dynamic/system/datatypes/function.sp: -------------------------------------------------------------------------------- 1 | /** 2 | * ============================================================================= 3 | * Dynamic for SourceMod (C)2016 Matthew J Dunn. All rights reserved. 4 | * ============================================================================= 5 | * 6 | * This program is free software; you can redistribute it and/or modify it under 7 | * the terms of the GNU General Public License, version 3.0, as published by the 8 | * Free Software Foundation. 9 | * 10 | * This program is distributed in the hope that it will be useful, but WITHOUT 11 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 12 | * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more 13 | * details. 14 | * 15 | * You should have received a copy of the GNU General Public License along with 16 | * this program. If not, see . 17 | * 18 | */ 19 | 20 | #if defined _dynamic_system_datatypes_function 21 | #endinput 22 | #endif 23 | #define _dynamic_system_datatypes_function 24 | 25 | stock Function _GetFunction(ArrayList data, int position, int offset, int blocksize) 26 | { 27 | Dynamic_MemberType type = _Dynamic_GetMemberDataType(data, position, offset, blocksize); 28 | if (type == DynamicType_Function) 29 | return _Dynamic_GetMemberDataFunction(data, position, offset, blocksize); 30 | else 31 | { 32 | ThrowNativeError(SP_ERROR_NATIVE, "Unsupported member datatype (%d)", type); 33 | return INVALID_FUNCTION; 34 | } 35 | } 36 | 37 | stock Dynamic_MemberType _SetFunction(ArrayList data, int position, int offset, int blocksize, Function value, const char[] membername="") 38 | { 39 | Dynamic_MemberType type = _Dynamic_GetMemberDataType(data, position, offset, blocksize); 40 | if (type == DynamicType_Function) 41 | { 42 | _Dynamic_SetMemberDataFunction(data, position, offset, blocksize, value); 43 | return DynamicType_Function; 44 | } 45 | else 46 | { 47 | ThrowNativeError(SP_ERROR_NATIVE, "Unsupported member datatype (%d)", type); 48 | return DynamicType_Unknown; 49 | } 50 | } 51 | 52 | stock Function _Dynamic_GetFunction(DynamicObject dynamic, const char[] membername) 53 | { 54 | if (!dynamic.IsValid(true)) 55 | return INVALID_FUNCTION; 56 | 57 | DynamicOffset offset; 58 | if (!_Dynamic_GetMemberDataOffset(dynamic, membername, false, offset, DynamicType_Function)) 59 | return INVALID_FUNCTION; 60 | 61 | return _GetFunction(dynamic.Data, offset.Index, offset.Cell, dynamic.BlockSize); 62 | } 63 | 64 | stock DynamicOffset _Dynamic_SetFunction(DynamicObject dynamic, const char[] membername, Function value) 65 | { 66 | if (!dynamic.IsValid(true)) 67 | return INVALID_DYNAMIC_OFFSET; 68 | 69 | DynamicOffset offset; 70 | if (!_Dynamic_GetMemberDataOffset(dynamic, membername, true, offset, DynamicType_Function)) 71 | return INVALID_DYNAMIC_OFFSET; 72 | 73 | Dynamic_MemberType type = _SetFunction(dynamic.Data, offset.Index, offset.Cell, dynamic.BlockSize, value); 74 | _Dynamic_CallOnChangedForward(dynamic, offset, membername, type); 75 | return offset; 76 | } 77 | 78 | stock Function _Dynamic_GetFunctionByOffset(DynamicObject dynamic, DynamicOffset offset) 79 | { 80 | if (!dynamic.IsValid(true)) 81 | return INVALID_FUNCTION; 82 | 83 | return _GetFunction(dynamic.Data, offset.Index, offset.Cell, dynamic.BlockSize); 84 | } 85 | 86 | stock bool _Dynamic_SetFunctionByOffset(DynamicObject dynamic, DynamicOffset offset, Function value) 87 | { 88 | if (!dynamic.IsValid(true)) 89 | return false; 90 | 91 | Dynamic_MemberType type = _SetFunction(dynamic.Data, offset.Index, offset.Cell, dynamic.BlockSize, value); 92 | _Dynamic_CallOnChangedForwardByOffset(dynamic, offset, type); 93 | return true; 94 | } 95 | 96 | stock int _Dynamic_PushFunction(DynamicObject dynamic, Function value, const char[] name="") 97 | { 98 | if (!dynamic.IsValid(true)) 99 | return INVALID_DYNAMIC_INDEX; 100 | 101 | DynamicOffset offset; 102 | int memberindex = _Dynamic_CreateMemberOffset(dynamic, offset, name, DynamicType_Function); 103 | _Dynamic_SetMemberDataFunction(dynamic.Data, offset.Index, offset.Cell, dynamic.BlockSize, value); 104 | _Dynamic_CallOnChangedForward(dynamic, offset, name, DynamicType_Function); 105 | return memberindex; 106 | } 107 | 108 | stock Function _Dynamic_GetFunctionByIndex(DynamicObject dynamic, int memberindex) 109 | { 110 | if (!dynamic.IsValid(true)) 111 | return INVALID_FUNCTION; 112 | 113 | DynamicOffset offset = _Dynamic_GetMemberOffsetByIndex(dynamic, memberindex); 114 | if (offset == INVALID_DYNAMIC_OFFSET) 115 | return INVALID_FUNCTION; 116 | 117 | return _Dynamic_GetFunctionByOffset(dynamic, offset); 118 | } 119 | 120 | stock Function _Dynamic_GetMemberDataFunction(ArrayList data, int position, int offset, int blocksize) 121 | { 122 | // Move the offset forward by one cell as this is where the value is stored 123 | offset++; 124 | 125 | // Calculate internal data array index and cell position 126 | _Dynamic_RecalculateOffset(position, offset, blocksize); 127 | 128 | // Return value 129 | return data.Get(position, offset); 130 | } 131 | 132 | stock void _Dynamic_SetMemberDataFunction(ArrayList data, int position, int offset, int blocksize, Function value) 133 | { 134 | // Move the offset forward by one cell as this is where the value is stored 135 | offset++; 136 | 137 | // Calculate internal data array index and cell position 138 | _Dynamic_RecalculateOffset(position, offset, blocksize); 139 | 140 | // Set the value 141 | SetArrayCell(data, position, view_as(value), offset); 142 | } -------------------------------------------------------------------------------- /scripting/dynamic/system/datatypes/handle.sp: -------------------------------------------------------------------------------- 1 | /** 2 | * ============================================================================= 3 | * Dynamic for SourceMod (C)2016 Matthew J Dunn. All rights reserved. 4 | * ============================================================================= 5 | * 6 | * This program is free software; you can redistribute it and/or modify it under 7 | * the terms of the GNU General Public License, version 3.0, as published by the 8 | * Free Software Foundation. 9 | * 10 | * This program is distributed in the hope that it will be useful, but WITHOUT 11 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 12 | * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more 13 | * details. 14 | * 15 | * You should have received a copy of the GNU General Public License along with 16 | * this program. If not, see . 17 | * 18 | */ 19 | 20 | #if defined _dynamic_system_datatypes_handle 21 | #endinput 22 | #endif 23 | #define _dynamic_system_datatypes_handle 24 | 25 | stock int _GetHandle(ArrayList data, int position, int offset, int blocksize) 26 | { 27 | Dynamic_MemberType type = _Dynamic_GetMemberDataType(data, position, offset, blocksize); 28 | if (type == DynamicType_Handle) 29 | return _Dynamic_GetMemberDataInt(data, position, offset, blocksize); 30 | else 31 | { 32 | ThrowNativeError(SP_ERROR_NATIVE, "Unsupported member datatype (%d)", type); 33 | return 0; 34 | } 35 | } 36 | 37 | stock Dynamic_MemberType _SetHandle(ArrayList data, int position, int offset, int blocksize, int value, const char[] membername="") 38 | { 39 | Dynamic_MemberType type = _Dynamic_GetMemberDataType(data, position, offset, blocksize); 40 | if (type == DynamicType_Handle) 41 | { 42 | _Dynamic_SetMemberDataInt(data, position, offset, blocksize, view_as(value)); 43 | return DynamicType_Handle; 44 | } 45 | else 46 | { 47 | ThrowNativeError(SP_ERROR_NATIVE, "Unsupported member datatype (%d)", type); 48 | return DynamicType_Unknown; 49 | } 50 | } 51 | 52 | stock int _Dynamic_GetHandle(DynamicObject dynamic, const char[] membername) 53 | { 54 | if (!dynamic.IsValid(true)) 55 | return 0; 56 | 57 | DynamicOffset offset; 58 | if (!_Dynamic_GetMemberDataOffset(dynamic, membername, false, offset, DynamicType_Handle)) 59 | return 0; 60 | 61 | return _GetHandle(dynamic.Data, offset.Index, offset.Cell, dynamic.BlockSize); 62 | } 63 | 64 | stock DynamicOffset _Dynamic_SetHandle(DynamicObject dynamic, const char[] membername, int value) 65 | { 66 | if (!dynamic.IsValid(true)) 67 | return INVALID_DYNAMIC_OFFSET; 68 | 69 | DynamicOffset offset; 70 | if (!_Dynamic_GetMemberDataOffset(dynamic, membername, true, offset, DynamicType_Handle)) 71 | return INVALID_DYNAMIC_OFFSET; 72 | 73 | Dynamic_MemberType type = _SetHandle(dynamic.Data, offset.Index, offset.Cell, dynamic.BlockSize, value); 74 | _Dynamic_CallOnChangedForward(dynamic, offset, membername, type); 75 | return offset; 76 | } 77 | 78 | stock int _Dynamic_GetHandleByOffset(DynamicObject dynamic, DynamicOffset offset) 79 | { 80 | if (!dynamic.IsValid(true)) 81 | return 0; 82 | 83 | return _GetHandle(dynamic.Data, offset.Index, offset.Cell, dynamic.BlockSize); 84 | } 85 | 86 | stock bool _Dynamic_SetHandleByOffset(DynamicObject dynamic, DynamicOffset offset, int value) 87 | { 88 | if (!dynamic.IsValid(true)) 89 | return false; 90 | 91 | Dynamic_MemberType type = _SetHandle(dynamic.Data, offset.Index, offset.Cell, dynamic.BlockSize, value); 92 | _Dynamic_CallOnChangedForwardByOffset(dynamic, offset, type); 93 | return true; 94 | } 95 | 96 | stock int _Dynamic_PushHandle(DynamicObject dynamic, int value, const char[] name="") 97 | { 98 | if (!dynamic.IsValid(true)) 99 | return INVALID_DYNAMIC_INDEX; 100 | 101 | DynamicOffset offset; 102 | int memberindex = _Dynamic_CreateMemberOffset(dynamic, offset, name, DynamicType_Dynamic); 103 | _Dynamic_SetMemberDataInt(dynamic.Data, offset.Index, offset.Cell, dynamic.BlockSize, value); 104 | _Dynamic_CallOnChangedForward(dynamic, offset, name, DynamicType_Handle); 105 | return memberindex; 106 | } 107 | 108 | stock int _Dynamic_GetHandleByIndex(DynamicObject dynamic, int memberindex) 109 | { 110 | if (!dynamic.IsValid(true)) 111 | return 0; 112 | 113 | DynamicOffset offset = _Dynamic_GetMemberOffsetByIndex(dynamic, memberindex); 114 | if (offset == INVALID_DYNAMIC_OFFSET) 115 | return 0; 116 | 117 | return _Dynamic_GetHandleByOffset(dynamic, offset); 118 | } -------------------------------------------------------------------------------- /scripting/dynamic/system/datatypes/int.sp: -------------------------------------------------------------------------------- 1 | /** 2 | * ============================================================================= 3 | * Dynamic for SourceMod (C)2016 Matthew J Dunn. All rights reserved. 4 | * ============================================================================= 5 | * 6 | * This program is free software; you can redistribute it and/or modify it under 7 | * the terms of the GNU General Public License, version 3.0, as published by the 8 | * Free Software Foundation. 9 | * 10 | * This program is distributed in the hope that it will be useful, but WITHOUT 11 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 12 | * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more 13 | * details. 14 | * 15 | * You should have received a copy of the GNU General Public License along with 16 | * this program. If not, see . 17 | * 18 | */ 19 | 20 | #if defined _dynamic_system_datatypes_int 21 | #endinput 22 | #endif 23 | #define _dynamic_system_datatypes_int 24 | 25 | stock int _GetInt(ArrayList data, int position, int offset, int blocksize, int defaultvalue) 26 | { 27 | Dynamic_MemberType type = _Dynamic_GetMemberDataType(data, position, offset, blocksize); 28 | if (type == DynamicType_Int || type == DynamicType_Bool) 29 | return _Dynamic_GetMemberDataInt(data, position, offset, blocksize); 30 | else if (type == DynamicType_Float) 31 | return RoundFloat(_Dynamic_GetMemberDataFloat(data, position, offset, blocksize)); 32 | else if (type == DynamicType_String) 33 | { 34 | int length = _Dynamic_GetMemberStringLength(data, position, offset, blocksize); 35 | char[] buffer = new char[length]; 36 | _Dynamic_GetMemberDataString(data, position, offset, blocksize, buffer, length); 37 | return StringToInt(buffer); 38 | } 39 | else if (type == DynamicType_Dynamic) 40 | return _Dynamic_GetMemberDataInt(data, position, offset, blocksize); 41 | else 42 | { 43 | ThrowNativeError(SP_ERROR_NATIVE, "Unsupported member datatype (%d)", type); 44 | return defaultvalue; 45 | } 46 | } 47 | 48 | stock Dynamic_MemberType _SetInt(ArrayList data, int position, int offset, int blocksize, int value) 49 | { 50 | Dynamic_MemberType type = _Dynamic_GetMemberDataType(data, position, offset, blocksize); 51 | if (type == DynamicType_Int) 52 | { 53 | _Dynamic_SetMemberDataInt(data, position, offset, blocksize, value); 54 | return DynamicType_Int; 55 | } 56 | else if (type == DynamicType_Float) 57 | { 58 | _Dynamic_SetMemberDataFloat(data, position, offset, blocksize, float(value)); 59 | return DynamicType_Float; 60 | } 61 | else if (type == DynamicType_Bool) 62 | { 63 | _Dynamic_SetMemberDataInt(data, position, offset, blocksize, value); 64 | return DynamicType_Bool; 65 | } 66 | else if (type == DynamicType_String) 67 | { 68 | int length = _Dynamic_GetMemberStringLength(data, position, offset, blocksize); 69 | char[] buffer = new char[length]; 70 | IntToString(value, buffer, length); 71 | _Dynamic_SetMemberDataString(data, position, offset, blocksize, buffer); 72 | return DynamicType_String; 73 | } 74 | else 75 | { 76 | ThrowNativeError(SP_ERROR_NATIVE, "Unsupported member datatype (%d)", type); 77 | return DynamicType_Unknown; 78 | } 79 | } 80 | 81 | stock int _Dynamic_GetInt(DynamicObject dynamic, const char[] membername, int defaultvalue=-1) 82 | { 83 | if (!dynamic.IsValid(true)) 84 | return defaultvalue; 85 | 86 | DynamicOffset offset; 87 | if (!_Dynamic_GetMemberDataOffset(dynamic, membername, false, offset, DynamicType_Int)) 88 | return defaultvalue; 89 | 90 | return _GetInt(dynamic.Data, offset.Index, offset.Cell, dynamic.BlockSize, defaultvalue); 91 | } 92 | 93 | // native int Dynamic_SetInt(Dynamic obj, const char[] membername, int value); 94 | stock DynamicOffset _Dynamic_SetInt(DynamicObject dynamic, const char[] membername, int value) 95 | { 96 | if (!dynamic.IsValid(true)) 97 | return INVALID_DYNAMIC_OFFSET; 98 | 99 | DynamicOffset offset; 100 | if (!_Dynamic_GetMemberDataOffset(dynamic, membername, true, offset, DynamicType_Int)) 101 | return INVALID_DYNAMIC_OFFSET; 102 | 103 | Dynamic_MemberType type = _SetInt(dynamic.Data, offset.Index, offset.Cell, dynamic.BlockSize, value); 104 | _Dynamic_CallOnChangedForward(dynamic, offset, membername, type); 105 | return offset; 106 | } 107 | 108 | stock int _Dynamic_GetIntByOffset(DynamicObject dynamic, DynamicOffset offset, int defaultvalue=-1) 109 | { 110 | if (!dynamic.IsValid(true)) 111 | return defaultvalue; 112 | 113 | return _GetInt(dynamic.Data, offset.Index, offset.Cell, dynamic.BlockSize, defaultvalue); 114 | } 115 | 116 | stock bool _Dynamic_SetIntByOffset(DynamicObject dynamic, DynamicOffset offset, int value) 117 | { 118 | if (!dynamic.IsValid(true)) 119 | return false; 120 | 121 | Dynamic_MemberType type = _SetInt(dynamic.Data, offset.Index, offset.Cell, dynamic.BlockSize, value); 122 | _Dynamic_CallOnChangedForwardByOffset(dynamic, offset, type); 123 | return true; 124 | } 125 | 126 | stock int _Dynamic_PushInt(DynamicObject dynamic, int value, const char[] name="") 127 | { 128 | if (!dynamic.IsValid(true)) 129 | return INVALID_DYNAMIC_INDEX; 130 | 131 | DynamicOffset offset; 132 | int memberindex = _Dynamic_CreateMemberOffset(dynamic, offset, name, DynamicType_Int); 133 | _Dynamic_SetMemberDataInt(dynamic.Data, offset.Index, offset.Cell, dynamic.BlockSize, value); 134 | _Dynamic_CallOnChangedForward(dynamic, offset, name, DynamicType_Int); 135 | return memberindex; 136 | } 137 | 138 | stock int _Dynamic_GetIntByIndex(DynamicObject dynamic, int memberindex, int defaultvalue=-1) 139 | { 140 | if (!dynamic.IsValid(true)) 141 | return INVALID_DYNAMIC_INDEX; 142 | 143 | DynamicOffset offset = _Dynamic_GetMemberOffsetByIndex(dynamic, memberindex); 144 | if (offset == INVALID_DYNAMIC_OFFSET) 145 | return defaultvalue; 146 | 147 | return _Dynamic_GetIntByOffset(dynamic, offset, defaultvalue); 148 | } 149 | 150 | stock int _Dynamic_GetMemberDataInt(ArrayList data, int position, int offset, int blocksize) 151 | { 152 | // Move the offset forward by one cell as this is where the value is stored 153 | offset++; 154 | 155 | // Calculate internal data array index and cell position 156 | _Dynamic_RecalculateOffset(position, offset, blocksize); 157 | 158 | // Return value 159 | return data.Get(position, offset); 160 | } 161 | 162 | stock void _Dynamic_SetMemberDataInt(ArrayList data, int position, int offset, int blocksize, int value) 163 | { 164 | // Move the offset forward by one cell as this is where the value is stored 165 | offset++; 166 | 167 | // Calculate internal data array index and cell position 168 | _Dynamic_RecalculateOffset(position, offset, blocksize); 169 | 170 | // Set the value 171 | SetArrayCell(data, position, value, offset); 172 | } -------------------------------------------------------------------------------- /scripting/dynamic/system/datatypes/string.sp: -------------------------------------------------------------------------------- 1 | /** 2 | * ============================================================================= 3 | * Dynamic for SourceMod (C)2016 Matthew J Dunn. All rights reserved. 4 | * ============================================================================= 5 | * 6 | * This program is free software; you can redistribute it and/or modify it under 7 | * the terms of the GNU General Public License, version 3.0, as published by the 8 | * Free Software Foundation. 9 | * 10 | * This program is distributed in the hope that it will be useful, but WITHOUT 11 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 12 | * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more 13 | * details. 14 | * 15 | * You should have received a copy of the GNU General Public License along with 16 | * this program. If not, see . 17 | * 18 | */ 19 | 20 | #if defined _dynamic_system_datatypes_string 21 | #endinput 22 | #endif 23 | #define _dynamic_system_datatypes_string 24 | 25 | stock bool _GetString(ArrayList data, int position, int offset, int blocksize, char[] buffer, int length) 26 | { 27 | Dynamic_MemberType type = _Dynamic_GetMemberDataType(data, position, offset, blocksize); 28 | if (type == DynamicType_String) 29 | { 30 | _Dynamic_GetMemberDataString(data, position, offset, blocksize, buffer, length); 31 | return true; 32 | } 33 | else if (type == DynamicType_Int) 34 | { 35 | int value = _Dynamic_GetMemberDataInt(data, position, offset, blocksize); 36 | IntToString(value, buffer, length); 37 | return true; 38 | } 39 | else if (type == DynamicType_Float) 40 | { 41 | float value = _Dynamic_GetMemberDataFloat(data, position, offset, blocksize); 42 | FloatToString(value, buffer, length); 43 | return true; 44 | } 45 | else if (type == DynamicType_Bool) 46 | { 47 | if (_Dynamic_GetMemberDataInt(data, position, offset, blocksize)) 48 | Format(buffer, length, "True"); 49 | else 50 | Format(buffer, length, "False"); 51 | return true; 52 | } 53 | else if (type == DynamicType_Vector) 54 | { 55 | float vector[3]; 56 | _Dynamic_GetMemberDataVector(data, position, offset, blocksize, vector); 57 | Format(buffer, length, "{%f, %f, %f}", vector[0], vector[1], vector[2]); 58 | return true; 59 | } 60 | else 61 | { 62 | ThrowNativeError(SP_ERROR_NATIVE, "Unsupported member datatype (%d)", type); 63 | buffer[0] = '\0'; 64 | return false; 65 | } 66 | } 67 | 68 | stock Dynamic_MemberType _SetString(ArrayList data, int position, int offset, int blocksize, const char[] value) 69 | { 70 | Dynamic_MemberType type = _Dynamic_GetMemberDataType(data, position, offset, blocksize); 71 | if (type == DynamicType_String) 72 | { 73 | _Dynamic_SetMemberDataString(data, position, offset, blocksize, value); 74 | return DynamicType_String; 75 | } 76 | else if (type == DynamicType_Int) 77 | { 78 | _Dynamic_SetMemberDataInt(data, position, offset, blocksize, StringToInt(value)); 79 | return DynamicType_Int; 80 | } 81 | else if (type == DynamicType_Float) 82 | { 83 | _Dynamic_SetMemberDataFloat(data, position, offset, blocksize, StringToFloat(value)); 84 | return DynamicType_Float; 85 | } 86 | else if (type == DynamicType_Bool) 87 | { 88 | if (StrEqual(value, "True")) 89 | _Dynamic_SetMemberDataInt(data, position, offset, blocksize, true); 90 | else if (StrEqual(value, "1")) 91 | _Dynamic_SetMemberDataInt(data, position, offset, blocksize, true); 92 | else 93 | _Dynamic_SetMemberDataInt(data, position, offset, blocksize, false); 94 | return DynamicType_Bool; 95 | } 96 | else if (type == DynamicType_Vector) 97 | { 98 | float vector[3]; 99 | if (!GetVectorFromString(value, vector)) 100 | { 101 | ThrowNativeError(SP_ERROR_NATIVE, "Unsupported member datatype (%d)", type); 102 | return DynamicType_Unknown; 103 | } 104 | 105 | _SetVector(data, position, offset, blocksize, vector); 106 | return DynamicType_Vector; 107 | } 108 | else 109 | { 110 | ThrowNativeError(SP_ERROR_NATIVE, "Unsupported member datatype (%d)", type); 111 | return DynamicType_Unknown; 112 | } 113 | } 114 | 115 | stock bool _Dynamic_GetString(DynamicObject dynamic, const char[] membername, char[] buffer, int length) 116 | { 117 | if (!dynamic.IsValid(true)) 118 | { 119 | buffer[0] = '\0'; 120 | return false; 121 | } 122 | 123 | DynamicOffset offset; 124 | if (!_Dynamic_GetMemberDataOffset(dynamic, membername, false, offset, DynamicType_String)) 125 | { 126 | buffer[0] = '\0'; 127 | return false; 128 | } 129 | 130 | return _GetString(dynamic.Data, offset.Index, offset.Cell, dynamic.BlockSize, buffer, length); 131 | } 132 | 133 | stock DynamicOffset _Dynamic_SetString(DynamicObject dynamic, const char[] membername, const char[] value, int length, int valuelength) 134 | { 135 | if (!dynamic.IsValid(true)) 136 | return INVALID_DYNAMIC_OFFSET; 137 | 138 | if (length == 0) 139 | length = valuelength; 140 | 141 | DynamicOffset offset; 142 | if (!_Dynamic_GetMemberDataOffset(dynamic, membername, true, offset, DynamicType_String, length)) 143 | return INVALID_DYNAMIC_OFFSET; 144 | 145 | Dynamic_MemberType type = _SetString(dynamic.Data, offset.Index, offset.Cell, dynamic.BlockSize, value); 146 | _Dynamic_CallOnChangedForward(dynamic, offset, membername, type); 147 | return offset; 148 | } 149 | 150 | stock bool _Dynamic_GetStringByOffset(DynamicObject dynamic, DynamicOffset offset, char[] buffer, int length) 151 | { 152 | if (!dynamic.IsValid(true)) 153 | { 154 | buffer[0] = '\0'; 155 | return false; 156 | } 157 | 158 | return _GetString(dynamic.Data, offset.Index, offset.Cell, dynamic.BlockSize, buffer, length); 159 | } 160 | 161 | stock bool _Dynamic_SetStringByOffset(DynamicObject dynamic, DynamicOffset offset, const char[] value) 162 | { 163 | if (!dynamic.IsValid(true)) 164 | return false; 165 | 166 | Dynamic_MemberType type = _SetString(dynamic.Data, offset.Index, offset.Cell, dynamic.BlockSize, value); 167 | _Dynamic_CallOnChangedForwardByOffset(dynamic, offset, type); 168 | return true; 169 | } 170 | 171 | stock int _Dynamic_PushString(DynamicObject dynamic, const char[] value, int length, int valuelength, const char[] name) 172 | { 173 | if (!dynamic.IsValid(true)) 174 | return INVALID_DYNAMIC_INDEX; 175 | 176 | if (length == 0) 177 | length = ++valuelength; 178 | 179 | DynamicOffset offset; 180 | int memberindex = _Dynamic_CreateMemberOffset(dynamic, offset, name, DynamicType_String, length); 181 | 182 | length+=2; // this can probably be removed (review Native_Dynamic_SetString for removal also) 183 | _Dynamic_SetMemberDataString(dynamic.Data, offset.Index, offset.Cell, dynamic.BlockSize, value); 184 | _Dynamic_CallOnChangedForward(dynamic, offset, name, DynamicType_String); 185 | return memberindex; 186 | } 187 | 188 | stock bool _Dynamic_GetStringByIndex(DynamicObject dynamic, int memberindex, char[] buffer, int length) 189 | { 190 | if (!dynamic.IsValid(true)) 191 | { 192 | buffer[0] = '\0'; 193 | return false; 194 | } 195 | 196 | DynamicOffset offset = _Dynamic_GetMemberOffsetByIndex(dynamic, memberindex); 197 | if (offset == INVALID_DYNAMIC_OFFSET) 198 | { 199 | buffer[0] = '\0'; 200 | return false; 201 | } 202 | 203 | if (_Dynamic_GetStringByOffset(dynamic, offset, buffer, length)) 204 | return true; 205 | 206 | return false; 207 | } 208 | 209 | stock int _Dynamic_GetStringLength(DynamicObject dynamic, const char[] membername) 210 | { 211 | if (!dynamic.IsValid(true)) 212 | return 0; 213 | 214 | DynamicOffset offset; 215 | if (!_Dynamic_GetMemberDataOffset(dynamic, membername, false, offset, DynamicType_String)) 216 | return 0; 217 | 218 | return _Dynamic_GetMemberStringLength(dynamic.Data, offset.Index, offset.Cell, dynamic.BlockSize); 219 | } 220 | 221 | stock bool _Dynamic_CompareString(DynamicObject dynamic, const char[] membername, const char[] value, bool casesensitive) 222 | { 223 | DynamicOffset offset = _Dynamic_GetMemberOffset(dynamic, membername); 224 | if (offset == INVALID_DYNAMIC_OFFSET) 225 | return false; 226 | 227 | return _Dynamic_CompareStringByOffset(dynamic, offset, value, casesensitive); 228 | } 229 | 230 | stock bool _Dynamic_CompareStringByOffset(DynamicObject dynamic, DynamicOffset offset, const char[] value, bool casesensitive) 231 | { 232 | int length = _Dynamic_GetStringLengthByOffset(dynamic, offset); 233 | char[] buffer = new char[length]; 234 | _Dynamic_GetStringByOffset(dynamic, offset, buffer, length); 235 | return StrEqual(value, buffer, casesensitive); 236 | } 237 | 238 | stock int _Dynamic_GetStringLengthByOffset(DynamicObject dynamic, DynamicOffset offset) 239 | { 240 | if (!dynamic.IsValid(true)) 241 | return 0; 242 | 243 | return _Dynamic_GetMemberStringLength(dynamic.Data, offset.Index, offset.Cell, dynamic.BlockSize); 244 | } 245 | 246 | stock int _Dynamic_GetMemberStringLength(ArrayList data, int position, int offset, int blocksize) 247 | { 248 | // Move the offset forward by one cell as this is where a strings length is stored 249 | offset++; 250 | 251 | // Calculate internal data array index and cell position 252 | _Dynamic_RecalculateOffset(position, offset, blocksize); 253 | 254 | // Return string length 255 | return data.Get(position, offset); 256 | } 257 | 258 | stock void _Dynamic_SetMemberStringLength(ArrayList data, DynamicOffset offset, int blocksize, int length) 259 | { 260 | offset = offset.Clone(blocksize, 1); 261 | data.Set(offset.Index, length, offset.Cell); 262 | } 263 | 264 | stock void _Dynamic_SetMemberDataString(ArrayList data, int position, int offset, int blocksize, const char[] buffer) 265 | { 266 | int length = _Dynamic_GetMemberStringLength(data, position, offset, blocksize); 267 | 268 | // Move the offset forward by two cells as this is where the string data starts 269 | offset+=2; 270 | _Dynamic_RecalculateOffset(position, offset, blocksize); 271 | 272 | // Offsets for Strings must by multiplied by 4 273 | offset*=4; 274 | 275 | // Set string data cell by cell and recalculate offset incase the string data wraps onto a new array index 276 | int i; 277 | char letter; 278 | for (i=0; i < length; i++) 279 | { 280 | letter = buffer[i]; 281 | SetArrayCell(data, position, letter, offset, true); 282 | 283 | // If the null terminator exists we are done 284 | if (letter == 0) 285 | return; 286 | 287 | offset++; 288 | _Dynamic_RecalculateOffset(position, offset, blocksize, true); 289 | } 290 | 291 | // Set null terminator 292 | SetArrayCell(data, position, 0, offset, true); 293 | } 294 | 295 | stock void _Dynamic_GetMemberDataString(ArrayList data, int position, int offset, int blocksize, char[] buffer, int length) 296 | { 297 | // Move the offset forward by two cells as this is where the string data starts 298 | offset+=2; 299 | _Dynamic_RecalculateOffset(position, offset, blocksize); 300 | 301 | // Offsets for Strings must by multiplied by 4 302 | offset*=4; 303 | 304 | // Get string data cell by cell and recalculate offset incase the string data wraps onto a new array index 305 | int i; char letter; 306 | for (i=0; i < length; i++) 307 | { 308 | letter = view_as(data.Get(position, offset, true)); 309 | buffer[i] = letter; 310 | 311 | // If the null terminator exists we are done 312 | if (letter == 0) 313 | return; 314 | 315 | offset++; 316 | _Dynamic_RecalculateOffset(position, offset, blocksize, true); 317 | } 318 | } -------------------------------------------------------------------------------- /scripting/dynamic/system/datatypes/vector.sp: -------------------------------------------------------------------------------- 1 | /** 2 | * ============================================================================= 3 | * Dynamic for SourceMod (C)2016 Matthew J Dunn. All rights reserved. 4 | * ============================================================================= 5 | * 6 | * This program is free software; you can redistribute it and/or modify it under 7 | * the terms of the GNU General Public License, version 3.0, as published by the 8 | * Free Software Foundation. 9 | * 10 | * This program is distributed in the hope that it will be useful, but WITHOUT 11 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 12 | * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more 13 | * details. 14 | * 15 | * You should have received a copy of the GNU General Public License along with 16 | * this program. If not, see . 17 | * 18 | */ 19 | 20 | #if defined _dynamic_system_datatypes_vector 21 | #endinput 22 | #endif 23 | #define _dynamic_system_datatypes_vector 24 | 25 | stock bool _GetVector(ArrayList data, int position, int offset, int blocksize, float value[3]) 26 | { 27 | Dynamic_MemberType type = _Dynamic_GetMemberDataType(data, position, offset, blocksize); 28 | if (type == DynamicType_Vector) 29 | return _Dynamic_GetMemberDataVector(data, position, offset, blocksize, value); 30 | else if (type == DynamicType_String) 31 | { 32 | int length = _Dynamic_GetMemberStringLength(data, position, offset, blocksize); 33 | char[] buffer = new char[length]; 34 | _Dynamic_GetMemberDataString(data, position, offset, blocksize, buffer, length); 35 | return GetVectorFromString(buffer, value); 36 | } 37 | else 38 | { 39 | ThrowNativeError(SP_ERROR_NATIVE, "Unsupported member datatype (%d)", type); 40 | return false; 41 | } 42 | } 43 | 44 | stock Dynamic_MemberType _SetVector(ArrayList data, int position, int offset, int blocksize, const float value[3], const char[] membername="") 45 | { 46 | Dynamic_MemberType type = _Dynamic_GetMemberDataType(data, position, offset, blocksize); 47 | if (type == DynamicType_Vector) 48 | { 49 | _Dynamic_SetMemberDataVector(data, position, offset, blocksize, value); 50 | return DynamicType_Vector; 51 | } 52 | else if (type == DynamicType_String) 53 | { 54 | char buffer[192]; 55 | Format(buffer, sizeof(buffer), "{%f, %f, %f}", value[0], value[1], value[2]); 56 | _Dynamic_SetMemberDataString(data, position, offset, blocksize, buffer); 57 | return DynamicType_String; 58 | } 59 | else 60 | { 61 | ThrowNativeError(SP_ERROR_NATIVE, "Unsupported member datatype (%d)", type); 62 | return DynamicType_Unknown; 63 | } 64 | } 65 | 66 | stock bool _Dynamic_GetVector(DynamicObject dynamic, const char[] membername, float[3] vector) 67 | { 68 | if (!dynamic.IsValid(true)) 69 | return false; 70 | 71 | DynamicOffset offset; 72 | if (!_Dynamic_GetMemberDataOffset(dynamic, membername, false, offset, DynamicType_Vector)) 73 | return false; 74 | 75 | return _GetVector(dynamic.Data, offset.Index, offset.Cell, dynamic.BlockSize, vector); 76 | } 77 | 78 | stock DynamicOffset _Dynamic_SetVector(DynamicObject dynamic, const char[] membername, const float value[3]) 79 | { 80 | if (!dynamic.IsValid(true)) 81 | return INVALID_DYNAMIC_OFFSET; 82 | 83 | DynamicOffset offset; 84 | if (!_Dynamic_GetMemberDataOffset(dynamic, membername, true, offset, DynamicType_Vector)) 85 | return INVALID_DYNAMIC_OFFSET; 86 | 87 | Dynamic_MemberType type = _SetVector(dynamic.Data, offset.Index, offset.Cell, dynamic.BlockSize, value, membername); 88 | _Dynamic_CallOnChangedForward(dynamic, offset, membername, type); 89 | return offset; 90 | } 91 | 92 | stock bool _Dynamic_GetVectorByOffset(DynamicObject dynamic, DynamicOffset offset, float[3] value) 93 | { 94 | if (!dynamic.IsValid(true)) 95 | return false; 96 | 97 | return _GetVector(dynamic.Data, offset.Index, offset.Cell, dynamic.BlockSize, value); 98 | } 99 | 100 | stock bool _Dynamic_SetVectorByOffset(DynamicObject dynamic, DynamicOffset offset, const float value[3]) 101 | { 102 | if (!dynamic.IsValid(true)) 103 | return false; 104 | 105 | Dynamic_MemberType type = _SetVector(dynamic.Data, offset.Index, offset.Cell, dynamic.BlockSize, value); 106 | _Dynamic_CallOnChangedForwardByOffset(dynamic, offset, type); 107 | return true; 108 | } 109 | 110 | stock int _Dynamic_PushVector(DynamicObject dynamic, const float value[3], const char[] name="") 111 | { 112 | if (!dynamic.IsValid(true)) 113 | return INVALID_DYNAMIC_INDEX; 114 | 115 | DynamicOffset offset; 116 | int memberindex = _Dynamic_CreateMemberOffset(dynamic, offset, name, DynamicType_Vector); 117 | _Dynamic_SetMemberDataVector(dynamic.Data, offset.Index, offset.Cell, dynamic.BlockSize, value); 118 | _Dynamic_CallOnChangedForward(dynamic, offset, name, DynamicType_Vector); 119 | return memberindex; 120 | } 121 | 122 | stock bool _Dynamic_GetVectorByIndex(DynamicObject dynamic, int memberindex, float value[3]) 123 | { 124 | if (!dynamic.IsValid(true)) 125 | return false; 126 | 127 | DynamicOffset offset = _Dynamic_GetMemberOffsetByIndex(dynamic, memberindex); 128 | if (offset == INVALID_DYNAMIC_OFFSET) 129 | return false; 130 | 131 | return _Dynamic_GetVectorByOffset(dynamic, offset, value); 132 | } 133 | 134 | stock bool _Dynamic_GetMemberDataVector(ArrayList data, int position, int offset, int blocksize, float vector[3]) 135 | { 136 | // A vector has 3 cells of data to be retrieved 137 | for (int i=0; i<3; i++) 138 | { 139 | // Move the offset forward by one cell as this is where the value is stored 140 | offset++; 141 | 142 | // Calculate internal data array index and cell position 143 | _Dynamic_RecalculateOffset(position, offset, blocksize); 144 | 145 | // Get the value 146 | vector[i] = data.Get(position, offset); 147 | } 148 | return true; 149 | } 150 | 151 | stock void _Dynamic_SetMemberDataVector(ArrayList data, int position, int offset, int blocksize, const float value[3]) 152 | { 153 | // A vector has 3 cells of data to be stored 154 | for (int i=0; i<3; i++) 155 | { 156 | // Move the offset forward by one cell as this is where the value is stored 157 | offset++; 158 | 159 | // Calculate internal data array index and cell position 160 | _Dynamic_RecalculateOffset(position, offset, blocksize); 161 | 162 | // Set the value 163 | SetArrayCell(data, position, value[i], offset); 164 | } 165 | } -------------------------------------------------------------------------------- /scripting/dynamic/system/flatconfigs.sp: -------------------------------------------------------------------------------- 1 | /** 2 | * ============================================================================= 3 | * Dynamic for SourceMod (C)2016 Matthew J Dunn. All rights reserved. 4 | * ============================================================================= 5 | * 6 | * This program is free software; you can redistribute it and/or modify it under 7 | * the terms of the GNU General Public License, version 3.0, as published by the 8 | * Free Software Foundation. 9 | * 10 | * This program is distributed in the hope that it will be useful, but WITHOUT 11 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 12 | * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more 13 | * details. 14 | * 15 | * You should have received a copy of the GNU General Public License along with 16 | * this program. If not, see . 17 | * 18 | */ 19 | 20 | #if defined _dynamic_system_flatconfigs 21 | #endinput 22 | #endif 23 | #define _dynamic_system_flatconfigs 24 | 25 | stock bool _Dynamic_ReadConfig(DynamicObject dynamic, const char[] path, bool use_valve_fs=false, int valuelength=128) 26 | { 27 | if (!dynamic.IsValid(true)) 28 | return false; 29 | 30 | // Check file exists 31 | if (!FileExists(path, use_valve_fs)) 32 | { 33 | ThrowNativeError(0, "Filepath '%s' doesn't exist!", path); 34 | return false; 35 | } 36 | 37 | // Open file for reading 38 | File stream = OpenFile(path, "r", use_valve_fs); 39 | 40 | // Exit if failed to open 41 | if (stream == null) 42 | { 43 | ThrowNativeError(0, "Unable to open file stream '%s'!", path); 44 | return false; 45 | } 46 | 47 | // Loop through file in blocks 48 | char buffer[16]; 49 | bool readingname = true; 50 | bool readingstring = false; 51 | bool readingvalue = false; 52 | int lastchar = 0; 53 | bool skippingcomment = false; 54 | ArrayList settingnamearray = CreateArray(1); 55 | int settingnamelength = 0; 56 | ArrayList settingvaluearray = CreateArray(1); 57 | int settingvaluelength = 0; 58 | int length; 59 | 60 | while ((length = stream.ReadString(buffer, sizeof(buffer))) > 0) 61 | { 62 | for (int i = 0; i < length; i++) 63 | { 64 | int byte = buffer[i]; 65 | 66 | // space and tabspace 67 | if (byte == 9 || byte == 32) 68 | { 69 | // continue if skipping comments 70 | if (skippingcomment) 71 | continue; 72 | 73 | if (readingname) 74 | { 75 | if (readingstring) 76 | { 77 | settingvaluearray.Push(byte); 78 | settingvaluelength++; 79 | } 80 | else 81 | { 82 | readingname = false; 83 | readingvalue = true; 84 | } 85 | } 86 | 87 | else if (readingvalue) 88 | { 89 | if (readingstring) 90 | { 91 | settingvaluearray.Push(byte); 92 | settingvaluelength++; 93 | } 94 | else 95 | { 96 | //if (settingvaluelength > 0) 97 | // skippingcomment = true; 98 | } 99 | } 100 | } 101 | 102 | // new line 103 | else if (byte == 10) 104 | { 105 | readingname = true; 106 | readingstring = false; 107 | readingvalue = false; 108 | 109 | if (skippingcomment) 110 | { 111 | skippingcomment = false; 112 | continue; 113 | } 114 | 115 | AddConfigSetting(dynamic, settingnamearray, settingnamelength, settingvaluearray, settingvaluelength, valuelength); 116 | settingnamelength = 0; 117 | settingvaluelength = 0; 118 | } 119 | 120 | // quote 121 | else if (byte == 34) 122 | { 123 | readingstring = !readingstring; 124 | 125 | if (!readingstring && readingvalue) 126 | { 127 | AddConfigSetting(dynamic, settingnamearray, settingnamelength, settingvaluearray, settingvaluelength, valuelength); 128 | settingnamelength = 0; 129 | settingvaluelength = 0; 130 | skippingcomment = true; 131 | } 132 | } 133 | else 134 | { 135 | // continue if skipping a comment 136 | if (skippingcomment) 137 | continue; 138 | 139 | // skip double backslash comments 140 | if (byte == 92 && lastchar == 92) 141 | { 142 | skippingcomment = true; 143 | settingnamearray.Clear(); 144 | settingnamelength = 0; 145 | settingvaluelength = 0; 146 | continue; 147 | } 148 | 149 | // skip double forward slash comments 150 | if (byte == 47 && lastchar == 47) 151 | { 152 | skippingcomment = true; 153 | settingnamearray.Clear(); 154 | settingnamelength = 0; 155 | settingvaluelength = 0; 156 | continue; 157 | } 158 | 159 | lastchar = byte; 160 | if (readingname) 161 | { 162 | settingnamearray.Push(byte); 163 | settingnamelength++; 164 | } 165 | else if (readingvalue) 166 | { 167 | settingvaluearray.Push(byte); 168 | settingvaluelength++; 169 | } 170 | } 171 | } 172 | } 173 | 174 | delete stream; 175 | delete settingnamearray; 176 | delete settingvaluearray; 177 | return true; 178 | } 179 | 180 | stock void AddConfigSetting(DynamicObject dynamic, ArrayList name, int namelength, ArrayList value, int valuelength, int maxlength) 181 | { 182 | char[] settingname = new char[namelength]; 183 | GetArrayStackAsString(name, settingname, namelength); 184 | name.Clear(); 185 | 186 | char[] settingvalue = new char[valuelength]; 187 | GetArrayStackAsString(value, settingvalue, valuelength); 188 | value.Clear(); 189 | 190 | CreateMemberFromString(dynamic, settingname, settingvalue, maxlength); 191 | } 192 | 193 | stock Dynamic_MemberType CreateMemberFromString(DynamicObject dynamic, const char[] membername, const char[] value, int maxlength) 194 | { 195 | bool canbeint = true; 196 | bool canbefloat = false; 197 | int byte; 198 | int val; 199 | 200 | for (int i = 0; (byte = value[i]) != 0; i++) 201 | { 202 | // 48 = `0`, 57 = `9`, 46 = `.`, 45 = `-` 203 | if (byte < 48 || byte > 57) 204 | { 205 | // allow negative 206 | if (i == 0 && byte == 45) 207 | continue; 208 | 209 | // cant be an int anymore 210 | canbeint = false; 211 | 212 | // allow floats 213 | if (byte == 46) 214 | { 215 | // dont allow multiple periods 216 | if (canbefloat) 217 | { 218 | canbefloat = false; 219 | break; 220 | } 221 | canbeint = false; 222 | canbefloat = true; 223 | } 224 | } 225 | 226 | if (!canbeint && !canbefloat) 227 | break; 228 | } 229 | 230 | if (canbeint) 231 | { 232 | // Longs need to be stored as strings 233 | val = StringToInt(value); 234 | if (val == -1 && !StrEqual(value, "-1")) 235 | { 236 | _Dynamic_SetString(dynamic, membername, value, maxlength, maxlength); 237 | return DynamicType_String; 238 | } 239 | else 240 | { 241 | _Dynamic_SetInt(dynamic, membername, val); 242 | return DynamicType_Int; 243 | } 244 | } 245 | else if (canbefloat) 246 | { 247 | _Dynamic_SetFloat(dynamic, membername, StringToFloat(value)); 248 | return DynamicType_Float; 249 | } 250 | else 251 | { 252 | // make regex if required 253 | if (g_sRegex_Vector == null) 254 | g_sRegex_Vector = CompileRegex("^\\{ ?+([-+]?[0-9]*\\.?[0-9]+) ?+, ?+([-+]?[0-9]*\\.?[0-9]+) ?+, ?+([-+]?[0-9]*\\.?[0-9]+) ?+\\}$"); 255 | 256 | // check for vector 257 | int count = MatchRegex(g_sRegex_Vector, value); 258 | if (count == 4) 259 | { 260 | float vec[3]; 261 | char matchbuffer[64]; 262 | 263 | GetRegexSubString(g_sRegex_Vector, 1, matchbuffer, sizeof(matchbuffer)); 264 | vec[0] = StringToFloat(matchbuffer); 265 | 266 | GetRegexSubString(g_sRegex_Vector, 2, matchbuffer, sizeof(matchbuffer)); 267 | vec[1] = StringToFloat(matchbuffer); 268 | 269 | GetRegexSubString(g_sRegex_Vector, 3, matchbuffer, sizeof(matchbuffer)); 270 | vec[2] = StringToFloat(matchbuffer); 271 | 272 | _Dynamic_SetVector(dynamic, membername, vec); 273 | return DynamicType_Vector; 274 | } 275 | 276 | // check for bool last 277 | if (StrEqual(value, "true", false)) 278 | { 279 | _Dynamic_SetBool(dynamic, membername, true); 280 | return DynamicType_Bool; 281 | } 282 | else if (StrEqual(value, "false", false)) 283 | { 284 | _Dynamic_SetBool(dynamic, membername, false); 285 | return DynamicType_Bool; 286 | } 287 | 288 | _Dynamic_SetString(dynamic, membername, value, maxlength, maxlength); 289 | return DynamicType_String; 290 | } 291 | } 292 | 293 | stock bool GetVectorFromString(const char[] input, float output[3]) 294 | { 295 | // make regex if required 296 | if (g_sRegex_Vector == null) 297 | g_sRegex_Vector = CompileRegex("^\\{ ?+([-+]?[0-9]*\\.?[0-9]+) ?+, ?+([-+]?[0-9]*\\.?[0-9]+) ?+, ?+([-+]?[0-9]*\\.?[0-9]+) ?+\\}$"); 298 | 299 | // check for vector 300 | int count = MatchRegex(g_sRegex_Vector, input); 301 | if (count == 4) 302 | { 303 | char buffer[64]; 304 | 305 | GetRegexSubString(g_sRegex_Vector, 1, buffer, sizeof(buffer)); 306 | output[0] = StringToFloat(buffer); 307 | 308 | GetRegexSubString(g_sRegex_Vector, 2, buffer, sizeof(buffer)); 309 | output[1] = StringToFloat(buffer); 310 | 311 | GetRegexSubString(g_sRegex_Vector, 3, buffer, sizeof(buffer)); 312 | output[2] = StringToFloat(buffer); 313 | return true; 314 | } 315 | return false; 316 | } 317 | 318 | stock void GetArrayStackAsString(ArrayList stack, char[] buffer, int length) 319 | { 320 | for (int i = 0; i < length; i++) 321 | { 322 | buffer[i] = view_as(stack.Get(i)); 323 | } 324 | } 325 | 326 | stock bool _Dynamic_WriteConfig(DynamicObject dynamic, const char[] path) 327 | { 328 | if (!dynamic.IsValid(true)) 329 | return false; 330 | 331 | // Open file for writting 332 | File stream = OpenFile(path, "w", false); 333 | 334 | // Exit if failed to open 335 | if (stream == null) 336 | { 337 | ThrowNativeError(0, "Unable to open file stream '%s'!", path); 338 | return false; 339 | } 340 | 341 | int count = _Dynamic_GetMemberCount(dynamic); 342 | DynamicOffset memberoffset; 343 | int length; 344 | char membername[DYNAMIC_MEMBERNAME_MAXLEN]; 345 | for (int i = 0; i < count; i++) 346 | { 347 | memberoffset = _Dynamic_GetMemberOffsetByIndex(dynamic, i); 348 | _Dynamic_GetMemberNameByIndex(dynamic, i, membername, sizeof(membername)); 349 | 350 | switch (_Dynamic_GetMemberTypeByOffset(dynamic, memberoffset)) 351 | { 352 | case DynamicType_Int: 353 | { 354 | int value = _Dynamic_GetIntByOffset(dynamic, memberoffset); 355 | stream.WriteLine("%s\t\"%d\"", membername, value); 356 | } 357 | case DynamicType_Bool: 358 | { 359 | bool value = _Dynamic_GetBoolByOffset(dynamic, memberoffset); 360 | stream.WriteLine("%s\t\"%d\"", membername, value); 361 | } 362 | case DynamicType_Float: 363 | { 364 | float value = _Dynamic_GetFloatByOffset(dynamic, memberoffset); 365 | stream.WriteLine("%s\t\"%f\"", membername, value); 366 | } 367 | case DynamicType_String: 368 | { 369 | length = _Dynamic_GetStringLengthByOffset(dynamic, memberoffset); 370 | char[] value = new char[length]; 371 | _Dynamic_GetStringByOffset(dynamic, memberoffset, value, length); 372 | stream.WriteLine("%s\t\"%s\"", membername, value); 373 | } 374 | case DynamicType_Object: 375 | { 376 | LogError("Unable to serialise type Dynamic in flat config!"); 377 | } 378 | case DynamicType_Handle: 379 | { 380 | LogError("Unable to serialise type Handle in flat config!"); 381 | } 382 | case DynamicType_Vector: 383 | { 384 | float value[3]; 385 | _Dynamic_GetVectorByOffset(dynamic, memberoffset, value); 386 | stream.WriteLine("%s\t\"{%f, %f, %f}\"", membername, value[0], value[1], value[2]); 387 | } 388 | default: 389 | { 390 | LogError("Unable to serialise type Unknown in flat config!"); 391 | } 392 | } 393 | } 394 | 395 | delete stream; 396 | return true; 397 | } -------------------------------------------------------------------------------- /scripting/dynamic/system/handleusage.sp: -------------------------------------------------------------------------------- 1 | /** 2 | * ============================================================================= 3 | * Dynamic for SourceMod (C)2016 Matthew J Dunn. All rights reserved. 4 | * ============================================================================= 5 | * 6 | * This program is free software; you can redistribute it and/or modify it under 7 | * the terms of the GNU General Public License, version 3.0, as published by the 8 | * Free Software Foundation. 9 | * 10 | * This program is distributed in the hope that it will be useful, but WITHOUT 11 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 12 | * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more 13 | * details. 14 | * 15 | * You should have received a copy of the GNU General Public License along with 16 | * this program. If not, see . 17 | * 18 | */ 19 | 20 | #if defined _dynamic_system_handleusage 21 | #endinput 22 | #endif 23 | #define _dynamic_system_handleusage 24 | 25 | public void _Dynamic_HandleUsage(any userid) 26 | { 27 | int client = 0; 28 | if (userid > 0) 29 | { 30 | client = GetClientOfUserId(userid); 31 | if (!IsClientConnected(client)) 32 | client = 0; 33 | } 34 | 35 | _Dynamic_HandleUsage_TotalHandleCount(client); 36 | 37 | // Loop plugins 38 | Handle iterator = GetPluginIterator(); 39 | Handle plugin; 40 | while (MorePlugins(iterator)) 41 | { 42 | plugin = ReadPlugin(iterator); 43 | _Dynamic_HandleUsage_CountPluginHandles(plugin, client); 44 | } 45 | CloseHandle(iterator); 46 | } 47 | 48 | stock void _Dynamic_HandleUsage_TotalHandleCount(int client) 49 | { 50 | int count = 0; 51 | int persistant = 0; 52 | DynamicObject dynamic; 53 | for (int i = MAXPLAYERS; i < s_CollectionSize; i++) 54 | { 55 | dynamic = view_as(i); 56 | 57 | // Skip disposed objects 58 | if (!dynamic.IsValid(false)) 59 | continue; 60 | 61 | if (dynamic.Persistent) 62 | persistant++; 63 | 64 | count++; 65 | } 66 | 67 | ReplyToCommand(client, "-> Total Handles: %d (%d persistant handles)", count, persistant); 68 | } 69 | 70 | stock void _Dynamic_HandleUsage_CountPluginHandles(Handle plugin, int client) 71 | { 72 | int count = 0; 73 | int persistant = 0; 74 | 75 | DynamicObject dynamic; 76 | for (int i = MAXPLAYERS; i < s_CollectionSize; i++) 77 | { 78 | dynamic = view_as(i); 79 | 80 | // Skip disposed objects 81 | if (!dynamic.IsValid(false)) 82 | continue; 83 | 84 | if (dynamic.OwnerPluginHandle == plugin) 85 | { 86 | if (dynamic.Persistent) 87 | persistant++; 88 | 89 | count++; 90 | } 91 | } 92 | 93 | if (count == 0) 94 | return; 95 | 96 | char pluginname[64]; 97 | GetPluginInfo(plugin, PlInfo_Name, pluginname, sizeof(pluginname)); 98 | ReplyToCommand(client, "--> `%s`: %d Handles (%d persistant handles)", pluginname, count, persistant); 99 | } 100 | -------------------------------------------------------------------------------- /scripting/dynamic/system/hooks.sp: -------------------------------------------------------------------------------- 1 | /** 2 | * ============================================================================= 3 | * Dynamic for SourceMod (C)2016 Matthew J Dunn. All rights reserved. 4 | * ============================================================================= 5 | * 6 | * This program is free software; you can redistribute it and/or modify it under 7 | * the terms of the GNU General Public License, version 3.0, as published by the 8 | * Free Software Foundation. 9 | * 10 | * This program is distributed in the hope that it will be useful, but WITHOUT 11 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 12 | * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more 13 | * details. 14 | * 15 | * You should have received a copy of the GNU General Public License along with 16 | * this program. If not, see . 17 | * 18 | */ 19 | 20 | #if defined _dynamic_system_hooks 21 | #endinput 22 | #endif 23 | #define _dynamic_system_hooks 24 | 25 | stock bool _Dynamic_HookChanges(DynamicObject dynamic, Dynamic_HookType callback, Handle plugin) 26 | { 27 | if (!dynamic.IsValid(true)) 28 | return false; 29 | 30 | Handle forwards = dynamic.Forwards; 31 | if (forwards == null) 32 | dynamic.Forwards = forwards = CreateForward(ET_Ignore, Param_Cell, Param_Cell, Param_String, Param_Cell); 33 | 34 | // Add forward to objects forward list 35 | AddToForward(forwards, plugin, callback); 36 | 37 | // Increment callback count 38 | dynamic.HookCount++; 39 | return true; 40 | } 41 | 42 | stock bool _Dynamic_UnHookChanges(DynamicObject dynamic, Dynamic_HookType callback, Handle plugin) 43 | { 44 | if (!dynamic.IsValid(true)) 45 | return false; 46 | 47 | Handle forwards = dynamic.Forwards; 48 | if (forwards == null) 49 | dynamic.Forwards = forwards = CreateForward(ET_Ignore, Param_Cell, Param_Cell, Param_String, Param_Cell); 50 | 51 | // Remove forward from objects forward list 52 | RemoveFromForward(forwards, plugin, callback); 53 | 54 | // Decrement callback count 55 | if (--dynamic.HookCount == 0) 56 | { 57 | // Remove unused handle 58 | CloseHandle(forwards); 59 | dynamic.Forwards = null; 60 | } 61 | return true; 62 | } 63 | 64 | stock int _Dynamic_HookCount(DynamicObject dynamic) 65 | { 66 | if (!dynamic.IsValid(true)) 67 | return 0; 68 | 69 | return dynamic.HookCount; 70 | } 71 | 72 | stock void _Dynamic_CallOnChangedForward(DynamicObject dynamic, DynamicOffset offset, const char[] member, Dynamic_MemberType type) 73 | { 74 | Handle forwards = dynamic.Forwards; 75 | if (forwards == null) 76 | return; 77 | 78 | Call_StartForward(forwards); 79 | Call_PushCell(dynamic); 80 | Call_PushCell(offset); 81 | Call_PushString(member); 82 | Call_PushCell(type); 83 | Call_Finish(); 84 | } 85 | 86 | stock void _Dynamic_CallOnChangedForwardByOffset(DynamicObject dynamic, DynamicOffset offset, Dynamic_MemberType type) 87 | { 88 | if (dynamic.HookCount > 0) 89 | { 90 | char membername[DYNAMIC_MEMBERNAME_MAXLEN]; 91 | _Dynamic_GetMemberNameByOffset(dynamic, offset, membername, sizeof(membername)); 92 | _Dynamic_CallOnChangedForward(dynamic, offset, membername, type); 93 | } 94 | } -------------------------------------------------------------------------------- /scripting/dynamic/system/keyvalues.sp: -------------------------------------------------------------------------------- 1 | /** 2 | * ============================================================================= 3 | * Dynamic for SourceMod (C)2016 Matthew J Dunn. All rights reserved. 4 | * ============================================================================= 5 | * 6 | * This program is free software; you can redistribute it and/or modify it under 7 | * the terms of the GNU General Public License, version 3.0, as published by the 8 | * Free Software Foundation. 9 | * 10 | * This program is distributed in the hope that it will be useful, but WITHOUT 11 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 12 | * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more 13 | * details. 14 | * 15 | * You should have received a copy of the GNU General Public License along with 16 | * this program. If not, see . 17 | * 18 | */ 19 | 20 | #if defined _dynamic_system_keyvalues 21 | #endinput 22 | #endif 23 | #define _dynamic_system_keyvalues 24 | 25 | stock bool _Dynamic_ReadKeyValues(Handle plugin, DynamicObject dynamic, const char[] path, int valuelength=128, Dynamic_HookType hook=INVALID_FUNCTION) 26 | { 27 | if (!dynamic.IsValid(true)) 28 | return false; 29 | 30 | // Check file exists 31 | if (!FileExists(path, false)) 32 | { 33 | ThrowNativeError(0, "Filepath '%s' doesn't exist!", path); 34 | return false; 35 | } 36 | 37 | KeyValues kv = new KeyValues(""); 38 | kv.SetEscapeSequences(true); 39 | if (!kv.ImportFromFile(path)) 40 | { 41 | delete kv; 42 | return false; 43 | } 44 | 45 | Handle callbackforward = null; 46 | if (hook != INVALID_FUNCTION) 47 | { 48 | callbackforward = CreateForward(ET_Single, Param_Cell, Param_String, Param_Cell); 49 | AddToForward(callbackforward, plugin, hook); 50 | } 51 | 52 | IterateKeyValues(plugin, kv, dynamic, valuelength, callbackforward); 53 | delete kv; 54 | 55 | if (callbackforward != null) 56 | { 57 | RemoveFromForward(callbackforward, plugin, hook); 58 | delete callbackforward; 59 | } 60 | return true; 61 | } 62 | 63 | stock void IterateKeyValues(Handle plugin, KeyValues kv, DynamicObject dynamic, int valuelength, Handle callbackforward, int depth=0) 64 | { 65 | char key[DYNAMIC_MEMBERNAME_MAXLEN]; 66 | KvDataTypes type; 67 | 68 | do 69 | { 70 | kv.GetSectionName(key, sizeof(key)); 71 | if (kv.GotoFirstSubKey(false)) 72 | { 73 | Action result; 74 | if (callbackforward != null) 75 | { 76 | Call_StartForward(callbackforward); 77 | Call_PushCell(dynamic); 78 | Call_PushString(key); 79 | Call_PushCell(depth); 80 | Call_Finish(result); 81 | } 82 | 83 | if (result == Plugin_Continue) 84 | { 85 | if (depth == 0) 86 | { 87 | IterateKeyValues(plugin, kv, dynamic, valuelength, callbackforward, depth+1); 88 | } 89 | else 90 | { 91 | DynamicObject child = _Dynamic_GetDynamic(dynamic, key); 92 | if (!child.IsValid(false)) 93 | { 94 | child = DynamicObject(); 95 | child.Initialise(plugin); 96 | 97 | _Dynamic_SetDynamic(dynamic, key, child); 98 | } 99 | IterateKeyValues(plugin, kv, child, valuelength, callbackforward, depth+1); 100 | } 101 | } 102 | kv.GoBack(); 103 | } 104 | else 105 | { 106 | type = kv.GetDataType(NULL_STRING); 107 | switch(type) 108 | { 109 | case KvData_String: 110 | { 111 | char[] value = new char[valuelength]; 112 | kv.GetString(NULL_STRING, value, valuelength); 113 | _Dynamic_SetString(dynamic, key, value, valuelength, valuelength); 114 | } 115 | case KvData_Int: 116 | { 117 | _Dynamic_SetInt(dynamic, key, kv.GetNum(NULL_STRING)); 118 | } 119 | case KvData_Float: 120 | { 121 | _Dynamic_SetFloat(dynamic, key, kv.GetFloat(NULL_STRING)); 122 | } 123 | case KvData_Ptr: 124 | { 125 | LogError("Type `KvData_Ptr` not yet supported!"); 126 | } 127 | case KvData_WString: 128 | { 129 | LogError("Type `KvData_WString` not yet supported!"); 130 | } 131 | case KvData_Color: 132 | { 133 | LogError("Type `KvData_Color` not yet supported!"); 134 | } 135 | case KvData_UInt64: 136 | { 137 | LogError("Type `KvData_UInt64` not yet supported!"); 138 | } 139 | } 140 | } 141 | } 142 | while (kv.GotoNextKey(false)); 143 | } 144 | 145 | stock bool _Dynamic_WriteKeyValues(DynamicObject dynamic, const char[] path, const char[] basekey) 146 | { 147 | if (!dynamic.IsValid(true)) 148 | return false; 149 | 150 | // Open file for writting 151 | File stream = OpenFile(path, "w", false); 152 | 153 | // Exit if failed to open 154 | if (stream == null) 155 | { 156 | ThrowNativeError(0, "Unable to open file stream '%s'!", path); 157 | return false; 158 | } 159 | 160 | stream.WriteLine("\"%s\"", basekey); 161 | stream.WriteLine("{"); 162 | _Dynamic_KeyValues_WriteDynamic(stream, dynamic, 1); 163 | stream.WriteLine("}"); 164 | 165 | delete stream; 166 | return true; 167 | } 168 | 169 | stock void _Dynamic_KeyValues_WriteDynamic(File stream, DynamicObject dynamic, int indent) 170 | { 171 | // Create indent 172 | char indextext[16]; 173 | for (int i = 0; i < indent; i++) 174 | indextext[i] = 9; 175 | indextext[indent] = 0; 176 | int length = 1024; 177 | char buffer[1024]; 178 | 179 | int count = dynamic.MemberCount; 180 | DynamicOffset memberoffset; 181 | char membername[DYNAMIC_MEMBERNAME_MAXLEN]; 182 | for (int i = 0; i < count; i++) 183 | { 184 | memberoffset = _Dynamic_GetMemberOffsetByIndex(dynamic, i); 185 | _Dynamic_GetMemberNameByIndex(dynamic, i, membername, sizeof(membername)); 186 | Dynamic_MemberType type = _Dynamic_GetMemberTypeByOffset(dynamic, memberoffset); 187 | 188 | if (type == DynamicType_Dynamic) 189 | { 190 | if (StrEqual(membername, "")) 191 | stream.WriteLine("%s\"%d\"", indextext, i); 192 | else 193 | { 194 | _Dynamic_KeyValues_EscapeString(membername, buffer, sizeof(membername)); 195 | stream.WriteLine("%s\"%s\"", indextext, buffer); 196 | } 197 | stream.WriteLine("%s{", indextext); 198 | _Dynamic_KeyValues_WriteDynamic(stream, _Dynamic_GetDynamicByOffset(dynamic, memberoffset), indent+1); 199 | stream.WriteLine("%s}", indextext); 200 | } 201 | else 202 | { 203 | //length = GetStringLengthByOffset(view_as(dynamic), memberoffset); 204 | char[] membervalue = new char[length]; 205 | _Dynamic_GetStringByOffset(dynamic, memberoffset, membervalue, length); 206 | _Dynamic_KeyValues_EscapeString(membervalue, buffer, sizeof(buffer)); 207 | stream.WriteLine("%s\"%s\"\t\"%s\"", indextext, membername, membervalue); 208 | } 209 | } 210 | } 211 | 212 | stock void _Dynamic_KeyValues_EscapeString(const char[] input, char[] output, int length) 213 | { 214 | int pos_in=0; 215 | int pos_out=0; 216 | int x; 217 | do 218 | { 219 | x = input[pos_in++]; 220 | switch (x) 221 | { 222 | case 34: // `"` -> `\"` 223 | { 224 | if (pos_out+1 >= length) 225 | return; 226 | 227 | output[pos_out++] = 92; 228 | output[pos_out++] = 34; 229 | } 230 | case 92: // `\` -> `\\` 231 | { 232 | if (pos_out+1 >= length) 233 | return; 234 | 235 | output[pos_out++] = 92; 236 | output[pos_out++] = 92; 237 | } 238 | case 10: // newline -> `\n` 239 | { 240 | if (pos_out+1 >= length) 241 | return; 242 | 243 | output[pos_out++] = 92; 244 | output[pos_out++] = 110; 245 | } 246 | case 13: // linefeed -> `\r` 247 | { 248 | if (pos_out+1 >= length) 249 | return; 250 | 251 | output[pos_out++] = 92; 252 | output[pos_out++] = 114; 253 | } 254 | default: 255 | { 256 | if (pos_out == length) 257 | return; 258 | 259 | output[pos_out++] = x; 260 | } 261 | } 262 | } 263 | while(x != 0); 264 | } -------------------------------------------------------------------------------- /scripting/dynamic/system/methodmaps/dynamicobject.sp: -------------------------------------------------------------------------------- 1 | /** 2 | * ============================================================================= 3 | * Dynamic for SourceMod (C)2016 Matthew J Dunn. All rights reserved. 4 | * ============================================================================= 5 | * 6 | * This program is free software; you can redistribute it and/or modify it under 7 | * the terms of the GNU General Public License, version 3.0, as published by the 8 | * Free Software Foundation. 9 | * 10 | * This program is distributed in the hope that it will be useful, but WITHOUT 11 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 12 | * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more 13 | * details. 14 | * 15 | * You should have received a copy of the GNU General Public License along with 16 | * this program. If not, see . 17 | * 18 | */ 19 | 20 | #if defined _dynamic_system_methomaps_dynamicobject 21 | #endinput 22 | #endif 23 | #define _dynamic_system_methomaps_dynamicobject 24 | 25 | #define Dynamic_Index 0 26 | // Size isn't yet implement for optimisation around _Dynamic_ExpandIfRequired() 27 | #define Dynamic_Size 1 28 | #define Dynamic_Blocksize 2 29 | #define Dynamic_Offsets 3 30 | #define Dynamic_MemberNames 4 31 | #define Dynamic_Data 5 32 | #define Dynamic_Forwards 6 33 | #define Dynamic_NextOffset 7 34 | #define Dynamic_CallbackCount 8 35 | #define Dynamic_ParentObject 9 36 | #define Dynamic_MemberCount 10 37 | #define Dynamic_OwnerPlugin 11 38 | #define Dynamic_Persistent 12 39 | #define Dynamic_ParentOffset 13 40 | #define Dynamic_Field_Count 14 41 | #define me view_as(this) 42 | 43 | // this should be static 44 | ArrayList s_Collection = null; 45 | 46 | methodmap DynamicObject 47 | { 48 | public DynamicObject() 49 | { 50 | int index = PushArrayCell(s_Collection, -1); 51 | s_CollectionSize++; 52 | return view_as(index); 53 | } 54 | 55 | public void Initialise(Handle plugin, int blocksize=64, int startsize=0, bool persistent=false) 56 | { 57 | SetArrayCell(s_Collection, me, me, Dynamic_Index); 58 | SetArrayCell(s_Collection, me, 0, Dynamic_Size); 59 | SetArrayCell(s_Collection, me, blocksize, Dynamic_Blocksize); 60 | SetArrayCell(s_Collection, me, new StringMap(), Dynamic_Offsets); 61 | SetArrayCell(s_Collection, me, new ArrayList(blocksize, startsize), Dynamic_Data); 62 | SetArrayCell(s_Collection, me, 0, Dynamic_Forwards); 63 | SetArrayCell(s_Collection, me, new ArrayList(g_iDynamic_MemberLookup_Offset+1), Dynamic_MemberNames); 64 | SetArrayCell(s_Collection, me, 0, Dynamic_NextOffset); 65 | SetArrayCell(s_Collection, me, 0, Dynamic_CallbackCount); 66 | SetArrayCell(s_Collection, me, INVALID_DYNAMIC_OBJECT, Dynamic_ParentObject); 67 | SetArrayCell(s_Collection, me, INVALID_DYNAMIC_OFFSET, Dynamic_ParentOffset); 68 | SetArrayCell(s_Collection, me, 0, Dynamic_MemberCount); 69 | SetArrayCell(s_Collection, me, _Dynamic_Plugins_GetIndex(plugin), Dynamic_OwnerPlugin); 70 | SetArrayCell(s_Collection, me, persistent, Dynamic_Persistent); 71 | } 72 | 73 | public void Dispose(bool reuse=false) 74 | { 75 | CloseHandle(GetArrayCell(s_Collection, me, Dynamic_Offsets)); 76 | CloseHandle(GetArrayCell(s_Collection, me, Dynamic_Data)); 77 | if (GetArrayCell(s_Collection, me, Dynamic_Forwards) != 0) 78 | CloseHandle(GetArrayCell(s_Collection, me, Dynamic_Forwards)); 79 | CloseHandle(GetArrayCell(s_Collection, me, Dynamic_MemberNames)); 80 | if (!reuse) 81 | SetArrayCell(s_Collection, me, Invalid_Dynamic_Object, Dynamic_Index); 82 | } 83 | 84 | property int BlockSize 85 | { 86 | public get() 87 | { 88 | return GetArrayCell(s_Collection, me, Dynamic_Blocksize); 89 | } 90 | } 91 | 92 | public void Reset(int blocksize=0, int startsize=0) 93 | { 94 | SetArrayCell(s_Collection, me, CreateTrie(), Dynamic_Offsets); 95 | 96 | if (blocksize == 0) 97 | blocksize = this.BlockSize; 98 | SetArrayCell(s_Collection, me, CreateArray(blocksize, startsize), Dynamic_Data); 99 | SetArrayCell(s_Collection, me, 0, Dynamic_Forwards); 100 | SetArrayCell(s_Collection, me, CreateArray(g_iDynamic_MemberLookup_Offset+1), Dynamic_MemberNames); 101 | SetArrayCell(s_Collection, me, 0, Dynamic_NextOffset); 102 | SetArrayCell(s_Collection, me, 0, Dynamic_CallbackCount); 103 | SetArrayCell(s_Collection, me, 0, Dynamic_Size); 104 | SetArrayCell(s_Collection, me, 0, Dynamic_MemberCount); 105 | } 106 | 107 | property int Index 108 | { 109 | public get() 110 | { 111 | return me; 112 | } 113 | } 114 | 115 | public bool IsValid(bool throwerror=false, bool fromnative=true) 116 | { 117 | return _Dynamic_IsValid(me, throwerror, fromnative); 118 | } 119 | 120 | public bool GetName(char[] buffer, int length) 121 | { 122 | return _Dynamic_GetName(this, buffer, length); 123 | } 124 | 125 | public bool SetName(const char[] objectname, bool replace) 126 | { 127 | return _Dynamic_SetName(this, objectname, replace); 128 | } 129 | 130 | property int Size 131 | { 132 | public get() 133 | { 134 | return 0; 135 | } 136 | } 137 | 138 | property ArrayList MemberNames 139 | { 140 | public get() 141 | { 142 | return GetArrayCell(s_Collection, me, Dynamic_MemberNames); 143 | } 144 | } 145 | 146 | property StringMap Offsets 147 | { 148 | public get() 149 | { 150 | return GetArrayCell(s_Collection, me, Dynamic_Offsets); 151 | } 152 | } 153 | 154 | property ArrayList Data 155 | { 156 | public get() 157 | { 158 | return GetArrayCell(s_Collection, me, Dynamic_Data); 159 | } 160 | } 161 | 162 | property Handle Forwards 163 | { 164 | public get() 165 | { 166 | return GetArrayCell(s_Collection, me, Dynamic_Forwards); 167 | } 168 | public set(Handle value) 169 | { 170 | SetArrayCell(s_Collection, me, value, Dynamic_Forwards); 171 | } 172 | } 173 | 174 | property DynamicOffset NextOffset 175 | { 176 | public get() 177 | { 178 | return GetArrayCell(s_Collection, me, Dynamic_NextOffset); 179 | } 180 | public set(DynamicOffset value) 181 | { 182 | SetArrayCell(s_Collection, me, value, Dynamic_NextOffset); 183 | } 184 | } 185 | 186 | property int HookCount 187 | { 188 | public get() 189 | { 190 | return GetArrayCell(s_Collection, me, Dynamic_CallbackCount); 191 | } 192 | public set(int value) 193 | { 194 | SetArrayCell(s_Collection, me, value, Dynamic_CallbackCount); 195 | } 196 | } 197 | 198 | property DynamicObject Parent 199 | { 200 | public get() 201 | { 202 | return GetArrayCell(s_Collection, me, Dynamic_ParentObject); 203 | } 204 | public set(DynamicObject value) 205 | { 206 | SetArrayCell(s_Collection, me, value, Dynamic_ParentObject); 207 | } 208 | } 209 | 210 | property DynamicOffset ParentOffset 211 | { 212 | public get() 213 | { 214 | return GetArrayCell(s_Collection, me, Dynamic_ParentOffset); 215 | } 216 | public set(DynamicOffset value) 217 | { 218 | SetArrayCell(s_Collection, me, value, Dynamic_ParentOffset); 219 | } 220 | } 221 | 222 | property int MemberCount 223 | { 224 | public get() 225 | { 226 | return GetArrayCell(s_Collection, me, Dynamic_MemberCount); 227 | } 228 | public set(int value) 229 | { 230 | SetArrayCell(s_Collection, me, value, Dynamic_MemberCount); 231 | } 232 | } 233 | 234 | property int OwnerPlugin 235 | { 236 | public get() 237 | { 238 | return GetArrayCell(s_Collection, me, Dynamic_OwnerPlugin); 239 | } 240 | public set(int value) 241 | { 242 | SetArrayCell(s_Collection, me, value, Dynamic_OwnerPlugin); 243 | } 244 | } 245 | 246 | property Handle OwnerPluginHandle 247 | { 248 | public get() 249 | { 250 | return _Dynamic_Plugins_GetHandleFromIndex(GetArrayCell(s_Collection, me, Dynamic_OwnerPlugin)); 251 | } 252 | } 253 | 254 | property bool Persistent 255 | { 256 | public get() 257 | { 258 | return GetArrayCell(s_Collection, me, Dynamic_Persistent); 259 | } 260 | public set(bool value) 261 | { 262 | SetArrayCell(s_Collection, me, value, Dynamic_Persistent); 263 | } 264 | } 265 | } 266 | -------------------------------------------------------------------------------- /scripting/dynamic/system/plugins.sp: -------------------------------------------------------------------------------- 1 | /** 2 | * ============================================================================= 3 | * Dynamic for SourceMod (C)2016 Matthew J Dunn. All rights reserved. 4 | * ============================================================================= 5 | * 6 | * This program is free software; you can redistribute it and/or modify it under 7 | * the terms of the GNU General Public License, version 3.0, as published by the 8 | * Free Software Foundation. 9 | * 10 | * This program is distributed in the hope that it will be useful, but WITHOUT 11 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 12 | * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more 13 | * details. 14 | * 15 | * You should have received a copy of the GNU General Public License along with 16 | * this program. If not, see . 17 | * 18 | */ 19 | 20 | public int _Dynamic_Plugins_GetIndex(Handle plugin) 21 | { 22 | // Return plugin handle index if already registered 23 | int index = g_aPlugins.FindValue(plugin, 0); 24 | if (index > -1) 25 | return index; 26 | 27 | // Create forward and add plugin handle 28 | Handle pluginforward = CreateForward(ET_Ignore); 29 | AddToForward(pluginforward, plugin, view_as(1)); 30 | 31 | // Create new index and push plugin handle and forward 32 | index = g_aPlugins.Push(plugin); 33 | g_aPlugins.Set(index, pluginforward, 1); 34 | return index; 35 | } 36 | 37 | public bool _Dynamic_Plugins_IsLoaded(int plugin) 38 | { 39 | // Get the plugins forward handle 40 | Handle pluginforward = g_aPlugins.Get(plugin, 1); 41 | 42 | // Check if the forward still has functions assigned to it 43 | if (GetForwardFunctionCount(pluginforward) == 0) 44 | return false; 45 | 46 | return true; 47 | } 48 | 49 | public Handle _Dynamic_Plugins_GetHandleFromIndex(int plugin) 50 | { 51 | return g_aPlugins.Get(plugin); 52 | } 53 | -------------------------------------------------------------------------------- /scripting/dynamic/system/preparedquery.sp: -------------------------------------------------------------------------------- 1 | /** 2 | * ============================================================================= 3 | * Dynamic for SourceMod (C)2016 Matthew J Dunn. All rights reserved. 4 | * ============================================================================= 5 | * 6 | * This program is free software; you can redistribute it and/or modify it under 7 | * the terms of the GNU General Public License, version 3.0, as published by the 8 | * Free Software Foundation. 9 | * 10 | * This program is distributed in the hope that it will be useful, but WITHOUT 11 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 12 | * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more 13 | * details. 14 | * 15 | * You should have received a copy of the GNU General Public License along with 16 | * this program. If not, see . 17 | * 18 | */ 19 | 20 | public bool _Dynamic_PreparedQuery_Compile(const char[] query, Dynamic obj) 21 | { 22 | PrintToServer("query: %s", query); 23 | int i=0; 24 | char byte; 25 | 26 | char[] buffer = new char[strlen(query)+1]; 27 | int bufferpos=0; 28 | 29 | char membername[DYNAMIC_MEMBERNAME_MAXLEN]; 30 | int membernamepos=0; 31 | bool readingmembername=false; 32 | 33 | bool instring=false; 34 | char stringbyte; 35 | 36 | while ((byte=query[i++]) != '\0') 37 | { 38 | // " ' ? ` = \ " LOL WITHOUT THIS QUOTE THE COMPILER THROWS AN ERROR 39 | // 034 039 063 096 061 092 40 | 41 | if (byte==96) // ` 42 | { 43 | buffer[bufferpos++]=byte; 44 | if (instring) 45 | continue; 46 | 47 | readingmembername=!readingmembername; 48 | 49 | if (readingmembername) 50 | membername[membernamepos=0]='\0'; 51 | else 52 | membername[membernamepos++]='\0'; 53 | } 54 | else if (byte==34 || byte==39) // " or ' 55 | { 56 | buffer[bufferpos++]=byte; 57 | if (instring) 58 | { 59 | if (stringbyte==byte) // same string byte 60 | { 61 | if (query[i-2] == 92) // \ " LOL WITHOUT THIS QUOTE THE COMPILER THROWS AN ERROR 62 | continue; // is escaped 63 | } 64 | else 65 | continue; // different string byte 66 | 67 | instring=false; 68 | } 69 | else 70 | { 71 | instring=true; 72 | stringbyte=byte; 73 | } 74 | } 75 | else if (byte==63) // ? 76 | { 77 | buffer[bufferpos++]='\0'; 78 | obj.PushString(buffer); 79 | obj.PushString(membername); 80 | buffer[0]='\0'; 81 | bufferpos=0; 82 | } 83 | else // any other char 84 | { 85 | if (readingmembername) 86 | membername[membernamepos++]=byte; 87 | 88 | buffer[bufferpos++]=byte; 89 | } 90 | } 91 | return true; 92 | } 93 | 94 | public bool _Dynamic_PreparedQuery_Prepare(Dynamic query, Database db, Dynamic parameters, char[] buffer, int buffersize) 95 | { 96 | int bufferpos = 0; 97 | int count = query.MemberCount; 98 | bool issection=true; 99 | DynamicOffset offset; 100 | int length; 101 | char membername[DYNAMIC_MEMBERNAME_MAXLEN]; 102 | char valuebuffer[64]; 103 | for (int i=0; i buffersize) 110 | { 111 | LogError("Buffer is to small for Dynamic.PreparedQuery() instance."); 112 | return false; 113 | } 114 | query.GetStringByOffset(offset, buffer[bufferpos], length); 115 | bufferpos+=length-2; 116 | } 117 | else 118 | { 119 | query.GetStringByIndex(i, membername, sizeof(membername)); 120 | offset = parameters.GetMemberOffset(membername); 121 | 122 | if (!offset.IsValid) 123 | { 124 | LogError("Member `%s` not found in PreparedQuery.SendQuery().", membername); 125 | return false; 126 | } 127 | 128 | switch (parameters.GetMemberType(offset)) 129 | { 130 | case DynamicType_Int, DynamicType_Float, DynamicType_Bool: 131 | { 132 | parameters.GetStringByOffset(offset, valuebuffer, sizeof(valuebuffer)); 133 | length = strlen(valuebuffer); 134 | if (length+bufferpos > buffersize) 135 | { 136 | LogError("Buffer is to small for Dynamic.PreparedQuery() instance."); 137 | return false; 138 | } 139 | for (int x=0; x buffersize) 156 | { 157 | LogError("Buffer is to small for Dynamic.PreparedQuery() instance."); 158 | return false; 159 | } 160 | buffer[bufferpos++] = 39; 161 | strcopy(buffer[bufferpos], length, strbuffer); 162 | bufferpos+=length-1; 163 | buffer[bufferpos++] = 39; 164 | } 165 | default: 166 | { 167 | LogError("MemberType %d is not supported by PreparedQuery.SendQuery().", parameters.GetMemberType(offset)); 168 | return false; 169 | } 170 | } 171 | } 172 | issection=!issection; 173 | } 174 | 175 | PrintToServer("Prepared Query: %s", buffer); 176 | return true; 177 | } 178 | 179 | public bool _Dynamic_PreparedQuery_Execute(Dynamic query, Database db, Dynamic parameters, SQLQueryCallback callback, any data, int buffersize) 180 | { 181 | char[] buffer = new char[buffersize]; 182 | if (!_Dynamic_PreparedQuery_Prepare(query, db, parameters, buffer, buffersize)) 183 | return false; 184 | 185 | if (callback == INVALID_FUNCTION) 186 | callback = _Dynamic_PreparedQuery_Callback; 187 | 188 | db.Query(callback, buffer, data); 189 | return true; 190 | } 191 | 192 | public void _Dynamic_PreparedQuery_Callback(Database db, DBResultSet results, const char[] error, any data) 193 | { 194 | if (results == null) 195 | LogError("Database error: %s", error); 196 | } -------------------------------------------------------------------------------- /scripting/include/dynamic-example.inc: -------------------------------------------------------------------------------- 1 | #if defined _dynamic_class_myclass_ 2 | #endinput 3 | #endif 4 | #define _dynamic_class_myclass_ 5 | 6 | methodmap MyClass < Dynamic 7 | { 8 | public MyClass() 9 | { 10 | // First we make a new dymanic object 11 | Dynamic myclass = Dynamic(64, 0); 12 | 13 | // Next we will define all the members 14 | // -> We do this to force the offsets to always be in the same location 15 | // over multiple instances of the same class. 16 | myclass.SetInt("SomeInt", 0); 17 | myclass.SetFloat("SomeFloat", 0.0); 18 | myclass.SetBool("SomeBool", false); 19 | myclass.SetString("SomeString", "", 64); 20 | myclass.SetHandle("SomeHandle", null); 21 | myclass.SetObject("SomeObject", view_as(INVALID_DYNAMIC_OBJECT)); 22 | myclass.SetVector("SomeVector", NULL_VECTOR); 23 | return view_as(myclass); 24 | } 25 | 26 | // Note that I use static offsets to access members. 27 | // -> This improves performance by caching member offsets 28 | // -> This is why we force the members in during the contructor 29 | // -> Failure to force members in the constructor will cause corruption 30 | 31 | property int SomeInt 32 | { 33 | public get() 34 | { 35 | static int offset = INVALID_DYNAMIC_OFFSET; 36 | if (offset == INVALID_DYNAMIC_OFFSET) 37 | { 38 | offset = this.GetMemberOffset("SomeInt"); 39 | if (offset == INVALID_DYNAMIC_OFFSET) 40 | SetFailState("A serious error occured in Dynamic!"); 41 | } 42 | return this.GetIntByOffset(offset); 43 | } 44 | public set(int value) 45 | { 46 | static int offset = INVALID_DYNAMIC_OFFSET; 47 | if (offset == INVALID_DYNAMIC_OFFSET) 48 | { 49 | offset = this.GetMemberOffset("SomeInt"); 50 | if (offset == INVALID_DYNAMIC_OFFSET) 51 | { 52 | offset = this.SetInt("SomeInt", value); 53 | return; 54 | } 55 | } 56 | this.SetIntByOffset(offset, value); 57 | } 58 | } 59 | 60 | property float SomeFloat 61 | { 62 | public get() 63 | { 64 | static int offset = INVALID_DYNAMIC_OFFSET; 65 | if (offset == INVALID_DYNAMIC_OFFSET) 66 | { 67 | offset = this.GetMemberOffset("SomeFloat"); 68 | if (offset == INVALID_DYNAMIC_OFFSET) 69 | SetFailState("A serious error occured in Dynamic!"); 70 | } 71 | return this.GetFloatByOffset(offset); 72 | } 73 | public set(float value) 74 | { 75 | static int offset = INVALID_DYNAMIC_OFFSET; 76 | if (offset == INVALID_DYNAMIC_OFFSET) 77 | { 78 | offset = this.GetMemberOffset("SomeFloat"); 79 | if (offset == INVALID_DYNAMIC_OFFSET) 80 | { 81 | offset = this.SetFloat("SomeFloat", value); 82 | return; 83 | } 84 | } 85 | this.SetFloatByOffset(offset, value); 86 | } 87 | } 88 | 89 | property bool SomeBool 90 | { 91 | public get() 92 | { 93 | static int offset = INVALID_DYNAMIC_OFFSET; 94 | if (offset == INVALID_DYNAMIC_OFFSET) 95 | { 96 | offset = this.GetMemberOffset("SomeBool"); 97 | if (offset == INVALID_DYNAMIC_OFFSET) 98 | SetFailState("A serious error occured in Dynamic!"); 99 | } 100 | return this.GetBoolByOffset(offset); 101 | } 102 | public set(bool value) 103 | { 104 | static int offset = INVALID_DYNAMIC_OFFSET; 105 | if (offset == INVALID_DYNAMIC_OFFSET) 106 | { 107 | offset = this.GetMemberOffset("SomeBool"); 108 | if (offset == INVALID_DYNAMIC_OFFSET) 109 | { 110 | offset = this.SetBool("SomeBool", value); 111 | return; 112 | } 113 | } 114 | this.SetBoolByOffset(offset, value); 115 | } 116 | } 117 | 118 | public bool GetSomeString(char[] buffer, int length) 119 | { 120 | static int offset = INVALID_DYNAMIC_OFFSET; 121 | if (offset == INVALID_DYNAMIC_OFFSET) 122 | { 123 | offset = this.GetMemberOffset("SomeString"); 124 | if (offset == INVALID_DYNAMIC_OFFSET) 125 | SetFailState("A serious error occured in Dynamic!"); 126 | } 127 | this.GetStringByOffset(offset, buffer, length); 128 | return true; 129 | } 130 | 131 | public void SetSomeString(const char[] buffer) 132 | { 133 | static int offset = INVALID_DYNAMIC_OFFSET; 134 | if (offset == INVALID_DYNAMIC_OFFSET) 135 | { 136 | offset = this.GetMemberOffset("SomeString"); 137 | if (offset == INVALID_DYNAMIC_OFFSET) 138 | { 139 | offset = this.SetString("SomeString", buffer); 140 | return; 141 | } 142 | } 143 | this.SetStringByOffset(offset, buffer); 144 | } 145 | 146 | property Handle SomeHandle 147 | { 148 | public get() 149 | { 150 | static int offset = INVALID_DYNAMIC_OFFSET; 151 | if (offset == INVALID_DYNAMIC_OFFSET) 152 | { 153 | offset = this.GetMemberOffset("SomeHandle"); 154 | if (offset == INVALID_DYNAMIC_OFFSET) 155 | SetFailState("A serious error occured in Dynamic!"); 156 | } 157 | return this.GetHandleByOffset(offset); 158 | } 159 | public set(Handle value) 160 | { 161 | static int offset = INVALID_DYNAMIC_OFFSET; 162 | if (offset == INVALID_DYNAMIC_OFFSET) 163 | { 164 | offset = this.GetMemberOffset("SomeHandle"); 165 | if (offset == INVALID_DYNAMIC_OFFSET) 166 | { 167 | offset = this.SetHandle("SomeHandle", value); 168 | return; 169 | } 170 | } 171 | this.SetHandleByOffset(offset, value); 172 | } 173 | } 174 | 175 | property Dynamic SomeObject 176 | { 177 | public get() 178 | { 179 | static int offset = INVALID_DYNAMIC_OFFSET; 180 | if (offset == INVALID_DYNAMIC_OFFSET) 181 | { 182 | offset = this.GetMemberOffset("SomeObject"); 183 | if (offset == INVALID_DYNAMIC_OFFSET) 184 | SetFailState("A serious error occured in Dynamic!"); 185 | } 186 | return this.GetObjectByOffset(offset); 187 | } 188 | public set(Dynamic value) 189 | { 190 | static int offset = INVALID_DYNAMIC_OFFSET; 191 | if (offset == INVALID_DYNAMIC_OFFSET) 192 | { 193 | offset = this.GetMemberOffset("SomeObject"); 194 | if (offset == INVALID_DYNAMIC_OFFSET) 195 | { 196 | offset = this.SetObject("SomeObject", value); 197 | return; 198 | } 199 | } 200 | this.SetObjectByOffset(offset, value); 201 | } 202 | } 203 | 204 | public bool GetSomeVector(float[3] value) 205 | { 206 | static int offset = INVALID_DYNAMIC_OFFSET; 207 | if (offset == INVALID_DYNAMIC_OFFSET) 208 | { 209 | offset = this.GetMemberOffset("SomeVector"); 210 | if (offset == INVALID_DYNAMIC_OFFSET) 211 | SetFailState("A serious error occured in Dynamic!"); 212 | } 213 | this.GetVectorByOffset(offset, value); 214 | return true; 215 | } 216 | 217 | public void SetSomeVector(const float[3] value) 218 | { 219 | static int offset = INVALID_DYNAMIC_OFFSET; 220 | if (offset == INVALID_DYNAMIC_OFFSET) 221 | { 222 | offset = this.GetMemberOffset("SomeVector"); 223 | if (offset == INVALID_DYNAMIC_OFFSET) 224 | { 225 | offset = this.SetVector("SomeVector", value); 226 | return; 227 | } 228 | } 229 | this.SetVectorByOffset(offset, value); 230 | } 231 | } -------------------------------------------------------------------------------- /scripting/include/dynamic.inc: -------------------------------------------------------------------------------- 1 | /** 2 | * ============================================================================= 3 | * Dynamic for SourceMod (C)2016 Matthew J Dunn. All rights reserved. 4 | * ============================================================================= 5 | * 6 | * This program is free software; you can redistribute it and/or modify it under 7 | * the terms of the GNU General Public License, version 3.0, as published by the 8 | * Free Software Foundation. 9 | * 10 | * This program is distributed in the hope that it will be useful, but WITHOUT 11 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 12 | * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more 13 | * details. 14 | * 15 | * You should have received a copy of the GNU General Public License along with 16 | * this program. If not, see . 17 | * 18 | */ 19 | 20 | #if defined _dynamic_included 21 | #endinput 22 | #endif 23 | #define _dynamic_included 24 | 25 | #define INVALID_DYNAMIC_OBJECT view_as(-1) 26 | #define Invalid_Dynamic_Object -1 27 | #define INVALID_DYNAMIC_OFFSET view_as(-1) 28 | #define INVALID_DYNAMIC_INDEX -1 29 | #define DYNAMIC_MEMBERNAME_MAXLEN 64 30 | 31 | enum Dynamic_MemberType 32 | { 33 | DynamicType_Int = 0, 34 | DynamicType_Float = 1, 35 | DynamicType_String = 2, 36 | DynamicType_Object = 3, 37 | DynamicType_Dynamic = 3, 38 | DynamicType_Bool = 4, 39 | DynamicType_Handle = 5, 40 | DynamicType_Vector = 6, 41 | DynamicType_Function = 7, 42 | DynamicType_Unknown = 8 43 | } 44 | 45 | enum Dynamic_Operator 46 | { 47 | DynamicOperator_Equals=0, 48 | DynamicOperator_NotEquals, 49 | } 50 | 51 | typeset Dynamic_HookType 52 | { 53 | // HookChanges 54 | function void (Dynamic obj, DynamicOffset offset, const char[] member, Dynamic_MemberType type); 55 | 56 | // DynamicReadKeyValue 57 | function Action (Dynamic obj, const char[] member, int depth); 58 | } 59 | 60 | #include 61 | #include 62 | #include 63 | #include 64 | #include 65 | #include 66 | 67 | public SharedPlugin __pl_dynamic = 68 | { 69 | name = "dynamic", 70 | file = "dynamic.smx", 71 | #if defined REQUIRE_PLUGIN 72 | required = 1, 73 | #else 74 | required = 0, 75 | #endif 76 | }; -------------------------------------------------------------------------------- /scripting/include/dynamic/methodmaps/basic.inc: -------------------------------------------------------------------------------- 1 | /** 2 | * ============================================================================= 3 | * Dynamic for SourceMod (C)2016 Matthew J Dunn. All rights reserved. 4 | * ============================================================================= 5 | * 6 | * This program is free software; you can redistribute it and/or modify it under 7 | * the terms of the GNU General Public License, version 3.0, as published by the 8 | * Free Software Foundation. 9 | * 10 | * This program is distributed in the hope that it will be useful, but WITHOUT 11 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 12 | * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more 13 | * details. 14 | * 15 | * You should have received a copy of the GNU General Public License along with 16 | * this program. If not, see . 17 | * 18 | */ 19 | 20 | #if defined _dynamic_basic_included 21 | #endinput 22 | #endif 23 | #define _dynamic_basic_included 24 | 25 | /* 26 | This methodmap is based on the Dynamic methodmap while using a StringMap methodmap 27 | for implementation. This methodmap doesn't implement the full features of the Dynamic 28 | methodmap (type conversion, object naming, plugin sharing, ect). This methodmap can 29 | be used for basic storage using the standard Dynamic methodmap Methods. 30 | 31 | Please see '\scripting\dynamic\examples\basic\' for an example usage of this methodmap 32 | */ 33 | 34 | methodmap Basic < StringMap 35 | { 36 | public Basic() 37 | { 38 | return new StringMap(); 39 | } 40 | 41 | public void Dispose(bool disposemembers=true) 42 | { 43 | delete this; 44 | } 45 | 46 | public int GetInt(const char[] membername, int defaultvalue=-1) 47 | { 48 | int value; 49 | if (this.GetValue(membername, value)) 50 | return value; 51 | 52 | return defaultvalue; 53 | } 54 | 55 | public void SetInt(const char[] membername, int value) 56 | { 57 | this.SetValue(membername, value); 58 | } 59 | 60 | public bool GetBool(const char[] membername, bool defaultvalue=false) 61 | { 62 | bool value; 63 | if (this.GetValue(membername, value)) 64 | return value; 65 | 66 | return defaultvalue; 67 | } 68 | 69 | public void SetBool(const char[] membername, bool value) 70 | { 71 | this.SetValue(membername, value); 72 | } 73 | 74 | public float GetFloat(const char[] membername, float defaultvalue=-1.0) 75 | { 76 | float value; 77 | if (this.GetValue(membername, value)) 78 | return value; 79 | 80 | return defaultvalue; 81 | } 82 | 83 | public void SetFloat(const char[] membername, float value) 84 | { 85 | this.SetValue(membername, value); 86 | } 87 | 88 | public bool GetString(const char[] membername, char[] buffer, int length) 89 | { 90 | return this.GetString(membername, buffer, length); 91 | } 92 | 93 | public void SetString(const char[] membername, const char[] value) 94 | { 95 | this.SetString(membername, value); 96 | } 97 | 98 | public Dynamic GetObject(const char[] membername) 99 | { 100 | Dynamic value; 101 | if (this.GetValue(membername, value)) 102 | return value; 103 | 104 | return INVALID_DYNAMIC_OBJECT; 105 | } 106 | 107 | public void SetObject(const char[] membername, Dynamic value) 108 | { 109 | this.SetValue(membername, value); 110 | } 111 | 112 | public Handle GetHandle(const char[] membername) 113 | { 114 | Handle value; 115 | if (this.GetValue(membername, value)) 116 | return value; 117 | 118 | return null; 119 | } 120 | 121 | public void SetHandle(const char[] membername, Handle value) 122 | { 123 | this.SetValue(membername, value); 124 | } 125 | 126 | public bool GetVector(const char[] membername, float[3] vector) 127 | { 128 | return this.GetArray(membername, vector, sizeof(vector)); 129 | } 130 | 131 | public void SetVector(const char[] membername, const float[3] value) 132 | { 133 | this.SetArray(membername, value, sizeof(value)); 134 | } 135 | } -------------------------------------------------------------------------------- /scripting/include/dynamic/methodmaps/collection.inc: -------------------------------------------------------------------------------- 1 | /** 2 | * ============================================================================= 3 | * Dynamic for SourceMod (C)2016 Matthew J Dunn. All rights reserved. 4 | * ============================================================================= 5 | * 6 | * This program is free software; you can redistribute it and/or modify it under 7 | * the terms of the GNU General Public License, version 3.0, as published by the 8 | * Free Software Foundation. 9 | * 10 | * This program is distributed in the hope that it will be useful, but WITHOUT 11 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 12 | * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more 13 | * details. 14 | * 15 | * You should have received a copy of the GNU General Public License along with 16 | * this program. If not, see . 17 | * 18 | */ 19 | 20 | #if defined _dynamic_collection_included 21 | #endinput 22 | #endif 23 | #define _dynamic_collection_included 24 | 25 | /* 26 | This methodmap is used to store typed collections based on Dynamic methodmaps. Internally 27 | an ArrayList is used for storage. This methodmap can be inherited by your own methodmaps 28 | where you can override the Items method to return your custom methodmap type which MUST 29 | inherit a Dynamic methodmap. 30 | 31 | Please see '\scripting\dynamic\examples\collections\' for an example usage of this methodmap 32 | */ 33 | 34 | methodmap Collection < ArrayList 35 | { 36 | public Collection() 37 | { 38 | return view_as(new ArrayList()); 39 | } 40 | 41 | public void Clear(bool disposemembers=true) 42 | { 43 | if (disposemembers) 44 | { 45 | int count = this.Length; 46 | Dynamic member; 47 | for (int i = 0; i < count; i++) 48 | { 49 | member = view_as(this.Get(i)); 50 | if (!member.IsValid) 51 | continue; 52 | 53 | member.Dispose(); 54 | } 55 | } 56 | 57 | this.Clear(); 58 | } 59 | 60 | public void Dispose(bool disposemembers=true) 61 | { 62 | if (disposemembers) 63 | this.Clear(true); 64 | 65 | CloseHandle(this); 66 | } 67 | 68 | public Dynamic Items(int index) 69 | { 70 | return this.Get(index); 71 | } 72 | 73 | property int Count 74 | { 75 | public get() 76 | { 77 | return this.Length; 78 | } 79 | } 80 | 81 | public int AddItem(Dynamic item) 82 | { 83 | this.Push(item); 84 | } 85 | 86 | public int FindItem(Dynamic item) 87 | { 88 | int count = this.Length; 89 | for (int i = 0; i < count; i++) 90 | { 91 | if (this.Get(i) == item) 92 | return i; 93 | } 94 | return -1; 95 | } 96 | 97 | public void RemoveItem(Dynamic item) 98 | { 99 | int index = this.FindItem(item); 100 | if (index == -1) 101 | return; 102 | 103 | this.Erase(index); 104 | } 105 | 106 | public void RemoveIndex(int index) 107 | { 108 | this.Erase(index); 109 | } 110 | } -------------------------------------------------------------------------------- /scripting/include/dynamic/methodmaps/dynamic.inc: -------------------------------------------------------------------------------- 1 | /** 2 | * ============================================================================= 3 | * Dynamic for SourceMod (C)2016 Matthew J Dunn. All rights reserved. 4 | * ============================================================================= 5 | * 6 | * This program is free software; you can redistribute it and/or modify it under 7 | * the terms of the GNU General Public License, version 3.0, as published by the 8 | * Free Software Foundation. 9 | * 10 | * This program is distributed in the hope that it will be useful, but WITHOUT 11 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 12 | * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more 13 | * details. 14 | * 15 | * You should have received a copy of the GNU General Public License along with 16 | * this program. If not, see . 17 | * 18 | */ 19 | 20 | methodmap Dynamic 21 | { 22 | #if defined dynamic_persistent 23 | public Dynamic(int blocksize=64, int startsize=0, bool persistent=true) 24 | #else 25 | public Dynamic(int blocksize=64, int startsize=0, bool persistent=false) 26 | #endif 27 | { 28 | return Dynamic_Initialise(blocksize, startsize, persistent); 29 | } 30 | 31 | public static bool IsLoaded() 32 | { 33 | if (GetFeatureStatus(FeatureType_Native, "Native_Dynamic_Initialise") == FeatureStatus_Available) 34 | return true; 35 | else 36 | return false; 37 | } 38 | 39 | property int IsValid 40 | { 41 | public get() 42 | { 43 | return Dynamic_IsValid(view_as(this), false); 44 | } 45 | } 46 | 47 | property bool Persistent 48 | { 49 | public get() 50 | { 51 | return Dynamic_GetPersistence(this); 52 | } 53 | public set(bool value) 54 | { 55 | Dynamic_SetPersistence(this, value); 56 | } 57 | } 58 | 59 | property Dynamic Parent 60 | { 61 | public get() 62 | { 63 | return Dynamic_GetParent(this); 64 | } 65 | } 66 | 67 | public bool GetName(char[] buffer, int length) 68 | { 69 | return Dynamic_GetName(this, buffer, length); 70 | } 71 | 72 | property int MemberCount 73 | { 74 | public get() 75 | { 76 | return Dynamic_GetMemberCount(this); 77 | } 78 | } 79 | 80 | public void Dispose(bool disposemembers=true) 81 | { 82 | Dynamic_Dispose(view_as(this), disposemembers); 83 | } 84 | 85 | public bool Reset(bool disposemembers=true, int blocksize=0, int startsize=0) 86 | { 87 | return Dynamic_ResetObject(view_as(this), disposemembers, blocksize, startsize); 88 | } 89 | 90 | property Handle OwnerPlugin 91 | { 92 | public get() 93 | { 94 | return Dynamic_GetOwnerPlugin(this); 95 | } 96 | } 97 | 98 | public bool SetName(const char[] objectname, bool replace=false) 99 | { 100 | return Dynamic_SetName(this, objectname, replace); 101 | } 102 | 103 | public static Dynamic FindByName(const char[] objectname) 104 | { 105 | return Dynamic_FindByName(objectname); 106 | } 107 | 108 | public bool ReadConfig(const char[] path, bool use_valve_fs = false, int valuelength=256) 109 | { 110 | return Dynamic_ReadConfig(this, path, use_valve_fs, valuelength); 111 | } 112 | 113 | public bool WriteConfig(const char[] path) 114 | { 115 | return Dynamic_WriteConfig(this, path); 116 | } 117 | 118 | public bool ReadKeyValues(const char[] path, int valuelength = 256, Dynamic_HookType callback = INVALID_FUNCTION) 119 | { 120 | return Dynamic_ReadKeyValues(this, path, valuelength, callback); 121 | } 122 | 123 | public bool WriteKeyValues(const char[] path, const char[] basekey="") 124 | { 125 | return Dynamic_WriteKeyValues(this, path, basekey); 126 | } 127 | 128 | public static Dynamic GetSettings() 129 | { 130 | return view_as(0); 131 | } 132 | 133 | public static Dynamic GetPlayerSettings(int client) 134 | { 135 | return view_as(client); 136 | } 137 | 138 | public int GetInt(const char[] membername, int defaultvalue=-1) 139 | { 140 | return Dynamic_GetInt(this, membername, defaultvalue); 141 | } 142 | 143 | public DynamicOffset SetInt(const char[] membername, int value) 144 | { 145 | return Dynamic_SetInt(this, membername, value); 146 | } 147 | 148 | public int GetIntByOffset(DynamicOffset offset, int defaultvalue=-1) 149 | { 150 | return Dynamic_GetIntByOffset(this, offset, defaultvalue); 151 | } 152 | 153 | public void SetIntByOffset(DynamicOffset offset, int value) 154 | { 155 | Dynamic_SetIntByOffset(this, offset, value); 156 | } 157 | 158 | public int PushInt(int value, const char[] name="") 159 | { 160 | return Dynamic_PushInt(this, value, name); 161 | } 162 | 163 | public int GetIntByIndex(int index, int defaultvalue=-1) 164 | { 165 | return Dynamic_GetIntByIndex(this, index, defaultvalue); 166 | } 167 | 168 | public bool GetBool(const char[] membername, bool defaultvalue = false) 169 | { 170 | return Dynamic_GetBool(this, membername, defaultvalue); 171 | } 172 | 173 | public DynamicOffset SetBool(const char[] membername, bool value) 174 | { 175 | return Dynamic_SetBool(this, membername, value); 176 | } 177 | 178 | public bool GetBoolByOffset(DynamicOffset offset, bool defaultvalue = false) 179 | { 180 | return Dynamic_GetBoolByOffset(this, offset, defaultvalue); 181 | } 182 | 183 | public void SetBoolByOffset(DynamicOffset offset, bool value) 184 | { 185 | Dynamic_SetBoolByOffset(this, offset, value); 186 | } 187 | 188 | public int PushBool(bool value, const char[] name="") 189 | { 190 | return Dynamic_PushBool(this, value, name); 191 | } 192 | 193 | public bool GetBoolByIndex(int index, bool defaultvalue = false) 194 | { 195 | return Dynamic_GetBoolByIndex(this, index, defaultvalue); 196 | } 197 | 198 | public float GetFloat(const char[] membername, float defaultvalue=-1.0) 199 | { 200 | return Dynamic_GetFloat(this, membername, defaultvalue); 201 | } 202 | 203 | public DynamicOffset SetFloat(const char[] membername, float value) 204 | { 205 | return Dynamic_SetFloat(this, membername, value); 206 | } 207 | 208 | public float GetFloatByOffset(DynamicOffset offset, float defaultvalue=-1.0) 209 | { 210 | return Dynamic_GetFloatByOffset(this, offset, defaultvalue); 211 | } 212 | 213 | public void SetFloatByOffset(DynamicOffset offset, float value) 214 | { 215 | Dynamic_SetFloatByOffset(this, offset, value); 216 | } 217 | 218 | public int PushFloat(float value, const char[] name="") 219 | { 220 | return Dynamic_PushFloat(this, value, name); 221 | } 222 | 223 | public float GetFloatByIndex(int index, float defaultvalue=-1.0) 224 | { 225 | return Dynamic_GetFloatByIndex(this, index, defaultvalue); 226 | } 227 | 228 | public bool GetString(const char[] membername, char[] buffer, int length) 229 | { 230 | return Dynamic_GetString(this, membername, buffer, length); 231 | } 232 | 233 | public DynamicOffset SetString(const char[] membername, const char[] value, int length=0) 234 | { 235 | return Dynamic_SetString(this, membername, value, length); 236 | } 237 | 238 | public bool GetStringByOffset(DynamicOffset offset, char[] buffer, int length) 239 | { 240 | return Dynamic_GetStringByOffset(this, offset, buffer, length); 241 | } 242 | 243 | public void SetStringByOffset(const DynamicOffset offset, const char[] value) 244 | { 245 | Dynamic_SetStringByOffset(this, offset, value); 246 | } 247 | 248 | public int PushString(const char[] value, int length=0, const char[] name="") 249 | { 250 | return Dynamic_PushString(this, value, length, name); 251 | } 252 | 253 | public bool GetStringByIndex(int index, char[] buffer, int length) 254 | { 255 | return Dynamic_GetStringByIndex(this, index, buffer, length); 256 | } 257 | 258 | public int GetStringLength(const char[] membername) 259 | { 260 | return Dynamic_GetStringLength(this, membername); 261 | } 262 | 263 | public int GetStringLengthByOffset(DynamicOffset offset) 264 | { 265 | return Dynamic_GetStringLengthByOffset(this, offset); 266 | } 267 | 268 | public bool CompareString(const char[] membername, const char[] value, bool casesensitive=true) 269 | { 270 | return Dynamic_CompareString(this, membername, value, casesensitive); 271 | } 272 | 273 | public Dynamic GetDynamic(const char[] membername) 274 | { 275 | return Dynamic_GetDynamic(this, membername); 276 | } 277 | 278 | public DynamicOffset SetDynamic(const char[] membername, Dynamic value) 279 | { 280 | return Dynamic_SetDynamic(this, membername, value); 281 | } 282 | 283 | public Dynamic GetDynamicByOffset(DynamicOffset offset) 284 | { 285 | return Dynamic_GetDynamicByOffset(this, offset); 286 | } 287 | 288 | public void SetDynamicByOffset(DynamicOffset offset, Dynamic value) 289 | { 290 | Dynamic_SetDynamicByOffset(this, offset, value); 291 | } 292 | 293 | public int PushDynamic(Dynamic value, const char[] name="") 294 | { 295 | return Dynamic_PushDynamic(this, value, name); 296 | } 297 | 298 | public Dynamic GetDynamicByIndex(int index) 299 | { 300 | return Dynamic_GetDynamicByIndex(this, index); 301 | } 302 | 303 | public bool SetDynamicByIndex(int index, Dynamic value) 304 | { 305 | return Dynamic_SetDynamicByIndex(this, index, value); 306 | } 307 | 308 | public Handle GetHandle(const char[] membername) 309 | { 310 | return Dynamic_GetHandle(this, membername); 311 | } 312 | 313 | public DynamicOffset SetHandle(const char[] membername, Handle value) 314 | { 315 | return Dynamic_SetHandle(this, membername, value); 316 | } 317 | 318 | public Handle GetHandleByOffset(DynamicOffset offset) 319 | { 320 | return Dynamic_GetHandleByOffset(this, offset); 321 | } 322 | 323 | public void SetHandleByOffset(DynamicOffset offset, Handle value) 324 | { 325 | Dynamic_SetHandleByOffset(this, offset, value); 326 | } 327 | 328 | public int PushHandle(Handle value, const char[] name="") 329 | { 330 | return Dynamic_PushHandle(this, value, name); 331 | } 332 | 333 | public Handle GetHandleByIndex(int index) 334 | { 335 | return Dynamic_GetHandleByIndex(this, index); 336 | } 337 | 338 | public bool GetVector(const char[] membername, float value[3]) 339 | { 340 | return Dynamic_GetVector(this, membername, value); 341 | } 342 | 343 | public DynamicOffset SetVector(const char[] membername, const float value[3]) 344 | { 345 | return Dynamic_SetVector(this, membername, value); 346 | } 347 | 348 | public bool GetVectorByOffset(DynamicOffset offset, float[3] value) 349 | { 350 | return Dynamic_GetVectorByOffset(this, offset, value); 351 | } 352 | 353 | public void SetVectorByOffset(DynamicOffset offset, const float[3] value) 354 | { 355 | Dynamic_SetVectorByOffset(this, offset, value); 356 | } 357 | 358 | public int PushVector(const float value[3], const char[] name="") 359 | { 360 | return Dynamic_PushVector(this, value, name); 361 | } 362 | 363 | public bool GetVectorByIndex(int index, float[3] value) 364 | { 365 | return Dynamic_GetVectorByIndex(this, index, value); 366 | } 367 | 368 | public Function GetFunction(const char[] membername) 369 | { 370 | return Dynamic_GetFunction(this, membername); 371 | } 372 | 373 | public DynamicOffset SetFunction(const char[] membername, Function value) 374 | { 375 | return Dynamic_SetFunction(this, membername, value); 376 | } 377 | 378 | public Function GetFunctionByOffset(DynamicOffset offset) 379 | { 380 | return Dynamic_GetFunctionByOffset(this, offset); 381 | } 382 | 383 | public void SetFunctionByOffset(DynamicOffset offset, Function value) 384 | { 385 | Dynamic_SetFunctionByOffset(this, offset, value); 386 | } 387 | 388 | public int PushFunction(Function value, const char[] name="") 389 | { 390 | return Dynamic_PushFunction(this, value, name); 391 | } 392 | 393 | public Function GetFunctionByIndex(int index) 394 | { 395 | return Dynamic_GetFunctionByIndex(this, index); 396 | } 397 | 398 | public void HookChanges(Dynamic_HookType callback) 399 | { 400 | Dynamic_HookChanges(this, callback); 401 | } 402 | 403 | public void UnHookChanges(Dynamic_HookType callback) 404 | { 405 | Dynamic_UnHookChanges(this, callback); 406 | } 407 | 408 | public int CallbackCount() 409 | { 410 | return Dynamic_CallbackCount(this); 411 | } 412 | 413 | public DynamicOffset GetMemberOffset(const char[] membername) 414 | { 415 | return Dynamic_GetMemberOffset(this, membername); 416 | } 417 | 418 | public Dynamic_MemberType GetMemberType(DynamicOffset offset) 419 | { 420 | return Dynamic_GetMemberTypeByOffset(this, offset); 421 | } 422 | 423 | public bool GetMemberNameByIndex(int index, char[] buffer, int length) 424 | { 425 | return Dynamic_GetMemberNameByIndex(this, index, buffer, length); 426 | } 427 | 428 | public DynamicOffset GetMemberOffsetByIndex(int index) 429 | { 430 | return Dynamic_GetMemberOffsetByIndex(this, index); 431 | } 432 | 433 | public bool GetMemberNameByOffset(DynamicOffset offset, char[] buffer, int length) 434 | { 435 | return Dynamic_GetMemberNameByOffset(this, offset, buffer, length); 436 | } 437 | 438 | public bool SortMembers(SortOrder order = Sort_Ascending) 439 | { 440 | return Dynamic_SortMembers(this, order); 441 | } 442 | 443 | public ArrayList FindByMemberValue(Dynamic params) 444 | { 445 | return Dynamic_FindByMemberValue(this, params); 446 | } 447 | 448 | public void CloseHandleByOffset(DynamicOffset offset) 449 | { 450 | Handle handle = this.GetHandleByOffset(offset); 451 | delete handle; 452 | this.SetHandleByOffset(offset, null); 453 | } 454 | 455 | public void CloseHandle(const char[] membername) 456 | { 457 | DynamicOffset offset = this.GetMemberOffset(membername); 458 | if (offset == INVALID_DYNAMIC_OFFSET) 459 | return; 460 | 461 | this.CloseHandleByOffset(offset); 462 | } 463 | } 464 | -------------------------------------------------------------------------------- /scripting/include/dynamic/methodmaps/dynamicoffset.inc: -------------------------------------------------------------------------------- 1 | /** 2 | * ============================================================================= 3 | * Dynamic for SourceMod (C)2016 Matthew J Dunn. All rights reserved. 4 | * ============================================================================= 5 | * 6 | * This program is free software; you can redistribute it and/or modify it under 7 | * the terms of the GNU General Public License, version 3.0, as published by the 8 | * Free Software Foundation. 9 | * 10 | * This program is distributed in the hope that it will be useful, but WITHOUT 11 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 12 | * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more 13 | * details. 14 | * 15 | * You should have received a copy of the GNU General Public License along with 16 | * this program. If not, see . 17 | * 18 | */ 19 | 20 | methodmap DynamicOffset 21 | { 22 | public DynamicOffset(int index, int cell) 23 | { 24 | return view_as(index << 16 | cell); 25 | } 26 | 27 | property int Index 28 | { 29 | public get() 30 | { 31 | return view_as(this) >>> 16; 32 | } 33 | } 34 | 35 | property int Cell 36 | { 37 | public get() 38 | { 39 | return view_as(this) & 0xFFFF; 40 | } 41 | } 42 | 43 | property bool IsValid 44 | { 45 | public get() 46 | { 47 | if (this == INVALID_DYNAMIC_OFFSET) 48 | return false; 49 | return true; 50 | } 51 | } 52 | 53 | public DynamicOffset Clone(int blocksize, int addcells) 54 | { 55 | if (addcells == 0) 56 | { 57 | return this; 58 | } 59 | 60 | int index = this.Index; 61 | int cell = this.Cell + addcells; 62 | 63 | while (cell >= blocksize) 64 | { 65 | index++; 66 | cell-=blocksize; 67 | } 68 | 69 | return DynamicOffset(index, cell); 70 | } 71 | } -------------------------------------------------------------------------------- /scripting/include/dynamic/methodmaps/preparedquery.inc: -------------------------------------------------------------------------------- 1 | /** 2 | * ============================================================================= 3 | * Dynamic for SourceMod (C)2016 Matthew J Dunn. All rights reserved. 4 | * ============================================================================= 5 | * 6 | * This program is free software; you can redistribute it and/or modify it under 7 | * the terms of the GNU General Public License, version 3.0, as published by the 8 | * Free Software Foundation. 9 | * 10 | * This program is distributed in the hope that it will be useful, but WITHOUT 11 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 12 | * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more 13 | * details. 14 | * 15 | * You should have received a copy of the GNU General Public License along with 16 | * this program. If not, see . 17 | * 18 | */ 19 | #if defined _dynamic_class_preparedquery_ 20 | #endinput 21 | #endif 22 | #define _dynamic_class_preparedquery_ 23 | 24 | methodmap PreparedQuery < Dynamic 25 | { 26 | public PreparedQuery() 27 | { 28 | Dynamic myclass = Dynamic(64, 0); 29 | return view_as(myclass); 30 | } 31 | 32 | public bool Compile(const char[] query) 33 | { 34 | return _Dynamic_PreparedQuery_Compile(query, this); 35 | } 36 | 37 | public bool Prepare(Database db, Dynamic parameters, char[] buffer, int buffersize) 38 | { 39 | return _Dynamic_PreparedQuery_Prepare(this, db, parameters, buffer, buffersize); 40 | } 41 | 42 | public bool Execute(Database db, Dynamic parameters, SQLQueryCallback callback=INVALID_FUNCTION, any data=0, int buffersize=512) 43 | { 44 | return _Dynamic_PreparedQuery_Execute(this, db, parameters, callback, data, buffersize); 45 | } 46 | } -------------------------------------------------------------------------------- /scripting/include/dynamic/natives.inc: -------------------------------------------------------------------------------- 1 | /** 2 | * ============================================================================= 3 | * Dynamic for SourceMod (C)2016 Matthew J Dunn. All rights reserved. 4 | * ============================================================================= 5 | * 6 | * This program is free software; you can redistribute it and/or modify it under 7 | * the terms of the GNU General Public License, version 3.0, as published by the 8 | * Free Software Foundation. 9 | * 10 | * This program is distributed in the hope that it will be useful, but WITHOUT 11 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 12 | * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more 13 | * details. 14 | * 15 | * You should have received a copy of the GNU General Public License along with 16 | * this program. If not, see . 17 | * 18 | */ 19 | 20 | native int Dynamic_GetCollectionSize(); 21 | 22 | native Dynamic Dynamic_Initialise(int blocksize=64, int startsize=0, bool persistent=false); 23 | native bool Dynamic_IsValid(int index, bool throwerror=false); 24 | native bool Dynamic_Dispose(int index, bool disposemembers=true); 25 | native bool Dynamic_ResetObject(int index, bool disposemembers=true, int blocksize=0, int startsize=0); 26 | native Handle Dynamic_GetOwnerPlugin(Dynamic obj); 27 | 28 | native bool Dynamic_SetName(Dynamic obj, const char[] objectname, bool replace=false); 29 | native Dynamic Dynamic_FindByName(const char[] objectname); 30 | native Dynamic Dynamic_GetParent(Dynamic obj); 31 | native bool Dynamic_GetName(Dynamic obj, char[] buffer, int length); 32 | 33 | native bool Dynamic_GetPersistence(Dynamic obj); 34 | native bool Dynamic_SetPersistence(Dynamic obj, bool value); 35 | 36 | native bool Dynamic_ReadConfig(Dynamic obj, const char[] path, bool use_valve_fs=false, int valuelength=256); 37 | native bool Dynamic_WriteConfig(Dynamic obj, const char[] path); 38 | 39 | native bool Dynamic_ReadKeyValues(Dynamic obj, const char[] path, int valuelength, Dynamic_HookType callback=INVALID_FUNCTION); 40 | native bool Dynamic_WriteKeyValues(Dynamic obj, const char[] path, const char[] basekey); 41 | 42 | native int Dynamic_GetMemberCount(Dynamic obj); 43 | native DynamicOffset Dynamic_GetMemberOffset(Dynamic obj, const char[] membername); 44 | native DynamicOffset Dynamic_GetMemberOffsetByIndex(Dynamic obj, int index); 45 | native bool Dynamic_GetMemberNameByIndex(Dynamic obj, int index, char[] buffer, int length); 46 | native bool Dynamic_GetMemberNameByOffset(Dynamic obj, DynamicOffset offset, char[] buffer, int length); 47 | native Dynamic_MemberType Dynamic_GetMemberType(Dynamic obj, const char[] membername); 48 | native Dynamic_MemberType Dynamic_GetMemberTypeByOffset(Dynamic obj, DynamicOffset offset); 49 | native bool Dynamic_SortMembers(Dynamic obj, SortOrder order); 50 | native ArrayList Dynamic_FindByMemberValue(Dynamic obj, Dynamic params); 51 | 52 | native int Dynamic_CallbackCount(Dynamic obj); 53 | native bool Dynamic_HookChanges(Dynamic obj, Dynamic_HookType callback); 54 | native bool Dynamic_UnHookChanges(Dynamic obj, Dynamic_HookType callback); 55 | 56 | native int Dynamic_GetInt(Dynamic obj, const char[] membername, int defaultvalue=-1); 57 | native DynamicOffset Dynamic_SetInt(Dynamic obj, const char[] membername, int value); 58 | native int Dynamic_GetIntByOffset(Dynamic obj, DynamicOffset offset, int defaultvalue=-1); 59 | native bool Dynamic_SetIntByOffset(Dynamic obj, DynamicOffset offset, int value); 60 | native int Dynamic_PushInt(Dynamic obj, int value, const char[] name=""); 61 | native int Dynamic_GetIntByIndex(Dynamic obj, int index, int defaultvalue=-1); 62 | 63 | native float Dynamic_GetFloat(Dynamic obj, const char[] membername, float defaultvalue=-1.0); 64 | native DynamicOffset Dynamic_SetFloat(Dynamic obj, const char[] membername, float value); 65 | native float Dynamic_GetFloatByOffset(Dynamic obj, DynamicOffset offset, float defaultvalue=-1.0); 66 | native bool Dynamic_SetFloatByOffset(Dynamic obj, DynamicOffset offset, float value); 67 | native int Dynamic_PushFloat(Dynamic obj, float value, const char[] name=""); 68 | native float Dynamic_GetFloatByIndex(Dynamic obj, int index, float defaultvalue=-1.0); 69 | 70 | native bool Dynamic_GetString(Dynamic obj, const char[] membername, char[] buffer, int length); 71 | native DynamicOffset Dynamic_SetString(Dynamic obj, const char[] membername, const char[] value, int length=0); 72 | native bool Dynamic_GetStringByOffset(Dynamic obj, DynamicOffset offset, char[] buffer, int length); 73 | native bool Dynamic_SetStringByOffset(Dynamic obj, DynamicOffset offset, const char[] value, int length=0); 74 | native int Dynamic_PushString(Dynamic obj, const char[] value, int length=0, const char[] name=""); 75 | native bool Dynamic_GetStringByIndex(Dynamic obj, int index, char[] buffer, int length); 76 | native int Dynamic_GetStringLength(Dynamic obj, const char[] membername); 77 | native int Dynamic_GetStringLengthByOffset(Dynamic obj, DynamicOffset offset); 78 | native bool Dynamic_CompareString(Dynamic obj, const char[] membername, const char[] value, bool casesensitive=true); 79 | 80 | // This can be removed at some point in the future 81 | #pragma deprecated Use Dynamic_GetDynamic() instead 82 | native Dynamic Dynamic_GetObject(Dynamic obj, const char[] membername); 83 | #pragma deprecated Use Dynamic_SetDynamic() instead 84 | native DynamicOffset Dynamic_SetObject(Dynamic obj, const char[] membername, Dynamic value); 85 | #pragma deprecated Use Dynamic_GetDynamicByOffset() instead 86 | native Dynamic Dynamic_GetObjectByOffset(Dynamic obj, DynamicOffset offset); 87 | #pragma deprecated Use Dynamic_SetDynamicByOffset() instead 88 | native bool Dynamic_SetObjectByOffset(Dynamic obj, DynamicOffset offset, Dynamic value); 89 | #pragma deprecated Use Dynamic_PushDynamic() instead 90 | native int Dynamic_PushObject(Dynamic obj, Dynamic value, const char[] name=""); 91 | #pragma deprecated Use Dynamic_GetDynamicByIndex() instead 92 | native Dynamic Dynamic_GetObjectByIndex(Dynamic obj, int index); 93 | #pragma deprecated Use Dynamic_SetDynamicByIndex() instead 94 | native bool Dynamic_SetObjectByIndex(Dynamic obj, int index, Dynamic value); 95 | 96 | native Dynamic Dynamic_GetDynamic(Dynamic obj, const char[] membername); 97 | native DynamicOffset Dynamic_SetDynamic(Dynamic obj, const char[] membername, Dynamic value); 98 | native Dynamic Dynamic_GetDynamicByOffset(Dynamic obj, DynamicOffset offset); 99 | native bool Dynamic_SetDynamicByOffset(Dynamic obj, DynamicOffset offset, Dynamic value); 100 | native int Dynamic_PushDynamic(Dynamic obj, Dynamic value, const char[] name=""); 101 | native Dynamic Dynamic_GetDynamicByIndex(Dynamic obj, int index); 102 | native bool Dynamic_SetDynamicByIndex(Dynamic obj, int index, Dynamic value); 103 | 104 | native bool Dynamic_GetBool(Dynamic obj, const char[] membername, bool defaultvalue=false); 105 | native DynamicOffset Dynamic_SetBool(Dynamic obj, const char[] membername, bool value); 106 | native bool Dynamic_GetBoolByOffset(Dynamic obj, DynamicOffset offset, bool defaultvalue=false); 107 | native bool Dynamic_SetBoolByOffset(Dynamic obj, DynamicOffset offset, bool value); 108 | native int Dynamic_PushBool(Dynamic obj, bool value, const char[] name=""); 109 | native bool Dynamic_GetBoolByIndex(Dynamic obj, int index, bool defaultvalue=false); 110 | 111 | native Handle Dynamic_GetHandle(Dynamic obj, const char[] membername); 112 | native DynamicOffset Dynamic_SetHandle(Dynamic obj, const char[] membername, Handle value); 113 | native Handle Dynamic_GetHandleByOffset(Dynamic obj, DynamicOffset offset); 114 | native bool Dynamic_SetHandleByOffset(Dynamic obj, DynamicOffset offset, Handle value); 115 | native int Dynamic_PushHandle(Dynamic obj, Handle value, const char[] name=""); 116 | native Handle Dynamic_GetHandleByIndex(Dynamic obj, int index); 117 | 118 | native bool Dynamic_GetVector(Dynamic obj, const char[] membername, float value[3]); 119 | native DynamicOffset Dynamic_SetVector(Dynamic obj, const char[] membername, const float value[3]); 120 | native bool Dynamic_GetVectorByOffset(Dynamic obj, DynamicOffset offset, float value[3]); 121 | native bool Dynamic_SetVectorByOffset(Dynamic obj, DynamicOffset offset, const float value[3]); 122 | native int Dynamic_PushVector(Dynamic obj, const float value[3], const char[] name=""); 123 | native bool Dynamic_GetVectorByIndex(Dynamic obj, int index, float value[3]); 124 | 125 | native Function Dynamic_GetFunction(Dynamic obj, const char[] membername); 126 | native DynamicOffset Dynamic_SetFunction(Dynamic obj, const char[] membername, Function value); 127 | native Function Dynamic_GetFunctionByOffset(Dynamic obj, DynamicOffset offset); 128 | native bool Dynamic_SetFunctionByOffset(Dynamic obj, DynamicOffset offset, Function value); 129 | native int Dynamic_PushFunction(Dynamic obj, Function value, const char[] name=""); 130 | native Function Dynamic_GetFunctionByIndex(Dynamic obj, int index); 131 | 132 | #if !defined REQUIRE_PLUGIN 133 | public __pl_dynamic_SetNTVOptional() 134 | { 135 | MarkNativeAsOptional("Dynamic_Initialise"); 136 | MarkNativeAsOptional("Dynamic_IsValid"); 137 | MarkNativeAsOptional("Dynamic_Dispose"); 138 | MarkNativeAsOptional("Dynamic_ResetObject"); 139 | MarkNativeAsOptional("Dynamic_GetOwnerPlugin"); 140 | MarkNativeAsOptional("Dynamic_SetName"); 141 | MarkNativeAsOptional("Dynamic_FindByName"); 142 | MarkNativeAsOptional("Dynamic_GetParent"); 143 | MarkNativeAsOptional("Dynamic_GetName"); 144 | MarkNativeAsOptional("Dynamic_GetPersistence"); 145 | MarkNativeAsOptional("Dynamic_SetPersistence"); 146 | MarkNativeAsOptional("Dynamic_ReadConfig"); 147 | MarkNativeAsOptional("Dynamic_WriteConfig"); 148 | MarkNativeAsOptional("Dynamic_ReadKeyValues"); 149 | MarkNativeAsOptional("Dynamic_WriteKeyValues"); 150 | MarkNativeAsOptional("Dynamic_GetInt"); 151 | MarkNativeAsOptional("Dynamic_SetInt"); 152 | MarkNativeAsOptional("Dynamic_GetIntByOffset"); 153 | MarkNativeAsOptional("Dynamic_SetIntByOffset"); 154 | MarkNativeAsOptional("Dynamic_PushInt"); 155 | MarkNativeAsOptional("Dynamic_GetIntByIndex"); 156 | MarkNativeAsOptional("Dynamic_GetBool"); 157 | MarkNativeAsOptional("Dynamic_SetBool"); 158 | MarkNativeAsOptional("Dynamic_GetBoolByOffset"); 159 | MarkNativeAsOptional("Dynamic_SetBoolByOffset"); 160 | MarkNativeAsOptional("Dynamic_PushBool"); 161 | MarkNativeAsOptional("Dynamic_GetBoolByIndex"); 162 | MarkNativeAsOptional("Dynamic_GetFloat"); 163 | MarkNativeAsOptional("Dynamic_SetFloat"); 164 | MarkNativeAsOptional("Dynamic_GetFloatByOffset"); 165 | MarkNativeAsOptional("Dynamic_SetFloatByOffset"); 166 | MarkNativeAsOptional("Dynamic_PushFloat"); 167 | MarkNativeAsOptional("Dynamic_GetFloatByIndex"); 168 | MarkNativeAsOptional("Dynamic_GetString"); 169 | MarkNativeAsOptional("Dynamic_SetString"); 170 | MarkNativeAsOptional("Dynamic_GetStringByOffset"); 171 | MarkNativeAsOptional("Dynamic_SetStringByOffset"); 172 | MarkNativeAsOptional("Dynamic_PushString"); 173 | MarkNativeAsOptional("Dynamic_GetStringByIndex"); 174 | MarkNativeAsOptional("Dynamic_GetStringLength"); 175 | MarkNativeAsOptional("Dynamic_GetStringLengthByOffset"); 176 | MarkNativeAsOptional("Dynamic_CompareString"); 177 | MarkNativeAsOptional("Dynamic_GetDynamic"); 178 | MarkNativeAsOptional("Dynamic_SetDynamic"); 179 | MarkNativeAsOptional("Dynamic_GetDynamicByOffset"); 180 | MarkNativeAsOptional("Dynamic_SetDynamicByOffset"); 181 | MarkNativeAsOptional("Dynamic_PushDynamic"); 182 | MarkNativeAsOptional("Dynamic_GetDynamicByIndex"); 183 | MarkNativeAsOptional("Dynamic_SetDynamicByIndex"); 184 | MarkNativeAsOptional("Dynamic_GetHandle"); 185 | MarkNativeAsOptional("Dynamic_SetHandle"); 186 | MarkNativeAsOptional("Dynamic_GetHandleByOffset"); 187 | MarkNativeAsOptional("Dynamic_SetHandleByOffset"); 188 | MarkNativeAsOptional("Dynamic_PushHandle"); 189 | MarkNativeAsOptional("Dynamic_GetHandleByIndex"); 190 | MarkNativeAsOptional("Dynamic_GetVector"); 191 | MarkNativeAsOptional("Dynamic_SetVector"); 192 | MarkNativeAsOptional("Dynamic_GetVectorByOffset"); 193 | MarkNativeAsOptional("Dynamic_SetVectorByOffset"); 194 | MarkNativeAsOptional("Dynamic_PushVector"); 195 | MarkNativeAsOptional("Dynamic_GetVectorByIndex"); 196 | MarkNativeAsOptional("Dynamic_GetFunction"); 197 | MarkNativeAsOptional("Dynamic_SetFunction"); 198 | MarkNativeAsOptional("Dynamic_GetFunctionByOffset"); 199 | MarkNativeAsOptional("Dynamic_SetFunctionByOffset"); 200 | MarkNativeAsOptional("Dynamic_PushFunction"); 201 | MarkNativeAsOptional("Dynamic_GetFunctionByIndex"); 202 | MarkNativeAsOptional("Dynamic_GetCollectionSize"); 203 | MarkNativeAsOptional("Dynamic_GetMemberCount"); 204 | MarkNativeAsOptional("Dynamic_HookChanges"); 205 | MarkNativeAsOptional("Dynamic_UnHookChanges"); 206 | MarkNativeAsOptional("Dynamic_CallbackCount"); 207 | MarkNativeAsOptional("Dynamic_GetMemberOffset"); 208 | MarkNativeAsOptional("Dynamic_GetMemberOffsetByIndex"); 209 | MarkNativeAsOptional("Dynamic_GetMemberType"); 210 | MarkNativeAsOptional("Dynamic_GetMemberTypeByOffset"); 211 | MarkNativeAsOptional("Dynamic_GetMemberNameByIndex"); 212 | MarkNativeAsOptional("Dynamic_GetMemberNameByOffset"); 213 | MarkNativeAsOptional("Dynamic_SortMembers"); 214 | MarkNativeAsOptional("Dynamic_FindByMemberValue"); 215 | 216 | // These are marked as deprecated 217 | MarkNativeAsOptional("Dynamic_GetObject"); 218 | MarkNativeAsOptional("Dynamic_SetObject"); 219 | MarkNativeAsOptional("Dynamic_GetObjectByOffset"); 220 | MarkNativeAsOptional("Dynamic_SetObjectByOffset"); 221 | MarkNativeAsOptional("Dynamic_PushObject"); 222 | MarkNativeAsOptional("Dynamic_GetObjectByIndex"); 223 | MarkNativeAsOptional("Dynamic_SetObjectByIndex"); 224 | } 225 | #endif --------------------------------------------------------------------------------