Game Development Community

Problem creating my own datablock...

by Felix999 · in Technical Issues · 08/28/2008 (4:59 pm) · 15 replies

Hi,
i'm trying to create a datablock that will store information on the player's inventory for a single player game.
i created the following files in engine/game:

inventory.h
////code start
#include "game/gameBase.h"


struct InventoryData: public GameBaseData 
{
   typedef GameBaseData Parent;
   
   bool fireBall1;
   bool fireBall2;
   bool fireBall3;
   bool ice1;
   F32 mpCrystal;

   DECLARE_CONOBJECT(InventoryData);
   InventoryData();
   static void initPersistFields();
   virtual void packData(BitStream* stream);
   virtual void unpackData(BitStream* stream);
};


class Inventory: public GameBase  
{
   typedef GameBase Parent;

   DECLARE_CONOBJECT(Inventory);
   Inventory();
   ~Inventory();
};

#endif
///code end

-----------------------------------------------------------------------------------------------

inventory.cc
///code start

#include "game/inventory.h"


IMPLEMENT_CO_NETOBJECT_V1(InventoryData);

InventoryData::InventoryData()
{
   fireBall1 = false;
   fireBall2 = false;
   fireBall3 = false;
   ice1 = false;
   mpCrystal = 0;
};


void InventoryData::initPersistFields()
{
   Parent::initPersistFields();
   
   addField("fireBall1",  TypeBool, Offset(fireBall1,         InventoryData));
   addField("fireBall2",  TypeBool, Offset(fireBall2,         InventoryData));
   addField("fireBall3",  TypeBool, Offset(fireBall3,         InventoryData));
   addField("ice1",  TypeBool, Offset(ice1,         InventoryData));
   addField("mpCrystal",  TypeF32, Offset(mpCrystal,         InventoryData));
}

void InventoryData::packData(BitStream* stream)
{
   Parent::packData(stream);

   stream->write(fireBall1);
   stream->write(fireBall2);
   stream->write(fireBall3);
   stream->write(ice1);
   stream->write(mpCrystal);
}

void InventoryData::unpackData(BitStream* stream)
{
   Parent::unpackData(stream);

   stream->read(&fireBall1);
   stream->read(&fireBall2);
   stream->read(&fireBall3);
   stream->read(&ice1);
   stream->read(&mpCrystal);
}


IMPLEMENT_CO_NETOBJECT_V1(Inventory);

Inventory::Inventory()
{
}

Inventory::~Inventory()
{
}

///code end
-----------------------------------------------------------------------------------------------

i created the following file in server/scripts:

inventory.cs
//code start
datablock InventoryData(Inv)
{
   mpCrystal = 2;
};

///code end
-----------------------------------------------------------------------------------------------

i added inventory.cc to the targets.torque.mk file at the end of the SOURCE.GAME section, making sure the tabs were the same as the other entries.


when i run the game i get the following error in the console:

unable to instantiate non-conobject class InventoryData

-----------------------------------------------------------------------------------------------

i'm pretty new to torque and not the best c++ programmer ever, which is probably the reason why this is driving me bonkers.
if anyone can tell me where i've fugged up i'd be really grateful.
thanks.

#1
08/28/2008 (5:20 pm)
Try changing
IMPLEMENT_CO_NETOBJECT_V1(InventoryData);
to
IMPLEMENT_CO_DATABLOCK_V1(InventoryData);
IMPLEMENT_CO_NETOBJECT_V1(Inventory);
When in doubt, study other files :-)

Also, you should use {code} and {/code} tags (with square brackets instead of braces) to make your code blocks easier to read. I also saw you didn't add some sort of compile-guard. Look at the other .h files, they all have some sort of
#ifndef _PLAYER_H_
#define _PLAYER_H_
At the very top of the file to keep it from being included multiple times, and end the .h with an #endif. There's also #pragma once, but I don't even know if that will work with TGE, I just learned about it a little while ago.
#2
08/29/2008 (10:18 am)
Hi Morrock,
thanks for taking the time to respond.
i added the things you suggested and compared my files to some other .cc and .h files but i still get the same error in the console.

my inventory.h file now looks like this...

#ifndef _INVENTORY_H_
#define _INVENTORY_H_

#ifndef _GAMEBASE_H_
#include "game/gameBase.h"
#endif


struct InventoryData: public GameBaseData 
{
   typedef GameBaseData Parent;
   
   bool fireBall1;
   bool fireBall2;
   bool fireBall3;
   bool ice1;
   F32 mpCrystal;
   
   DECLARE_CONOBJECT(InventoryData);
   InventoryData();
   static void initPersistFields();
   virtual void packData(BitStream* stream);
   virtual void unpackData(BitStream* stream);
};


class Inventory: public GameBase  
{
   typedef GameBase Parent;
 
   DECLARE_CONOBJECT(Inventory);
   Inventory();
   ~Inventory();

};

#endif


my inventory.cc file now looks like this...

#include "game/inventory.h"

IMPLEMENT_CO_DATABLOCK_V1(InventoryData);
IMPLEMENT_CO_NETOBJECT_V1(Inventory);

InventoryData::InventoryData()
{
   fireBall1 = false;
   fireBall2 = false;
   fireBall3 = false;
   ice1 = false;
   mpCrystal = 0;
}


void InventoryData::initPersistFields()
{
   Parent::initPersistFields();
   
   addField("fireBall1",  TypeBool, Offset(fireBall1,         InventoryData));
   addField("fireBall2",  TypeBool, Offset(fireBall2,         InventoryData));
   addField("fireBall3",  TypeBool, Offset(fireBall3,         InventoryData));
   addField("ice1",  TypeBool, Offset(ice1,         InventoryData));
   addField("mpCrystal",  TypeF32, Offset(mpCrystal,         InventoryData));
}

void InventoryData::packData(BitStream* stream)
{
   Parent::packData(stream);

   stream->write(fireBall1);
   stream->write(fireBall2);
   stream->write(fireBall3);
   stream->write(ice1);
   stream->write(mpCrystal);
}

void InventoryData::unpackData(BitStream* stream)
{
   Parent::unpackData(stream);

   stream->read(&fireBall1);
   stream->read(&fireBall2);
   stream->read(&fireBall3);
   stream->read(&ice1);
   stream->read(&mpCrystal);
}

Inventory::Inventory()
{
}

Inventory::~Inventory()
{
}

the only reason why it doesn't work that i can think of is that for some reason inventory.cc isn't being executed.
this may sound a bit brow slappingly silly, but i'm assuming that all the .cc files listed in targets.torque.mk get executed when you run your game via the exe. is that right?
if not then that would explain why the datablock can't be created.
#3
08/29/2008 (2:08 pm)
Have you rebuilt the engine?

If you've updated targets.torque.mk you need to rebuild via makefiles, for example using Make and GCC.

The alternative, if you're using windows, is to add the two new files you've created to the visual studio project and rebuild from within visual studio.

On an unrelated note, and more of a pet peeve of mine...

Quote:
#ifndef _PLAYER_H_
#define _PLAYER_H_

At the very top of the file to keep it from being included multiple times, and end the .h with an #endif. There's also #pragma once, but I don't even know if that will work with TGE, I just learned about it a little while ago.

Avoid prefixing header guards (or anything for that matter) with single or double underscores. Although the chances of it been a problem are probably remote, double underscores as well as leading single underscores followed by an upper case letter are supposed to be reserved by the C++ standard for compiler usage.

Although I've seen a lot of code that ignores that and haven't hit a problem with any of it, it's probably a habit best avoided.
#4
08/29/2008 (4:02 pm)
_CLASSNAME_H_ is the standard in Torque used in every single header file, its nice to always know its the same so you don't have to goto the header to figure out what the define is every time you add a new include.
#5
08/29/2008 (6:26 pm)
Hi Gary,
thanks for replying.
i added my files to the visual studio project and recompiled the engine with no errors, but i still get the same error in the console when i run the game. i checked the compile log, and inventory.cc did compile.
#6
08/29/2008 (8:41 pm)
I don't see anything you are missing... Could you be building a release/debug and running the other for in your test that fails?
#7
08/29/2008 (9:46 pm)
After the end of your InventoryData class declaration, put:

DECLARE_CONSOLETYPE(InventoryData);
#8
08/29/2008 (10:29 pm)
Nevermind that.

Have you considered doing the inventory with TorqueScript?
#9
08/30/2008 (11:53 am)
Hi James,
there is a torqueDemo_DEBUG.exe in the example directory now. but when i run it i get the following error:
error, ran over the shapebase assumptions of convex hulls
does the fact that it created a torqueDemo_DEBUG.exe mean that it didn't update the original?
thanks for replying.

hi John,
i did consider doing it in torque script, but then i realised i didn't have the foggiest how to do it.
to me the easiest way seemed to just create a datablock with custom data that i can access and manipulate from torquescript.
but everyone here can see how that turned out :S
thanks for replying.
#10
08/30/2008 (1:29 pm)
It might mean you are compiling in Debug mode instead of Release? If you are using VC++, there should be a drop-down menu on the top of the screen, to the right of the Save/Save All icons (near a big green play arrow, see it?) See if this is set to Release and not Debug.
#11
08/30/2008 (1:52 pm)
That did it!!!
it was compiling in debug_fastrelight mode.
thanks Morrock!!
#12
08/30/2008 (2:48 pm)
Awesome! Yeah can't tell you how many times that happen to me. Or how about when you make some script changes but forget to do "precompile" in Torsion and when your changes don't seem to be in the game it turns out you have a simple syntax error and its using the old dso '-p
#13
08/30/2008 (3:07 pm)
I hate it when it uses a dso and you don't notice it too James. In fact, I wonder if there is a way to centerprint() about any compilation errors on mission start....

Hope the Inventory works Felix, does it? :-D
#14
08/30/2008 (3:23 pm)
If you run from Torsion all the time (which I generally do) it will first precompile all your scripts before actually starting the game, and if there are any errors it has a nice big popup that says "There were script errors, continue?" where you normally click no, and go fix the error. This has to be one of the simplest but most useful features of Torsion.

C++ asserts are generally used to really get your attention if its something you really need to know about. A little insider info, Tom Spilman has torquescript-asserts implemented and we would like to get that feature into the engine. Eg. the assert fails, you get a popup, and you can connect and debug with torsion at that point.
#15
08/30/2008 (3:32 pm)
Yeah the inventory works. now all i have to do is create a gui...gulp.
thanks for all the help guys!!