Page 1 of 1

IrrNet - Example 4 by Midnight

Posted: Thu Feb 22, 2007 3:45 am
by Midnight
OLD CODE NOW NATIVE TO IRRNET

Code: Select all

#include <irrlicht.h>
#include <irrNet.h>

#include "Animators.h"
#include "chatQue.h"

using namespace irr;
using namespace scene;
using namespace video;
using namespace core;
using namespace gui;
using namespace io;
using namespace net;

#pragma comment(lib, "Irrlicht.lib")
#pragma comment(lib, "ws2_32.lib")

// Comment/Uncomment this to define if this is a client or server.
#define CLIENT

// Objects used in the Event Receiver, for camera and player animation.
CSceneNodeAnimator3PCamera *camAnim;
CSceneNodeAnimator3PPlayer *ninjaAnim;

IrrlichtDevice* device = 0;
irr::gui::IGUIEnvironment* guienv;
irr::net::INetManager* netmgr;
IGUIEditBox* editbox;
ChatQue* chatQue;
irr::net::OutPacket* myOutPacket;
bool switch1;
bool switch2;
stringc chatstring; // Create a chat string. (stringc for non wide chars.)
int ping;

// Irrlicht input reciever class..
class MyEventReceiver : public irr::IEventReceiver
{
public:
	virtual bool OnEvent(irr::SEvent event)
	{
		if(event.EventType == irr::EET_LOG_TEXT_EVENT)
		{
			OutputDebugString(event.LogEvent.Text);
			OutputDebugString("\n");

			return true;
		}

		if(!guienv->hasFocus(editbox))	
		{
			if(camAnim->OnEvent(event))
				return true;
			if(ninjaAnim->OnEvent(event))
				return true;
		}

		if(event.EventType == irr::EET_KEY_INPUT_EVENT)
		{
			
			if(event.KeyInput.Key == KEY_KEY_T &&! event.KeyInput.PressedDown)
			{
					
				guienv->setFocus(editbox);
			}

			if(event.KeyInput.Key == KEY_RETURN)
			{
				if(switch1)
				{
					chatQue->addMessage(editbox->getText());
					

					// Make sure to clear this if you are re-using it.
					myOutPacket->clearData();

					// Use our chat packet id of 50.
					c8 packetid = 50; 
					myOutPacket->addData(packetid);

					chatstring = editbox->getText();

					// Follow that by the char array itself.
					myOutPacket->addData(chatstring.c_str());

					// Send the packet.
					netmgr->sendOutPacket(myOutPacket);

					// Clear the edit box. (There is also a switch incase send button is held down.)
					guienv->removeFocus(editbox);
					editbox->setText(L"");
					switch1 = 0;
	
				}
			
				else
				{
					switch1 = 1;
				}
			}
		}
		return false;
	}
};


// I declared the selector here so the handler can access it.
irr::scene::ITriangleSelector *selector = 0;


// Here I make a Custom Operations class. This is passed the node and irrlicht device and allows you to perform operations
// on newly created Net nodes. This counts both for nodes created locally and nodes created by request from other peers.
// Here I am using it to set a collision response animator to every new Net node created, you can do pretty much anything
// you want though. The reason to have a Custom Operations class is because you don't know how many or what nodes are going
// to be created dynamically by the server/client, so here you can make sure you get what you want done to them. In essence,
// this is very similar to a scene node animator, except it applys to all net nodes of the node type its set to, and only 
// occurs one time after they are created. If you want to do these things for all new Net nodes you can set this in 
// setGlobalCustomOperations. (Look into Node Types in API document if you are interested)

class CollisionOperator :
	public irr::net::CustomOperations
{
public:
	CollisionOperator();
	virtual void Operations(IAnimatedMeshSceneNode* node, irr::IrrlichtDevice *device);
};

CollisionOperator::CollisionOperator()
{
}

void CollisionOperator::Operations(irr::scene::IAnimatedMeshSceneNode *node, irr::IrrlichtDevice *device)
{
	scene::ISceneNodeAnimator* anim = device->getSceneManager()->createCollisionResponseAnimator(
	selector, node, core::vector3df(10,50,10),
	core::vector3df(0,-3,0), 
	core::vector3df(0,-50,0));
	node->addAnimator(anim);
	anim->drop();
}

// This is an example of how to make a Custom Handler, this handles packets in any way you want. This must be enabled using
// setCustomHandling, look in main function and in API documentation for more info.

class myCustomHandler :
            public irr::net::CustomHandler
{
public:
    myCustomHandler();
    virtual ~myCustomHandler(void);
    virtual void Handle(irr::net::InPacket * packet);
private:
	char* buffer[1000]; // This is a buffer for storing the char string.
	c8 packetid;	// This is a single 8-bit char for storing the packet id.
};

myCustomHandler::myCustomHandler()
{}

myCustomHandler::~myCustomHandler(void)
{}

//! animates the scene node
void myCustomHandler::Handle(irr::net::InPacket * packet)
{
	packet->getNextItem(packetid);
	// Lets say packet id 50 is a chat message.
	if(packetid == 50)
	{

	// String size handling is integrated into the packets. The default header size is u16, which would support up to
	// 65500-ish characters. If you wish to optimize the size to c8 (Which would limit you to 255 chars.), you would
	// have to uncomment the lines in Packets.cpp to use a header size of 1 and also find a way to get this across.
	// Personally I recommend not caring too much about that and leave it u16, its less of a headache that way.
	packet->getNextItem((char*)buffer);

	// And display it! (Dont forget to "(char*)" it!)
	chatQue->addMessage((char*)buffer);
	}
}



//! Main game loop

int main()
{

	// Set up event reciever.
	MyEventReceiver receiver;

	// Create Device
	device = irr::createDevice(irr::video::EDT_DIRECT3D9,irr::core::dimension2d<irr::s32>(800,600),32,0,0,1,&receiver);
		
	// Make pointers to irrlicht stuff
	irr::video::IVideoDriver*driver = device->getVideoDriver();
	irr::scene::ISceneManager*smgr = device->getSceneManager();
	guienv = device->getGUIEnvironment();
	irr::gui::ICursorControl*cursor = device->getCursorControl();
	irr::scene::ICameraSceneNode*camera = smgr->addCameraSceneNode();

	// Make a new INetManager
	netmgr = new irr::net::INetManager(device);

	
	// Here you can set the NetManager to output info to console...
	// netmgr->setVerbose(1);
	


	// If we're a client set up a client, if we're a server set up a server.
#ifdef CLIENT
	netmgr->setUpClient();
#else
	netmgr->setUpServer();
#endif

	

	// Load file system
	device->getFileSystem()->addZipFileArchive("./media/demo.dta");

	// Load a map, and set up the selector. Dont worry about all this it has nothing to do with irrNet...
	smgr->loadScene("temple.irr");

	scene::IAnimatedMesh* q3levelmesh = smgr->getMesh("temple.dae");
	scene::ISceneNode* q3node = 0;

	if (q3levelmesh)
		q3node = smgr->getSceneNodeFromName("templemap");

	if (q3node)
	{		
		selector = smgr->createOctTreeTriangleSelector(q3levelmesh->getMesh(0), q3node, 128);
		q3node->setTriangleSelector(selector);
		selector->drop();
	}

	q3node->setMaterialFlag(irr::video::EMF_LIGHTING,false);
	q3node->setMaterialTexture(0, driver->getTexture("wood.png"));

	// Here is some fun stuff, creating and modifying the material for our first node type.
	SMaterial nmaterial;
	nmaterial.Texture1 = driver->getTexture("nskinbr.jpg");
	nmaterial.Lighting = false;
	nmaterial.NormalizeNormals = true;

	// Here we load the mesh.
	irr::scene::IAnimatedMesh *ninjaMesh = smgr->getMesh("ninja.ms3d");

	// Here we make a new instance of our CustomOperations class.
	CollisionOperator* coop = new CollisionOperator();
	
	// Here we set the Node Type 1, with the material, mesh, (no animator), and our CustomOperations class.
	// This will mean that every new node of type 1 created will be made with that material, mesh, animator,
	// and will have our collision operations performed on them. You can use enums and label NINJA as 1 or
	// just remember the numbers like I do, it is not very hard, but you can use enums for big projects to
	// make it easier. So anyway, now you know all nodes of Type 1, are Ninjas! :D
	netmgr->setNodeType(1,nmaterial,ninjaMesh,0,coop);

	// Here we make our ninja net node, this will create the node locally and also send a request to other connected peers
	// to create it. It will also be kept on the list on the server so it will be created when new clients join on, unless
	// it is destroyed or the client who created it disconnects. Please note the first value, it is very important. It sets
	// the node type for the node. To create a net node you MUST create a node type first like I did and set the mesh,
	// material, etc to it, so that it is able to be created on connected computers. Here I am setting node type 1, so we
	// are creating a ninja. :D Please note that connected computers will need the same node type to have the same mesh,
	// material, etc. So that they are created the same. (You were not actually thinking of sending the mesh were you :P)
	irr::scene::IAnimatedMeshSceneNode *ninja =
	netmgr->addNetSceneNode(1,core::vector3df(800,10,0),core::vector3df(0, -90, 0),core::vector3df(5.0f, 5.0f, 5.0f));

	// Here i am using the auto senders, each node has its personal auto send animator, allowing you to send data at specified
	// intervals. Here I am sending the position every second (1000 ms), the rotation every 50 ms, and the frame every 100 ms.
	// (Frame defaults to 100 ms if no second value is entered.) Please note all others default to 0, or as much as possible.
	netmgr->sendPositionAuto(ninja, 1000);
	netmgr->sendRotationAuto(ninja, 50);
	netmgr->sendFrameAuto(ninja);

	// Create the camera animator (Only attaching locally because we only want camera on our own ninja.)
	camAnim = new CSceneNodeAnimator3PCamera(smgr,cursor,ninja,50,180,10,irr::core::vector3df(0,20,0));
	camera->addAnimator(camAnim);
	camAnim->drop();
	camera->setNearValue(3.5f);
	camera->setFOV(PI / 3.0f);

	// Create the player animator (Same here we only want to control our own ninja.)
	ninjaAnim = new CSceneNodeAnimator3PPlayer(device,camera,camAnim,1.5f,selector, netmgr);
	ninja->addAnimator(ninjaAnim);
	ninjaAnim->drop();

	// Get rid of annoying mouse
	cursor->setVisible(false);


	//netmgr->setDefaultHandling(false);
	// Enable our custom handler.
	myCustomHandler* myHandler = new myCustomHandler();
	netmgr->setCustomHandling(true,myHandler);

	// Make the GUI elements. (Thanks to Rambus for his chatQue class.)
	// (Else this demo will spend too long covering the visual side!)
	// Remember to have a font in the proper directory!!!
	IGUIFont* guiFont = device->getGUIEnvironment()->getFont("media/font.bmp");
	chatQue = new ChatQue();
	chatQue->initialise(device,core::rect<s32>(20,400,700,520),guiFont,10000,500);
	chatQue->addMessage("Welcome to the Custom Handling with chat demo.");
	guienv->getSkin()->setFont(guienv->getFont("media/font.bmp"));
	editbox = guienv->addEditBox(L"",rect<s32>(20,500,800,600),false);
	editbox->setOverrideColor(SColor(255,255,255,255));
	
	int lastFPS = -1;
	switch1 = 1;
	
	myOutPacket = netmgr->createOutPacket(); // Make an OutPacket.

	// Main run loop
	while(device->run())
	{
			driver->beginScene(true, true,irr::video::SColor(0,0,0,0));
			smgr->drawAll();
			guienv->drawAll(); // not that we have GUI stuff
			chatQue->draw();
			driver->endScene();


#ifdef CLIENT 
			netmgr->updateClient();
#else
			netmgr->updateServer();
#endif
		int fps = driver->getFPS();

		// Use the new feature "getPing" to retrieve the first ENet peer and use its "rountTripTime" variable as the ping :)
		// Please note that the ping may take a few seconds to stabilize after connection.
		ping = netmgr->getPing();

		if (lastFPS != fps)
		{
			wchar_t tmp[1024];
			swprintf_s(tmp, 1024, L"Network Test[%ls] fps: %d ping: %d", 
				driver->getName(), fps, ping);
			device->setWindowCaption(tmp);
			lastFPS = fps;
		}
	}

	// Kill renderer
	if(device)
	{
		device->drop();
		device = NULL;
	}
	return 0;
}

// And thats it! Easy peasy stuff...

I combined Example 2 and 3 to demostrate proof of concept on multiplayer + chat capability of IrrNet.

You're Welcome! 8)

Posted: Thu Feb 22, 2007 4:05 am
by monkeycracks
Very very nice, I like :D

Posted: Fri Feb 23, 2007 11:59 am
by BlindSide
Thanks dude, Ill be sure to stick something like this in the next release :D
Maybe other stuff too!

Posted: Sun Feb 25, 2007 12:40 am
by Midnight
like file transfer? 8)

Posted: Sun Feb 25, 2007 7:03 pm
by monkeycracks
Midnight wrote:like file transfer? 8)
Yes, file transfer pleeeaaaase.

Posted: Mon Feb 26, 2007 6:31 pm
by Rambus
" // And display it! (Dont forget to "(char*)" it!)
chatQue->addMessage((char*)buffer); "

Hey some one is actually using my chatQue :)

Posted: Fri Mar 02, 2007 11:08 am
by BlindSide
I think you should port precompiled demo Midnight, so people can experience how kool it is. Also you forgot to tell them to press "T" to start talking.

Posted: Wed Mar 14, 2007 4:27 pm
by fuzzybunnyonslaught
I have a stupid question or two... :oops:

Is IrrNet available to the general public, and if so where would you get it?

I searched the website and the API and there is not mention of it there.

EDIT: nevermind, I'm retarded
http://irrlicht.sourceforge.net/phpBB2/ ... ght=irrnet

Posted: Mon Mar 19, 2007 3:04 pm
by Midnight
BlindSide wrote:I think you should port precompiled demo Midnight, so people can experience how kool it is. Also you forgot to tell them to press "T" to start talking.
lol yeah I'm busy and it's all written in code.

this is depricated now please don't use it later then v0.35 everybody.

Posted: Tue Mar 20, 2007 5:40 am
by BlindSide
Actually it would still work, it just sucks cuz of sendframeauto offcourse...