Main Page | Modules | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Class Members | Related Pages | Examples

4. Construction of objects

This test will set up a ServerData object on the server and then call ServerData::sendCreateObjectToAll(). The client will have set up a static method for creating objects of this class using the method:
ClientFramework::registerConstructor(unsigned int class_id, ClientData * (*func)(ClientFramework *, FrameworkPacket *))
This method should be called, and a new ClientData object should be created from the FrameworkPacket.

Client Application

In this example you should notice the new class MyClientData, which is a subclass of ClientData. This class has a static method that constructs new objects of this class. It is not necessary to place this static method on the class it self, but it makes sense to keep them together.

You should also notice how this "constructor" method is registered in the ClientFramework, the most important thing is the ID with which it is registered, this ID is the same as the server-object uses to specify what "constructor" function to use. Hence they MUST match.

Also you should notice the constructor of MyClientData, it takes the framework and the packet with which it should be constructed as arguments. And after calling its superclasses constructor it reads the values from the supplied ClientPacket.

/// @cond EXCLUDEDTESTSOURCES
/***************************************************************************
 * The contents of this file are subject to the Mozilla Public             *
 * License Version 1.1 (the "License"); you may not use this file          *
 * except in compliance with the License. You may obtain a copy of         *
 * the License at http://www.mozilla.org/MPL/                              *
 *                                                                         *
 * Software distributed under the License is distributed on an "AS         *
 * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or              *
 * implied. See the License for the specific language governing            *
 * rights and limitations under the License.                               *
 *                                                                         *
 * The Original Code is Game Network Framework (GaNeF).                    *
 *                                                                         *
 * The Initial Developers of the Original Code are                         *
 * Lars Langer and Emanuel Greisen                                         *
 * Copyright (C) 2005. Lars Langer & Emanuel Greisen                       *
 * All Rights Reserved.                                                    *
 *                                                                         *
 * Contributor(s):                                                         *
 *   none yet....                                                          *
 *                                                                         *
 ***************************************************************************/

#include <iostream>
#include <cstdlib>

#include "../Ganef/client/clientframework.h"
#include "../Ganef/client/clientdata.h"


class MyClientData : public ClientData
{
   private:
      int x,y;

   public:
      MyClientData(ClientFramework * f, ClientPacket * p) : ClientData(f,p),x(0),y(0)
      {
         x = p->readInt32();
         y = p->readInt32();
         std::cout << "Constructed a new object of class: MyClientData" << std::endl;
         std::cout << " - The new object has ID: " << getFrameworkId() << std::endl;
         std::cout << " - And (x:"<<x<<",y:"<<y<<")" << std::endl;
      }
      virtual void updatePacket(ClientFramework * f, unsigned char updatetype, ClientPacket * packet)
      {
         // Here we receive updates (but no updates are comming in this test)
      }

      static ClientData * constructMyClientData(ClientFramework * f, ClientPacket * p)
      {
         return new MyClientData(f,p);
      }
};


/**
 * This is just a test-client-framework.
 * @author Lars Langer and Emanuel Greisen
 */
class TestClientFramework : public ClientFramework
{
   private:
      bool is_running;
      std::string server_hostname;

   public:
      TestClientFramework(const std::string & server_hostname) : ClientFramework(int(0)),server_hostname(server_hostname)
      {
         // Notice how the constructor is registered, now all we need is the
         // server sending a packet telling us to construct an object of
         // class with id: 0x424242
         registerConstructor(0x424242, MyClientData::constructMyClientData);
      }
      ~TestClientFramework()
      {
      };

   protected: // These must be implemented in a derived class
      virtual void writeHandshakeInitMessage( ClientPacket * fp ){}
      virtual void onHandshakingDiscontinue( ClientPacket * fp ){}
      virtual bool onHandshakeDescription( ClientPacket * fp, ClientPacket * reply )
      {
         return true;
      }
      virtual void onDisconnect( ) { std::cout << "Disconnected\n"; }
      virtual void onConnect( ){ std::cout << "Connected\n"; }

   public:
      void mainLoop( )
      {
         std::cout << "Connecting to: " << server_hostname <<":"<< 8000<< std::endl;
         initServerConnection(server_hostname, 8000);
         is_running = true;
         while(is_running)
         {
            // Get/handle Packets from the framework
            keepAlive();

            // Then we sleep to let the CPU live
            psleep(50);
         }
      }
};




int main(int argc, char *argv[])
{
   std::string server_host("localhost");
   if(argc > 1)
      server_host = argv[1];
   TestClientFramework app(server_host);

   // Start the Application
   app.mainLoop();
}

/// @endcond

Server Application

This test-server has like the test-client a datatype MyServerData, and this class is a subclass of ServerData.

The interesting things to notice in this test are the method fillCreateObjectPacket() and getClassId() which are called when the ServerFramework wants to create a constructor packet. The getClassId() MUST match the ID with which the constructor function is registered on the client, and the fillCreateObjectPacket() must fill in all data required for the client-version of this data-type to construct.

The object-ID (as opposed to the Class-ID) of the data (which is the same on the server and client version of the data-entity, you need not worry about, this will be taken care of by the framework).

/// @cond EXCLUDEDTESTSOURCES
/***************************************************************************
 * The contents of this file are subject to the Mozilla Public             *
 * License Version 1.1 (the "License"); you may not use this file          *
 * except in compliance with the License. You may obtain a copy of         *
 * the License at http://www.mozilla.org/MPL/                              *
 *                                                                         *
 * Software distributed under the License is distributed on an "AS         *
 * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or              *
 * implied. See the License for the specific language governing            *
 * rights and limitations under the License.                               *
 *                                                                         *
 * The Original Code is Game Network Framework (GaNeF).                    *
 *                                                                         *
 * The Initial Developers of the Original Code are                         *
 * Lars Langer and Emanuel Greisen                                         *
 * Copyright (C) 2005. Lars Langer & Emanuel Greisen                       *
 * All Rights Reserved.                                                    *
 *                                                                         *
 * Contributor(s):                                                         *
 *   none yet....                                                          *
 *                                                                         *
 ***************************************************************************/

#include <iostream>
#include <cstdlib>
#include <vector>


#include "../Ganef/server/serverframework.h"


class MyServerData : public ServerData
{
   private:
      int x,y;

   public:
      // The two last parameters for ServerData is the priority of its updatepackets
      //  and wether they should be sent reliable.
      MyServerData(ServerFramework * fw) : ServerData(fw, 10, false)
      {
         x = 200;
         y = 150;
      };
   public:
      /// This must produce a unique id for this class, it will be used on the client side to construct new objects.
      virtual const unsigned int getClassId() const { return 0x424242; };
      /// Here the data-class should fill in data according to update type `type`.
      virtual void fillUpdatePacket(ServerPacket * packet, unsigned char type) const
      {
         // We do not use updates in this test.
      }
      /// Here the data-class should fill in all data required by the constructor on the client side.
      virtual void fillCreateObjectPacket(ServerPacket * packet) const
      {
         // Here we supply enough data to create the client-version of this object
         // Remember to make absolutely sure that what you write here is exactly the
         //   same as the client version reads in its constructor.
         packet->writeInt32(x);
         packet->writeInt32(y);
      }
      /// Called when ever we receive a packet for this object from a client.
      virtual void clientPacket(Client * client, unsigned char type, ServerPacket * packet)
      {
         // We do not receive any actions from the client in this test.
      }

};

/**
 * This is just a test server-framework;
 * @author Lars Langer and Emanuel Greisen
 */
class TestServerFramework : public ServerFramework
{
   public:
      TestServerFramework() : ServerFramework(8000)
      {
      }

      ~TestServerFramework()
      {
      }

   protected: // These method should be implemented on the GameServer
      virtual bool onInitialHandshake(ServerPacket * handshake, ServerPacket * reply)
      {
         return true; // Accept all clients.
      }
      virtual void onClientConnected(Client * client)
      {
         std::cout << "Client: " << client->getId() << " connected\n";
      }
      virtual void onClientDisconnected(Client * client)
      {
         std::cout << "Client: " << client->getId() << " disconnected\n";
      }
      virtual Client * createClient(const ipaddress &addr, int port)
      {
         return new Client(this, addr, port);
      }

   public:
      void mainLoop()
      {
         std::cout << "TestServerFramework: Running\n";
         MyServerData mydata(this);
         while(true)
         {
            // Get all incomming messages
            keepAlive();

            // Send create object to all connected clients (this is silly to do more than once)
            if(getAllClients().size() > 0)
            {
               mydata.sendCreateObjectToAll();
            }

            // Sleep a little
            psleep(100);
         }
      }
};




int main(int argc, char *argv[])
{
   try
   {
      // Create a framework
      TestServerFramework framework;

      // Start the framework
      framework.start();

      // GameLoop
      framework.mainLoop();
   }
   catch(FrameworkError *err)
   {
      std::cout << "FrameworkError:" << err->msg << std::endl;
   }
   catch(PacketError *err)
   {
      std::cout << "PacketError:" << err->msg << std::endl;
   }

   return EXIT_SUCCESS;
}

/// @endcond

Generated on Mon Feb 6 12:24:57 2006 for Ganef by  doxygen 1.4.4