Item Deletion Causes Crash
by Jay Barnson · in Torque Game Engine · 10/06/2005 (12:06 am) · 19 replies
I found a couple of threads dealing with this problem, but none had a resolution that work for me.
I'm trying to delete an item. I'm trying to be nice and deleting it via the scheduler - even fading it out nicely for now so I can see it dissapear.
Sometime after it dissapears, I get a crash on this line in netGhost.cc, in the NetConnection::ghostReadPacket method.
Obviously, this doesn't happen if the item is created in TorqueScript with the static=true flag.
I haven't modified the Item code (except to add some debugging help after this thing reared its head). Anyone got any ideas? Am I creating my items incorrectly somehow?
(Note - deleting players works just fine - it's only items where I'm having a problem).
I'm trying to delete an item. I'm trying to be nice and deleting it via the scheduler - even fading it out nicely for now so I can see it dissapear.
Sometime after it dissapears, I get a crash on this line in netGhost.cc, in the NetConnection::ghostReadPacket method.
Unhandled exception at 0x006bf0f5 in Appalachia_DEBUG.exe: 0xC0000005: Access violation reading location 0x0000004c --->mLocalGhosts[index]->unpackUpdate(this, bstream);What looks to be happening (AFAICT) is that this ghost object doesn't exist anymore - the server object pointer is set to 0xcececece, the name is NULL, etc. The pointer at mLocalGhosts[index] is not null - it looks like it's pointing to memory that was being used for something once upon a time.
Obviously, this doesn't happen if the item is created in TorqueScript with the static=true flag.
I haven't modified the Item code (except to add some debugging help after this thing reared its head). Anyone got any ideas? Am I creating my items incorrectly somehow?
(Note - deleting players works just fine - it's only items where I'm having a problem).
About the author
Jay has been a mainstream and indie game developer for a... uh, long time. His professional start came in 1994 developing titles for the then-unknown and upcoming Sony Playstation. He runs Rampant Games and blogs at Tales of the Rampant Coyote.
#2
10/06/2005 (10:09 am)
It's pretty straightforward:function CreateItem(%spawnPoint, %itemID)
{
%dataBlockType = GetItemDataBlockByMasterID(%itemID);
%itemName = GetItemNameByMasterID(%itemID);
%itemPortrait = GetItemPortraitByMasterID(%itemID);
echo("Creating item "@ %itemName @" of ID "@%itemID@" and datablock "@ %dataBlockType);
%item = new Item(%dataBlockType.pickupName)
{
datablock = %dataBlockType;
};
%item.setTransform(%spawnPoint);
%item.itemID = %itemID;
%item.name = %itemName;
MissionCleanup::add(%item);
return %item;
}
#3
The only thing that looks strange is %item = new Item(%dataBlockType.pickupName)
I'm not sure if that would be causing the problem but, what is it in there for?
Try removing it and see what happens.
Just saw this
MissionCleanup::add(%item);
should be
MissionCleanup.add(%item);
10/06/2005 (12:36 pm)
%item = new Item(%dataBlockType.pickupName)
{
datablock = %dataBlockType;
};The only thing that looks strange is %item = new Item(%dataBlockType.pickupName)
I'm not sure if that would be causing the problem but, what is it in there for?
Try removing it and see what happens.
Just saw this
MissionCleanup::add(%item);
should be
MissionCleanup.add(%item);
#4
I did add (for the sake of monitoring stuff) the commands:
static = false;
rotate=true;
inside the datablock last night. Naturally, changing static to true fixed things - but this is an RPG, so items laying around can't be static :(
For the sake of completeness, here's how I delete the objects (after they have been picked up):
I have also tried the direct approach with a simple call to %obj.delete(), omitted the fade-out, and mucked around with the timing on scheduling the delete (from 0, to 1+ the time delay on the fade when I have the fade-out enabled.
10/06/2005 (1:47 pm)
No change :(I did add (for the sake of monitoring stuff) the commands:
static = false;
rotate=true;
inside the datablock last night. Naturally, changing static to true fixed things - but this is an RPG, so items laying around can't be static :(
For the sake of completeness, here's how I delete the objects (after they have been picked up):
%obj.schedule(0, "startFade", 500, 0, true); %obj.schedule(500,delete);
I have also tried the direct approach with a simple call to %obj.delete(), omitted the fade-out, and mucked around with the timing on scheduling the delete (from 0, to 1+ the time delay on the fade when I have the fade-out enabled.
#6
10/06/2005 (1:53 pm)
Nope. I doubted it would - I'm not yet leaving the initial mission. I have also commented it out entirely "jussincase."
#7
10/06/2005 (1:57 pm)
Edit I see you have duh me :)
#8
10/06/2005 (2:07 pm)
Sorry - I went and edited my post too fast. :)
#9
10/06/2005 (2:07 pm)
This may be a dumb question but hey :) are you sure your deleting the item and not deleting yourself or something else that would cause a crash? Do an echo and a dump() on %obj and comment out the deletion. I'm off to work so if you don't figure it out I will try helping out again tomorrow.
#10
%item = new Item(%dataBlockType.pickupName)
{
datablock = %dataBlockType;
};
MissionCleanup.add(%item);
%item.setTransform(%spawnPoint);
%item.itemID = %itemID;
%item.name = %itemName;
return %item;
}
I don't know if that makes a difference. Other than that your links to the functions
GetItemDataBlockByMasterID
and the other ones could be causing it if there was something wrong with those. Other than that it looks pretty clean.
10/06/2005 (3:45 pm)
Ussualy mission cleanup is directly after the new item datablock your code would look like this%item = new Item(%dataBlockType.pickupName)
{
datablock = %dataBlockType;
};
MissionCleanup.add(%item);
%item.setTransform(%spawnPoint);
%item.itemID = %itemID;
%item.name = %itemName;
return %item;
}
I don't know if that makes a difference. Other than that your links to the functions
GetItemDataBlockByMasterID
and the other ones could be causing it if there was something wrong with those. Other than that it looks pretty clean.
#11
@Master Treb: The datablock seems fine - it actually called it directly before I moved items out to a master list. The object wouldn't appear if I'd messed that one up. But I will take a closer look at the datablock just in case. It's pretty much duplicated from the health pick-up (albeit with a new model) in the FPS starter kit.
10/06/2005 (7:35 pm)
@Michael: Yep, the object itself is fading and then dissapearing, and then the game crashes about a second later in that spot. It looks like the code is then trying to update the ghost after the ghost has been dropped from the client. Something like that. I don't understand the logic flow well yet.@Master Treb: The datablock seems fine - it actually called it directly before I moved items out to a master list. The object wouldn't appear if I'd messed that one up. But I will take a closer look at the datablock just in case. It's pretty much duplicated from the health pick-up (albeit with a new model) in the FPS starter kit.
#12
10/06/2005 (8:11 pm)
Well when nothing is working I back up all the files that might be causing it and then start deleting chunks until it starts working. for example in this line of code you might comment out the first 4 lines and replace the variables the assigned with numbers run it and see if it works if it doesn't comment more out and run it again etc... etc...
#13
and remove the scheduled reapearance.
I have to say i'm pretty stumped to why you are crashing.
10/07/2005 (6:00 am)
Jay can I ask what your trying to achieve as an overall outcome to what your doing? If you don't need respawnable items elsewhere in your game you could make it static and modifyfunction Item::respawn(%this)
and remove the scheduled reapearance.
I have to say i'm pretty stumped to why you are crashing.
#14
I'm doing an RPG, with players capable of picking up items and dropping them in the environment again. Though that latter part is still a little up in the air - I'm trying to keep the gameplay pretty simple, and if there's no restrictions to quantity of items in the inventory, do you REALLY ever want to drop something? Only if it's part of the game (put item X here to activate Y).
Yeah, I'm stumped too. Assuming I have time this weekend I may try and trace the logic for the lifespan of a ghost.
10/07/2005 (7:58 am)
Yeah, I'm actually thinking of making a pool of Items that never get deleted as a work-around for this problem (actually did that last night)- but that's a little kludgy. I'm doing an RPG, with players capable of picking up items and dropping them in the environment again. Though that latter part is still a little up in the air - I'm trying to keep the gameplay pretty simple, and if there's no restrictions to quantity of items in the inventory, do you REALLY ever want to drop something? Only if it's part of the game (put item X here to activate Y).
Yeah, I'm stumped too. Assuming I have time this weekend I may try and trace the logic for the lifespan of a ghost.
#15
It sounds as if you are bypassing the safe referencing concept that SimObject provides somehow, but without seeing your examples it is difficult to point out exactly where.
10/07/2005 (9:12 am)
Can you show your code for how you are deleting the item, and also show any functions that reference the item directly, and/or store variables related to the item itself?It sounds as if you are bypassing the safe referencing concept that SimObject provides somehow, but without seeing your examples it is difficult to point out exactly where.
#16
Then in my command handler on the server:
I have no TorqueScript functions dealing with objects outside creation and 'pickup'.
I do have some weirdness that could be throwing a wrench in the works by using the guiRTSTSCtrl as my main UI. I added items to the raycasting hit-detection for the mouse, and so there could be some bits that are just not working there with items under the mouse cursor. My version of guiRTSTSCtrl has been hacked up a bit, naturally - I am really not using much of its RTS functionality (now), but I was using it's mouse select (also available in the EditTSCtrl), and some of the selection / drawing code. So I was concerned about the potential of a stale object underneath the cursor or in the selection list.
I have some code in place to deal with deleting an item from the selection list and the cursor "hit" object, but it's not being called.
Any ideas?
10/07/2005 (2:12 pm)
In my control handler on the client, I have a function that reads the mouse-down:echo("Clicking on "@%obj.getClassname());
switch$(%obj.getClassName())
{
.
.
.
case "Item":
echo("Picking up item "@%obj);
commandToServer('PlayerPickupItem',%obj);
}Then in my command handler on the server:
function serverCmdPlayerPickupItem(%client, %obj)
{
%obj.schedule(0, "startFade", 500, 0, true);
%obj.schedule(501,delete);
}I have no TorqueScript functions dealing with objects outside creation and 'pickup'.
I do have some weirdness that could be throwing a wrench in the works by using the guiRTSTSCtrl as my main UI. I added items to the raycasting hit-detection for the mouse, and so there could be some bits that are just not working there with items under the mouse cursor. My version of guiRTSTSCtrl has been hacked up a bit, naturally - I am really not using much of its RTS functionality (now), but I was using it's mouse select (also available in the EditTSCtrl), and some of the selection / drawing code. So I was concerned about the potential of a stale object underneath the cursor or in the selection list.
I have some code in place to deal with deleting an item from the selection list and the cursor "hit" object, but it's not being called.
Any ideas?
#17
It looks like the command handler on the server (this IS running on a single system) is somehow calling the delete directly on the client object. So only the client object is getting deleted (I think) - I'm kinda confused as to why / how this is happening, or if I'm simply observing the wrong thing.
So when I'm making the call
If this is the behavior of sending an obj (I thought it was a common index number) to the server, that would really break multiplayer, too. Unless I can figure out some other way of fixing this issue, I guess I can try and de-reference it another way. Guess I did that thing that happens when you assume something.
Any suggestions?
10/09/2005 (8:20 pm)
Okay - somewhat bizarre possibility here...It looks like the command handler on the server (this IS running on a single system) is somehow calling the delete directly on the client object. So only the client object is getting deleted (I think) - I'm kinda confused as to why / how this is happening, or if I'm simply observing the wrong thing.
So when I'm making the call
commandToServer('PlayerPickupItem',%obj);What's getting picked up on the server side is the actual client object (?? !! ??)If this is the behavior of sending an obj (I thought it was a common index number) to the server, that would really break multiplayer, too. Unless I can figure out some other way of fixing this issue, I guess I can try and de-reference it another way. Guess I did that thing that happens when you assume something.
Any suggestions?
#18
Whenever the client is referencing an object, it is using it's own unique ghostID for that object. Since you are passing that ghostID via the commandToServer, the server must use the ghostID dereferencing system built into Torque's networking model to get the authoritative simID of the object in question (See the TDN article on Torque Ghosting for a detailed explanation) so that you can reference it properly.
Short answer: change your server code to this:
Other examples for research/reference would be the many "Issue" commands (IssueAttack, IssueMove, etc.) in the RTS-SK server side scripting.
10/10/2005 (6:38 am)
Not a bizarre possibility at all..in fact, you nailed it!Whenever the client is referencing an object, it is using it's own unique ghostID for that object. Since you are passing that ghostID via the commandToServer, the server must use the ghostID dereferencing system built into Torque's networking model to get the authoritative simID of the object in question (See the TDN article on Torque Ghosting for a detailed explanation) so that you can reference it properly.
Short answer: change your server code to this:
function serverCmdPlayerPickupItem(%client, %obj)
{
%serverObjID = %client.resolveObjectFromGhostIndex(%obj);
%serverObjID.schedule(0, "startFade", 500, 0, true);
%serverObjID.schedule(501,delete);
}Other examples for research/reference would be the many "Issue" commands (IssueAttack, IssueMove, etc.) in the RTS-SK server side scripting.
#19
It's all working beautifully now - I'm a happy camper. Thanks!
10/10/2005 (8:29 am)
Heh - I was looking through the RTS-SK stuff last night for the issue commands also, but it was getting too late and I was falling asleep.It's all working beautifully now - I'm a happy camper. Thanks!
Torque 3D Owner Michael Cozzolino
Big Monk Games
Lets see how your doing it. We are creating items for grenades so maybe I could see if something looks out of wack.