Tuesday, April 13, 2010

Ooz Object to Object communication.


Ooz is the scripting language that I wrote for Elderlands and all If-Else Software games. It is a very small yet robust scripting engine. It supports micro-threading, is extendable and is designed with performance in mind.

One thing I’m researching is a sort of ‘signals and slots’ system that would be integrated into the scripting language. The C++ framework called QT already supports signals and slots but has a pre-processor and is not very efficient from a performances standpoint. I need something that is performance oriented. It is very flexible in the sense that objects can hook to signals of other objects and receive callbacks through slots (class methods which are called). This works even across threads.

So I’ve been pondering how to create a system that provides the flexibility of a generic signal/slot system while keeping performance the #1 priority in the Ooz language.

I currently have extended the language to support an event system. Objects can register events they care about and receive a callback whenever any event is fired that they care about. Event parameters are handled through a structure which is nothing more than a container of data types that are sequentially added. Event types are defined in a large enumeration .

Example:
class ObjectA
{
  // Register Event
  declare ObjectA()
  {
    RegisterEvent(Event_SomethingHappens);
  }

  declare void OnEvent(EventType _eEvent, EventParams _kParams)
  {
    if(_eEvent==Event_SomethingHappens)
    {
      int iParam1=_kParams.Get(0);
      // Do something
    }
  }
}

class CObjectB
{
  // Someplace in another object…
  declare void MakeSomethingHappen(int _iParam)
  {
    EventParams kParams=new EventParams;
    kParams.Set(0,_iParam);
    TriggerEvent(Event_SomethingHappens,kParams);
  }
}

Now an integrated signals and slot system could make the code look much cleaner and if done correctly could be more efficient. A big benefit is the system is handled internally to the language and not as part of an extension.

Signals are defined like method prototypes and are fired off with the ‘emit’ keyword. The slots are receiving methods that are called when the signal is fired.

Example:

CObjectA objA=new CObjectA;
CObjectB objB=new CObjectB;

// Connect objA’s slot to objB’s signal.
connect objA.MySlot to objB.MySignal;

// Invoke a method of objB that will fire off a signal.
objB.DoStuff();


class ObjectA
{
  // This is the method that will be connected to a particular
  // signal.
  declare void MySlot(int _iParam)
  {
    // Do something
  }
}

class ObjectB
{
  // Declare an event that others can connect to.
  declare signal MySignal(int _iParam);

  declare void DoStuff()
  {
    // Emit the signal with a given parameter.
    emit MyEvent(50);
  }
}


Now one area where the signals/slots system seems to have a weakness compared to the event system is when I have events that are generated on the Elderlands Game server and received by objects on the Client. Of course this could be handled by creating global objects representing the ‘server’ and have all client objects connect to the server signals they care. It would take a bit of massaging, but overall this looks like a good direction to go.

1 comment: