EntityExists()?

Blitz3D Forums/Blitz3D Programming/EntityExists()?

mrtricks(Posted 2004) [#1]
Is there a command that you can call to find out if an entity (or mesh) exists, and that you haven't Freed it?


fredborg(Posted 2004) [#2]
I think EntityClass() might work...

Edit: Nah, forget it, that didn't work


PsychicParrot(Posted 2004) [#3]
Can you check if it's either void or 0? I think you may be able to. I don't think there is an entityexists as such, though :(


jhocking(Posted 2004) [#4]
A couple weeks ago I was asking about the same thing. I/we concluded nothing like this exists in the commands, and a lot of people told me I'm a bad programmer for writing routines in which it is possible for my functions to attempt to do something with an entity which no longer exists. Frankly though I think this would be a very useful command. No matter how careful you are, in a large program you can never be 100% sure, so basic error trapping with an EntityExists command is vital.

What I couldn't understand is that people think checking if a load was successful before using loaded data makes sense, but these same people think checking if an entity exists before using it is lazy. The way I see it, if it'll crash your program then it's something to check for.

Psychicparrot: That only helps for a specific handle. You can check if a specific handle has been set to zero (since handles are just integer variables,) but you can't check if the entity a handle points to actually exists.


PsychicParrot(Posted 2004) [#5]
Yes, I see what you mean. If you use freeentity, though, the handle should go to 0 shouldn't it?


jhocking(Posted 2004) [#6]
No. Again, handles are just integer variables, not some special entity-related data structure. Not only does that mean FreeEntity has no way of knowing about the handles, you can make as many handles as you want. You can (and should) set handles for an entity to 0 when you free an entity, but that can be a non-trivial task for complex code if there are multiple handles in various places, like fields of various type objects. In many cases you cannot really be 100% sure you've zeroed all handles pointing to a given entity.


PsychicParrot(Posted 2004) [#7]
hmmm. Pity, that! Shockwave has an Entityexist command and (even though some might say it's bad programming!) it really IS a useful command to have.

I guess the only way to do this would be to build functions that took over the role of the loadentity and freeentity commands, so instead of using those you call the functions which update info stored in types .. messy!


Ken Lynch(Posted 2004) [#8]
This has been asked for time and time again. I came across the need for it several times, including when writing a homing missile system. There may be several missiles following one enemy, but when the enemy is destroyed the other missiles needed to know. The best way I've found round the lack of this command is to encapsulate all entities into type structures, this way you can delete the type and all references to that type now end up as NULL.


*(Posted 2004) [#9]
The way I got around this one was to have a entitytype which had ID$ and the entity itself then when the entity was freed I deleted the ID and the type entry. This means any call to EntityExist( ID$ ) would search the type and if it doesnt exist I just return false else I return true =). The only trouble is there is a small overhead on the copying of entities.


Techlord(Posted 2004) [#10]
IMHO an EntityExist Command is not needed.
Function EntityFree(entity%)
	FreeEntity entity%
End Function ;Returns 0 by default

;Use
myentity=EntityFree(myentity)

If myentity 
	EntityExist=True
Else
	EntityExist=False
EndIf



jhocking(Posted 2004) [#11]
That's bass ackwards. If you can't figure out which handles point to an entity when freeing it, how can you figure out which entity the handle points to for checking if it exists? That is, how can you tell which myentity variable to check?

Imagine a situation like your average simulation game (RTS, whatever.) A potentially limitless number of entities can be created at any time, and any of those enitities can be destroyed at any time. Now imagine coding some AI where multiple entities decide to attack one other entity. When that other entity is destroyed, it is non-trivial to convey that fact back to the attacking entities (so that they stop checking the position of the target, for example) in the open ended situation of an RTS game.

The little trick you described would work well if you had a strictly limited number of entities, all created from the beginning of the game, but then the trick would be useless in that situation.

ADDITION: Wait, re-reading your post I don't think you understand the problem. If there is only one handle to an entity that's easy to deal with. Then it is pretty obvious what handle points to that entity since there is only one handle. Your trick is needlessly obfuscating the code; just make the next line after freeing the entity myentity=0 and don't bother with a special entity free function. The problem is if multiple handles exist to a single entity. This situation is especially problematic if the handles are buried in the fields of multiple type objects. In that situation it is really difficult (impossible basically) to know all the handles which point to a given entity and set them all to 0.


@Ken and edzup: Could you post some code demonstrating what you are talking about? That sounds pretty useful but I'm not exactly understanding what you described.

Wait, I think I get it. Instead of making additional handles pointing to an entity, you make handles to a type object which has, as one of its fields, the handle to the entity. Then when you need to access that entity you do so by accessing the type object first, and then the field of the type object. Thus only one direct handle to the entity exists. Hm, this would work very well actually. Do you understand the trick they suggested, mrtricks? Because this should solve the problem.


MadJack(Posted 2004) [#12]
My own experience with this is that if your code is correct (i.e. pointer/s to a deleted object are cleared on object deletion), then it souldn't be a problem.

Practically though, I have a lot of objects checking/referencing each other per updateworld and I'm only a so-so coder and so I've taken to hiding deleted objects and then freeing them in the next updateworld.

So ok, you can point out how wrong I am now to do this..


big10p(Posted 2004) [#13]
I've not yet updated to the latest versio of B3D but was under the impression (for some reason) that an EntityExists() function had been added. I'm obviously mistaken. Booo! C'mon, lets have it. Trying to keep track of multiple handles to the same ent etc. is an unwelcome extra headache for the programmer, IMO.


Techlord(Posted 2004) [#14]
The reason why one would need such a command, is because there is no other form of recordkeeping implemented in the beginning of the app. There is truly no such thing as infinite objects as they are limited by the amount of physical memory your hardware possesses.

The code above works, give it a try. I could only imagine how bloated Blitz3D would be, if a command was in added for every scenerio. This is something a Blitz programmer can control.


Robert(Posted 2004) [#15]
Aside from that, how could an entity exist command be written?

Assuming that an entity handle is a pointer to an area of memory, how could Blitz know if that was a valid memory address short of keeping and searching through a list of all handles, which would be expanded each time an entity was created and edited each time an entry was removed. IMO this would be quite slow.


big10p(Posted 2004) [#16]
A couple of solutions spring to mind (well, OK, I had to think about it for a bit :) ...

1) Use multiple indirection: When Blitz creates an entity, create an internal pointer to that entity and return the address of this pointer as the entity's handle (i.e. the handle will be a-pointer-to-a-pointer-to-an-entity). Then, when an entity is freed, set the internal pointer to NULL.

An EntityExists(handle) function would then only have to check to see if the handle points to a NULL pointer in order to see if the entity exists or not.

This mechanism would work even if your prog had multiple handles to the same entity.

Downsides: the internal pointer (4 bytes) would have to remain in mem for the duration of the prog. Accessing entities through their handles would have a slight overhead due to the multiple indirection. Then again, I think Blitz already does this: I'm pretty sure Blitz entity handles aren't direct pointers to the actual entity's data. I could be wrong.


2) Store unique entity IDs in a binary tree (or some-such suitable structure): So, each time an entity is created, we get a pointer to it which, when converted to an integer, represents a unique entity ID. Next, add this ID to the tree and in it's node have the pointer to the entity. Again, return the address of this pointer as the entity handle.

An EntityExists(handle) function would then have to dereference the handle (to get the pointer to the actual entity), convert it to an ID integer, and then search the tree for it. If it's in the tree then the entity exists, otherwise it doesn't. This should be quicker than it sounds!

When an entity is freed, it's tree node can be deleted which will also mean the 4 bytes used as the entity's internal pointer is freed also, unlike the first method, above.

Hope some of that made sense! :)

[EDIT] I guess I should have made it clear that the solutions I offer above are not for implementation in Blitz code, but rather how I figure it would be possible for Mark to implement a native EntityExists() function. Not that I know jack about the internal workings of B3D, of course. :P


ChrML(Posted 2004) [#17]
Argh, this isn't hard. When you create a camera, you create it the normal way:

mesh = LoadMesh("mesh.3ds")


When you free it, you first free it, and then set it's value to 0:

FreeEntity mesh
mesh = 0


Then when you want to check if it exists, just do:

if mesh<>0 then
;code if mesh exists
else
;code if mesh NOT exists
endif


The variable mesh after loading the model is really just a 32 bit integer telling the position of the model in the memory. It's nothing more. So, just free it, and set the pointer value back to 0, so you can check if it exists later. Just make sure that you DON'T first set it to 0, and then free it, because that will cause it to try freeing a model at memory offset 0, which doesn't exists; Memory Access Violation. And don't just set it to 0 without freeing it first, cuz then it will never be unloaded, and then cause memoryleak (memory that gets used, but not freed) until the blitz appliaction closes. Also, an another common mistake is this:

mesh = LoadMesh("somemesh.3ds")
mesh = LoadMesh("anothermesh.3ds")

This will load a mesh into the memory, and put the pointer for using/freeing later into 'mesh', but then it loads an another model into the memory, and puts the pointer too into 'mesh'. That will make you loose the first pointer; you will not be able to free the first one again; memoryleak.


ChrML(Posted 2004) [#18]
Woops, bug in the first line :P. I meant:

When you load a mesh, you load it in the normal way:


jhocking(Posted 2004) [#19]
ChrML, thanks for trying to help, but you're not understanding the problem. We can't set the handle to 0 (or at least we aren't sure the handle has been set to 0) because we don't know where all the handles are. There are multiple handles to the entity, an unknown number created as fields of type objects, not just one clearly known handle. Setting one clearly known handle to 0 is easy, setting an unknown number of multiple handles in unknown type objects to 0 is difficult.

At any rate, other peoples' suggestions work. In particular, Ken and edzup's suggestion regarding referencing type ID's instead of entity handles works well.


ChrML(Posted 2004) [#20]
Well, I use the same system for multiple types. If there are multiple handles, and you want to free them all, then just:

For tmp.mytype = each mytype
if tmp.mytype<>0 then
FreeEntity tmp.mytype
tmp.mytype = 0
endif
Next


For my weapon system I have huge number of types both for the declarations loaded from a .mis file, types for the weapons placed in the world, and types for the weapon in your inventory. Many types refer to eachother with my id system. Like:

Weapon gets loaded into the declaration system, with the id 'ingram' for example. Then my PlaceWeapon command in my custom script system places it in the world, with the parameter 'ingram' then. Which means, when you pick the weapon, it checks the master record telling accuracy, firerate, type of gun etc..., and loads the info from there. Then when you pick it, the weapon in the inventory type also gets the same id as the master record has to get more info when it shoots.

Here's an example on how you can solve this:

Type Models
  Field id$,filename$,model
End Type


Function LoadModel(filename$,id$)
  For tmp.Models = each Models
    if tmp.Models\id$ = id$ then
      RuntimeError "Two models can't have same ID!"
    endif
  Next

  tmp.Models = New Models
  tmp.Models\id$ = id$
  tmp.Models\filename$ = filename$ ;store it just incase
  tmp.Models\model = LoadModel(filename$)

  if tmp.Models\model<>0 then
    RuntimeError "Error loading "+filename$+"! Illegal filename?"
  endif
End Function


Function KillModel(id$)
  For tmp.Models = Each Models
    if tmp.Models\id$ = id$ then
      FreeEntity tmp.Models\model
      Delete tmp.Models   ;no need to put it back to 0 here, cuz we delete the type entry
    endif
  Next
End Function


Then we just make similar functions for moving them, etc... This is just an example though! :) Handling multiple pointers with unknown number of types is never difficult. Just make sure you think of all bugs before you test :P.