Game Development Community

Is it a matter of declaring Object?

by game4Rest · in Torque Game Builder · 01/31/2006 (6:46 am) · 3 replies

As far as I know callbacks can have this form: "function className::callBack();".
For example, from the ServerConnection.cs which can be found in the common\client folder from our sample,

function GameConnection::onConnectRequestTimedOut(%this)
{
disconnectedCleanup();
MessageBoxOK( "TIMED OUT", "Your connection to the server timed out." );
}

Usually we do like this: objectName.function(). But callbacks can be different.

But, when I did something like that, it gave me no result.

In the code,

void addedClassName::onUpdated()
{
Con::executef(this, 1, "onUpdated");
}

In the script,

$Handle = new addedClassName(ObjectName);

function ObjectName::onUpdated()
{
do something;
}

When I run the game, onUpdated() is not called anyhow. Do I misunderstand something in declaring a class Object? Or is the Class in the ServerConnection.cs hiding some strategy behind?

Please give me any advice.

Thanks in advance.

Hong Jin

#1
01/31/2006 (8:20 am)
You are slightly confusing the concept of class namespaces with object namespaces. In your example c++ code, you are (correctly) using the object's class for your namespace:

addedClassName::

but, when you do the Con::executef(this, ...), the code will also be looking for the same namespace, just in script:

addedClassName::onUpdated()

instead, you are using an object's name as your namespace (instead of the class):

ObjectName::onUpdated()

Short answer: if you change ObjectName::onUpdated to addedClassName::onUpdated, it should work for you.

Long answer:

Some theory on namespaces and how they are added/linked for new objects:

Stock Torque (1.3 and up, including T2D) as part of the SimObject::onAdd() class method (C++) creates a single namespace for TorqueScript to access for the class, based on the class's name:

bool SimObject::onAdd()
{
   mFlags.set(Added);

   if(getClassRep())
      mNameSpace = getClassRep()->getNameSpace();

   // onAdd() should return FALSE if there was an error
   return true;
}

The key line here is the mNameSpace line. If you have created a new class and inherited from SimObject (as you have in this case), then that is the only namespace that is created for you.

However, (again, stock TGE, as well as T2D), Torque does do an additional step for certain objects--namely GUIObjects, as well as ScriptObjects, which is to link both the class namespace as well as the object's "name" namespace together so you can create your script methods in either namespace. For script objects, it even goes one step further and links in the parent/super-parent's namespaces as well, giving you oop-like inheritence:

bool ScriptObject::onAdd()
{
   if (!Parent::onAdd())
      return false;
   
   // it's possible that all the namespace links can fail, if
   // multiple objects are named the same thing with different script
   // hierarchies.
   // linkNamespaces will now return false and echo an error message
   // rather than asserting.
     
   // superClassName -> ScriptObject
   StringTableEntry parent = StringTable->insert("ScriptObject");
   if(mSuperClassName[0])
   {
      if(Con::linkNamespaces(parent, mSuperClassName))
         parent = mSuperClassName;
   }
      
   // className -> superClassName
   if (mClassName[0])
   {
      if(Con::linkNamespaces(parent, mClassName))
         parent = mClassName;
   }

   // objectName -> className
   StringTableEntry objectName = getName();
   if (objectName && objectName[0])
   {
      if(Con::linkNamespaces(parent, objectName))
         parent = objectName;
   }

   // Store our namespace
   mNameSpace = Con::lookupNamespace(parent);

   // Call onAdd in script!
   Con::executef(this, 2, "onAdd", Con::getIntArg(getId()));
   return true;
}

In the above code, we are actually linking our ScriptObject to four namespaces:

  • We call the parent's onAdd first, which links to the namespace based on the object class (ScriptObject::).
  • We check to see if we have a script based superClass, and if so, link to that namespace
  • We try to link our namespace with the parent's namespace (script based parent)
  • We check to see if we have named our object, and if so link to that namespace

  • For your above issue, if you really want to use the object's name as your namespace, you would need to add change your addedCassName::onAdd() to something like:

    bool myAddedClass::onAdd()
    {
       if (!Parent::onAdd())
          return false;
       const char *name = getName();
       if(name && name[0] && getClassRep())
       {    
          Namespace *parent = getClassRep()->getNameSpace();
          if(Con::linkNamespaces(parent->mName, name))
             mNameSpace = Con::lookupNamespace(name);
       }
    }

    DISCLAIMER: This code not tested, your mileage may vary.
    #2
    01/31/2006 (6:15 pm)
    Dear Stephen,

    On solving a troublesome problem, above stopped me. Even though I had tried everything that came into my head, the way you let me know didn't came to my mind.

    I don't have any special reason to use object's name as my namespace. The reason that I tried so was because of my ignorance.

    Now it works perfectly. I can update my player according to the data server provided.

    Stephen, you're taking too much pain teaching a slow student.

    Always thanks!

    Hong Jin
    #3
    01/31/2006 (7:27 pm)
    Well, even though we were focusing on your specific issue, everyone that comes along and reads this thread gains just a small kernel of knowledge that may turn on a lightbulb in their head, so it helps everyone!

    In addition, I've gotten some additional research out of the way for the ongoing TDN work--expect a writeup on how T2D uses namespaces in the future when I can get to it!

    I am glad that we were able to get things working for you...and personally I don't think you are a slow student at all--in fact you are attempting something that's pretty challenging!