irrNetLite 2.1 [BETA]

Announce new projects or updates of Irrlicht Engine related tools, games, and applications.
Also check the Wiki
grassblade
Posts: 27
Joined: Mon Jan 09, 2006 11:17 am

Post by grassblade »

Hello,
I have written some code based on irrnetlite tut and am able to run it. I am new to network programming. The problem is when two clients are running they play differently. They do not run the same animation but the console shows the updated value. I have run the server and two clients on the same machine, not having access to a LAN now. Here is the code. Please have a look. Especially inside the while loop as to how to set the frame loop. How can I update the same animation for a node in all clients? Thanks

Code: Select all



enum E_PACKET_TYPE

{   

    EPT_ANIMSTARTFRAME ,

    EPT_ANIMENDFRAME ,


};


// The server callback.========================================================================================

class ServerNetCallback : public net::INetCallback

{

	// We will store a pointer to the net manager.

	net::INetManager* netManager;

    s32 startframe;

    s32 endframe;

public:

	ServerNetCallback(net::INetManager* netManagerIn) : netManager(netManagerIn) {}

	// Our handlePacket function.

	virtual void handlePacket(net::SInPacket& packet)

	{

		// The packets will use a single char to store

		// the packet identifier, remember to use the

		// smallest possible datatype for storing your

		// packet identifiers. c8 is a typedef for char.

		c8 packetid;

		packet >> packetid;

		
		// Here we will switch based on the packet id.

		switch((E_PACKET_TYPE)packetid)

		{

		case EPT_ANIMSTARTFRAME:

            packet >> startframe;

			std::cout << "From server:The changed startframe by client is now " << startframe << std::endl;

		break;

			

		case EPT_ANIMENDFRAME:

			// Same here.

            packet >> endframe;

			std::cout << "From server:The changed endframe by client is now " << endframe << std::endl;

		break;

    }

	
    	// After handling a packet from a client, we will send an updated status of the startframe to all clients.

        net::SOutPacket animstartframePacket;

        animstartframePacket << (c8)EPT_ANIMSTARTFRAME;

	animstartframePacket << startframe;

        // Send the packet to all connected clients.

	netManager->sendOutPacket(animstartframePacket);

		
        net::SOutPacket animendframePacket;

        animendframePacket << (c8)EPT_ANIMENDFRAME;

	animendframePacket << endframe;

        // Send the packet to all connected clients.

	netManager->sendOutPacket(animendframePacket);

		
   	}

};    

 		
// The client callback.========================================================================================


class ClientNetCallback : public net::INetCallback

{

public:

    s32 startframefromserverpacket;

     s32 endframefromserverpacket;

    //core::stringc message;

	// Our handlePacket function.

	virtual void handlePacket(net::SInPacket& packet)

	{

		// Just like the server, we obtain the packet id and print

		// the information based on the packet we received. I hope the

		// rest of this function is self-explanatory.

		c8 packetid;

		packet >> packetid;

		

		

		switch((E_PACKET_TYPE)packetid)

		{

		case EPT_ANIMSTARTFRAME:

            //s32 startframefromserverpacket;

			packet >> startframefromserverpacket;

			std::cout << "From client:Server says that the startframe is now " << startframefromserverpacket<< std::endl;

			break;

	    case EPT_ANIMENDFRAME:

            //s32 endframefromserverpacket;

			packet >> endframefromserverpacket;

			std::cout << "From client:Server says that the endframe is now " << endframefromserverpacket<< std::endl;

			break;

		default:

			// We don't care about any other types for now, so we catch them here and break.

			
			break;

		}

	}

};



//===========================irrlicht event receiver code

class MyEventReceiver : public IEventReceiver

{

public:

	// This is the one method that we have to implement

	virtual bool OnEvent(const SEvent& event)

	{

		// Remember whether each key is down or up

		if (event.EventType == irr::EET_KEY_INPUT_EVENT)

			KeyIsDown[event.KeyInput.Key] = event.KeyInput.PressedDown;


	return false;

	}


	// This is used to check whether a key is being held down

	virtual bool IsKeyDown(EKEY_CODE keyCode) const

	{

		return KeyIsDown[keyCode];

	}

	
	MyEventReceiver()

	{

		for (u32 i=0; i<KEY_KEY_CODES_COUNT; ++i)

			KeyIsDown[i] = false;

			
	}


private:

	// We use this array to store the current state of each key

	bool KeyIsDown[KEY_KEY_CODES_COUNT];

};


//=============================

//main==================================================================================================================

int main()

{
   

	// Ask the user whether they want to be the server or a client.

	std::cout << "Client (c) or Server (s)?";

	char i;

	std::cin >> i;

	
	// If they typed 's' they are the server else they are the client.

	if(i == 's')

	{

		// Create an irrNetLite server.

		net::INetManager* netManager = net::createIrrNetServer(0);

		// Pass in a server specific net callback.

		ServerNetCallback* serverCallback = new ServerNetCallback(netManager);

		netManager->setNetCallback(serverCallback);

		// Here we update like usual, most of the logic is in the callback.

		while(netManager->getConnectionStatus() != net::EICS_FAILED)

			netManager->update(1000);


		// Delete everything.

		delete netManager;

		delete serverCallback;

	}

	//or if it is client

	else

	{


//now to the client code=======================================================================================

		// Create a client and pass in the client callback.

		// You may want to change the ip address to a remote one and experiment

		// with connecting to a remote host.

		

		ClientNetCallback* clientCallback = new ClientNetCallback();

		net::INetManager* netManager = net::createIrrNetClient(clientCallback, "127.0.0.1");

		//here we may create a packet to change a value and send it to the server

		

			// ---Here we create an animstart packet and send it to the server.------------------

			
				net::SOutPacket animchangestartPacket;

				animchangestartPacket << (c8)EPT_ANIMSTARTFRAME; // Remember to cast to the correct type.

                // Ask for the startframe.

				s32 startframefromclient;

				startframefromclient=1;//assign a value somehow, here for demo just assigned a coded value

			
				animchangestartPacket << startframefromclient;

				netManager->sendOutPacket(animchangestartPacket);

				
			//----Here we create an animend packet and send it to the server.---------------------------------------------------------------------------------------				

				net::SOutPacket animchangeendPacket;

				animchangeendPacket << (c8)EPT_ANIMENDFRAME; // Remember to cast to the correct type.

				// Ask for the startframe.

				s32 endframefromclient;

				endframefromclient=2;//assign a value somehow, here for demo just assigned a coded value

			animchangeendPacket << endframefromclient;

netManager->sendOutPacket(animchangeendPacket);

				
//========================================================================================================

netManager->update(10);//just for test. This line may be removed  later	because it is in loop.Using now just to update the values of animation from client before using it.

    //create irrlicht device==========================================================================================

    

    MyEventReceiver receiver;

    IrrlichtDevice *device =createDevice( video::EDT_SOFTWARE, dimension2d<s32>(640, 480), 16,

			false, false, false,  &receiver);

			
			driver = device->getVideoDriver();

	ISceneManager* smgr = device->getSceneManager();

	IGUIEnvironment* guienv = device->getGUIEnvironment();


    mesh = smgr->getMesh("../../media/sydney.md2");

	if (!mesh)

		return 1;

	node = smgr->addAnimatedMeshSceneNode( mesh );


	   if (node)

    	{

		  node->setMaterialFlag(EMF_LIGHTING, false);

		  node->setMD2Animation(scene::EMAT_STAND);

	      node->setMaterialTexture( 0, driver->getTexture("../../media/sydney.bmp") );

node->setFrameLoop(clientCallback->startframefromserverpacket,clientCallback->endframefromserverpacket);

       

		  node->setAnimationSpeed(15);

	    }


	smgr->addCameraSceneNode(0, vector3df(0,30,-40), vector3df(0,5,0));


//=======================================================================================		

		// Here is the update loop, we will exit if there is a connection problem.

		while(netManager->getConnectionStatus() != net::EICS_FAILED&& device->run())

		{

            if(receiver.IsKeyDown(irr::KEY_KEY_W))

		  {	

                //----Here we create an animstart packet and send it to the server.-----------------------------------

                net::SOutPacket animchangestartPacket;

				animchangestartPacket << (c8)EPT_ANIMSTARTFRAME; // Remember to cast to the correct type.

				// Change  startframe.

				s32 startframefromclient;

				startframefromclient=1;//assign a value somehow, here for demo just assigned a coded value

                animchangestartPacket << startframefromclient;

				netManager->sendOutPacket(animchangestartPacket); 

                 //----Here we create an animend packet and send it to the server.---------------------------------------------------------------------------------------	

				

				net::SOutPacket animchangeendPacket;

				animchangeendPacket << (c8)EPT_ANIMENDFRAME; // Remember to cast to the correct type.

				// Change  endframe.

				s32 endframefromclient;

				endframefromclient=100;//assign a value somehow, here for demo just assigned a coded value

                animchangeendPacket << endframefromclient;

				netManager->sendOutPacket(animchangeendPacket);

				

	             //  netManager->update(10);

				node->setFrameLoop(clientCallback->startframefromserverpacket,clientCallback->endframefromserverpacket);

        }

        else if(receiver.IsKeyDown(irr::KEY_KEY_R))

        {

                     //----Here we create an animstart packet and send it to the server.-----------------------------------

                net::SOutPacket animchangestartPacket;

				animchangestartPacket << (c8)EPT_ANIMSTARTFRAME; // Remember to cast to the correct type.

				// Change  startframe.

				s32 startframefromclient;

				startframefromclient=150;//assign a value somehow, here for demo just assigned a coded value

                animchangestartPacket << startframefromclient;

				netManager->sendOutPacket(animchangestartPacket); 

                 //----Here we create an animend packet and send it to the server.---------------------------------------------------------------------------------------	

				net::SOutPacket animchangeendPacket;

				animchangeendPacket << (c8)EPT_ANIMENDFRAME; // Remember to cast to the correct type.

				// Change  endframe.

				s32 endframefromclient;

				endframefromclient=200;//assign a value somehow, here for demo just assigned a coded value

                animchangeendPacket << endframefromclient;

				netManager->sendOutPacket(animchangeendPacket);


	           //netManager->update(10);
node->setFrameLoop(clientCallback->startframefromserverpacket,clientCallback->endframefromserverpacket); 

        }

netManager->update(10);


          driver->beginScene(true, true, SColor(200,0,0,0));

	  smgr->drawAll();

	    guienv->drawAll();

         driver->endScene(); 
	

		  		}

		
		// Clean up.

		delete netManager;

		delete clientCallback;

		device->drop();

	}


	// And we're done, return 0.

	return 0;

}


BlindSide
Admin
Posts: 2821
Joined: Thu Dec 08, 2005 9:09 am
Location: NZ!

Post by BlindSide »

If the console shows the right value then the problem is probably related more to your usage of setFrameLoop, make sure you are calling it at the right times using the right values.
ShadowMapping for Irrlicht!: Get it here
Need help? Come on the IRC!: #irrlicht on irc://irc.freenode.net
grassblade
Posts: 27
Joined: Mon Jan 09, 2006 11:17 am

Post by grassblade »

Thank you.
I have tried various combinations. Tried it inside begin scene; after endscene.
I created an update function inside the server and tried it. Tried it also from the client. Not working.
I will be greatful if you could give me a suggetion from where I should call it .Or a piece of working code.
Thanks again
Velladores
Posts: 1
Joined: Sat Apr 10, 2010 3:04 pm

Post by Velladores »

Hello,

my program crashes, when a client sends data to the server. It crashes after the packetHandler (of the server) processed the data. VC points me to irrAllocator.h:

Code: Select all

	//! Deallocate memory for an array of objects
	void deallocate(T* ptr)
	{
		internal_delete(ptr); <-- Here is the error
	}

If you need more information, tell me.
lg, Vell

//edit
somehow the problem was solved after I simply recompiled the lib (without the NoIrrlicht.h and so on)
Brainsaw
Posts: 1183
Joined: Wed Jan 07, 2004 12:57 pm
Location: Bavaria

Post by Brainsaw »

I had the same problem, and re-compiling it so that it doesn't use it's Irrlicht replacement classes fixed the problem for me as well.
Dustbin::Games on the web: https://www.dustbin-online.de/

Dustbin::Games on facebook: https://www.facebook.com/dustbingames/
Dustbin::Games on twitter: https://twitter.com/dustbingames
grassblade
Posts: 27
Joined: Mon Jan 09, 2006 11:17 am

Post by grassblade »

:oops: Stupid me. Just a conditional did it. :).
Bate
Posts: 364
Joined: Sun Nov 01, 2009 11:39 pm
Location: Germany

Post by Bate »

Thanks a lot, easy to use and works like a charm.

Is IrrNet going to be developed further or is that pretty much it? Not that I would need a lot more but the beta-tag might be scarring people away :)
Never take advice from someone who likes to give advice, so take my advice and don't take it.
BlindSide
Admin
Posts: 2821
Joined: Thu Dec 08, 2005 9:09 am
Location: NZ!

Post by BlindSide »

I have no interest in scaring people away or inviting them, it's there for whoever wants to use it. :P

If I have some time to clean it up and release 2.2 maybe without the BETA tag, there may still be some unresolved bugs, this is using some pretty old code (Although it seems to be working fine for most people).
ShadowMapping for Irrlicht!: Get it here
Need help? Come on the IRC!: #irrlicht on irc://irc.freenode.net
Brainsaw
Posts: 1183
Joined: Wed Jan 07, 2004 12:57 pm
Location: Bavaria

Post by Brainsaw »

IrrNetLite definetely works great for me, thanks for that. I think it's in sort of a final state (at least for me).
Dustbin::Games on the web: https://www.dustbin-online.de/

Dustbin::Games on facebook: https://www.facebook.com/dustbingames/
Dustbin::Games on twitter: https://twitter.com/dustbingames
Mag-got
Posts: 42
Joined: Tue Dec 04, 2007 5:53 pm

Post by Mag-got »

I'm getting a strange linker error on MSVC++ 2008, I haven't touched the library or header/source files that came with. Has anyone had this before, does anyone have an idea how to fix it?

Code: Select all

1>irrNetLite.lib(CNetManager.obj) : error LNK2019: unresolved external symbol __imp___invalid_parameter_noinfo referenced in function "private: struct _ENetPeer * __thiscall irr::net::CNetManager::getPlayerById(unsigned short)" (?getPlayerById@CNetManager@net@irr@@AAEPAU_ENetPeer@@G@Z)
BlindSide
Admin
Posts: 2821
Joined: Thu Dec 08, 2005 9:09 am
Location: NZ!

Post by BlindSide »

That's an interesting error. Did you try building by including the source code directly into the project instead of linking a library?
ShadowMapping for Irrlicht!: Get it here
Need help? Come on the IRC!: #irrlicht on irc://irc.freenode.net
Mag-got
Posts: 42
Joined: Tue Dec 04, 2007 5:53 pm

Post by Mag-got »

I tried building by including just irrNet.h, irrNetLite.lib and ws2_32.lib.

Seems like doing what you said did the trick, thanks
ChaoticXSinZ
Posts: 1
Joined: Sat Jul 03, 2010 7:59 pm

Post by ChaoticXSinZ »

Hey, thanks for the awesome library. Well I was looking through it and found this snippet in SPacket.h:

Code: Select all

#ifndef s64
typedef signed long long s64;
#endif

#ifndef u64
typedef signed long long u64;
#endif
Should u64 be defined as unsigned long long instead of being signed? Or am I just confused about what the u means.
Bate
Posts: 364
Joined: Sun Nov 01, 2009 11:39 pm
Location: Germany

Post by Bate »

Nope, u means unsigned, so you're right. I guess since most people use Irrlicht along with irrNet nobody noticed the non-irrlicht part. :)

Btw, enet has been updated: now, even compression is built-in.

Code: Select all

ENet 1.3.0 (June 5, 2010):

* enet_host_create() now requires the channel limit to be specified as
a parameter
* enet_host_connect() now accepts a data parameter which is supplied 
to the receiving receiving host in the event data field for a connect event
* added an adaptive order-2 PPM range coder as a built-in compressor option
which can be set with enet_host_compress_with_range_coder()
* added support for packet compression configurable with a callback
* improved session number handling to not rely on the packet checksum
field, saving 4 bytes per packet unless the checksum option is used
* removed the dependence on the rand callback for session number handling

Caveats: This version is not protocol compatible with the 1.2 series or 
earlier. The enet_host_connect and enet_host_create API functions require
supplying additional parameters.

ENet 1.2.2 (June 5, 2010):

* checksum functionality is now enabled by setting a checksum callback
inside ENetHost instead of being a configure script option
* added totalSentData, totalSentPackets, totalReceivedData, and
totalReceivedPackets counters inside ENetHost for getting usage
statistics
* added enet_host_channel_limit() for limiting the maximum number of
channels allowed by connected peers
* now uses dispatch queues for event dispatch rather than potentially
unscalable array walking
* added no_memory callback that is called when a malloc attempt fails,
such that if no_memory returns rather than aborts (the default behavior),
then the error is propagated to the return value of the API calls
* now uses packed attribute for protocol structures on platforms with 
strange alignment rules
* improved autoconf build system contributed by Nathan Brink allowing 
for easier building as a shared library

Caveats: If you were using the compile-time option that enabled checksums,
make sure to set the checksum callback inside ENetHost to enet_crc32 to
regain the old behavior. The ENetCallbacks structure has added new fields,
so make sure to clear the structure to zero before use if 
using enet_initialize_with_callbacks().
So maybe a final irrNet release using enet 1.3 would be a good idea? :)
(I already tried to extend it but hell -- all the low level buffer code is killing me)

In this regard: how do you solve the following problem?

There are serveral units. Player A sends a packet to Player B, E_PACKET_TYPE is EPT_UNIT_MOVED and the data is a vector3df. How do I send which unit has moved?

A giant packet type enum doesn't feel right (EPT_UNIT_01_MOVED etc). So, I guess I need to implement a custom packet, unfortunately that's where I'm forced to deal with the buffer code again.

Well, any help is appreciated.
Never take advice from someone who likes to give advice, so take my advice and don't take it.
Brainsaw
Posts: 1183
Joined: Wed Jan 07, 2004 12:57 pm
Location: Bavaria

Post by Brainsaw »

I use unique IDs for all of my objects. My plugin for IrrEdit (IrrOdEdit) does automatically produce these IDs. You just have to make sure all clients and the server use the same scene file.
Dustbin::Games on the web: https://www.dustbin-online.de/

Dustbin::Games on facebook: https://www.facebook.com/dustbingames/
Dustbin::Games on twitter: https://twitter.com/dustbingames
Post Reply