Jump to content

RakNet in Leadwerks Tutorial Files


Road Kill Kenny
 Share

Recommended Posts

File Name: RakNet in Leadwerks Tutorial Files

File Submitter: Engineer Ken

File Submitted: 13 Oct 2011

File Category: C++

 

In this tutorial series you will learn how to use RakNet in Leadwerks to network your games. The attached .h and .cpp files will be needed for the tutorial and can be altered for your personal use for your own games.

 

The video tutorials can be found as follows:

- Part 0 Setup -

- Part 1A Server -

- Part 1B Server -http://www.youtube.com/watch?v=QDweY9fbflM

 

Click here to download this file

STS - Scarlet Thread Studios

AKA: Engineer Ken

 

Fact: Game Development is hard... very bloody hard.. If you are not prepared to accept that.. Please give up now!

Link to comment
Share on other sites

Nice tutorial. Noticed you are using a switch statement (not sure if it's just because of the tutorial to keep it simple) but a long time ago someone showed me how to get some easy C++ "events" working. When I use RakNet I always use this because messing around with a giant switch statement is a pain after it gets huge (which in networking and dealing with messages it generally does).

 

Usage:

class Server
{
private:
     // the message id is the key, and the event which I make take a packet and a bitstream is the data stored
     map<RakNet::MessageID, Event2<RakNet::Packet*, RakNet::BitStream*>> _networkEvents;

     // network event handlers. this becomes where you handle the network messages
     void OnNewIncomingConnection(RakNet::Packet* p, RakNet::BitStream* reader){}
     void OnRequestLogin(RakNet::Packet* p, RakNet::BitStream* reader) {}
public:
     // assign the function "event" to the raknet message id. for each new message you just define the function like above and then add this 1 liner to link the function to the message
     // note that you can link multiple functions to the same message and when you raise the event each function will be called automatically for you, which can come in handy sometimes
     Server::Server(void)
     {
   _networkEvents[iD_NEW_INCOMING_CONNECTION].Bind(this, &Server::OnNewIncomingConnection);
     }
     // your main loop becomes nice and small and never changes now
     void Server::Run()
     {
while(1)
{
	for (_packet = _peer->Receive(); _packet; _peer->DeallocatePacket(_packet), _packet = _peer->Receive())
	{
		// if we registered this event then call the method it's bound to
		if(_networkEvents.find((RakNet::MessageID)_packet->data[0]) != _networkEvents.end())
		{
			RakNet::BitStream reader(_packet->data, _packet->length, false);

                              // this calls the function(s) for the message
			_networkEvents[_packet->data[0]].Raise(_packet, &reader);
		}
	}
     	}
     }
};

 

Your head will probably explode if you try to understand this code below (it took me some time to really fully understand what's happening and feel comfortable making changes) but if you can understand it you can add different event function signatures (return a value and/or take a different amount of parameters). I've found this code so useful in C++ in many different ways. From networking events to gui events to game events. If you can't understand it know that you can just copy and paste it in a header and use it as:

 

Event2<type1, type2> myEvent;

 

The file below is only setup to take 2 parameters of any type and return void. The code below doesn't have this but at some point I set it up to also take non class method points so you were able to mix and match class methods and non class functions to be fired which can be nice too.

 

EventHandler.h

#pragma once

#include <list>

using namespace std;

template<class P, class Q>
class TFunctor2
{
public:
  virtual void Call(P var1, Q var2)=0;
};

template <class TClass, class param1, class param2>
class TSpecificFunctor2 : public TFunctor2<param1, param2>
{
private:
  void (TClass::*fpt)(param1, param2);
  TClass* pt2Object;         
public:
  TSpecificFunctor2(TClass* _pt2Object, void(TClass::*_fpt)(param1, param2))
  { pt2Object = _pt2Object;  fpt=_fpt; }

  virtual void Call(param1 var1, param2 var2)
  { (*pt2Object.*fpt)(var1, var2); }
};

template<class T1, class T2>
class Event2
{
public:
  list<TFunctor2<T1, T2>* >  mCaller;

  template<class Target>
  Event2(Target* t, void (Target::*fnPtr)(T1, T2))
  { mCaller.push_back(new TSpecificFunctor2<Target, T1, T2>(t,fnPtr)); }

  Event2(){}

  template<class Target>
  void Bind(Target* t, void (Target::*fnPtr)(T1, T2))
  { mCaller.push_back(new TSpecificFunctor2<Target, T1, T2>(t,fnPtr)); }

  void Raise(T1 V1, T2 V2)
  {
     list<TFunctor2<T1, T2>*>::reverse_iterator iter;


     for (iter = mCaller.rbegin(); iter!= mCaller.rend(); iter++)
     {
        (*iter)->Call(V1, V2);
     }
  }   

  void Clear()
  {
     mCaller.clear();
  }
};

//////////////////////////////////////////////////

class TFunctor
{
public:
  virtual void Call()=0;
};

template <class TClass>
class TSpecificFunctor : public TFunctor
{
private:
  void (TClass::*fpt)();
  TClass* pt2Object;         
public:
  TSpecificFunctor(TClass* _pt2Object, void(TClass::*_fpt)())
  { pt2Object = _pt2Object;  fpt=_fpt; }

  virtual void Call()
  { (*pt2Object.*fpt)(); }
};

class Event0
{
public:
  list<TFunctor* >  mCaller;

  template<class Target>
  Event0(Target* t, void (Target::*fnPtr)())
  { mCaller.push_back(new TSpecificFunctor<Target>(t,fnPtr)); }

  Event0(){}

  template<class Target>
  void Bind(Target* t, void (Target::*fnPtr)())
  { mCaller.push_back(new TSpecificFunctor<Target>(t,fnPtr)); }

  void Raise()
  {
     list<TFunctor*>::reverse_iterator iter;


     for (iter = mCaller.rbegin(); iter!= mCaller.rend(); iter++)
     {
        (*iter)->Call();
     }
  }   

  void Clear()
  {
     mCaller.clear();
  }
};

Link to comment
Share on other sites

:lol: cool. Thanks for posting that.

 

The reason I use switch case is because its the only way I know how... Though it is also very simple to see and understand if you are trying to learn RakNet so for the purpose of this tutorial I'm going to stick with it. However, post away any code that may be useful because I'm sure people will explore things on their own once they have the basics down.

 

TBH I'm not a very good programmer, I just really wanted to learn how to do networking and I'm happy to share what I learnt about RakNet, hence most of what you posted goes straight over my head XD... But I'm sure there are plenty that would get it and be able to implement it into my networking stuff for the better. (Hopefully I'll get it some day ;)

 

I guess the real purpose of this series of tutorials is to de-mystify networking with RakNet in Leadwerks. I think that there are a lot of really good programmers that are a lot better than me at general programming. However, it seems like a lot of people are also almost.... 'scared' (for lack of a better word) of networking or fear it is to difficult to even try.

 

I guess what I'm saying is: Its not as bad as it looks peeps ;). If I can do it then so can you!

 

In later tutorials I hope to touch on the more..... itchy topics i'll say such as: hiding/disguising lag and networking techniques other than simply the code.

 

Edit: So what I gather from your code (after a quick look) you are using some function to determine message identifier and then calling a function depending on what the ID is... Have I got the basic jist?

STS - Scarlet Thread Studios

AKA: Engineer Ken

 

Fact: Game Development is hard... very bloody hard.. If you are not prepared to accept that.. Please give up now!

Link to comment
Share on other sites

Thanks Ken for taking time out to make those and put them up for the community.

 

I have been using quite large CASE statements myself but easier on the eye with careful grouping. I like the code Rick posted, that's quite useful and not too dissimilar from a special FX system. Never considered it for networking.

6600 2.4G / GTX 460 280.26 / 4GB Windows 7

Author: GROME Terrain Modeling for Unity, UDK, Ogre3D from PackT

Tricubic Studios Ltd. ~ Combat Helo

Link to comment
Share on other sites

There is a section for community tutorials here, and you can upload attachments with your post:

http://www.leadwerks.com/werkspace/page/Documentation/LE2/tutorials

 

Ah I forgot about that. I will move it this afternoon. :)

STS - Scarlet Thread Studios

AKA: Engineer Ken

 

Fact: Game Development is hard... very bloody hard.. If you are not prepared to accept that.. Please give up now!

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

 Share

×
×
  • Create New...