plugins/include/entity.inc
author David Anderson <dvander@alliedmods.net>
Fri Jun 22 14:59:26 2007 +0000 (2007-06-22)
changeset 1000 aefbd36eaf91
parent 827 032150a7cc40
child 1010 dbb473060167
permissions -rw-r--r--
added ability to use NULL_STRING in KeyValues natives
     1 /**
     2  * vim: set ts=4 :
     3  * ===============================================================
     4  * SourceMod (C)2004-2007 AlliedModders LLC.  All rights reserved.
     5  * ===============================================================
     6  *
     7  *  This file is part of the SourceMod/SourcePawn SDK.  This file may only be used 
     8  * or modified under the Terms and Conditions of its License Agreement, which is found 
     9  * in LICENSE.txt.  The Terms and Conditions for making SourceMod extensions/plugins 
    10  * may change at any time.  To view the latest information, see:
    11  *   http://www.sourcemod.net/license.php
    12  *
    13  * Version: $Id$
    14  */
    15  
    16 #if defined _entity_included
    17  #endinput
    18 #endif
    19 #define _entity_included
    20 
    21 /**
    22  * Property types for entities.
    23  */
    24 enum PropType
    25 {
    26 	Prop_Send = 0,	/**< This property is networked. */
    27 	Prop_Data = 1,	/**< This property is for saved game files. */
    28 };
    29 
    30 /**
    31  * For more information on these, see the HL2SDK (public/edict.h)
    32  */
    33 #define FL_EDICT_CHANGED	(1<<0)	/**< Game DLL sets this when the entity state changes
    34 										 Mutually exclusive with FL_EDICT_PARTIAL_CHANGE. */
    35 #define FL_EDICT_FREE		(1<<1)	/**< this edict if free for reuse */
    36 #define FL_EDICT_FULL		(1<<2)	/**< this is a full server entity */
    37 #define FL_EDICT_FULLCHECK	(0<<0)  /**< call ShouldTransmit() each time, this is a fake flag */
    38 #define FL_EDICT_ALWAYS		(1<<3)	/**< always transmit this entity */
    39 #define FL_EDICT_DONTSEND	(1<<4)	/**< don't transmit this entity */
    40 #define FL_EDICT_PVSCHECK	(1<<5)	/**< always transmit entity, but cull against PVS */
    41 #define FL_EDICT_PENDING_DORMANT_CHECK	(1<<6)
    42 #define FL_EDICT_DIRTY_PVS_INFORMATION	(1<<7)
    43 #define FL_FULL_EDICT_CHANGED			(1<<8)
    44 
    45 /**
    46  * Returns the maximum number of entities.
    47  *
    48  * @return				Maximum number of entities.
    49  */
    50 native GetMaxEntities();
    51 
    52 /**
    53  * Returns the number of entities in the server.
    54  *
    55  * @return				Number of entities in the server.
    56  */
    57 native GetEntityCount();
    58 
    59 /**
    60  * Returns whether or not an entity is valid.  Returns false
    61  * if there is no matching CBaseEntity for this edict index.
    62  *
    63  * @param edict			Index of the entity/edict.
    64  * @return				True if valid, false otherwise.
    65  */
    66 native bool:IsValidEntity(edict);
    67 
    68 /**
    69  * Returns whether or not an edict index is valid.
    70  *
    71  * @param edict			Index of the edict.
    72  * @return				True if valid, false otherwise.
    73  */
    74 native bool:IsValidEdict(edict);
    75 
    76 /**
    77  * Returns whether or not an entity is a valid networkable edict.
    78  *
    79  * @param edict			Index of the edict.
    80  * @return				True if networkable, false if invalid or not networkable.
    81  */
    82 native bool:IsEntNetworkable(edict);
    83 
    84 /**
    85  * Creates a new edict (the basis of a networkable entity)
    86  *
    87  * @return				Index of the edict, 0 on failure.
    88  */
    89 native CreateEdict();
    90 
    91 /** 
    92  * Removes an edict from the world.
    93  *
    94  * @param edict			Index of the edict.
    95  * @noreturn
    96  * @error				Invalid edict index.
    97  */
    98 native RemoveEdict(edict);
    99 
   100 /**
   101  * Returns the flags on an edict.  These are not the same as entity flags.
   102  *
   103  * @param edict			Index of the entity.
   104  * @return				Edict flags.
   105  * @error				Invalid edict index.
   106  */
   107 native GetEdictFlags(edict);
   108 
   109 /**
   110  * Sets the flags on an edict.  These are not the same as entity flags.
   111  *
   112  * @param edict			Index of the entity.
   113  * @param flags			Flags to set.
   114  * @noreturn
   115  * @error				Invalid edict index.
   116  */
   117 native SetEdictFlags(edict, flags);
   118 
   119 /**
   120  * Retrieves an edict classname.
   121  *
   122  * @param edict			Index of the entity.
   123  * @param clsname		Buffer to store the classname.
   124  * @param maxlength		Maximum length of the buffer.
   125  * @return				True on success, false if there is no classname set.
   126  */
   127 native bool:GetEdictClassname(edict, String:clsname[], maxlength);
   128 
   129 /**
   130  * Retrieves an entity's networkable serverclass name.
   131  * This is not the same as the classname and is used for networkable state changes.
   132  *
   133  * @param edict			Index of the entity.
   134  * @param clsname		Buffer to store the serverclass name.
   135  * @param maxlength		Maximum lnegth of the buffer.
   136  * @return				True on success, false if the edict is not networkable.
   137  * @error				Invalid edict index.
   138  */
   139 native bool:GetEntityNetClass(edict, String:clsname[], maxlength);
   140 
   141 /**
   142  * @section Entity offset functions
   143  *
   144  * Offsets should be specified in byte distance from the CBaseEntity 
   145  * structure, not short (double byte) or integer (four byte) multiples.  
   146  * It is somewhat common practice to use offsets aligned to their final 
   147  * type, and thus make sure you are not falling to this error in SourceMod.
   148  * For example, if your "integer-aligned" offset was 119, your byte-aligned
   149  * offset is 119*4, or 476.
   150  
   151  * Specifying incorrect offsets or the incorrect data type for an offset
   152  * can have fatal consequences.  If you are hardcoding offsets, and the 
   153  * layout of CBaseEntity does not match, you can easily crash the server.
   154  *
   155  * The reasonable bounds for offsets is greater than or equal to 0 and 
   156  * below 32768.  Offsets out of these bounds will throw an error.  However,
   157  * this does not represent any real range, it is simply a sanity check for
   158  * illegal values.  Any range outside of the CBaseEntity structure's private
   159  * size will cause undefined behaviour or even crash.
   160  */
   161  
   162 /**
   163  * Marks an entity as state changed.  This can be useful if you set an offset 
   164  * and wish for it to be immediately changed over the network.  By default this 
   165  * is not done for offset setting functions.  
   166  *
   167  * @param edict			Index to the edict.
   168  * @param offset		Offset to mark as changed.  If 0, 
   169  *						the entire edict is marked as changed.
   170  * @noreturn
   171  * @error				Invalid entity or offset out of bounds.
   172  */
   173 native ChangeEdictState(edict, offset = 0);
   174 
   175 /**
   176  * Peeks into an entity's object data and retrieves the integer value at 
   177  * the given offset.
   178  * 
   179  * @param entity		Edict index.
   180  * @param offset		Offset to use.
   181  * @param size			Number of bytes to read (valid values are 1, 2, or 4).
   182  * @return				Value at the given memory location.
   183  * @error				Invalid entity or offset out of reasonable bounds.
   184  */
   185 native GetEntData(entity, offset, size=4);
   186 
   187 /**
   188  * Peeks into an entity's object data and sets the integer value at 
   189  * the given offset.
   190  *
   191  * @param entity		Edict index.
   192  * @param offset		Offset to use.
   193  * @param size			Number of bytes to write (valid values are 1, 2, or 4).
   194  * @param changeState	If true, change will be sent over the network.
   195  * @return				Value at the given memory location.
   196  * @error				Invalid entity or offset out of reasonable bounds.
   197  * @noreturn
   198  */
   199 native SetEntData(entity, offset, value, size=4, bool:changeState=false);
   200 
   201 /**
   202  * Peeks into an entity's object data and retrieves the float value at 
   203  * the given offset.
   204  * 
   205  * @param entity		Edict index.
   206  * @param offset		Offset to use.
   207  * @return				Value at the given memory location.
   208  * @error				Invalid entity or offset out of reasonable bounds.
   209  */
   210 native Float:GetEntDataFloat(entity, offset);
   211 
   212 /**
   213  * Peeks into an entity's object data and sets the integer value at 
   214  * the given offset.
   215  *
   216  * @param entity		Edict index.
   217  * @param offset		Offset to use.
   218  * @param changeState	If true, change will be sent over the network.
   219  * @return				Value at the given memory location.
   220  * @error				Invalid entity or offset out of reasonable bounds.
   221  * @noreturn
   222  */
   223 native SetEntDataFloat(entity, offset, Float:value, bool:changeState=false);
   224 
   225 /**
   226  * Peeks into an entity's object data and retrieves the entity handle
   227  * info at the given offset.
   228  * 
   229  * @param entity		Edict index.
   230  * @param offset		Offset to use.
   231  * @return				Entity index at the given location, or 0 if none.
   232  * @error				Invalid entity or offset out of reasonable bounds.
   233  */
   234 native GetEntDataEnt(entity, offset);
   235 
   236 /**
   237  * Peeks into an entity's object data and sets the entity handle info
   238  * at the given offset.
   239  * 
   240  * @param entity		Edict index.
   241  * @param offset		Offset to use.
   242  * @param other			Entity index to set, or 0 to clear.
   243  * @param changeState	If true, change will be sent over the network.
   244  * @noreturn
   245  * @error				Invalid entity or offset out of reasonable bounds.
   246  */
   247 native SetEntDataEnt(entity, offset, other, bool:changeState=false);
   248 
   249 /**
   250  * Peeks into an entity's object data and retrieves the vector at the 
   251  * given offset.
   252  * @note Both a Vector and a QAngle are three floats.  This is a 
   253  * convenience function and will work with both types.
   254  * 
   255  * @param entity		Edict index.
   256  * @param offset		Offset to use.
   257  * @param vec			Vector buffer to store data in.
   258  * @noreturn
   259  * @error				Invalid entity or offset out of reasonable bounds.
   260  */
   261 native GetEntDataVector(entity, offset, Float:vec[3]);
   262 
   263 /**
   264  * Peeks into an entity's object data and sets the vector at the given 
   265  * offset.
   266  * @note Both a Vector and a QAngle are three floats.  This is a 
   267  * convenience function and will work with both types.
   268  * 
   269  * @param entity		Edict index.
   270  * @param offset		Offset to use.
   271  * @param vec			Vector to set.
   272  * @param changeState	If true, change will be sent over the network.
   273  * @noreturn
   274  * @error				Invalid entity or offset out of reasonable bounds.
   275  */
   276 native SetEntDataVector(entity, offset, const Float:vec[3], bool:changeState=false);
   277 
   278 /**
   279  * Peeks into an entity's object data and retrieves the string at 
   280  * the given offset.
   281  * 
   282  * @param entity		Edict index.
   283  * @param offset		Offset to use.
   284  * @param buffer		Destination string buffer.
   285  * @param maxlen		Maximum length of output string buffer.
   286  * @return			Number of non-null bytes written.
   287  * @error				Invalid entity or offset out of reasonable bounds.
   288  */
   289 native GetEntDataString(entity, offset, String:buffer[], maxlen);
   290 
   291 /**
   292  * Peeks into an entity's object data and sets the string at 
   293  * the given offset.
   294  * 
   295  * @param entity		Edict index.
   296  * @param offset		Offset to use.
   297  * @param buffer		String to set.
   298  * @param maxlen		Maximum length of bytes to write.
   299  * @param changeState	If true, change will be sent over the network.
   300  * @return			Number of non-null bytes written.
   301  * @error				Invalid entity or offset out of reasonable bounds.
   302  */
   303 native SetEntDataString(entity, offset, const String:buffer[], maxlen, bool:changeState=false);
   304 
   305 /**
   306  * @endsection
   307  */
   308 
   309 /**
   310  * Given a ServerClass name, finds a networkable send property offset.
   311  * This information is cached for future calls.
   312  *
   313  * @param cls			Classname.
   314  * @param prop			Property name.
   315  * @return				An offset, or -1 on failure.
   316  */
   317 native FindSendPropOffs(const String:cls[], const String:prop[]);
   318 
   319 /**
   320  * Given an entity, finds a datamap property offset.
   321  * This information is cached for future calls.
   322  *
   323  * @param entity		Entity index.
   324  * @param prop			Property name.
   325  * @return				An offset, or -1 on failure.
   326  */
   327 native FindDataMapOffs(entity, const String:prop[]);
   328 
   329 /**
   330  * Wrapper function for finding a send property for a particular entity.
   331  *
   332  * @param ent			Entity index.
   333  * @param prop			Property name.
   334  * @return				An offset, or -1 on failure.
   335  */
   336 stock GetEntSendPropOffs(ent, const String:prop[])
   337 {
   338 	decl String:cls[64];
   339 	
   340 	if (!GetEntityNetClass(ent, cls, sizeof(cls)))
   341 	{
   342 		return -1;
   343 	}
   344 	
   345 	return FindSendPropOffs(cls, prop);
   346 }
   347 
   348 /**
   349  * Gets a network property as an integer; wrapper around GetEntData().
   350  * 
   351  * @param entity		Edict index.
   352  * @param type			Property type.
   353  * @param prop			Property to use.
   354  * @param size			Number of bytes to read (valid values are 1, 2, or 4).
   355  * @return				Value at the given property offset.
   356  * @error				Invalid entity or property not found.
   357  */
   358 stock GetEntProp(entity, PropType:type, const String:prop[], size=4)
   359 {
   360 	new offs;
   361 
   362 	switch (type)
   363 	{
   364 		case Prop_Send:
   365 		{
   366 			offs = GetEntSendPropOffs(entity, prop);
   367 		}
   368 		case Prop_Data:
   369 		{
   370 			offs = FindDataMapOffs(entity, prop);
   371 		}
   372 		default:
   373 		{
   374 			ThrowError("Invalid Property type %d", type);
   375 		}
   376 	}
   377 
   378 	if (offs == -1)
   379 	{
   380 		ThrowError("Property \"%s\" not found for entity %d", prop, entity);
   381 	}
   382 
   383 	return GetEntData(entity, offs, size);
   384 }
   385 
   386 /**
   387  * Sets a network property as an integer; wrapper around GetEntData().
   388  *
   389  * @param entity		Edict index.
   390  * @param type			Property type.
   391  * @param prop			Property to use.
   392  * @param size			Number of bytes to write (valid values are 1, 2, or 4).
   393  * @error				Invalid entity or offset out of reasonable bounds.
   394  * @noreturn
   395  */
   396 stock SetEntProp(entity, PropType:type, const String:prop[], value, size=4)
   397 {
   398 	new offs;
   399 
   400 	switch (type)
   401 	{
   402 		case Prop_Send:
   403 		{
   404 			offs = GetEntSendPropOffs(entity, prop);
   405 		}
   406 		case Prop_Data:
   407 		{
   408 			offs = FindDataMapOffs(entity, prop);
   409 		}
   410 		default:
   411 		{
   412 			ThrowError("Invalid Property type %d", type);
   413 		}
   414 	}
   415 
   416 	if (offs == -1)
   417 	{
   418 		ThrowError("Property \"%s\" not found for entity %d", prop, entity);
   419 	}
   420 
   421 	return SetEntData(entity, offs, value, size, true);
   422 }
   423 
   424 /**
   425  * Gets a network property as a float; wrapper around GetEntDataFloat().
   426  * 
   427  * @param entity		Edict index.
   428  * @param type			Property type.
   429  * @param prop			Property to use.
   430  * @return				Value at the given property offset.
   431  * @error				Invalid entity or offset out of reasonable bounds.
   432  */
   433 stock Float:GetEntPropFloat(entity, PropType:type, const String:prop[])
   434 {
   435 	new offs;
   436 
   437 	switch (type)
   438 	{
   439 		case Prop_Send:
   440 		{
   441 			offs = GetEntSendPropOffs(entity, prop);
   442 		}
   443 		case Prop_Data:
   444 		{
   445 			offs = FindDataMapOffs(entity, prop);
   446 		}
   447 		default:
   448 		{
   449 			ThrowError("Invalid Property type %d", type);
   450 		}
   451 	}
   452 
   453 	if (offs == -1)
   454 	{
   455 		ThrowError("Property \"%s\" not found for entity %d", prop, entity);
   456 	}
   457 
   458 	return GetEntDataFloat(entity, offs);
   459 }
   460 
   461 /**
   462  * Sets a network property as a float; wrapper around SetEntDataFloat().
   463  * 
   464  * @param entity		Edict index.
   465  * @param type			Property type.
   466  * @param prop			Property to use.
   467  * @param value			Value to set.
   468  * @noreturn
   469  * @error				Invalid entity or offset out of reasonable bounds.
   470  */
   471 stock SetEntPropFloat(entity, PropType:type, const String:prop[], Float:value)
   472 {
   473 	new offs;
   474 
   475 	switch (type)
   476 	{
   477 		case Prop_Send:
   478 		{
   479 			offs = GetEntSendPropOffs(entity, prop);
   480 		}
   481 		case Prop_Data:
   482 		{
   483 			offs = FindDataMapOffs(entity, prop);
   484 		}
   485 		default:
   486 		{
   487 			ThrowError("Invalid Property type %d", type);
   488 		}
   489 	}
   490 
   491 	if (offs == -1)
   492 	{
   493 		ThrowError("Property \"%s\" not found for entity %d", prop, entity);
   494 	}
   495 
   496 	return SetEntDataFloat(entity, offs, value, true);
   497 }
   498 
   499 /**
   500  * Gets a network property as a handle entity; wrapper around GetEntDataEnt().
   501  * 
   502  * @param entity		Edict index.
   503  * @param type			Property type.
   504  * @param prop			Property to use.
   505  * @return				Entity index at the given property, or 0 if none.
   506  * @error				Invalid entity or offset out of reasonable bounds.
   507  */
   508 stock GetEntPropEnt(entity, PropType:type, const String:prop[])
   509 {
   510 	new offs;
   511 
   512 	switch (type)
   513 	{
   514 		case Prop_Send:
   515 		{
   516 			offs = GetEntSendPropOffs(entity, prop);
   517 		}
   518 		case Prop_Data:
   519 		{
   520 			offs = FindDataMapOffs(entity, prop);
   521 		}
   522 		default:
   523 		{
   524 			ThrowError("Invalid Property type %d", type);
   525 		}
   526 	}
   527 
   528 	if (offs == -1)
   529 	{
   530 		ThrowError("Property \"%s\" not found for entity %d", prop, entity);
   531 	}
   532 
   533 	return GetEntDataEnt(entity, offs);
   534 }
   535 
   536 /**
   537  * Sets a network property as a handle entity; wrapper around SetEntDataEnt().
   538  * 
   539  * @param entity		Edict index.
   540  * @param type			Property type.
   541  * @param prop			Property to use.
   542  * @param other			Entity index to set, or 0 to unset.
   543  * @noreturn
   544  * @error				Invalid entity or offset out of reasonable bounds.
   545  */
   546 stock SetEntPropEnt(entity, PropType:type, const String:prop[], other)
   547 {
   548 	new offs;
   549 
   550 	switch (type)
   551 	{
   552 		case Prop_Send:
   553 		{
   554 			offs = GetEntSendPropOffs(entity, prop);
   555 		}
   556 		case Prop_Data:
   557 		{
   558 			offs = FindDataMapOffs(entity, prop);
   559 		}
   560 		default:
   561 		{
   562 			ThrowError("Invalid Property type %d", type);
   563 		}
   564 	}
   565 
   566 	if (offs == -1)
   567 	{
   568 		ThrowError("Property \"%s\" not found for entity %d", prop, entity);
   569 	}
   570 
   571 	return SetEntDataEnt(entity, offs, other, true);
   572 }
   573 
   574 /**
   575  * Gets a network property as a vector; wrapper around GetEntDataVector().
   576  * @note Both a Vector and a QAngle are three floats.  This is a 
   577  * convenience function and will work with both types.
   578  * 
   579  * @param entity		Edict index.
   580  * @param type			Property type.
   581  * @param prop			Property to use.
   582  * @param vec			Vector buffer to store data in.
   583  * @noreturn
   584  * @error				Invalid entity or offset out of reasonable bounds.
   585  */
   586 stock GetEntPropVector(entity, PropType:type, const String:prop[], Float:vec[3])
   587 {
   588 	new offs;
   589 
   590 	switch (type)
   591 	{
   592 		case Prop_Send:
   593 		{
   594 			offs = GetEntSendPropOffs(entity, prop);
   595 		}
   596 		case Prop_Data:
   597 		{
   598 			offs = FindDataMapOffs(entity, prop);
   599 		}
   600 		default:
   601 		{
   602 			ThrowError("Invalid Property type %d", type);
   603 		}
   604 	}
   605 
   606 	if (offs == -1)
   607 	{
   608 		ThrowError("Property \"%s\" not found for entity %d", prop, entity);
   609 	}
   610 
   611 	return GetEntDataVector(entity, offs, vec);
   612 }
   613 
   614 /**
   615  * Sets a network property as a vector; wrapper around SetEntDataVector().
   616  * @note Both a Vector and a QAngle are three floats.  This is a 
   617  * convenience function and will work with both types.
   618  * 
   619  * @param entity		Edict index.
   620  * @param type			Property type.
   621  * @param prop			Property to use.
   622  * @param vec			Vector to set.
   623  * @noreturn
   624  * @error				Invalid entity or offset out of reasonable bounds.
   625  */
   626 stock SetEntPropVector(entity, PropType:type, const String:prop[], const Float:vec[3])
   627 {
   628 	new offs;
   629 
   630 	switch (type)
   631 	{
   632 		case Prop_Send:
   633 		{
   634 			offs = GetEntSendPropOffs(entity, prop);
   635 		}
   636 		case Prop_Data:
   637 		{
   638 			offs = FindDataMapOffs(entity, prop);
   639 		}
   640 		default:
   641 		{
   642 			ThrowError("Invalid Property type %d", type);
   643 		}
   644 	}
   645 
   646 	if (offs == -1)
   647 	{
   648 		ThrowError("Property \"%s\" not found for entity %d", prop, entity);
   649 	}
   650 
   651 	return SetEntDataVector(entity, offs, vec, true);
   652 }
   653 
   654 /**
   655  * Gets a network property as a string.
   656  * 
   657  * @param entity		Edict index.
   658  * @param type			Property type.
   659  * @param prop			Property to use.
   660  * @param buffer		Destination string buffer.
   661  * @param maxlen		Maximum length of output string buffer.		
   662  * @return				Number of non-null bytes written.
   663  * @error				Invalid entity, offset out of reasonable bounds, or property is not a valid string.
   664  */
   665 native GetEntPropString(entity, PropType:type, const String:prop[], String:buffer[], maxlen);
   666 
   667 /**
   668  * Sets a network property as a string.
   669  * 
   670  * @param entity		Edict index.
   671  * @param type			Property type.
   672  * @param prop			Property to use.
   673  * @param buffer		String to set.		
   674  * @return				Number of non-null bytes written.
   675  * @error				Invalid entity, offset out of reasonable bounds, or property is not a valid string.
   676  */
   677 native SetEntPropString(entity, PropType:type, const String:prop[], const String:buffer[]);
   678 
   679 /**
   680  * Copies an array of cells from an entity at a given offset.
   681  *
   682  * @param entity		Entity index.
   683  * @param offset		Offset to use.
   684  * @param array			Array to read into.
   685  * @param arraySize		Number of values to read.
   686  * @param dataSize		Size of each value in bytes (1, 2, or 4).
   687  * @noreturn
   688  * @error				Invalid entity or offset out of reasonable bounds.
   689  */
   690 stock GetEntDataArray(entity, offset, array[], arraySize, dataSize=4)
   691 {
   692 	for (new i=0; i<arraySize; i++)
   693 	{
   694 		array[i] = GetEntData(entity, offset, dataSize)
   695 		offset += dataSize;
   696 	}
   697 }
   698 
   699 
   700 /**
   701  * Copies an array of cells to an entity at a given offset.
   702  *
   703  * @param entity		Entity index.
   704  * @param offset		Offset to use.
   705  * @param array			Array of values to copy.
   706  * @param arraySize		Number of values to copy.
   707  * @param dataSize		Size of each value in bytes (1, 2, or 4).
   708  * @param changeState	True to set the network state as changed; false otherwise.
   709  * @noreturn
   710  * @error				Invalid entity or offset out of reasonable bounds.
   711  */
   712 stock SetEntDataArray(entity, offset, value, const array[], arraySize, dataSize=4, bool:changeState=false)
   713 {
   714 	for (new i=0; i<arraySize; i++)
   715 	{
   716 		SetEntData(entity, real_offset, array[i], dataSize, changeState);
   717 		offset += dataSize;
   718 	}
   719 }