commit 18b7ce6bc9116432f58d649267ddc93638b135a8 Author: rna88 Date: Sat Mar 10 20:07:10 2018 -0800 Initial commit. diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..60894cf --- /dev/null +++ b/.gitmodules @@ -0,0 +1,6 @@ +[submodule "zlib"] + path = zlib + url = https://github.com/madler/zlib +[submodule "enet"] + path = enet + url = https://github.com/rna88/enet diff --git a/README.md b/README.md new file mode 100644 index 0000000..93a58fc --- /dev/null +++ b/README.md @@ -0,0 +1,27 @@ +## Irrnet + +An updated version of the (irrNetLite)[http://irrlicht.sourceforge.net/forum/viewtopic.php?f=6&t=22658] networking library compiled against recent versions of (enet)[https://github.com/lsalzman/enet] and (zlib)[https://github.com/madler/zlib]. + +## Compiling for Linux + +When cloning use the `--recurse-submodules` flag to retrieve the enet and zlib libraries needed by the project: + +`git clone --recurse-submodules https://github.com/rna88/irrnet.git` + +Then run `make` in the `source/` directory to build the library. + +## Building examples + +Navigate to `examples/` and run: + +`./linux_buildAllExamples.sh` + +or to build them with optimizations: + +`./linux_buildAllExamples.sh release` + +The compiled binaries will be found in `examples/bin/` + + + +Original code by Ahmed Hilali. diff --git a/enet b/enet new file mode 160000 index 0000000..7900e72 --- /dev/null +++ b/enet @@ -0,0 +1 @@ +Subproject commit 7900e72b709798ac285431bf1860014c6e1caf91 diff --git a/examples/Example1/Makefile b/examples/Example1/Makefile new file mode 100644 index 0000000..f5c46fc --- /dev/null +++ b/examples/Example1/Makefile @@ -0,0 +1,28 @@ +CXX = g++ +Target := Example1 +TargetPath := ../bin/ +Sources := main.cpp + +CXXINCS = -I../../include/ + +#ifndef NDEBUG +CXXFLAGS_D = -g -Wall +#else +CXXFLAGS_R = -fexpensive-optimizations -O3 +#endif + +LDIR =../../lib/ +LIBS = -L$(LDIR) -lirrnet + +debug: main.cpp + $(CXX) $(CXXFLAGS_D) $(CXXINCS) -o $(Target) $(Sources) $(LIBS) + mv $(Target) $(TargetPath) + +release: main.cpp + $(CXX) $(CXXFLAGS_R) $(CXXINCS) -o $(Target) $(Sources) $(LIBS) + mv $(Target) $(TargetPath) + +clean: + rm -f *.o $(TargetPath)$(Target) + +.PHONY: clean debug release diff --git a/examples/Example1/main.cpp b/examples/Example1/main.cpp new file mode 100644 index 0000000..bfbc8ce --- /dev/null +++ b/examples/Example1/main.cpp @@ -0,0 +1,252 @@ +/* +Example 1: Packet Identification. + +In this example I will expain the basics of packet identification. +For a more basic introduction please refer to Tutorial.cpp first. +(Recommended) +*/ + +// Do the usual things here. +#include +#include + +using namespace irr; + +#pragma comment(lib, "irrNetLite.lib") +#pragma comment(lib, "ws2_32.lib") + +// Now, in this example, I will teach you the basics of packet +// identification. What is packet identification? For instance, +// lets say the client sends 3 floating point values to the server, +// how will the server now if these represent a position, a rotation, +// or something completely different? How will it even know these +// are floating point values and not integers, or maybe a 12-byte +// string? Obviously, we need some kind of mechanism to define this. +// So in this example, we are going to define a few basic packet +// types, that let us differentiate between the different kinds of +// information coming into our client/server. + +// I will start off by creating an enum that holds a simple id +// for each of our packet types. (Note, you don't have to +// explicitly set the values like I do, I am just doing that +// for clarity.) +enum E_PACKET_TYPE +{ + EPT_ROTATION = 1, + EPT_POWER = 2, + EPT_MESSAGE = 3 +}; + +// In this example we will create 2 different callback classes, one +// for the clients and one for the server. We will have an imaginary +// cannon on the server, and the clients can send messages to change +// it's angle and power. + +// The server callback. +class ServerNetCallback : public net::INetCallback +{ + // We will store a pointer to the net manager. + net::INetManager* netManager; + + // Here we will store the cannon's power and angle. + // Remember that f32 is just a typedef for float. + f32 cannonPower; + f32 cannonAngle; +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_ROTATION: + // We obtain the cannon angle from the packet. + packet >> cannonAngle; + std::cout << "The cannon angle is now " << cannonAngle << std::endl; + break; + case EPT_POWER: + // Same here. + packet >> cannonPower; + std::cout << "The cannon power is now " << cannonPower << std::endl; + break; + case EPT_MESSAGE: + // Now this is a special case (Pun intended, or is it even a pun?... nevermind), + // The client has sent us a message as a string, so we will just print that + // to the console. + core::stringc message; + packet >> message; + + // We can obtain a unique "player id" from a packet identifying the client that + // sent it. More details about the player id in a later example, for now we will + // just print it out with the message so we know whos saying what. + std::cout << "Client " << packet.getPlayerId() << " says: " << message.c_str(); + std::cout << std::endl; + break; + } + + // After handling a packet, we will send an updated status of the cannon to all clients. + net::SOutPacket rotationPacket; + + // The packet id is the first thing that goes in a packet. Note that I am casting it to a char, + // because that is what we want to store it as, to save space. Be careful to use the same types + // when sending and receiving, don't send as a char and receive as an int, it will cause trouble. + rotationPacket << (c8)EPT_ROTATION; + rotationPacket << cannonAngle; + + // Send the packet to all connected clients. + netManager->sendOutPacket(rotationPacket); + + // Send a power update too. + net::SOutPacket powerPacket; + powerPacket << (c8)EPT_POWER; + powerPacket << cannonPower; + netManager->sendOutPacket(powerPacket); + } +}; + +// The client callback. +class ClientNetCallback : public net::INetCallback +{ +public: + // 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_ROTATION: + f32 cannonAngle; + packet >> cannonAngle; + std::cout << "Server says that the cannon angle is now " << cannonAngle << std::endl; + break; + case EPT_POWER: + f32 cannonPower; + packet >> cannonPower; + std::cout << "Server says that the cannon power is now " << cannonPower << std::endl; + break; + default: + // We don't care about any other types, so we catch them here and break. + break; + } + } +}; + +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; + } + else + { + // 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"); + + // Print a simple menu. + std::cout << "Example 1. What would you like to do?" << std::endl + << "1. Change the cannon rotation." << std::endl + << "2. Change the cannon power." << std::endl + << "3. Send a message." << std::endl; + + // Take the input. + char i = 0; + std::cin >> i; + + // Switch based on input. + switch(i) + { + case '1': + { + // Here we create a rotation packet and send it to the server. + net::SOutPacket rotationPacket; + rotationPacket << (c8)EPT_ROTATION; // Remember to cast to the correct type. + + // Ask for the rotation. + f32 rotation; + std::cout << "Please enter a rotation: "; + std::cin >> rotation; + rotationPacket << rotation; + netManager->sendOutPacket(rotationPacket); + break; + } + case '2': + { + // And here we create a power packet and send it to the server. + net::SOutPacket powerPacket; + powerPacket << (c8)EPT_POWER; // Remember to cast to the correct type. + // Ask for the power. + f32 power; + std::cout << "Please enter the power: "; + std::cin >> power; + powerPacket << power; + netManager->sendOutPacket(powerPacket); + break; + } + case '3': + { + // We'll also send the server a message in the form of a string. + net::SOutPacket messagePacket; + messagePacket << (c8)EPT_MESSAGE; // Remember to cast to the correct type. + // Ask for the message. + char message[512] = {}; + std::cout << "Please enter a message:" << std::endl; + std::cin >> message; + messagePacket << message; + netManager->sendOutPacket(messagePacket); + break; + } + default: + break; + } + + // Here is the update loop, we will exit if there is a connection problem. + while(netManager->getConnectionStatus() != net::EICS_FAILED) + { + // Here we update. + netManager->update(1000); + } + + // Clean up. + delete netManager; + delete clientCallback; + } + + // And we're done, return 0 and make like a banana. + return 0; +} diff --git a/examples/Example2/Makefile b/examples/Example2/Makefile new file mode 100644 index 0000000..b8c38ed --- /dev/null +++ b/examples/Example2/Makefile @@ -0,0 +1,28 @@ +CXX = g++ +Target := Example2 +TargetPath := ../bin/ +Sources := main.cpp + +CXXINCS = -I../../include/ + +#ifndef NDEBUG +CXXFLAGS_D = -g -Wall +#else +CXXFLAGS_R = -fexpensive-optimizations -O3 +#endif + +LDIR =../../lib/ +LIBS = -L$(LDIR) -lirrnet + +debug: main.cpp + $(CXX) $(CXXFLAGS_D) $(CXXINCS) -o $(Target) $(Sources) $(LIBS) + mv $(Target) $(TargetPath) + +release: main.cpp + $(CXX) $(CXXFLAGS_R) $(CXXINCS) -o $(Target) $(Sources) $(LIBS) + mv $(Target) $(TargetPath) + +clean: + rm -f *.o $(TargetPath)$(Target) + +.PHONY: clean debug release diff --git a/examples/Example2/main.cpp b/examples/Example2/main.cpp new file mode 100644 index 0000000..5fcc50e --- /dev/null +++ b/examples/Example2/main.cpp @@ -0,0 +1,230 @@ +/* +Example 2: Client management. + +In this example I will demonstrate client management. +For a more basic introduction please refer to Tutorial.cpp first. +(Recommended) +*/ + +// Do the usual things here. +#include +#include + +using namespace irr; + +#pragma comment(lib, "irrNetLite.lib") +#pragma comment(lib, "ws2_32.lib") + +// In this tutorial, I will show you how to kick/ban clients, +// set a limit on how many clients can join a server, and +// respond when a client connects/disconnects. + +// Our server callback will be doing a little more than just +// handling packets this time. We will override 2 more virtual +// methods, onConnect and onDisconnect, that will notify us +// with the player id of the client that has just connected or +// disconnected. What is a player id? A player id is a unique +// number that irrNetLite assigns to a client when they connect +// to the server. The ids will start at 1 and grow until there +// are no available slots left. Ids are not specific to a +// computer or ip address, and are re-used when freed, +// so if the client with played id 1 disconnects, and +// a different one connects, he will take over that player id. +// You may be thinking, "But how do I know which player is +// connecting?" or, "How can I ban a player with a specific +// ip address using this system?". These questions will be +// answered in this tutorial, so pay close attention. +class ServerNetCallback : public net::INetCallback +{ +public: + ServerNetCallback(net::INetManager* netManagerIn) : netManager(netManagerIn) {} + + // Override the "onConnect" function, don't forget to get the method + // signature correct. Whenever a fresh client connects, their brand + // spanking new player id will be passed to this function. A "u16" + // is a typedef for an unsigned short, incase you were wondering. + virtual void onConnect(const u16 playerId) + { + // When a client connects we inform all other connected + // clients that a client with that player id has connected. + + // But first, lets say that we have already banned a few + // clients from this server, and that we are keeping a list + // of all the banned ip addresses. We can simply use + // "getClientAddress()", to obtain the 32-bit representation + // of the ip address and check it against the list. + bool playerIsBanned = false; + for(int i = 0;i < banList.size();++i) + { + if(netManager->getClientAddress(playerId) == banList[i]) + { + playerIsBanned = true; + break; + } + } + + // If the player is banned, send a message to all connected + // clients that a player that is banned tried to connect + // and then kick the naughty player. + if(playerIsBanned) + { + net::SOutPacket packet; + packet << "A player that is banned tried to connect, " \ + "so I kicked them."; + netManager->sendOutPacket(packet); + + // Kick the client by passing the player id. + netManager->kickClient(playerId); + } + else // Else we tell everyone who connected. + { + // I am using a core::stringc here, it is very + // similar to a std::string. You can use a std::string + // if you want. + net::SOutPacket packet; + core::stringc message; + message = "Client number "; + message += playerId; + message += " has just connected."; + packet << message; + netManager->sendOutPacket(packet); + } + } + + // Similar to the onConnect function, except it happens when a + // player disconnects. When this happens we will just report + // which player has disconnected. + virtual void onDisconnect(const u16 playerId) + { + net::SOutPacket packet; + core::stringc message; + message = "Client number "; + message += playerId; + message += " has just left the building."; + packet << message; + netManager->sendOutPacket(packet); + } + + // Handle the packets, as usual. + virtual void handlePacket(net::SInPacket& packet) + { + // Now, we need a good reason to ban players. + // Lets say I don't like people who talk alot, + // so lets ban anyone who sends a greeting message + // that is longer than 20 characters, else just + // print the welcome message. + core::stringc message; + packet >> message; + + // We can grab the unique player id of the player + // that sent the packet from the packet itself. + u16 playerId = packet.getPlayerId(); + + + if(message.size() > 20) + { + // Kick and ban the player by adding their address to our list. + netManager->kickClient(playerId); + u32 address = netManager->getClientAddress(playerId); + banList.push_back(address); + std::cout << "Player from " << address << " banned." << std::endl; + } + else + { + // Print the message. + std::cout << "Client " << playerId << " said " << message.c_str() << std::endl; + } + } + +private: + // An array of "u32", a typedef for unsigned int. This core::array is a + // custom implementation of a dynamic array, very similar to std::vector. + core::array banList; + + // A pointer to the INetManager. + net::INetManager* netManager; +}; + +// The client callback. +class ClientNetCallback : public net::INetCallback +{ +public: + // Our handlePacket function. + virtual void handlePacket(net::SInPacket& packet) + { + // Very simple callback, just echo what the server says. + core::stringc message; + packet >> message; + std::cout << "Server says: " << message.c_str() << std::endl; + } +}; + +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; + } + else + { + // 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, especially for this example as, + // if you run all the clients from the same pc and ban one, you + // won't be able to create anymore clients unless you restart the server. + ClientNetCallback* clientCallback = new ClientNetCallback(); + net::INetManager* netManager = net::createIrrNetClient(clientCallback, "127.0.0.1"); + + // The clients in this example will simply send a custom greeting message + // when they connect and then wait and poll for events. + + // If there wasn't a problem connecting we will send a greeting message. + if(netManager->getConnectionStatus() != net::EICS_FAILED) + { + // Print a simple menu. + std::cout << "Example 2. Please enter a greeting message:" << std::endl; + + // Take the input. + std::string message; + std::cin >> message; + + // Send a packet with the message entered. + net::SOutPacket packet; + packet << message; + netManager->sendOutPacket(packet); + } + + // Here is the update loop, we will exit if there is a connection problem. + while(netManager->getConnectionStatus() != net::EICS_FAILED) + { + // Here we update. + netManager->update(1000); + } + + // Clean up. + delete netManager; + delete clientCallback; + } + + // And we're done, return 0 and make like an egg. + return 0; +} diff --git a/examples/Tutorial/Makefile b/examples/Tutorial/Makefile new file mode 100644 index 0000000..90cc69a --- /dev/null +++ b/examples/Tutorial/Makefile @@ -0,0 +1,28 @@ +CXX = g++ +Target := Tutorial +TargetPath := ../bin/ +Sources := main.cpp + +CXXINCS = -I../../include/ + +#ifndef NDEBUG +CXXFLAGS_D = -g -Wall +#else +CXXFLAGS_R = -fexpensive-optimizations -O3 +#endif + +LDIR =../../lib/ +LIBS = -L$(LDIR) -lirrnet + +debug: main.cpp + $(CXX) $(CXXFLAGS_D) $(CXXINCS) -o $(Target) $(Sources) $(LIBS) + mv $(Target) $(TargetPath) + +release: main.cpp + $(CXX) $(CXXFLAGS_R) $(CXXINCS) -o $(Target) $(Sources) $(LIBS) + mv $(Target) $(TargetPath) + +clean: + rm -f *.o $(TargetPath)$(Target) + +.PHONY: clean debug release diff --git a/examples/Tutorial/main.cpp b/examples/Tutorial/main.cpp new file mode 100644 index 0000000..6effa23 --- /dev/null +++ b/examples/Tutorial/main.cpp @@ -0,0 +1,177 @@ +/* +Welcome to the simple, introductory tutorial for irrNetLite. This will show you the +very basics of setting up a client and server, and sending and receiving packets. +Because irrNetLite is so easy to use, I think you will not find many actual lines of +code in this example, rather most of it is documentation. + +For much more sophisticated use of irrNetLite, I recommend taking a look in the +examples subdirectory. +*/ + +// Include the main irrNet.h header for irrNetLite. +#include +#include + +// irrNetLite resides within the irr::net:: namespace, therefore, +// we use "using namespace irr" here to simplify things. +// Alternatively you can add "using namespace net" after +// this so that net:: doesn't have to be used either. +using namespace irr; + +// These pragmas are for MSVC users, they ease the linking of librarys. +// "ws2_32.lib" is part of the Windows Platform SDK and must be linked +// in when compiling on windows. On linux/mac machines, these pragmas +// will simply be ignored, and the linking to irrNetLite static lib +// should be performed by a makefile. +#pragma comment(lib, "irrNetLite.lib") +#pragma comment(lib, "ws2_32.lib") + +// You must derive a class from INetCallback and override the +// "handlePacket" method. When a packet is received it will be +// passed to this function, and you may dissect it as you wish. +// If this is the server you may retrieve the player ID using +// packet.getPlayerId(). +class MyNetCallback : public net::INetCallback +{ +public: + virtual void handlePacket(net::SInPacket& packet) + { + // irrNetLite encryption is very easy to use! Just pass + // a 16-byte (128-bit) string to encryptPacket/decryptPacket + // to encrypt/decrypt a packet respectively. Do not try to + // decrypt an un-encrypted packet or read from an encrypted + // packet without decrypting it first or bad things will happen! + packet.decryptPacket("hushthisissecret"); + + // irrNetLite compression is even easier! The ZLib library is used + // here, just call compressPacket/decompressPacket to + // compress/decompress a packet. Again, do not try to decompress + // an un-compressed packet or read from a compressed packet without + // decompressing it! Another thing to keep in mind is that you should + // decompress and decrypt in the correct order. If you compressed a file + // and then encrypted it when it was sent, you must decrypt it first + // before trying to decompress it, same goes for the other order. + packet.deCompressPacket(); + + // Extracting info from a received packet is simple. You can treat + // the packet as an input stream, the >> operator is overloaded + // and works for most built in types. The string class in irrNetLite + // is a custom implementation not unlike the std::string. You can + // also send and receive strings as "char*". Note that the "char*" + // and stringc are interchangeable, you can send a stringc and + // receive a char*, or vice-versa. + core::stringc str; + packet >> str; + + // Support for a simple 3-dimensional vector class is there too. Both + // vector3df and core::stringc are borrowed from Irrlicht and included + // here for convenience. + core::vector3df vec; + packet >> vec; + + // Here we are obtaining the last value from the packet. f32 is just a + // typedef for float. + f32 height; + packet >> height; + + // Print the values to the console. + std::cout << "Message: " << str.c_str(); + std::cout << " Position: " << vec.X << " " << vec.Y << " " << vec.Z; + std::cout << " Height: " << height << " ft"; + std::cout << std::endl; + } +}; + +// Ok, lets go from the start, int 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 a server and pass in a new instance of our callback class. The default + // port that clients can connect to is set to 45000. + MyNetCallback* netCallback = new MyNetCallback(); + net::INetManager* netManager = net::createIrrNetServer(netCallback); + + // Setting verbose to true makes irrNetLite spit out debug information to the console. + netManager->setVerbose(true); + + // While the connection is active (Not failed), we update the netManager. + // Note that since this is a server the connection will pretty much always + // be flagged as active, unless some error occured whilst creating the server. + // A value of 1000 is passed to update to make it hang for a second and wait for + // packets to arrive. (Recommended for servers, so you don't busy-loop). + while(netManager->getConnectionStatus() != net::EICS_FAILED) + netManager->update(1000); + + // Don't forget to clean up! + delete netManager; + delete netCallback; + } + else + { + // Create an irrNet client, in this example we will just connect to the localhost + // address ("127.0.0.1"), which basically means we are connecting to the same + // computer the client is on. Note that we just pass a value of 0 as our + // INetCallback, because the client in this example does no need to handle any + // packets. You can safely pass a value of 0 if this is the case. + net::INetManager* netManager = net::createIrrNetClient(0, "127.0.0.1"); + + // Enable debug messages. + netManager->setVerbose(true); + + // Here comes the fun part, while the client is connected we update the netManager + // and ask it to wait 1 second (1000 milliseconds) for new packets to arrive before + // returning. Since the client in this example doesn't actually receive any packets, + // the only purpose of the update call is to leave a 1 second interval between each + // packet we send. + + int i = 0; + // To send a packet, first you create an SOutPacket object. + net::SOutPacket packet; + + while(netManager->getConnectionStatus() != net::EICS_FAILED && i < 10 ) + { + + // To send a packet, first you create an SOutPacket object. + //net::SOutPacket packet; + + // Then you can use the streaming operator << to add new data to it. + packet << "Help I am stuck on a mountain!"; + + // You can even chain the << operators like so, just like with ostream. + packet << core::vector3df(50.0f, 30.0f, 20.0f) << 50.0f; + + // Compress the packet, not much to be said. + packet.compressPacket(); + + // Encrypt the packet. Note that here we are just using a simple key + // that is shared among the client and the server. In more sophisticated + // implementations you may want to generate a random key on the server for + // each client and send that using a shared key, then use the new key for + // further communication. Remember that the key should be 16 characters + // long, and obviously the client and server must share the same key. + packet.encryptPacket("hushthisissecret"); + + // A simple call to "sendOutPacket" will send the packet to the server. + netManager->sendOutPacket(packet); + + netManager->update(1000); + packet.clearData(); + i++; + } + + // When the connection disconnects (Or fails), the loop will terminate. + // Remember to delete the netManager so that all the low level networking + // stuff is cleaned up properly. + delete netManager; + } + + // And we're done, return 0 and make like a tree. + return 0; +} diff --git a/examples/bin/Example1 b/examples/bin/Example1 new file mode 100755 index 0000000..46b2875 Binary files /dev/null and b/examples/bin/Example1 differ diff --git a/examples/bin/Example2 b/examples/bin/Example2 new file mode 100755 index 0000000..ebeefd2 Binary files /dev/null and b/examples/bin/Example2 differ diff --git a/examples/bin/Tutorial b/examples/bin/Tutorial new file mode 100755 index 0000000..28c6b61 Binary files /dev/null and b/examples/bin/Tutorial differ diff --git a/examples/linux_compile_all.sh b/examples/linux_compile_all.sh new file mode 100755 index 0000000..47a9caa --- /dev/null +++ b/examples/linux_compile_all.sh @@ -0,0 +1,15 @@ +#! /bin/bash +[ -z $1 ] || TARGET=$1 +[ -z $TARGET ] && TARGET=debug +for i in Tutorial Example* ; do + echo "Building $i"; + pushd $i && make clean $TARGET; + popd; +done + + + + +#g++ Tutorial.cpp -I../irrnet -L../lib -lirrnet -o Tutorial +#g++ Example1.cpp -I../irrnet -L../lib -lirrnet -o Example1 +#g++ Example2.cpp -I../irrnet -L../lib -lirrnet -o Example2 diff --git a/include/CEncryption.h b/include/CEncryption.h new file mode 100644 index 0000000..b0a144f --- /dev/null +++ b/include/CEncryption.h @@ -0,0 +1,411 @@ +// AES encryption class, based on work by Karl Malbrain, malbrain@yahoo.com, +// original license shown here: + +/* +This work, including the source code, documentation +and related data, is placed into the public domain. + +The orginal author is Karl Malbrain. + +THIS SOFTWARE IS PROVIDED AS-IS WITHOUT WARRANTY +OF ANY KIND, NOT EVEN THE IMPLIED WARRANTY OF +MERCHANTABILITY. THE AUTHOR OF THIS SOFTWARE, +ASSUMES _NO_ RESPONSIBILITY FOR ANY CONSEQUENCE +RESULTING FROM THE USE, MODIFICATION, OR +REDISTRIBUTION OF THIS SOFTWARE. +*/ + +typedef unsigned char uchar; +#include +#include + +// AES only supports Nb=4 +#define Nb 4 // number of columns in the state & expanded key + +#define Nk 4 // number of columns in a key +#define Nr 10 // number of rounds in encryption + +static const uchar Sbox[256] = { // forward s-box +0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, +0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, +0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, +0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, +0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, +0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, +0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, +0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, +0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, +0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, +0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, +0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, +0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, +0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, +0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, +0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16}; + +static const uchar InvSbox[256] = { // inverse s-box +0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb, +0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb, +0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e, +0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25, +0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92, +0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84, +0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06, +0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b, +0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73, +0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e, +0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b, +0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4, +0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f, +0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef, +0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61, +0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d}; + +// combined Xtimes2[Sbox[]] +static const uchar Xtime2Sbox[256] = { +0xc6, 0xf8, 0xee, 0xf6, 0xff, 0xd6, 0xde, 0x91, 0x60, 0x02, 0xce, 0x56, 0xe7, 0xb5, 0x4d, 0xec, +0x8f, 0x1f, 0x89, 0xfa, 0xef, 0xb2, 0x8e, 0xfb, 0x41, 0xb3, 0x5f, 0x45, 0x23, 0x53, 0xe4, 0x9b, +0x75, 0xe1, 0x3d, 0x4c, 0x6c, 0x7e, 0xf5, 0x83, 0x68, 0x51, 0xd1, 0xf9, 0xe2, 0xab, 0x62, 0x2a, +0x08, 0x95, 0x46, 0x9d, 0x30, 0x37, 0x0a, 0x2f, 0x0e, 0x24, 0x1b, 0xdf, 0xcd, 0x4e, 0x7f, 0xea, +0x12, 0x1d, 0x58, 0x34, 0x36, 0xdc, 0xb4, 0x5b, 0xa4, 0x76, 0xb7, 0x7d, 0x52, 0xdd, 0x5e, 0x13, +0xa6, 0xb9, 0x00, 0xc1, 0x40, 0xe3, 0x79, 0xb6, 0xd4, 0x8d, 0x67, 0x72, 0x94, 0x98, 0xb0, 0x85, +0xbb, 0xc5, 0x4f, 0xed, 0x86, 0x9a, 0x66, 0x11, 0x8a, 0xe9, 0x04, 0xfe, 0xa0, 0x78, 0x25, 0x4b, +0xa2, 0x5d, 0x80, 0x05, 0x3f, 0x21, 0x70, 0xf1, 0x63, 0x77, 0xaf, 0x42, 0x20, 0xe5, 0xfd, 0xbf, +0x81, 0x18, 0x26, 0xc3, 0xbe, 0x35, 0x88, 0x2e, 0x93, 0x55, 0xfc, 0x7a, 0xc8, 0xba, 0x32, 0xe6, +0xc0, 0x19, 0x9e, 0xa3, 0x44, 0x54, 0x3b, 0x0b, 0x8c, 0xc7, 0x6b, 0x28, 0xa7, 0xbc, 0x16, 0xad, +0xdb, 0x64, 0x74, 0x14, 0x92, 0x0c, 0x48, 0xb8, 0x9f, 0xbd, 0x43, 0xc4, 0x39, 0x31, 0xd3, 0xf2, +0xd5, 0x8b, 0x6e, 0xda, 0x01, 0xb1, 0x9c, 0x49, 0xd8, 0xac, 0xf3, 0xcf, 0xca, 0xf4, 0x47, 0x10, +0x6f, 0xf0, 0x4a, 0x5c, 0x38, 0x57, 0x73, 0x97, 0xcb, 0xa1, 0xe8, 0x3e, 0x96, 0x61, 0x0d, 0x0f, +0xe0, 0x7c, 0x71, 0xcc, 0x90, 0x06, 0xf7, 0x1c, 0xc2, 0x6a, 0xae, 0x69, 0x17, 0x99, 0x3a, 0x27, +0xd9, 0xeb, 0x2b, 0x22, 0xd2, 0xa9, 0x07, 0x33, 0x2d, 0x3c, 0x15, 0xc9, 0x87, 0xaa, 0x50, 0xa5, +0x03, 0x59, 0x09, 0x1a, 0x65, 0xd7, 0x84, 0xd0, 0x82, 0x29, 0x5a, 0x1e, 0x7b, 0xa8, 0x6d, 0x2c +}; + +// combined Xtimes3[Sbox[]] +static const uchar Xtime3Sbox[256] = { +0xa5, 0x84, 0x99, 0x8d, 0x0d, 0xbd, 0xb1, 0x54, 0x50, 0x03, 0xa9, 0x7d, 0x19, 0x62, 0xe6, 0x9a, +0x45, 0x9d, 0x40, 0x87, 0x15, 0xeb, 0xc9, 0x0b, 0xec, 0x67, 0xfd, 0xea, 0xbf, 0xf7, 0x96, 0x5b, +0xc2, 0x1c, 0xae, 0x6a, 0x5a, 0x41, 0x02, 0x4f, 0x5c, 0xf4, 0x34, 0x08, 0x93, 0x73, 0x53, 0x3f, +0x0c, 0x52, 0x65, 0x5e, 0x28, 0xa1, 0x0f, 0xb5, 0x09, 0x36, 0x9b, 0x3d, 0x26, 0x69, 0xcd, 0x9f, +0x1b, 0x9e, 0x74, 0x2e, 0x2d, 0xb2, 0xee, 0xfb, 0xf6, 0x4d, 0x61, 0xce, 0x7b, 0x3e, 0x71, 0x97, +0xf5, 0x68, 0x00, 0x2c, 0x60, 0x1f, 0xc8, 0xed, 0xbe, 0x46, 0xd9, 0x4b, 0xde, 0xd4, 0xe8, 0x4a, +0x6b, 0x2a, 0xe5, 0x16, 0xc5, 0xd7, 0x55, 0x94, 0xcf, 0x10, 0x06, 0x81, 0xf0, 0x44, 0xba, 0xe3, +0xf3, 0xfe, 0xc0, 0x8a, 0xad, 0xbc, 0x48, 0x04, 0xdf, 0xc1, 0x75, 0x63, 0x30, 0x1a, 0x0e, 0x6d, +0x4c, 0x14, 0x35, 0x2f, 0xe1, 0xa2, 0xcc, 0x39, 0x57, 0xf2, 0x82, 0x47, 0xac, 0xe7, 0x2b, 0x95, +0xa0, 0x98, 0xd1, 0x7f, 0x66, 0x7e, 0xab, 0x83, 0xca, 0x29, 0xd3, 0x3c, 0x79, 0xe2, 0x1d, 0x76, +0x3b, 0x56, 0x4e, 0x1e, 0xdb, 0x0a, 0x6c, 0xe4, 0x5d, 0x6e, 0xef, 0xa6, 0xa8, 0xa4, 0x37, 0x8b, +0x32, 0x43, 0x59, 0xb7, 0x8c, 0x64, 0xd2, 0xe0, 0xb4, 0xfa, 0x07, 0x25, 0xaf, 0x8e, 0xe9, 0x18, +0xd5, 0x88, 0x6f, 0x72, 0x24, 0xf1, 0xc7, 0x51, 0x23, 0x7c, 0x9c, 0x21, 0xdd, 0xdc, 0x86, 0x85, +0x90, 0x42, 0xc4, 0xaa, 0xd8, 0x05, 0x01, 0x12, 0xa3, 0x5f, 0xf9, 0xd0, 0x91, 0x58, 0x27, 0xb9, +0x38, 0x13, 0xb3, 0x33, 0xbb, 0x70, 0x89, 0xa7, 0xb6, 0x22, 0x92, 0x20, 0x49, 0xff, 0x78, 0x7a, +0x8f, 0xf8, 0x80, 0x17, 0xda, 0x31, 0xc6, 0xb8, 0xc3, 0xb0, 0x77, 0x11, 0xcb, 0xfc, 0xd6, 0x3a +}; + +// modular multiplication tables +// based on: + +// Xtime2[x] = (x & 0x80 ? 0x1b : 0) ^ (x + x) +// Xtime3[x] = x^Xtime2[x]; + +static const uchar Xtime2[256] = { +0x00, 0x02, 0x04, 0x06, 0x08, 0x0a, 0x0c, 0x0e, 0x10, 0x12, 0x14, 0x16, 0x18, 0x1a, 0x1c, 0x1e, +0x20, 0x22, 0x24, 0x26, 0x28, 0x2a, 0x2c, 0x2e, 0x30, 0x32, 0x34, 0x36, 0x38, 0x3a, 0x3c, 0x3e, +0x40, 0x42, 0x44, 0x46, 0x48, 0x4a, 0x4c, 0x4e, 0x50, 0x52, 0x54, 0x56, 0x58, 0x5a, 0x5c, 0x5e, +0x60, 0x62, 0x64, 0x66, 0x68, 0x6a, 0x6c, 0x6e, 0x70, 0x72, 0x74, 0x76, 0x78, 0x7a, 0x7c, 0x7e, +0x80, 0x82, 0x84, 0x86, 0x88, 0x8a, 0x8c, 0x8e, 0x90, 0x92, 0x94, 0x96, 0x98, 0x9a, 0x9c, 0x9e, +0xa0, 0xa2, 0xa4, 0xa6, 0xa8, 0xaa, 0xac, 0xae, 0xb0, 0xb2, 0xb4, 0xb6, 0xb8, 0xba, 0xbc, 0xbe, +0xc0, 0xc2, 0xc4, 0xc6, 0xc8, 0xca, 0xcc, 0xce, 0xd0, 0xd2, 0xd4, 0xd6, 0xd8, 0xda, 0xdc, 0xde, +0xe0, 0xe2, 0xe4, 0xe6, 0xe8, 0xea, 0xec, 0xee, 0xf0, 0xf2, 0xf4, 0xf6, 0xf8, 0xfa, 0xfc, 0xfe, +0x1b, 0x19, 0x1f, 0x1d, 0x13, 0x11, 0x17, 0x15, 0x0b, 0x09, 0x0f, 0x0d, 0x03, 0x01, 0x07, 0x05, +0x3b, 0x39, 0x3f, 0x3d, 0x33, 0x31, 0x37, 0x35, 0x2b, 0x29, 0x2f, 0x2d, 0x23, 0x21, 0x27, 0x25, +0x5b, 0x59, 0x5f, 0x5d, 0x53, 0x51, 0x57, 0x55, 0x4b, 0x49, 0x4f, 0x4d, 0x43, 0x41, 0x47, 0x45, +0x7b, 0x79, 0x7f, 0x7d, 0x73, 0x71, 0x77, 0x75, 0x6b, 0x69, 0x6f, 0x6d, 0x63, 0x61, 0x67, 0x65, +0x9b, 0x99, 0x9f, 0x9d, 0x93, 0x91, 0x97, 0x95, 0x8b, 0x89, 0x8f, 0x8d, 0x83, 0x81, 0x87, 0x85, +0xbb, 0xb9, 0xbf, 0xbd, 0xb3, 0xb1, 0xb7, 0xb5, 0xab, 0xa9, 0xaf, 0xad, 0xa3, 0xa1, 0xa7, 0xa5, +0xdb, 0xd9, 0xdf, 0xdd, 0xd3, 0xd1, 0xd7, 0xd5, 0xcb, 0xc9, 0xcf, 0xcd, 0xc3, 0xc1, 0xc7, 0xc5, +0xfb, 0xf9, 0xff, 0xfd, 0xf3, 0xf1, 0xf7, 0xf5, 0xeb, 0xe9, 0xef, 0xed, 0xe3, 0xe1, 0xe7, 0xe5}; + +static const uchar Xtime9[256] = { +0x00, 0x09, 0x12, 0x1b, 0x24, 0x2d, 0x36, 0x3f, 0x48, 0x41, 0x5a, 0x53, 0x6c, 0x65, 0x7e, 0x77, +0x90, 0x99, 0x82, 0x8b, 0xb4, 0xbd, 0xa6, 0xaf, 0xd8, 0xd1, 0xca, 0xc3, 0xfc, 0xf5, 0xee, 0xe7, +0x3b, 0x32, 0x29, 0x20, 0x1f, 0x16, 0x0d, 0x04, 0x73, 0x7a, 0x61, 0x68, 0x57, 0x5e, 0x45, 0x4c, +0xab, 0xa2, 0xb9, 0xb0, 0x8f, 0x86, 0x9d, 0x94, 0xe3, 0xea, 0xf1, 0xf8, 0xc7, 0xce, 0xd5, 0xdc, +0x76, 0x7f, 0x64, 0x6d, 0x52, 0x5b, 0x40, 0x49, 0x3e, 0x37, 0x2c, 0x25, 0x1a, 0x13, 0x08, 0x01, +0xe6, 0xef, 0xf4, 0xfd, 0xc2, 0xcb, 0xd0, 0xd9, 0xae, 0xa7, 0xbc, 0xb5, 0x8a, 0x83, 0x98, 0x91, +0x4d, 0x44, 0x5f, 0x56, 0x69, 0x60, 0x7b, 0x72, 0x05, 0x0c, 0x17, 0x1e, 0x21, 0x28, 0x33, 0x3a, +0xdd, 0xd4, 0xcf, 0xc6, 0xf9, 0xf0, 0xeb, 0xe2, 0x95, 0x9c, 0x87, 0x8e, 0xb1, 0xb8, 0xa3, 0xaa, +0xec, 0xe5, 0xfe, 0xf7, 0xc8, 0xc1, 0xda, 0xd3, 0xa4, 0xad, 0xb6, 0xbf, 0x80, 0x89, 0x92, 0x9b, +0x7c, 0x75, 0x6e, 0x67, 0x58, 0x51, 0x4a, 0x43, 0x34, 0x3d, 0x26, 0x2f, 0x10, 0x19, 0x02, 0x0b, +0xd7, 0xde, 0xc5, 0xcc, 0xf3, 0xfa, 0xe1, 0xe8, 0x9f, 0x96, 0x8d, 0x84, 0xbb, 0xb2, 0xa9, 0xa0, +0x47, 0x4e, 0x55, 0x5c, 0x63, 0x6a, 0x71, 0x78, 0x0f, 0x06, 0x1d, 0x14, 0x2b, 0x22, 0x39, 0x30, +0x9a, 0x93, 0x88, 0x81, 0xbe, 0xb7, 0xac, 0xa5, 0xd2, 0xdb, 0xc0, 0xc9, 0xf6, 0xff, 0xe4, 0xed, +0x0a, 0x03, 0x18, 0x11, 0x2e, 0x27, 0x3c, 0x35, 0x42, 0x4b, 0x50, 0x59, 0x66, 0x6f, 0x74, 0x7d, +0xa1, 0xa8, 0xb3, 0xba, 0x85, 0x8c, 0x97, 0x9e, 0xe9, 0xe0, 0xfb, 0xf2, 0xcd, 0xc4, 0xdf, 0xd6, +0x31, 0x38, 0x23, 0x2a, 0x15, 0x1c, 0x07, 0x0e, 0x79, 0x70, 0x6b, 0x62, 0x5d, 0x54, 0x4f, 0x46}; + +static const uchar XtimeB[256] = { +0x00, 0x0b, 0x16, 0x1d, 0x2c, 0x27, 0x3a, 0x31, 0x58, 0x53, 0x4e, 0x45, 0x74, 0x7f, 0x62, 0x69, +0xb0, 0xbb, 0xa6, 0xad, 0x9c, 0x97, 0x8a, 0x81, 0xe8, 0xe3, 0xfe, 0xf5, 0xc4, 0xcf, 0xd2, 0xd9, +0x7b, 0x70, 0x6d, 0x66, 0x57, 0x5c, 0x41, 0x4a, 0x23, 0x28, 0x35, 0x3e, 0x0f, 0x04, 0x19, 0x12, +0xcb, 0xc0, 0xdd, 0xd6, 0xe7, 0xec, 0xf1, 0xfa, 0x93, 0x98, 0x85, 0x8e, 0xbf, 0xb4, 0xa9, 0xa2, +0xf6, 0xfd, 0xe0, 0xeb, 0xda, 0xd1, 0xcc, 0xc7, 0xae, 0xa5, 0xb8, 0xb3, 0x82, 0x89, 0x94, 0x9f, +0x46, 0x4d, 0x50, 0x5b, 0x6a, 0x61, 0x7c, 0x77, 0x1e, 0x15, 0x08, 0x03, 0x32, 0x39, 0x24, 0x2f, +0x8d, 0x86, 0x9b, 0x90, 0xa1, 0xaa, 0xb7, 0xbc, 0xd5, 0xde, 0xc3, 0xc8, 0xf9, 0xf2, 0xef, 0xe4, +0x3d, 0x36, 0x2b, 0x20, 0x11, 0x1a, 0x07, 0x0c, 0x65, 0x6e, 0x73, 0x78, 0x49, 0x42, 0x5f, 0x54, +0xf7, 0xfc, 0xe1, 0xea, 0xdb, 0xd0, 0xcd, 0xc6, 0xaf, 0xa4, 0xb9, 0xb2, 0x83, 0x88, 0x95, 0x9e, +0x47, 0x4c, 0x51, 0x5a, 0x6b, 0x60, 0x7d, 0x76, 0x1f, 0x14, 0x09, 0x02, 0x33, 0x38, 0x25, 0x2e, +0x8c, 0x87, 0x9a, 0x91, 0xa0, 0xab, 0xb6, 0xbd, 0xd4, 0xdf, 0xc2, 0xc9, 0xf8, 0xf3, 0xee, 0xe5, +0x3c, 0x37, 0x2a, 0x21, 0x10, 0x1b, 0x06, 0x0d, 0x64, 0x6f, 0x72, 0x79, 0x48, 0x43, 0x5e, 0x55, +0x01, 0x0a, 0x17, 0x1c, 0x2d, 0x26, 0x3b, 0x30, 0x59, 0x52, 0x4f, 0x44, 0x75, 0x7e, 0x63, 0x68, +0xb1, 0xba, 0xa7, 0xac, 0x9d, 0x96, 0x8b, 0x80, 0xe9, 0xe2, 0xff, 0xf4, 0xc5, 0xce, 0xd3, 0xd8, +0x7a, 0x71, 0x6c, 0x67, 0x56, 0x5d, 0x40, 0x4b, 0x22, 0x29, 0x34, 0x3f, 0x0e, 0x05, 0x18, 0x13, +0xca, 0xc1, 0xdc, 0xd7, 0xe6, 0xed, 0xf0, 0xfb, 0x92, 0x99, 0x84, 0x8f, 0xbe, 0xb5, 0xa8, 0xa3}; + +static const uchar XtimeD[256] = { +0x00, 0x0d, 0x1a, 0x17, 0x34, 0x39, 0x2e, 0x23, 0x68, 0x65, 0x72, 0x7f, 0x5c, 0x51, 0x46, 0x4b, +0xd0, 0xdd, 0xca, 0xc7, 0xe4, 0xe9, 0xfe, 0xf3, 0xb8, 0xb5, 0xa2, 0xaf, 0x8c, 0x81, 0x96, 0x9b, +0xbb, 0xb6, 0xa1, 0xac, 0x8f, 0x82, 0x95, 0x98, 0xd3, 0xde, 0xc9, 0xc4, 0xe7, 0xea, 0xfd, 0xf0, +0x6b, 0x66, 0x71, 0x7c, 0x5f, 0x52, 0x45, 0x48, 0x03, 0x0e, 0x19, 0x14, 0x37, 0x3a, 0x2d, 0x20, +0x6d, 0x60, 0x77, 0x7a, 0x59, 0x54, 0x43, 0x4e, 0x05, 0x08, 0x1f, 0x12, 0x31, 0x3c, 0x2b, 0x26, +0xbd, 0xb0, 0xa7, 0xaa, 0x89, 0x84, 0x93, 0x9e, 0xd5, 0xd8, 0xcf, 0xc2, 0xe1, 0xec, 0xfb, 0xf6, +0xd6, 0xdb, 0xcc, 0xc1, 0xe2, 0xef, 0xf8, 0xf5, 0xbe, 0xb3, 0xa4, 0xa9, 0x8a, 0x87, 0x90, 0x9d, +0x06, 0x0b, 0x1c, 0x11, 0x32, 0x3f, 0x28, 0x25, 0x6e, 0x63, 0x74, 0x79, 0x5a, 0x57, 0x40, 0x4d, +0xda, 0xd7, 0xc0, 0xcd, 0xee, 0xe3, 0xf4, 0xf9, 0xb2, 0xbf, 0xa8, 0xa5, 0x86, 0x8b, 0x9c, 0x91, +0x0a, 0x07, 0x10, 0x1d, 0x3e, 0x33, 0x24, 0x29, 0x62, 0x6f, 0x78, 0x75, 0x56, 0x5b, 0x4c, 0x41, +0x61, 0x6c, 0x7b, 0x76, 0x55, 0x58, 0x4f, 0x42, 0x09, 0x04, 0x13, 0x1e, 0x3d, 0x30, 0x27, 0x2a, +0xb1, 0xbc, 0xab, 0xa6, 0x85, 0x88, 0x9f, 0x92, 0xd9, 0xd4, 0xc3, 0xce, 0xed, 0xe0, 0xf7, 0xfa, +0xb7, 0xba, 0xad, 0xa0, 0x83, 0x8e, 0x99, 0x94, 0xdf, 0xd2, 0xc5, 0xc8, 0xeb, 0xe6, 0xf1, 0xfc, +0x67, 0x6a, 0x7d, 0x70, 0x53, 0x5e, 0x49, 0x44, 0x0f, 0x02, 0x15, 0x18, 0x3b, 0x36, 0x21, 0x2c, +0x0c, 0x01, 0x16, 0x1b, 0x38, 0x35, 0x22, 0x2f, 0x64, 0x69, 0x7e, 0x73, 0x50, 0x5d, 0x4a, 0x47, +0xdc, 0xd1, 0xc6, 0xcb, 0xe8, 0xe5, 0xf2, 0xff, 0xb4, 0xb9, 0xae, 0xa3, 0x80, 0x8d, 0x9a, 0x97}; + +static const uchar XtimeE[256] = { +0x00, 0x0e, 0x1c, 0x12, 0x38, 0x36, 0x24, 0x2a, 0x70, 0x7e, 0x6c, 0x62, 0x48, 0x46, 0x54, 0x5a, +0xe0, 0xee, 0xfc, 0xf2, 0xd8, 0xd6, 0xc4, 0xca, 0x90, 0x9e, 0x8c, 0x82, 0xa8, 0xa6, 0xb4, 0xba, +0xdb, 0xd5, 0xc7, 0xc9, 0xe3, 0xed, 0xff, 0xf1, 0xab, 0xa5, 0xb7, 0xb9, 0x93, 0x9d, 0x8f, 0x81, +0x3b, 0x35, 0x27, 0x29, 0x03, 0x0d, 0x1f, 0x11, 0x4b, 0x45, 0x57, 0x59, 0x73, 0x7d, 0x6f, 0x61, +0xad, 0xa3, 0xb1, 0xbf, 0x95, 0x9b, 0x89, 0x87, 0xdd, 0xd3, 0xc1, 0xcf, 0xe5, 0xeb, 0xf9, 0xf7, +0x4d, 0x43, 0x51, 0x5f, 0x75, 0x7b, 0x69, 0x67, 0x3d, 0x33, 0x21, 0x2f, 0x05, 0x0b, 0x19, 0x17, +0x76, 0x78, 0x6a, 0x64, 0x4e, 0x40, 0x52, 0x5c, 0x06, 0x08, 0x1a, 0x14, 0x3e, 0x30, 0x22, 0x2c, +0x96, 0x98, 0x8a, 0x84, 0xae, 0xa0, 0xb2, 0xbc, 0xe6, 0xe8, 0xfa, 0xf4, 0xde, 0xd0, 0xc2, 0xcc, +0x41, 0x4f, 0x5d, 0x53, 0x79, 0x77, 0x65, 0x6b, 0x31, 0x3f, 0x2d, 0x23, 0x09, 0x07, 0x15, 0x1b, +0xa1, 0xaf, 0xbd, 0xb3, 0x99, 0x97, 0x85, 0x8b, 0xd1, 0xdf, 0xcd, 0xc3, 0xe9, 0xe7, 0xf5, 0xfb, +0x9a, 0x94, 0x86, 0x88, 0xa2, 0xac, 0xbe, 0xb0, 0xea, 0xe4, 0xf6, 0xf8, 0xd2, 0xdc, 0xce, 0xc0, +0x7a, 0x74, 0x66, 0x68, 0x42, 0x4c, 0x5e, 0x50, 0x0a, 0x04, 0x16, 0x18, 0x32, 0x3c, 0x2e, 0x20, +0xec, 0xe2, 0xf0, 0xfe, 0xd4, 0xda, 0xc8, 0xc6, 0x9c, 0x92, 0x80, 0x8e, 0xa4, 0xaa, 0xb8, 0xb6, +0x0c, 0x02, 0x10, 0x1e, 0x34, 0x3a, 0x28, 0x26, 0x7c, 0x72, 0x60, 0x6e, 0x44, 0x4a, 0x58, 0x56, +0x37, 0x39, 0x2b, 0x25, 0x0f, 0x01, 0x13, 0x1d, 0x47, 0x49, 0x5b, 0x55, 0x7f, 0x71, 0x63, 0x6d, +0xd7, 0xd9, 0xcb, 0xc5, 0xef, 0xe1, 0xf3, 0xfd, 0xa7, 0xa9, 0xbb, 0xb5, 0x9f, 0x91, 0x83, 0x8d}; + +// exchanges columns in each of 4 rows +// row0 - unchanged, row1- shifted left 1, +// row2 - shifted left 2 and row3 - shifted left 3 +static void ShiftRows (uchar *state) +{ + uchar tmp; + + // just substitute row 0 + state[0] = Sbox[state[0]], state[4] = Sbox[state[4]]; + state[8] = Sbox[state[8]], state[12] = Sbox[state[12]]; + + // rotate row 1 + tmp = Sbox[state[1]], state[1] = Sbox[state[5]]; + state[5] = Sbox[state[9]], state[9] = Sbox[state[13]], state[13] = tmp; + + // rotate row 2 + tmp = Sbox[state[2]], state[2] = Sbox[state[10]], state[10] = tmp; + tmp = Sbox[state[6]], state[6] = Sbox[state[14]], state[14] = tmp; + + // rotate row 3 + tmp = Sbox[state[15]], state[15] = Sbox[state[11]]; + state[11] = Sbox[state[7]], state[7] = Sbox[state[3]], state[3] = tmp; +} + +// restores columns in each of 4 rows +// row0 - unchanged, row1- shifted right 1, +// row2 - shifted right 2 and row3 - shifted right 3 +static void InvShiftRows (uchar *state) +{ + uchar tmp; + + // restore row 0 + state[0] = InvSbox[state[0]], state[4] = InvSbox[state[4]]; + state[8] = InvSbox[state[8]], state[12] = InvSbox[state[12]]; + + // restore row 1 + tmp = InvSbox[state[13]], state[13] = InvSbox[state[9]]; + state[9] = InvSbox[state[5]], state[5] = InvSbox[state[1]], state[1] = tmp; + + // restore row 2 + tmp = InvSbox[state[2]], state[2] = InvSbox[state[10]], state[10] = tmp; + tmp = InvSbox[state[6]], state[6] = InvSbox[state[14]], state[14] = tmp; + + // restore row 3 + tmp = InvSbox[state[3]], state[3] = InvSbox[state[7]]; + state[7] = InvSbox[state[11]], state[11] = InvSbox[state[15]], state[15] = tmp; +} + +// recombine and mix each row in a column +static void MixSubColumns (uchar *state) +{ + uchar tmp[4 * Nb]; + + // mixing column 0 + tmp[0] = Xtime2Sbox[state[0]] ^ Xtime3Sbox[state[5]] ^ Sbox[state[10]] ^ Sbox[state[15]]; + tmp[1] = Sbox[state[0]] ^ Xtime2Sbox[state[5]] ^ Xtime3Sbox[state[10]] ^ Sbox[state[15]]; + tmp[2] = Sbox[state[0]] ^ Sbox[state[5]] ^ Xtime2Sbox[state[10]] ^ Xtime3Sbox[state[15]]; + tmp[3] = Xtime3Sbox[state[0]] ^ Sbox[state[5]] ^ Sbox[state[10]] ^ Xtime2Sbox[state[15]]; + + // mixing column 1 + tmp[4] = Xtime2Sbox[state[4]] ^ Xtime3Sbox[state[9]] ^ Sbox[state[14]] ^ Sbox[state[3]]; + tmp[5] = Sbox[state[4]] ^ Xtime2Sbox[state[9]] ^ Xtime3Sbox[state[14]] ^ Sbox[state[3]]; + tmp[6] = Sbox[state[4]] ^ Sbox[state[9]] ^ Xtime2Sbox[state[14]] ^ Xtime3Sbox[state[3]]; + tmp[7] = Xtime3Sbox[state[4]] ^ Sbox[state[9]] ^ Sbox[state[14]] ^ Xtime2Sbox[state[3]]; + + // mixing column 2 + tmp[8] = Xtime2Sbox[state[8]] ^ Xtime3Sbox[state[13]] ^ Sbox[state[2]] ^ Sbox[state[7]]; + tmp[9] = Sbox[state[8]] ^ Xtime2Sbox[state[13]] ^ Xtime3Sbox[state[2]] ^ Sbox[state[7]]; + tmp[10] = Sbox[state[8]] ^ Sbox[state[13]] ^ Xtime2Sbox[state[2]] ^ Xtime3Sbox[state[7]]; + tmp[11] = Xtime3Sbox[state[8]] ^ Sbox[state[13]] ^ Sbox[state[2]] ^ Xtime2Sbox[state[7]]; + + // mixing column 3 + tmp[12] = Xtime2Sbox[state[12]] ^ Xtime3Sbox[state[1]] ^ Sbox[state[6]] ^ Sbox[state[11]]; + tmp[13] = Sbox[state[12]] ^ Xtime2Sbox[state[1]] ^ Xtime3Sbox[state[6]] ^ Sbox[state[11]]; + tmp[14] = Sbox[state[12]] ^ Sbox[state[1]] ^ Xtime2Sbox[state[6]] ^ Xtime3Sbox[state[11]]; + tmp[15] = Xtime3Sbox[state[12]] ^ Sbox[state[1]] ^ Sbox[state[6]] ^ Xtime2Sbox[state[11]]; + + memcpy (state, tmp, sizeof(tmp)); +} + +// restore and un-mix each row in a column +static void InvMixSubColumns (uchar *state) +{ + uchar tmp[4 * Nb]; + int i; + + // restore column 0 + tmp[0] = XtimeE[state[0]] ^ XtimeB[state[1]] ^ XtimeD[state[2]] ^ Xtime9[state[3]]; + tmp[5] = Xtime9[state[0]] ^ XtimeE[state[1]] ^ XtimeB[state[2]] ^ XtimeD[state[3]]; + tmp[10] = XtimeD[state[0]] ^ Xtime9[state[1]] ^ XtimeE[state[2]] ^ XtimeB[state[3]]; + tmp[15] = XtimeB[state[0]] ^ XtimeD[state[1]] ^ Xtime9[state[2]] ^ XtimeE[state[3]]; + + // restore column 1 + tmp[4] = XtimeE[state[4]] ^ XtimeB[state[5]] ^ XtimeD[state[6]] ^ Xtime9[state[7]]; + tmp[9] = Xtime9[state[4]] ^ XtimeE[state[5]] ^ XtimeB[state[6]] ^ XtimeD[state[7]]; + tmp[14] = XtimeD[state[4]] ^ Xtime9[state[5]] ^ XtimeE[state[6]] ^ XtimeB[state[7]]; + tmp[3] = XtimeB[state[4]] ^ XtimeD[state[5]] ^ Xtime9[state[6]] ^ XtimeE[state[7]]; + + // restore column 2 + tmp[8] = XtimeE[state[8]] ^ XtimeB[state[9]] ^ XtimeD[state[10]] ^ Xtime9[state[11]]; + tmp[13] = Xtime9[state[8]] ^ XtimeE[state[9]] ^ XtimeB[state[10]] ^ XtimeD[state[11]]; + tmp[2] = XtimeD[state[8]] ^ Xtime9[state[9]] ^ XtimeE[state[10]] ^ XtimeB[state[11]]; + tmp[7] = XtimeB[state[8]] ^ XtimeD[state[9]] ^ Xtime9[state[10]] ^ XtimeE[state[11]]; + + // restore column 3 + tmp[12] = XtimeE[state[12]] ^ XtimeB[state[13]] ^ XtimeD[state[14]] ^ Xtime9[state[15]]; + tmp[1] = Xtime9[state[12]] ^ XtimeE[state[13]] ^ XtimeB[state[14]] ^ XtimeD[state[15]]; + tmp[6] = XtimeD[state[12]] ^ Xtime9[state[13]] ^ XtimeE[state[14]] ^ XtimeB[state[15]]; + tmp[11] = XtimeB[state[12]] ^ XtimeD[state[13]] ^ Xtime9[state[14]] ^ XtimeE[state[15]]; + + for( i=0; i < 4 * Nb; i++ ) + state[i] = InvSbox[tmp[i]]; +} + +// encrypt/decrypt columns of the key +// n.b. you can replace this with +// byte-wise xor if you wish. + +static void AddRoundKey (unsigned *state, unsigned *key) +{ + int idx; + + for( idx = 0; idx < 4; idx++ ) + state[idx] ^= key[idx]; +} + +static const uchar Rcon[11] = { +0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36}; + +class CEncryption +{ +public: + // produce Nb bytes for each round + static void SetEncryptionKey(uchar* key) + { + uchar* expkey = &expKey[0]; + uchar tmp0, tmp1, tmp2, tmp3, tmp4; + unsigned idx; + + memcpy (expkey, key, Nk * 4); + + for( idx = Nk; idx < Nb * (Nr + 1); idx++ ) { + tmp0 = expkey[4*idx - 4]; + tmp1 = expkey[4*idx - 3]; + tmp2 = expkey[4*idx - 2]; + tmp3 = expkey[4*idx - 1]; + if( !(idx % Nk) ) { + tmp4 = tmp3; + tmp3 = Sbox[tmp0]; + tmp0 = Sbox[tmp1] ^ Rcon[idx/Nk]; + tmp1 = Sbox[tmp2]; + tmp2 = Sbox[tmp4]; + } else if( Nk > 6 && idx % Nk == 4 ) { + tmp0 = Sbox[tmp0]; + tmp1 = Sbox[tmp1]; + tmp2 = Sbox[tmp2]; + tmp3 = Sbox[tmp3]; + } + + expkey[4*idx+0] = expkey[4*idx - 4*Nk + 0] ^ tmp0; + expkey[4*idx+1] = expkey[4*idx - 4*Nk + 1] ^ tmp1; + expkey[4*idx+2] = expkey[4*idx - 4*Nk + 2] ^ tmp2; + expkey[4*idx+3] = expkey[4*idx - 4*Nk + 3] ^ tmp3; + } + } + + // encrypt one 128 bit block + static void Encrypt(uchar* in, uchar* out) + { + uchar* expkey = &expKey[0]; + uchar state[Nb * 4]; + unsigned round; + + memcpy (state, in, Nb * 4); + AddRoundKey ((unsigned *)state, (unsigned *)expkey); + + for( round = 1; round < Nr + 1; round++ ) { + if( round < Nr ) + MixSubColumns (state); + else + ShiftRows (state); + + AddRoundKey ((unsigned *)state, (unsigned *)expkey + round * Nb); + } + + memcpy (out, state, sizeof(state)); + } + + static void Decrypt(uchar* in, uchar* out) + { + uchar* expkey = &expKey[0]; + uchar state[Nb * 4]; + unsigned round; + + memcpy (state, in, sizeof(state)); + + AddRoundKey ((unsigned *)state, (unsigned *)expkey + Nr * Nb); + InvShiftRows(state); + + for( round = Nr; round--; ) + { + AddRoundKey ((unsigned *)state, (unsigned *)expkey + round * Nb); + if( round ) + InvMixSubColumns (state); + } + + memcpy (out, state, sizeof(state)); + } + +private: + static uchar expKey[4 * Nb * (Nr + 1)]; +}; diff --git a/include/CNetManager.h b/include/CNetManager.h new file mode 100644 index 0000000..245d3c3 --- /dev/null +++ b/include/CNetManager.h @@ -0,0 +1,120 @@ +#ifndef IRRNET_CNM_H +#define IRRNET_CNM_H + +#include +#include +#include +#include + +#include "INetManager.h" +#include "SPacket.h" +#include "enet/enet.h" + +using namespace irr; +using namespace core; + +namespace irr +{ + namespace net + { + + class CNetManager : public INetManager + { + public: + /// This constructor sets up a server, as it only takes a port as a parameter to bind the host to. + CNetManager(INetCallback* handler, u32 const port = 45000, const SNetParams& params = SNetParams()); + + /// This constructor sets up a client, as it takes an address and a port to connect to. Connecting + /// will commence immediately after the INetManager is initialised. + CNetManager(INetCallback* handler, const c8* addressc, const u32 port = 45000, const SNetParams& params = SNetParams()); + + /// Destructor + ~CNetManager(); + + virtual void update(const u32 timeOut = 0); + virtual void setVerbose(bool isverbose); + virtual void setNetIterations(u16 iterations) {netIterations = iterations;} + virtual void setNetCallback(INetCallback* netCallback) {pHandler = netCallback;} + virtual void setGlobalPacketRelay(bool relay); + virtual void sendOutPacket(SOutPacket& outpacket); + virtual void sendOutPacket(SOutPacket& outpacket, const u16 playerId); + virtual void sendOutPacketUnreliable(SOutPacket& outpacket); + virtual void sendOutPacketUnreliable(SOutPacket& outpacket, const u16 playerId); + virtual void kickClient(const u16 playerId, bool hardKick); + + virtual const u32 getPeerCount(); + virtual const u32 getPing(); + virtual const u32 getClientAddress(const u16 playerId); + + virtual const u16 getPlayerNumber(); + + virtual E_IRRNET_CONNECTION_STATUS getConnectionStatus(); + + enum E_NET_MODE + { + ENM_SERVER, + ENM_CLIENT, + + ENM_COUNT + }; + + struct SPeerData + { + SPeerData(u16 pID, ENetPeer* enetPeerIn) : playerID(pID), enetPeer(enetPeerIn) {}; + + u16 playerID; + ENetPeer* enetPeer; + }; + + private: + ENetHost* host; + ENetPeer* peer; + ENetAddress address; + + u16 playerID; + + INetCallback* pHandler; + u32 netIterations; + SNetParams netParams; + + std::vector players; + bool verbose; + bool globPacketRelay; + + E_IRRNET_CONNECTION_STATUS connectionStatus; + E_NET_MODE mode; + + bool setUpClient(const c8* addressc, u32 port); + bool setUpServer(u32 port); + + ENetPeer* getPlayerById(u16 id); + ENetPeer* getPeer(); + ENetHost* getHost(); + }; + + } // Close Net Namespace +} // Close Irr namespace + +#endif + +// Copyright(C) Ahmed Hilali 2007 + +/* License: + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgement in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be clearly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + */ diff --git a/include/INetManager.h b/include/INetManager.h new file mode 100644 index 0000000..b7eec88 --- /dev/null +++ b/include/INetManager.h @@ -0,0 +1,242 @@ +#ifndef IRRNET_INM_H +#define IRRNET_INM_H + +#include "SPacket.h" + +/** \mainpage + +Welcome to irrNetLite. + +*/ + +namespace irr +{ +namespace net +{ + +/** +E_IRRNET_CONNECTION_STATUS: + +EICS_PENDING +------------ +The connection is still in progress. + +EICS_ESTABLISHED +------------ +The connection has been successfully established. + +EICS_FAILED +------------ +The connection has failed. The current INetManager is invalid. To retry, you must create a new NetManager. +*/ +enum E_IRRNET_CONNECTION_STATUS +{ + EICS_PENDING, + EICS_ESTABLISHED, + EICS_FAILED, + + EICS_COUNT +}; + +/** +Optional settings for the creation of the INetManager. + +downBandwidth +------------- +The down (incoming) bandwidth of the current internet connection. You may set this value for +more accurate packet throttling. In kbps. + +upBandwidth +----------- +The up (outgoing) bandwidth of the current internet connection. You may set this value for +more accurate packet throttling. In kbps. + +maxClients +---------- +The maximum number of clients allowed for a server. Any clients that attempt to join +after this number has been reached will be rejected. (For servers only.) + +connectionTimeout +----------------- +The maximum connection timeout allowed when connecting to a server. In milliseconds. (For +clients only.) +*/ +struct SNetParams +{ + SNetParams() : downBandwidth(128000), upBandwidth(56000), maxClients(100), connectionTimeout(5000) {}; + + u32 downBandwidth; + u32 upBandwidth; + u32 maxClients; + u32 connectionTimeout; +}; + +/** +You must create a derived class of INetCallback and override the "handlePacket" method to perform +your own packet handling functions. Everytime a packet is recieved over the network, an SInPacket +is passed to this method. When initialising a INetManager, a pointer to an instance of the +derived class must be passed. Please see SInPacket regarding information on handling InPackets. +*/ +class INetCallback +{ +public: + virtual void handlePacket(SInPacket& packet) = 0; + virtual void onConnect(const u16 playerId) {}; + virtual void onDisconnect(const u16 playerId) {}; + + virtual ~INetCallback() {}; +}; + +/** +INetManager class. +*/ +class INetManager +{ +public: + /** + This function updates the state of the NetManager and handles the sending/receiving of packets. + Make sure to stick this in your run loop, or at the very least update it very often. If this + function is not updated pending packets will not be sent and received packets will not be handled. + Optionally a timeout may be specified if you want this function to block and wait for packets + to a arrive for a specified interval of time (In MilliSeconds). + */ + virtual void update(const u32 timeOut = 0) = 0; + + /// Virtual destructor + virtual ~INetManager() {}; + + /** + If set to true INetManager will output debug info to console. Output resembles: + + "irrNetLite: A packet of length 50 was recieved."; + + or + + "irrNetLite: Player number 23 disconnected."; + + It may be useful for debugging purposes. + */ + virtual void setVerbose(bool isverbose) = 0; + + /// Sets a new INetCallback as the net callback. + virtual void setNetCallback(INetCallback* netCallback) = 0; + + /** + This function sends an SOutPacket. Out packets provide an easy interface for sending data across a network. + Conversions etc are all taken care of by irrNet. All you have to do is create some kind of variable then add it, + then read the data from the SInPacket on the recieving end. Here is an example of adding data to an SOutPacket: + + \code + SOutPacket MyOutPacket; + // We add data using the "<<" operator, similar to iostreams. + float myValue = 0.238723f; + MyOutPacket << myValue; + MyOutPacket << vector3df(23,354,35); + MyOutPacket << 43988434; + + // And now to send. + NetManager->sendOutPacket(MyOutPacket); + \endcode + + This sends the packet to all connected clients if you are the server, or directly to the server if you + are a client. To send to a specific client use "sendOutPacket(SOutPacket& outpacket, const u16 playerId)". + Please refer to SOutPacket for more information on what types of variables an SOutPacket can handle + automatically. + */ + virtual void sendOutPacket(SOutPacket& outpacket) = 0; + + /** + This sends an SOutPacket to a specific player denoted by the player number. Players are numbered + automatically as they connect to the server. IMPORTANT: This feature is only valid if you are the server. + This is because clients can only send packets to the server, making this function unusable. + Please refer to sendOutPacket(const SOutPacket& outpacket) for more info. + */ + virtual void sendOutPacket(SOutPacket& outpacket, const u16 playerId) = 0; + + /** + This sends the SOutPacket specified unreliably. This is not recommended for critical information. + Please refer to sendOutPacket(const SOutPacket& outpacket) for more info. + */ + virtual void sendOutPacketUnreliable(SOutPacket& outpacket) = 0; + + /** + This sends an SOutPacket unreliably to a specific player denoted by the player number. + Players are numbered automatically as they connect to the server. IMPORTANT: This feature + is only valid if you are the server. This is because clients can only send packets to the server, + making this function unusable. This is not recommended for critical information. + Please refer to sendOutPacket(const SOutPacket& outpacket) for more info. + */ + virtual void sendOutPacketUnreliable(SOutPacket& outpacket, const u16 playerId) = 0; + + /// This gets the number of players connected. This is only valid for servers. + virtual const u32 getPeerCount() = 0; + + /// This returns the playerID for this machine. Only valid for Clients. + virtual const u16 getPlayerNumber() = 0; + + /// Returns the client ip address with the specified player ID. This is only valid for servers. + /// The address is in 32-bit integer format. + virtual const u32 getClientAddress(const u16 playerId) = 0; + + /// Kicks the client with the specified player Id. + /// You may set the hardKick option to true to forcifully disconnect them immediately. + /// Note that if a "hardKick" is performed, no disconnect event will be generated. + virtual void kickClient(const u16 playerId, bool hardKick = false) = 0; + + /** + This returns a value of type E_IRRNET_CONNECTION_STATUS. This can either be EICS_PENDING, which indicates the + connection is still in process, EICS_ESTABLISHED, which indicates the connection has been successfully established, + or EICS_FAILED, which indicates the connection was not successful or has since disconnected. This is generally only + useful for clients, but the information is provided for servers incase there is a fault with the server setup. + */ + virtual E_IRRNET_CONNECTION_STATUS getConnectionStatus() = 0; + + /// This returns the ping. Useful for clients as it returns the ping to the server. For servers it returns + /// the ping to the first connected player. + virtual const u32 getPing() = 0; + + /// Sets the number of packet processing iterations per update. You may want to increase this number if + /// you are not updating frequently enough for all the packets to get processed. (Default: 10000) + virtual void setNetIterations(u16 iterations) = 0; + + /** + Enables or disables global packet relay, this is when the server relays all the packets it recieves to all + connected clients, this makes it easy to send information to all clients, but may not be suitable for + large-scale applications. Instead, a custom entity management and packet handling system should be designed. + Although for applications with less than 10 peers global packet relay should do just fine. (Default: false) + */ + virtual void setGlobalPacketRelay(bool relay) = 0; +}; + +/// Creates an irrNetLite client. +INetManager* createIrrNetClient(INetCallback* callback, const c8* addressc, const u32 port = 45000, const SNetParams& params = SNetParams()); + +/// Creates an irrNetLite server. +INetManager* createIrrNetServer(INetCallback* callback, const u32 port = 45000, const SNetParams& params = SNetParams()); + +} // Close Net Namespace +} // Close Irr namespace + +#endif + +// Copyright(C) Ahmed Hilali 2008 + +/* + License: + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgement in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be clearly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ + diff --git a/include/NoIrrlicht/IrrCompileConfig.h b/include/NoIrrlicht/IrrCompileConfig.h new file mode 100644 index 0000000..873453d --- /dev/null +++ b/include/NoIrrlicht/IrrCompileConfig.h @@ -0,0 +1,351 @@ +// Copyright (C) 2002-2007 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __IRR_COMPILE_CONFIG_H_INCLUDED__ +#define __IRR_COMPILE_CONFIG_H_INCLUDED__ + +//! Irrlicht SDK Version +#define IRRLICHT_SDK_VERSION "1.4" + +//! The defines for different operating system are: +//! _IRR_XBOX_PLATFORM_ for XBox +//! _IRR_WINDOWS_ for all irrlicht supported Windows versions +//! _IRR_WINDOWS_API_ for Windows or XBox +//! _IRR_LINUX_PLATFORM_ for Linux (it is defined here if no other os is defined) +//! _IRR_SOLARIS_PLATFORM_ for Solaris +//! _IRR_OSX_PLATFORM_ for Apple systems running OSX +//! _IRR_POSIX_API_ for Posix compatible systems +//! _IRR_USE_SDL_DEVICE_ for platform independent SDL framework +//! _IRR_USE_WINDOWS_DEVICE_ for Windows API based device +//! _IRR_USE_WINDOWS_CE_DEVICE_ for Windows CE API based device +//! _IRR_USE_LINUX_DEVICE_ for X11 based device +//! _IRR_USE_OSX_DEVICE_ for Cocoa native windowing on OSX +//! Note: PLATFORM defines the OS specific layer, API can groups several platforms +//! DEVICE is the windowing system used, several PLATFORMs support more than one DEVICE +//! Moreover, the DEVICE defined here is not directly related to the Irrlicht devices created in the app (but may depend on each other). + +//#define _IRR_USE_SDL_DEVICE_ 1 + +//! WIN32 for Windows32 +//! WIN64 for Windows64 +// The windows platform and API support SDL and WINDOW device +#if defined(_WIN32) || defined(_WIN64) || defined(WIN32) || defined(WIN64) || defined(_WIN32_WCE) +#define _IRR_WINDOWS_ +#define _IRR_WINDOWS_API_ +#ifndef _IRR_USE_SDL_DEVICE_ +#define _IRR_USE_WINDOWS_DEVICE_ +#endif +#endif + +// XBox only suppots the native Window stuff +#if defined(_XBOX) +#define _IRR_XBOX_PLATFORM_ +#define _IRR_WINDOWS_API_ +#define _IRR_USE_WINDOWS_DEVICE_ +#endif + +#if defined(__APPLE__) || defined(MACOSX) +#if !defined(MACOSX) +#define MACOSX // legacy support +#endif +#define _IRR_OSX_PLATFORM_ +#if !defined(_IRR_USE_LINUX_DEVICE_) // for X11 windowing declare this +#define _IRR_USE_OSX_DEVICE_ +#endif +#endif + +#if !defined(_IRR_WINDOWS_API_) && !defined(_IRR_OSX_PLATFORM_) +#if defined(__sparc__) || defined(__sun__) +#define __BIG_ENDIAN__ +#define _IRR_SOLARIS_PLATFORM_ +#else +#define _IRR_LINUX_PLATFORM_ +#endif +#define _IRR_POSIX_API_ + +#ifndef _IRR_USE_SDL_DEVICE_ +#define _IRR_USE_LINUX_DEVICE_ +#endif +#endif + +#include // TODO: Although included elsewhere this is required at least for mingw + +//! Define _IRR_COMPILE_WITH_DIRECT3D_8_ and _IRR_COMPILE_WITH_DIRECT3D_9_ to +//! compile the Irrlicht engine with Direct3D8 and/or DIRECT3D9. +/** If you only want to use the software device or opengl this can be useful. +This switch is mostly disabled because people do not get the g++ compiler compile +directX header files, and directX is only available on windows platforms. If you +are using Dev-Cpp, and want to compile this using a DX dev pack, you can define +_IRR_COMPILE_WITH_DX9_DEV_PACK_. So you simply need to add something like this +to the compiler settings: -DIRR_COMPILE_WITH_DX9_DEV_PACK +and this to the linker settings: -ld3dx9 -ld3dx8 **/ +#if defined(_IRR_WINDOWS_API_) && (!defined(__GNUC__) || defined(IRR_COMPILE_WITH_DX9_DEV_PACK)) + +//#define _IRR_COMPILE_WITH_DIRECT3D_8_ +//#define _IRR_COMPILE_WITH_DIRECT3D_9_ + +#endif + +#define _IRR_COMPILE_WITH_BLINDRT_ + +//! Define _IRR_COMPILE_WITH_OPENGL_ to compile the Irrlicht engine with OpenGL. +/** If you do not wish the engine to be compiled with OpengGL, comment this +define out. */ +//#define _IRR_COMPILE_WITH_OPENGL_ + +//! Define _IRR_COMPILE_WITH_SOFTWARE_ to compile the Irrlicht engine with software driver +/** If you do not need the software driver, or want to use Burning's Video instead, +comment this define out */ +//#define _IRR_COMPILE_WITH_SOFTWARE_ + +//! Define _IRR_COMPILE_WITH_BURNINGSVIDEO_ to compile the Irrlicht engine with Burning's video driver +/** If you do not need this software driver, you can comment this define out. */ +#define _IRR_COMPILE_WITH_BURNINGSVIDEO_ + +//! Define _IRR_COMPILE_WITH_X11_ to compile the Irrlicht engine with X11 support. +/** If you do not wish the engine to be compiled with X11, comment this +define out. */ +// Only used in LinuxDevice. +#define _IRR_COMPILE_WITH_X11_ + +//! Define _IRR_OPENGL_USE_EXTPOINTER_ if the OpenGL renderer should use OpenGL extensions via function pointers. +/** On some systems there is no support for the dynamic extension of OpenGL + via function pointers such that this has to be undef'ed. */ +#if !defined(_IRR_OSX_PLATFORM_) && !defined(_IRR_SOLARIS_PLATFORM_) +#define _IRR_OPENGL_USE_EXTPOINTER_ +#endif + +//! On some Linux systems the XF86 vidmode extension or X11 RandR are missing. Use these flags +//! to remove the dependencies such that Irrlicht will compile on those systems, too. +#if defined(_IRR_LINUX_PLATFORM_) +#define _IRR_LINUX_X11_VIDMODE_ +//#define _IRR_LINUX_X11_RANDR_ +#endif + +//! Define _IRR_COMPILE_WITH_GUI_ to compile the engine with the built-in GUI +/** Disable this if you are using an external library to draw the GUI. If you disable this then +you will not be able to use anything provided by the GUI Environment, including loading fonts. */ +#define _IRR_COMPILE_WITH_GUI_ + +//! Define _IRR_COMPILE_WITH_ZLIB_ to enable compiling the engine using zlib. +/** This enables the engine to read from compressed .zip archives. If you +disable this feature, the engine can still read archives, but only uncompressed +ones. */ +#define _IRR_COMPILE_WITH_ZLIB_ + +//! Define _IRR_USE_NON_SYSTEM_ZLIB_ to let irrlicht use the zlib which comes with irrlicht. +/** If this is commented out, Irrlicht will try to compile using the zlib installed in the system. + This is only used when _IRR_COMPILE_WITH_ZLIB_ is defined. */ +#define _IRR_USE_NON_SYSTEM_ZLIB_ + + +//! Define _IRR_COMPILE_WITH_JPEGLIB_ to enable compiling the engine using libjpeg. +/** This enables the engine to read jpeg images. If you comment this out, +the engine will no longer read .jpeg images. */ +#define _IRR_COMPILE_WITH_LIBJPEG_ + +//! Define _IRR_USE_NON_SYSTEM_JPEG_LIB_ to let irrlicht use the jpeglib which comes with irrlicht. +/** If this is commented out, Irrlicht will try to compile using the jpeg lib installed in the system. + This is only used when _IRR_COMPILE_WITH_LIBJPEG_ is defined. */ +#define _IRR_USE_NON_SYSTEM_JPEG_LIB_ + + +//! Define _IRR_COMPILE_WITH_LIBPNG_ to enable compiling the engine using libpng. +/** This enables the engine to read png images. If you comment this out, +the engine will no longer read .png images. */ +#define _IRR_COMPILE_WITH_LIBPNG_ + +//! Define _IRR_USE_NON_SYSTEM_LIBPNG_ to let irrlicht use the libpng which comes with irrlicht. +/** If this is commented out, Irrlicht will try to compile using the libpng installed in the system. + This is only used when _IRR_COMPILE_WITH_LIBPNG_ is defined. */ +#define _IRR_USE_NON_SYSTEM_LIB_PNG_ + + +//! Define _IRR_D3D_NO_SHADER_DEBUGGING to disable shader debugging in D3D9 +/** If _IRR_D3D_NO_SHADER_DEBUGGING is undefined in IrrCompileConfig.h, +it is possible to debug all D3D9 shaders in VisualStudio. All shaders +(which have been generated in memory or read from archives for example) will be emitted +into a temporary file at runtime for this purpose. To debug your shaders, choose +Debug->Direct3D->StartWithDirect3DDebugging in Visual Studio, and for every shader a +file named 'irr_dbg_shader_%%.vsh' or 'irr_dbg_shader_%%.psh' will be created. Drag'n'drop +the file you want to debug into visual studio. That's it. You can now set breakpoints and +watch registers, variables etc. This works with ASM, HLSL, and both with pixel and vertex shaders. +Note that the engine will run in D3D REF for this, which is a lot slower than HAL. */ +#define _IRR_D3D_NO_SHADER_DEBUGGING + + +#ifdef _IRR_WINDOWS_API_ + +#ifndef _IRR_STATIC_LIB_ +#ifdef IRRLICHT_EXPORTS +#define IRRLICHT_API __declspec(dllexport) +#else +#define IRRLICHT_API __declspec(dllimport) +#endif // IRRLICHT_EXPORT +#else +#define IRRLICHT_API +#endif // _IRR_STATIC_LIB_ + +// Declare the calling convention. +#if defined(_STDCALL_SUPPORTED) +#define IRRCALLCONV __stdcall +#else +#define IRRCALLCONV __cdecl +#endif // STDCALL_SUPPORTED + +#else +#define IRRLICHT_API +#define IRRCALLCONV +#endif // _IRR_WINDOWS_API_ + +// We need to disable DIRECT3D9 support for Visual Studio 6.0 because +// those $%&$!! disabled support for it since Dec. 2004 and users are complaining +// about linker errors. Comment this out only if you are knowing what you are +// doing. (Which means you have an old DX9 SDK and VisualStudio6). +#ifdef _MSC_VER +#if (_MSC_VER < 1300 && !defined(__GNUC__)) +#undef _IRR_COMPILE_WITH_DIRECT3D_9_ +#pragma message("Compiling Irrlicht with Visual Studio 6.0, support for DX9 is disabled.") +#endif +#endif + +//! Define one of the three setting for Burning's Video Software Rasterizer +/** So if we were marketing guys we could say Irrlicht has 4 Software-Rasterizers. + In a Nutshell: + All Burnings Rasterizers use 32 Bit Backbuffer, 32Bit Texture & 32 Bit Z or WBuffer, + 16 Bit/32 Bit can be adjusted on a global flag. + + BURNINGVIDEO_RENDERER_BEAUTIFUL + 32 Bit + Vertexcolor + Lighting + Per Pixel Perspective Correct + SubPixel/SubTexel Correct + + Bilinear Texturefiltering + WBuffer + + BURNINGVIDEO_RENDERER_FAST + 32 Bit + Per Pixel Perspective Correct + SubPixel/SubTexel Correct + WBuffer + + Bilinear Dithering TextureFiltering + WBuffer + + BURNINGVIDEO_RENDERER_ULTRA_FAST + 16Bit + SubPixel/SubTexel Correct + ZBuffer +*/ + +#define BURNINGVIDEO_RENDERER_BEAUTIFUL +//#define BURNINGVIDEO_RENDERER_FAST +//#define BURNINGVIDEO_RENDERER_ULTRA_FAST + + +//! Define _IRR_COMPILE_WITH_SKINNED_MESH_SUPPORT_ if you want to use bone based +/** animated meshes. If you compile without this, you will be unable to load +B3D, MS3D or X meshes */ +#define _IRR_COMPILE_WITH_SKINNED_MESH_SUPPORT_ + +#ifdef _IRR_COMPILE_WITH_SKINNED_MESH_SUPPORT_ +//! Define _IRR_COMPILE_WITH_B3D_LOADER_ if you want to use Blitz3D files +#define _IRR_COMPILE_WITH_B3D_LOADER_ +//! Define _IRR_COMPILE_WITH_B3D_LOADER_ if you want to Milkshape files +#define _IRR_COMPILE_WITH_MS3D_LOADER_ +//! Define _IRR_COMPILE_WITH_X_LOADER_ if you want to use Microsoft X files +#define _IRR_COMPILE_WITH_X_LOADER_ +#endif + +//! Define _IRR_COMPILE_WITH_IRR_MESH_LOADER_ if you want to load Irrlicht Engine .irrmesh files +#define _IRR_COMPILE_WITH_IRR_MESH_LOADER_ + +//! Define _IRR_COMPILE_WITH_MD2_LOADER_ if you want to load Quake 2 animated files +#define _IRR_COMPILE_WITH_MD2_LOADER_ +//! Define _IRR_COMPILE_WITH_MD3_LOADER_ if you want to load Quake 3 animated files +#define _IRR_COMPILE_WITH_MD3_LOADER_ + +//! Define _IRR_COMPILE_WITH_3DS_LOADER_ if you want to load 3D Studio Max files +#define _IRR_COMPILE_WITH_3DS_LOADER_ +//! Define _IRR_COMPILE_WITH_COLLADA_LOADER_ if you want to load Collada files +#define _IRR_COMPILE_WITH_COLLADA_LOADER_ +//! Define _IRR_COMPILE_WITH_CSM_LOADER_ if you want to load Cartography Shop files +#define _IRR_COMPILE_WITH_CSM_LOADER_ +//! Define _IRR_COMPILE_WITH_BSP_LOADER_ if you want to load Quake 3 BSP files +#define _IRR_COMPILE_WITH_BSP_LOADER_ +//! Define _IRR_COMPILE_WITH_DMF_LOADER_ if you want to load DeleD files +#define _IRR_COMPILE_WITH_DMF_LOADER_ +//! Define _IRR_COMPILE_WITH_LMTS_LOADER_ if you want to load LMTools files +#define _IRR_COMPILE_WITH_LMTS_LOADER_ +//! Define _IRR_COMPILE_WITH_MY3D_LOADER_ if you want to load MY3D files +#define _IRR_COMPILE_WITH_MY3D_LOADER_ +//! Define _IRR_COMPILE_WITH_OBJ_LOADER_ if you want to load Wavefront OBJ files +#define _IRR_COMPILE_WITH_OBJ_LOADER_ +//! Define _IRR_COMPILE_WITH_OCT_LOADER_ if you want to load FSRad OCT files +#define _IRR_COMPILE_WITH_OCT_LOADER_ +//! Define _IRR_COMPILE_WITH_OGRE_LOADER_ if you want to load Ogre 3D files +#define _IRR_COMPILE_WITH_OGRE_LOADER_ +//! Define _IRR_COMPILE_WITH_LWO_LOADER_ if you want to load Lightwave3D files +#define _IRR_COMPILE_WITH_LWO_LOADER_ +//! Define _IRR_COMPILE_WITH_STL_LOADER_ if you want to load .stl files +#define _IRR_COMPILE_WITH_STL_LOADER_ + +//! Define _IRR_COMPILE_WITH_IRR_WRITER_ if you want to write static .irr files +#define _IRR_COMPILE_WITH_IRR_WRITER_ +//! Define _IRR_COMPILE_WITH_COLLADA_WRITER_ if you want to write Collada files +#define _IRR_COMPILE_WITH_COLLADA_WRITER_ +//! Define _IRR_COMPILE_WITH_STL_WRITER_ if you want to write .stl files +#define _IRR_COMPILE_WITH_STL_WRITER_ + +//! Define _IRR_COMPILE_WITH_BMP_LOADER_ if you want to load .bmp files +//! Disabling this loader will also disable the built-in font +#define _IRR_COMPILE_WITH_BMP_LOADER_ +//! Define _IRR_COMPILE_WITH_JPG_LOADER_ if you want to load .jpg files +#define _IRR_COMPILE_WITH_JPG_LOADER_ +//! Define _IRR_COMPILE_WITH_PCX_LOADER_ if you want to load .pcx files +#define _IRR_COMPILE_WITH_PCX_LOADER_ +//! Define _IRR_COMPILE_WITH_PNG_LOADER_ if you want to load .png files +#define _IRR_COMPILE_WITH_PNG_LOADER_ +//! Define _IRR_COMPILE_WITH_PPM_LOADER_ if you want to load .ppm/.pgm/.pbm files +#define _IRR_COMPILE_WITH_PPM_LOADER_ +//! Define _IRR_COMPILE_WITH_PSD_LOADER_ if you want to load .psd files +#define _IRR_COMPILE_WITH_PSD_LOADER_ +//! Define _IRR_COMPILE_WITH_TGA_LOADER_ if you want to load .tga files +#define _IRR_COMPILE_WITH_TGA_LOADER_ +//! Define _IRR_COMPILE_WITH_WAL_LOADER_ if you want to load .wal files +#define _IRR_COMPILE_WITH_WAL_LOADER_ + +//! Define _IRR_COMPILE_WITH_BMP_WRITER_ if you want to write .bmp files +#define _IRR_COMPILE_WITH_BMP_WRITER_ +//! Define _IRR_COMPILE_WITH_JPG_WRITER_ if you want to write .jpg files +#define _IRR_COMPILE_WITH_JPG_WRITER_ +//! Define _IRR_COMPILE_WITH_PCX_WRITER_ if you want to write .pcx files +#define _IRR_COMPILE_WITH_PCX_WRITER_ +//! Define _IRR_COMPILE_WITH_PNG_WRITER_ if you want to write .png files +#define _IRR_COMPILE_WITH_PNG_WRITER_ +//! Define _IRR_COMPILE_WITH_PPM_WRITER_ if you want to write .ppm files +#define _IRR_COMPILE_WITH_PPM_WRITER_ +//! Define _IRR_COMPILE_WITH_PSD_WRITER_ if you want to write .psd files +#define _IRR_COMPILE_WITH_PSD_WRITER_ +//! Define _IRR_COMPILE_WITH_TGA_WRITER_ if you want to write .tga files +#define _IRR_COMPILE_WITH_TGA_WRITER_ + +//! Set FPU settings +/** Irrlicht should use approximate float and integer fpu techniques +precision will be lower but speed higher. currently X86 only +*/ +#if !defined(_IRR_OSX_PLATFORM_) && !defined(_IRR_SOLARIS_PLATFORM_) + //#define IRRLICHT_FAST_MATH +#endif + +// Some cleanup +// XBox does not have OpenGL or DirectX9 +#if defined(_IRR_XBOX_PLATFORM_) +#undef _IRR_COMPILE_WITH_OPENGL_ +#undef _IRR_COMPILE_WITH_DIRECT3D_9_ +#endif + +// WinCE does not have OpenGL or DirectX9 +#if defined(_WIN32_WCE) + #undef _IRR_COMPILE_WITH_OPENGL_ + #undef _IRR_COMPILE_WITH_DIRECT3D_8_ + #undef _IRR_COMPILE_WITH_DIRECT3D_9_ + #undef _IRR_COMPILE_WITH_SOFTWARE_ + #undef BURNINGVIDEO_RENDERER_BEAUTIFUL + #undef _IRR_USE_WINDOWS_DEVICE_ + #define _IRR_USE_WINDOWS_CE_DEVICE_ + #define BURNINGVIDEO_RENDERER_CE +#endif + +#endif // __IRR_COMPILE_CONFIG_H_INCLUDED__ + diff --git a/include/NoIrrlicht/NoIrrlicht.h b/include/NoIrrlicht/NoIrrlicht.h new file mode 100644 index 0000000..1d5441b --- /dev/null +++ b/include/NoIrrlicht/NoIrrlicht.h @@ -0,0 +1,9 @@ +#ifndef IRRNET_INO_IRRLICHT_H +#define IRRNET_INO_IRRLICHT_H + +#include "irrTypes.h" +#include "irrArray.h" +#include "irrString.h" +#include "vector3d.h" + +#endif \ No newline at end of file diff --git a/include/NoIrrlicht/heapsort.h b/include/NoIrrlicht/heapsort.h new file mode 100644 index 0000000..b346364 --- /dev/null +++ b/include/NoIrrlicht/heapsort.h @@ -0,0 +1,71 @@ +// Copyright (C) 2002-2007 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __IRR_HEAPSORT_H_INCLUDED__ +#define __IRR_HEAPSORT_H_INCLUDED__ + +#include "irrTypes.h" + +namespace irr +{ +namespace core +{ + +//! Sinks an element into the heap. +template +inline void heapsink(T*array, s32 element, s32 max) +{ + while ((element<<1) < max) // there is a left child + { + s32 j = (element<<1); + + if (j+1 < max && array[j] < array[j+1]) + j = j+1; // take right child + + if (array[element] < array[j]) + { + T t = array[j]; // swap elements + array[j] = array[element]; + array[element] = t; + element = j; + } + else + return; + } +} + + +//! Sorts an array with size 'size' using heapsort. +template +inline void heapsort(T* array_, s32 size) +{ + // for heapsink we pretent this is not c++, where + // arrays start with index 0. So we decrease the array pointer, + // the maximum always +2 and the element always +1 + + T* virtualArray = array_ - 1; + s32 virtualSize = size + 2; + s32 i; + + // build heap + + for (i=((size-1)/2); i>=0; --i) + heapsink(virtualArray, i+1, virtualSize-1); + + // sort array + + for (i=size-1; i>=0; --i) + { + T t = array_[0]; + array_[0] = array_[i]; + array_[i] = t; + heapsink(virtualArray, 1, i + 1); + } +} + +} // end namespace core +} // end namespace irr + +#endif + diff --git a/include/NoIrrlicht/irrAllocator.h b/include/NoIrrlicht/irrAllocator.h new file mode 100644 index 0000000..91e0d1a --- /dev/null +++ b/include/NoIrrlicht/irrAllocator.h @@ -0,0 +1,116 @@ +// Copyright (C) 2002-2007 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine" and the "irrXML" project. +// For conditions of distribution and use, see copyright notice in irrlicht.h and irrXML.h + +#ifndef __IRR_ALLOCATOR_H_INCLUDED__ +#define __IRR_ALLOCATOR_H_INCLUDED__ + +#include "irrTypes.h" +#include +#include + +namespace irr +{ +namespace core +{ + +#ifdef DEBUG_CLIENTBLOCK +#undef DEBUG_CLIENTBLOCK +#define DEBUG_CLIENTBLOCK new +#endif + +//! Very simple allocator implementation, containers using it can +//! be used across dll boundaries +template +class irrAllocator +{ +public: + + //! destructor + virtual ~irrAllocator() {} + + //! allocate memory for an array of objects + T* allocate(size_t cnt) + { + return (T*)internal_new(cnt* sizeof(T)); + } + + //! deallocate memory for an array of objects + void deallocate(T* ptr) + { + internal_delete(ptr); + } + + //! construct an element + void construct(T* ptr, const T&e) + { + new ((void*)ptr) T(e); + } + + //! destruct an element + void destruct(T* ptr) + { + ptr->~T(); + } + +protected: + + virtual void* internal_new(size_t cnt) + { + return operator new(cnt); + } + + virtual void internal_delete(void* ptr) + { + operator delete(ptr); + } + +}; + + +//! fast allocator, only to be used in containers inside the same memory heap. +/** Containers using it are NOT able to be used it across dll boundaries. Use this +when using in an internal class or function or when compiled into a static lib */ +template +class irrAllocatorFast +{ +public: + + //! allocate memory for an array of objects + T* allocate(size_t cnt) + { + return (T*)operator new(cnt* sizeof(T)); + } + + //! deallocate memory for an array of objects + void deallocate(T* ptr) + { + operator delete(ptr); + } + + //! construct an element + void construct(T* ptr, const T&e) + { + new ((void*)ptr) T(e); + } + + //! destruct an element + void destruct(T* ptr) + { + ptr->~T(); + } +}; + + + +#ifdef DEBUG_CLIENTBLOCK +#undef DEBUG_CLIENTBLOCK +#define DEBUG_CLIENTBLOCK new( _CLIENT_BLOCK, __FILE__, __LINE__) +#endif + + +} // end namespace core +} // end namespace irr + +#endif + diff --git a/include/NoIrrlicht/irrArray.h b/include/NoIrrlicht/irrArray.h new file mode 100644 index 0000000..e11d896 --- /dev/null +++ b/include/NoIrrlicht/irrArray.h @@ -0,0 +1,515 @@ +// Copyright (C) 2002-2007 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine" and the "irrXML" project. +// For conditions of distribution and use, see copyright notice in irrlicht.h and irrXML.h + +#ifndef __IRR_ARRAY_H_INCLUDED__ +#define __IRR_ARRAY_H_INCLUDED__ + +#include "irrTypes.h" +#include "heapsort.h" +#include "irrAllocator.h" + +namespace irr +{ +namespace core +{ + +//! Self reallocating template array (like stl vector) with additional features. +/** Some features are: Heap sorting, binary search methods, easier debugging. +*/ +template > +class array +{ + +public: + + array() + : data(0), allocated(0), used(0), + free_when_destroyed(true), is_sorted(true) + { + } + + //! Constructs a array and allocates an initial chunk of memory. + //! \param start_count: Amount of elements to allocate. + array(u32 start_count) + : data(0), allocated(0), used(0), + free_when_destroyed(true), is_sorted(true) + { + reallocate(start_count); + } + + + //! Copy constructor + array(const array& other) + : data(0) + { + *this = other; + } + + + + //! Destructor. Frees allocated memory, if set_free_when_destroyed + //! was not set to false by the user before. + ~array() + { + if (free_when_destroyed) + { + for (u32 i=0; i allocated) + { + // reallocate(used * 2 +1); + // this doesn't work if the element is in the same array. So + // we'll copy the element first to be sure we'll get no data + // corruption + + T e(element); + reallocate(used * 2 +1); // increase data block + + allocator.construct(&data[used++], e); // data[used++] = e; // push_back + } + else + { + //data[used++] = element; + // instead of using this here, we copy it the safe way: + allocator.construct(&data[used++], element); + } + + is_sorted = false; + } + + + //! Adds an element at the front of the array. If the array is to small to + //! add this new element, the array is made bigger. Please note that this + //! is slow, because the whole array needs to be copied for this. + //! \param element: Element to add at the back of the array. + void push_front(const T& element) + { + insert(element); + } + + + //! Insert item into array at specified position. Please use this + //! only if you know what you are doing (possible performance loss). + //! The preferred method of adding elements should be push_back(). + //! \param element: Element to be inserted + //! \param index: Where position to insert the new element. + void insert(const T& element, u32 index=0) + { + _IRR_DEBUG_BREAK_IF(index>used) // access violation + + if (used + 1 > allocated) + reallocate(used +1); + + for (u32 i=used; i>index; --i) + { + if (i index) + allocator.destruct(&data[index]); + allocator.construct(&data[index], element); // data[index] = element; + is_sorted = false; + ++used; + } + + + + + //! Clears the array and deletes all allocated memory. + void clear() + { + for (u32 i=0; i& other) + { + if (data) + { + for (u32 i=0; i& other) const + { + if (used != other.used) + return false; + + for (u32 i=0; i& other) const + { + return !(*this==other); + } + + //! Direct access operator + T& operator [](u32 index) + { + _IRR_DEBUG_BREAK_IF(index>=used) // access violation + + return data[index]; + } + + + + //! Direct access operator + const T& operator [](u32 index) const + { + _IRR_DEBUG_BREAK_IF(index>=used) // access violation + + return data[index]; + } + + //! Gets last frame + T& getLast() + { + _IRR_DEBUG_BREAK_IF(!used) // access violation + + return data[used-1]; + } + + + //! Gets last frame + const T& getLast() const + { + _IRR_DEBUG_BREAK_IF(!used) // access violation + + return data[used-1]; + } + + //! Returns a pointer to the array. + //! \return Pointer to the array. + T* pointer() + { + return data; + } + + + + //! Returns a const pointer to the array. + //! \return Pointer to the array. + const T* const_pointer() const + { + return data; + } + + + + //! Returns size of used array. + //! \return Size of elements in the array. + u32 size() const + { + return used; + } + + + + //! Returns amount memory allocated. + //! \return Returns amount of memory allocated. The amount of bytes + //! allocated would be allocated_size() * sizeof(ElementsUsed); + u32 allocated_size() const + { + return allocated; + } + + + + //! Returns true if array is empty + //! \return True if the array is empty, false if not. + bool empty() const + { + return used == 0; + } + + + + //! Sorts the array using heapsort. There is no additional memory waste and + //! the algorithm performs O(n*log n) in worst case. + void sort() + { + if (is_sorted || used<2) + return; + + heapsort(data, used); + is_sorted = true; + } + + + + //! Performs a binary search for an element, returns -1 if not found. + //! The array will be sorted before the binary search if it is not + //! already sorted. + //! \param element: Element to search for. + //! \return Returns position of the searched element if it was found, + //! otherwise -1 is returned. + s32 binary_search(const T& element) + { + sort(); + return binary_search(element, 0, used-1); + } + + //! Performs a binary search for an element, returns -1 if not found. + //! The array must be sorted prior + //! \param element: Element to search for. + //! \return Returns position of the searched element if it was found, + //! otherwise -1 is returned. + s32 binary_search_const(const T& element) const + { + return binary_search(element, 0, used-1); + } + + + + //! Performs a binary search for an element, returns -1 if not found. + //! \param element: Element to search for. + //! \param left: First left index + //! \param right: Last right index. + //! \return Returns position of the searched element if it was found, + //! otherwise -1 is returned. + s32 binary_search(const T& element, s32 left, s32 right) const + { + if (!used) + return -1; + + s32 m; + + do + { + m = (left+right)>>1; + + if (element < data[m]) + right = m - 1; + else + left = m + 1; + + } while((element < data[m] || data[m] < element) && left<=right); + // this last line equals to: + // " while((element != array[m]) && left<=right);" + // but we only want to use the '<' operator. + // the same in next line, it is "(element == array[m])" + + + if (!(element < data[m]) && !(data[m] < element)) + return m; + + return -1; + } + + + //! Finds an element in linear time, which is very slow. Use + //! binary_search for faster finding. Only works if ==operator is implemented. + //! \param element: Element to search for. + //! \return Returns position of the searched element if it was found, + //! otherwise -1 is returned. + s32 linear_search(const T& element) const + { + for (u32 i=0; i=0; --i) + if (data[i] == element) + return i; + + return -1; + } + + + + //! Erases an element from the array. May be slow, because all elements + //! following after the erased element have to be copied. + //! \param index: Index of element to be erased. + void erase(u32 index) + { + _IRR_DEBUG_BREAK_IF(index>=used) // access violation + + for (u32 i=index+1; i=used || count<1 || index+count>used) // access violation + + u32 i; + for (i=index; i index+count) + allocator.destruct(&data[i-count]); + + allocator.construct(&data[i-count], data[i]); // data[i-count] = data[i]; + + if (i >= used-count) + allocator.destruct(&data[i]); + } + + used-= count; + } + + + //! Sets if the array is sorted + void set_sorted(bool _is_sorted) + { + is_sorted = _is_sorted; + } + + + private: + + T* data; + u32 allocated; + u32 used; + bool free_when_destroyed; + bool is_sorted; + TAlloc allocator; +}; + + +} // end namespace core +} // end namespace irr + + +#endif + diff --git a/include/NoIrrlicht/irrMath.h b/include/NoIrrlicht/irrMath.h new file mode 100644 index 0000000..b13e42d --- /dev/null +++ b/include/NoIrrlicht/irrMath.h @@ -0,0 +1,456 @@ +// Copyright (C) 2002-2007 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __IRR_MATH_H_INCLUDED__ +#define __IRR_MATH_H_INCLUDED__ + +#include "IrrCompileConfig.h" +#include "irrTypes.h" +#include + +#if defined(_IRR_SOLARIS_PLATFORM_) || defined(__BORLANDC__) || defined (__BCPLUSPLUS__) || defined (_WIN32_WCE) + #define sqrtf(X) (f32)sqrt((f64)(X)) + #define sinf(X) (f32)sin((f64)(X)) + #define cosf(X) (f32)cos((f64)(X)) + #define asinf(X) (f32)asin((f64)(X)) + #define acosf(X) (f32)acos((f64)(X)) + #define atan2f(X,Y) (f32)atan2((f64)(X),(f64)(Y)) + #define ceilf(X) (f32)ceil((f64)(X)) + #define floorf(X) (f32)floor((f64)(X)) + #define powf(X,Y) (f32)pow((f64)(X),(f64)(Y)) + #define fmodf(X,Y) (f32)fmod((f64)(X),(f64)(Y)) + #define fabsf(X) (f32)fabs((f64)(X)) +#endif + +namespace irr +{ +namespace core +{ + + //! Rounding error constant often used when comparing f32 values. + +#ifdef IRRLICHT_FAST_MATH + const f32 ROUNDING_ERROR_32 = 0.00005f; + const f64 ROUNDING_ERROR_64 = 0.000005f; +#else + const f32 ROUNDING_ERROR_32 = 0.000001f; + const f64 ROUNDING_ERROR_64 = 0.00000001f; +#endif + +#ifdef PI // make sure we don't collide with a define +#undef PI +#endif + //! Constant for PI. + const f32 PI = 3.14159265359f; + + //! Constant for reciprocal of PI. + const f32 RECIPROCAL_PI = 1.0f/PI; + + //! Constant for half of PI. + const f32 HALF_PI = PI/2.0f; + +#ifdef PI64 // make sure we don't collide with a define +#undef PI64 +#endif + //! Constant for 64bit PI. + const f64 PI64 = 3.1415926535897932384626433832795028841971693993751; + + //! Constant for 64bit reciprocal of PI. + const f64 RECIPROCAL_PI64 = 1.0/PI64; + + //! 32bit Constant for converting from degrees to radians + const f32 DEGTORAD = PI / 180.0f; + + //! 32bit constant for converting from radians to degrees (formally known as GRAD_PI) + const f32 RADTODEG = 180.0f / PI; + + //! 64bit constant for converting from degrees to radians (formally known as GRAD_PI2) + const f64 DEGTORAD64 = PI64 / 180.0; + + //! 64bit constant for converting from radians to degrees + const f64 RADTODEG64 = 180.0 / PI64; + + //! returns minimum of two values. Own implementation to get rid of the STL (VS6 problems) + template + inline const T& min_(const T& a, const T& b) + { + return a < b ? a : b; + } + + //! returns minimum of three values. Own implementation to get rid of the STL (VS6 problems) + template + inline const T& min_(const T& a, const T& b, const T& c) + { + return a < b ? min_(a, c) : min_(b, c); + } + + //! returns maximum of two values. Own implementation to get rid of the STL (VS6 problems) + template + inline const T& max_(const T& a, const T& b) + { + return a < b ? b : a; + } + + //! returns maximum of three values. Own implementation to get rid of the STL (VS6 problems) + template + inline const T& max_(const T& a, const T& b, const T& c) + { + return a < b ? max_(b, c) : max_(a, c); + } + + //! returns abs of two values. Own implementation to get rid of STL (VS6 problems) + template + inline T abs_(const T& a) + { + return a < (T)0 ? -a : a; + } + + //! returns linear interpolation of a and b with ratio t + //! \return: a if t==0, b if t==1, and the linear interpolation else + template + inline T lerp(const T& a, const T& b, const f32 t) + { + return (T)(a*(1.f-t)) + (b*t); + } + + //! clamps a value between low and high + template + inline const T clamp (const T& value, const T& low, const T& high) + { + return min_ (max_(value,low), high); + } + + //! returns if a equals b, taking possible rounding errors into account + inline bool equals(const f32 a, const f32 b, const f32 tolerance = ROUNDING_ERROR_32) + { + return (a + tolerance >= b) && (a - tolerance <= b); + } + + //! returns if a equals b, taking possible rounding errors into account + inline bool equals(const s32 a, const s32 b, const s32 tolerance = 0) + { + return (a + tolerance >= b) && (a - tolerance <= b); + } + + //! returns if a equals b, taking possible rounding errors into account + inline bool equals(const u32 a, const u32 b, const u32 tolerance = 0) + { + return (a + tolerance >= b) && (a - tolerance <= b); + } + + //! returns if a equals zero, taking rounding errors into account + inline bool iszero(const f32 a, const f32 tolerance = ROUNDING_ERROR_32) + { + return fabsf ( a ) <= tolerance; + } + + //! returns if a equals zero, taking rounding errors into account + inline bool iszero(const s32 a, const s32 tolerance = 0) + { + return ( a & 0x7ffffff ) <= tolerance; + } + + //! returns if a equals zero, taking rounding errors into account + inline bool iszero(const u32 a, const u32 tolerance = 0) + { + return a <= tolerance; + } + + inline s32 s32_min ( s32 a, s32 b) + { + s32 mask = (a - b) >> 31; + return (a & mask) | (b & ~mask); + } + + inline s32 s32_max ( s32 a, s32 b) + { + s32 mask = (a - b) >> 31; + return (b & mask) | (a & ~mask); + } + + inline s32 s32_clamp (s32 value, s32 low, s32 high) + { + return s32_min (s32_max(value,low), high); + } + + /* + + float IEEE-754 bit represenation + + 0 0x00000000 + 1.0 0x3f800000 + 0.5 0x3f000000 + 3 0x40400000 + +inf 0x7f800000 + -inf 0xff800000 + +NaN 0x7fc00000 or 0x7ff00000 + in general: number = (sign ? -1:1) * 2^(exponent) * 1.(mantissa bits) + */ + + #define F32_AS_S32(f) (*((s32 *) &(f))) + #define F32_AS_U32(f) (*((u32 *) &(f))) + #define F32_AS_U32_POINTER(f) ( ((u32 *) &(f))) + + #define F32_VALUE_0 0x00000000 + #define F32_VALUE_1 0x3f800000 + #define F32_SIGN_BIT 0x80000000U + #define F32_EXPON_MANTISSA 0x7FFFFFFFU + + //! code is taken from IceFPU + //! Integer representation of a floating-point value. + #define IR(x) ((u32&)(x)) + + //! Absolute integer representation of a floating-point value + #define AIR(x) (IR(x)&0x7fffffff) + + //! Floating-point representation of an integer value. + #define FR(x) ((f32&)(x)) + + #define IEEE_1_0 0x3f800000 //!< integer representation of 1.0 + #define IEEE_255_0 0x437f0000 //!< integer representation of 255.0 + +#ifdef IRRLICHT_FAST_MATH + #define F32_LOWER_0(f) (F32_AS_U32(f) > F32_SIGN_BIT) + #define F32_LOWER_EQUAL_0(f) (F32_AS_S32(f) <= F32_VALUE_0) + #define F32_GREATER_0(f) (F32_AS_S32(f) > F32_VALUE_0) + #define F32_GREATER_EQUAL_0(f) (F32_AS_U32(f) <= F32_SIGN_BIT) + #define F32_EQUAL_1(f) (F32_AS_U32(f) == F32_VALUE_1) + #define F32_EQUAL_0(f) ( (F32_AS_U32(f) & F32_EXPON_MANTISSA ) == F32_VALUE_0) + + // only same sign + #define F32_A_GREATER_B(a,b) (F32_AS_S32((a)) > F32_AS_S32((b))) + +#else + + #define F32_LOWER_0(n) ((n) < 0.0f) + #define F32_LOWER_EQUAL_0(n) ((n) <= 0.0f) + #define F32_GREATER_0(n) ((n) > 0.0f) + #define F32_GREATER_EQUAL_0(n) ((n) >= 0.0f) + #define F32_EQUAL_1(n) ((n) == 1.0f) + #define F32_EQUAL_0(n) ((n) == 0.0f) + #define F32_A_GREATER_B(a,b) ((a) > (b)) +#endif + + +#ifndef REALINLINE + #ifdef _MSC_VER + #define REALINLINE __forceinline + #else + #define REALINLINE inline + #endif +#endif + + + //! conditional set based on mask and arithmetic shift + REALINLINE u32 if_c_a_else_b ( const s32 condition, const u32 a, const u32 b ) + { + return ( ( -condition >> 31 ) & ( a ^ b ) ) ^ b; + } + + //! conditional set based on mask and arithmetic shift + REALINLINE u32 if_c_a_else_0 ( const s32 condition, const u32 a ) + { + return ( -condition >> 31 ) & a; + } + + /* + if (condition) state |= m; else state &= ~m; + */ + REALINLINE void setbit_cond ( u32 &state, s32 condition, u32 mask ) + { + // 0, or any postive to mask + //s32 conmask = -condition >> 31; + state ^= ( ( -condition >> 31 ) ^ state ) & mask; + } + + + + inline f32 round_( f32 x ) + { + return floorf( x + 0.5f ); + } + + REALINLINE void clearFPUException () + { +#ifdef IRRLICHT_FAST_MATH +#ifdef feclearexcept + feclearexcept(FE_ALL_EXCEPT); +#elif defined(_MSC_VER) + __asm fnclex; +#elif defined(__GNUC__) && defined(__x86__) + __asm__ __volatile__ ("fclex \n\t"); +#else +# warn clearFPUException not supported. +#endif +#endif + } + + REALINLINE f32 reciprocal_squareroot(const f32 x) + { +#ifdef IRRLICHT_FAST_MATH + // comes from Nvidia +#if 1 + u32 tmp = (u32(IEEE_1_0 << 1) + IEEE_1_0 - *(u32*)&x) >> 1; + f32 y = *(f32*)&tmp; + return y * (1.47f - 0.47f * x * y * y); +#elif defined(_MSC_VER) + // an sse2 version + __asm + { + movss xmm0, x + rsqrtss xmm0, xmm0 + movss x, xmm0 + } + return x; +#endif +#else // no fast math + return 1.f / sqrtf ( x ); +#endif + } + + + + REALINLINE f32 reciprocal ( const f32 f ) + { +#ifdef IRRLICHT_FAST_MATH + //! i do not divide through 0.. (fpu expection) + // instead set f to a high value to get a return value near zero.. + // -1000000000000.f.. is use minus to stay negative.. + // must test's here (plane.normal dot anything ) checks on <= 0.f + return 1.f / f; + //u32 x = (-(AIR(f) != 0 ) >> 31 ) & ( IR(f) ^ 0xd368d4a5 ) ^ 0xd368d4a5; + //return 1.f / FR ( x ); +#else // no fast math + return 1.f / f; +#endif + } + + + REALINLINE f32 reciprocal_approxim ( const f32 p ) + { +#ifdef IRRLICHT_FAST_MATH + register u32 x = 0x7F000000 - IR ( p ); + const f32 r = FR ( x ); + return r * (2.0f - p * r); +#else // no fast math + return 1.f / p; +#endif + } + + + REALINLINE s32 floor32(f32 x) + { +#ifdef IRRLICHT_FAST_MATH + const f32 h = 0.5f; + + s32 t; + +#if defined(_MSC_VER) + __asm + { + fld x + fsub h + fistp t + } +#elif defined(__GNUC__) + __asm__ __volatile__ ( + "fsub %2 \n\t" + "fistpl %0" + : "=m" (t) + : "t" (x), "f" (h) + : "st" + ); +#else +# warn IRRLICHT_FAST_MATH not supported. + return (s32) floorf ( x ); +#endif + return t; +#else // no fast math + return (s32) floorf ( x ); +#endif + } + + + REALINLINE s32 ceil32 ( f32 x ) + { +#ifdef IRRLICHT_FAST_MATH + const f32 h = 0.5f; + + s32 t; + +#if defined(_MSC_VER) + __asm + { + fld x + fadd h + fistp t + } +#elif defined(__GNUC__) + __asm__ __volatile__ ( + "fadd %2 \n\t" + "fistpl %0 \n\t" + : "=m"(t) + : "t"(x), "f"(h) + : "st" + ); +#else +# warn IRRLICHT_FAST_MATH not supported. + return (s32) ceilf ( x ); +#endif + return t; +#else // not fast math + return (s32) ceilf ( x ); +#endif + } + + + + REALINLINE s32 round32(f32 x) + { +#if defined(IRRLICHT_FAST_MATH) + s32 t; + +#if defined(_MSC_VER) + __asm + { + fld x + fistp t + } +#elif defined(__GNUC__) + __asm__ __volatile__ ( + "fistpl %0 \n\t" + : "=m"(t) + : "t"(x) + : "st" + ); +#else +# warn IRRLICHT_FAST_MATH not supported. + return (s32) round_(x); +#endif + return t; +#else // no fast math + return (s32) round_(x); +#endif + } + + inline f32 f32_max3(const f32 a, const f32 b, const f32 c) + { + return a > b ? (a > c ? a : c) : (b > c ? b : c); + } + + inline f32 f32_min3(const f32 a, const f32 b, const f32 c) + { + return a < b ? (a < c ? a : c) : (b < c ? b : c); + } + + inline f32 fract ( f32 x ) + { + return x - floorf ( x ); + } + +} // end namespace core +} // end namespace irr + +#endif + diff --git a/include/NoIrrlicht/irrString.h b/include/NoIrrlicht/irrString.h new file mode 100644 index 0000000..261f140 --- /dev/null +++ b/include/NoIrrlicht/irrString.h @@ -0,0 +1,891 @@ +// Copyright (C) 2002-2007 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine" and the "irrXML" project. +// For conditions of distribution and use, see copyright notice in irrlicht.h and irrXML.h + +#ifndef __IRR_STRING_H_INCLUDED__ +#define __IRR_STRING_H_INCLUDED__ + +#include "irrTypes.h" +#include "irrAllocator.h" +#include "irrMath.h" +#include +#include +#include + +namespace irr +{ +namespace core +{ + +//! Very simple string class with some useful features. +/** string and string work both with unicode AND ascii, +so you can assign unicode to string and ascii to string +(and the other way round) if your ever would want to. +Note that the conversation between both is not done using an encoding. + +Known bugs: +Special characters like umlauts are ignored in the +methods make_upper, make_lower and equals_ignore_case. +*/ +template > +class string +{ +public: + + //! Default constructor + string() + : array(0), allocated(1), used(1) + { + array = allocator.allocate(1); // new T[1]; + array[0] = 0x0; + } + + + + //! Constructor + string(const string& other) + : array(0), allocated(0), used(0) + { + *this = other; + } + + + + //! Constructs a string from a float + string(const double number) + : array(0), allocated(0), used(0) + { + c8 tmpbuf[255]; + snprintf(tmpbuf, 255, "%0.6f", number); + *this = tmpbuf; + } + + + + //! Constructs a string from an int + string(int number) + : array(0), allocated(0), used(0) + { + // store if negative and make positive + + bool negative = false; + if (number < 0) + { + number *= -1; + negative = true; + } + + // temporary buffer for 16 numbers + + c8 tmpbuf[16]; + tmpbuf[15] = 0; + u32 idx = 15; + + // special case '0' + + if (!number) + { + tmpbuf[14] = '0'; + *this = &tmpbuf[14]; + return; + } + + // add numbers + + while(number && idx) + { + --idx; + tmpbuf[idx] = (c8)('0' + (number % 10)); + number /= 10; + } + + // add sign + + if (negative) + { + --idx; + tmpbuf[idx] = '-'; + } + + *this = &tmpbuf[idx]; + } + + + + //! Constructs a string from an unsigned int + string(unsigned int number) + : array(0), allocated(0), used(0) + { + // temporary buffer for 16 numbers + + c8 tmpbuf[16]; + tmpbuf[15] = 0; + u32 idx = 15; + + // special case '0' + + if (!number) + { + tmpbuf[14] = '0'; + *this = &tmpbuf[14]; + return; + } + + // add numbers + + while(number && idx) + { + --idx; + tmpbuf[idx] = (c8)('0' + (number % 10)); + number /= 10; + } + + *this = &tmpbuf[idx]; + } + + + + //! Constructor for copying a string from a pointer with a given length + template + string(const B* const c, u32 length) + : array(0), allocated(0), used(0) + { + if (!c) + { + // correctly init the string to an empty one + *this=""; + return; + } + + allocated = used = length+1; + array = allocator.allocate(used); // new T[used]; + + for (u32 l = 0; l + string(const B* const c) + : array(0), allocated(0), used(0) + { + *this = c; + } + + + + //! destructor + ~string() + { + allocator.deallocate(array); // delete [] array; + } + + + + //! Assignment operator + string& operator=(const string& other) + { + if (this == &other) + return *this; + + allocator.deallocate(array); // delete [] array; + allocated = used = other.size()+1; + array = allocator.allocate(used); //new T[used]; + + const T* p = other.c_str(); + for (u32 i=0; i + string& operator=(const B* const c) + { + if (!c) + { + if (!array) + { + array = allocator.allocate(1); //new T[1]; + allocated = 1; + } + used = 1; + array[0] = 0x0; + return *this; + } + + if ((void*)c == (void*)array) + return *this; + + u32 len = 0; + const B* p = c; + while(*p) + { + ++len; + ++p; + } + + // we'll take the old string for a while, because the new + // string could be a part of the current string. + T* oldArray = array; + + ++len; + allocated = used = len; + array = allocator.allocate(used); //new T[used]; + + for (u32 l = 0; l operator+(const string& other) const + { + string str(*this); + str.append(other); + + return str; + } + + //! Add operator for strings, ascii and unicode + template + string operator+(const B* const c) const + { + string str(*this); + str.append(c); + + return str; + } + + + //! Direct access operator + T& operator [](const u32 index) + { + _IRR_DEBUG_BREAK_IF(index>=used) // bad index + return array[index]; + } + + + //! Direct access operator + const T& operator [](const u32 index) const + { + _IRR_DEBUG_BREAK_IF(index>=used) // bad index + return array[index]; + } + + + //! Comparison operator + bool operator ==(const T* const str) const + { + if (!str) + return false; + + u32 i; + for(i=0; array[i] && str[i]; ++i) + if (array[i] != str[i]) + return false; + + return !array[i] && !str[i]; + } + + + + //! Comparison operator + bool operator ==(const string& other) const + { + for(u32 i=0; array[i] && other.array[i]; ++i) + if (array[i] != other.array[i]) + return false; + + return used == other.used; + } + + + //! Is smaller operator + bool operator <(const string& other) const + { + for(u32 i=0; array[i] && other.array[i]; ++i) + { + s32 diff = array[i] - other.array[i]; + if ( diff ) + return diff < 0; +/* + if (array[i] != other.array[i]) + return (array[i] < other.array[i]); +*/ + } + + return used < other.used; + } + + + + //! Equals not operator + bool operator !=(const T* const str) const + { + return !(*this == str); + } + + + + //! Equals not operator + bool operator !=(const string& other) const + { + return !(*this == other); + } + + + + //! Returns length of string + /** \return Returns length of the string in characters. */ + u32 size() const + { + return used-1; + } + + + + //! Returns character string + /** \return Returns pointer to C-style zero terminated string. */ + const T* c_str() const + { + return array; + } + + + + //! Makes the string lower case. + void make_lower() + { + for (u32 i=0; i=a && array[i]<=z) + array[i] += diff; + } + } + + + + //! Compares the string ignoring case. + /** \param other: Other string to compare. + \return Returns true if the string are equal ignoring case. */ + bool equals_ignore_case(const string& other) const + { + for(u32 i=0; array[i] && other[i]; ++i) + if (ansi_lower(array[i]) != ansi_lower(other[i])) + return false; + + return used == other.used; + } + + //! Compares the string ignoring case. + /** \param other: Other string to compare. + \return Returns true if the string is smaller ignoring case. */ + bool lower_ignore_case(const string& other) const + { + for(u32 i=0; array[i] && other.array[i]; ++i) + { + s32 diff = (s32) ansi_lower ( array[i] ) - (s32) ansi_lower ( other.array[i] ); + if ( diff ) + return diff < 0; + } + + return used < other.used; + } + + + + //! compares the first n characters of the strings + bool equalsn(const string& other, u32 n) const + { + u32 i; + for(i=0; array[i] && other[i] && i < n; ++i) + if (array[i] != other[i]) + return false; + + // if one (or both) of the strings was smaller then they + // are only equal if they have the same length + return (i == n) || (used == other.used); + } + + + //! compares the first n characters of the strings + bool equalsn(const T* const str, u32 n) const + { + if (!str) + return false; + s32 i; + for(i=0; array[i] && str[i] && i < n; ++i) + if (array[i] != str[i]) + return false; + + // if one (or both) of the strings was smaller then they + // are only equal if they have the same length + return (i == n) || (array[i] == 0 && str[i] == 0); + } + + + //! Appends a character to this string + /** \param character: Character to append. */ + void append(T character) + { + if (used + 1 > allocated) + reallocate(used + 1); + + ++used; + + array[used-2] = character; + array[used-1] = 0; + } + + //! Appends a char string to this string + /** \param other: Char string to append. */ + void append(const T* const other) + { + if (!other) + return; + + u32 len = 0; + const T* p = other; + while(*p) + { + ++len; + ++p; + } + + if (used + len > allocated) + reallocate(used + len); + + --used; + ++len; + + for (u32 l=0; l& other) + { + --used; + u32 len = other.size()+1; + + if (used + len > allocated) + reallocate(used + len); + + for (u32 l=0; l& other, u32 length) + { + if (other.size() < length) + { + append(other); + return; + } + + if (used + length > allocated) + reallocate(used + length); + + --used; + + for (u32 l=0; l + s32 findFirstCharNotInList(const B* const c, u32 count) const + { + for (u32 i=0; i + s32 findLastCharNotInList(const B* const c, u32 count) const + { + for (s32 i=(s32)(used-2); i>=0; --i) + { + u32 j; + for (j=0; j=0; --i) + if (array[i] == c) + return i; + + return -1; + } + + //! finds last occurrence of a character of a list in string + /** \param c: List of strings to find. For example if the method + should find the last occurrence of 'a' or 'b', this parameter should be "ab". + \param count: Amount of characters in the list. Usually, + this should be strlen(c) + \return Returns position where one of the characters has been found, + or -1 if not found. */ + s32 findLastChar(const T* const c, u32 count) const + { + if (!c) + return -1; + + for (s32 i=used-1; i>=0; --i) + for (u32 j=0; j + s32 find(const B* const str) const + { + if (str && *str) + { + u32 len = 0; + + while (str[len]) + ++len; + + if (len > used-1) + return -1; + + for (s32 i=0; i subString(u32 begin, s32 length) const + { + if ((length+begin) > size()) + length = size()-begin; + if (length <= 0) + return string(""); + + string o; + o.reserve(length+1); + + for (s32 i=0; i& operator += (T c) + { + append(c); + return *this; + } + + + string& operator += (const T* const c) + { + append(c); + return *this; + } + + + string& operator += (const string& other) + { + append(other); + return *this; + } + + + string& operator += (const int i) + { + append(string(i)); + return *this; + } + + + string& operator += (const unsigned int i) + { + append(string(i)); + return *this; + } + + + string& operator += (const long i) + { + append(string(i)); + return *this; + } + + + string& operator += (const unsigned long& i) + { + append(string(i)); + return *this; + } + + + string& operator += (const double i) + { + append(string(i)); + return *this; + } + + + string& operator += (const float i) + { + append(string(i)); + return *this; + } + + + //! replaces all characters of a special type with another one + void replace(T toReplace, T replaceWith) + { + for (u32 i=0; i& trim() + { + const c8 whitespace[] = " \t\n\r"; + const u32 whitespacecount = 4; + + // find start and end of real string without whitespace + const s32 begin = findFirstCharNotInList(whitespace, whitespacecount); + if (begin == -1) + return (*this=""); + + const s32 end = findLastCharNotInList(whitespace, whitespacecount); + + return (*this = subString(begin, (end +1) - begin)); + } + + + //! Erases a character from the string. May be slow, because all elements + //! following after the erased element have to be copied. + //! \param index: Index of element to be erased. + void erase(u32 index) + { + _IRR_DEBUG_BREAK_IF(index>=used) // access violation + + for (u32 i=index+1; i=(T)'A' && t<=(T)'Z') + return t + ((T)'a' - (T)'A'); + else + return t; + } +*/ + //! Returns a character converted to lower case + inline T ansi_lower ( u32 x ) const + { + return x >= 'A' && x <= 'Z' ? (T) x + 0x20 : (T) x; + } + + + //! Reallocate the array, make it bigger or smaller + void reallocate(u32 new_size) + { + T* old_array = array; + + array = allocator.allocate(new_size); //new T[new_size]; + allocated = new_size; + + u32 amount = used < new_size ? used : new_size; + for (u32 i=0; i stringc; + +//! Typedef for wide character strings +typedef string stringw; + +} // end namespace core +} // end namespace irr + +#endif + diff --git a/include/NoIrrlicht/irrTypes.h b/include/NoIrrlicht/irrTypes.h new file mode 100644 index 0000000..c611455 --- /dev/null +++ b/include/NoIrrlicht/irrTypes.h @@ -0,0 +1,159 @@ +// Copyright (C) 2002-2007 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __IRR_TYPES_H_INCLUDED__ +#define __IRR_TYPES_H_INCLUDED__ + + +namespace irr +{ + +//! 8 bit unsigned variable. +/** This is a typedef for unsigned char, it ensures portability of the engine. */ +typedef unsigned char u8; + +//! 8 bit signed variable. +/** This is a typedef for signed char, it ensures portability of the engine. */ +typedef signed char s8; + +//! 8 bit character variable. +/** This is a typedef for char, it ensures portability of the engine. */ +typedef char c8; + + + +//! 16 bit unsigned variable. +/** This is a typedef for unsigned short, it ensures portability of the engine. */ +typedef unsigned short u16; + +//! 16 bit signed variable. +/** This is a typedef for signed short, it ensures portability of the engine. */ +typedef signed short s16; + + + +//! 32 bit unsigned variable. +/** This is a typedef for unsigned int, it ensures portability of the engine. */ +typedef unsigned int u32; + +//! 32 bit signed variable. +/** This is a typedef for signed int, it ensures portability of the engine. */ +typedef signed int s32; + + + +// 64 bit signed variable. +// This is a typedef for __int64, it ensures portability of the engine. +// This type is currently not used by the engine and not supported by compilers +// other than Microsoft Compilers, so it is outcommented. +//typedef __int64 s64; + + + +//! 32 bit floating point variable. +/** This is a typedef for float, it ensures portability of the engine. */ +typedef float f32; + +//! 64 bit floating point variable. +/** This is a typedef for double, it ensures portability of the engine. */ +typedef double f64; + + +} // end namespace irr + + +#include +#ifdef _IRR_WINDOWS_API_ +//! Defines for s{w,n}printf because these methods do not match the ISO C +//! standard on Windows platforms, but it does on all others. +//! These should be int snprintf(char *str, size_t size, const char *format, ...); +//! and int swprintf(wchar_t *wcs, size_t maxlen, const wchar_t *format, ...); +#if defined(_MSC_VER) && _MSC_VER > 1310 && !defined (_WIN32_WCE) +#define swprintf swprintf_s +#define snprintf sprintf_s +#else +#define swprintf _snwprintf +#define snprintf _snprintf +#endif + +// define the wchar_t type if not already built in. +#ifdef _MSC_VER +#ifndef _WCHAR_T_DEFINED +//! A 16 bit wide character type. +/** + Defines the wchar_t-type. + In VS6, its not possible to tell + the standard compiler to treat wchar_t as a built-in type, and + sometimes we just don't want to include the huge stdlib.h or wchar.h, + so we'll use this. +*/ +typedef unsigned short wchar_t; +#define _WCHAR_T_DEFINED +#endif // wchar is not defined +#endif // microsoft compiler +#endif // _IRR_WINDOWS_API_ + +//! define a break macro for debugging. +#if defined(_DEBUG) +#if defined(_IRR_WINDOWS_API_) && defined(_MSC_VER) && !defined (_WIN32_WCE) +#define _IRR_DEBUG_BREAK_IF( _CONDITION_ ) if (_CONDITION_) {_asm int 3} +#else +#include "assert.h" +#define _IRR_DEBUG_BREAK_IF( _CONDITION_ ) assert( !(_CONDITION_) ); +#endif +#else +#define _IRR_DEBUG_BREAK_IF( _CONDITION_ ) +#endif + +//! Defines a small statement to work around a microsoft compiler bug. +/** The microsft compiler 7.0 - 7.1 has a bug: +When you call unmanaged code that returns a bool type value of false from managed code, +the return value may appear as true. See +http://support.microsoft.com/default.aspx?kbid=823071 for details. +Compiler version defines: VC6.0 : 1200, VC7.0 : 1300, VC7.1 : 1310, VC8.0 : 1400*/ +#if defined(_IRR_WINDOWS_API_) && defined(_MSC_VER) && (_MSC_VER > 1299) && (_MSC_VER < 1400) +#define _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX __asm mov eax,100 +#else +#define _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX +#endif // _IRR_MANAGED_MARSHALLING_BUGFIX + + +// memory debugging +#if defined(_DEBUG) && defined(IRRLICHT_EXPORTS) && defined(_MSC_VER) && \ + (_MSC_VER > 1299) && !defined(_IRR_DONT_DO_MEMORY_DEBUGGING_HERE) && !defined(_WIN32_WCE) + + #define CRTDBG_MAP_ALLOC + #define _CRTDBG_MAP_ALLOC + #define DEBUG_CLIENTBLOCK new( _CLIENT_BLOCK, __FILE__, __LINE__) + #include + #include + #define new DEBUG_CLIENTBLOCK +#endif + +// disable truncated debug information warning in visual studio 6 by default +#if defined(_MSC_VER) && (_MSC_VER < 1300 ) +#pragma warning( disable: 4786) +#endif // _MSC + + +//! ignore VC8 warning deprecated +/** The microsoft compiler */ +#if defined(_IRR_WINDOWS_API_) && defined(_MSC_VER) && (_MSC_VER >= 1400) + //#pragma warning( disable: 4996) + //#define _CRT_SECURE_NO_DEPRECATE 1 + //#define _CRT_NONSTDC_NO_DEPRECATE 1 +#endif + + +//! creates four CC codes used in Irrlicht for simple ids +/** some compilers can create those by directly writing the +code like 'code', but some generate warnings so we use this macro here */ +#define MAKE_IRR_ID(c0, c1, c2, c3) \ + ((u32)(u8)(c0) | ((u32)(u8)(c1) << 8) | \ + ((u32)(u8)(c2) << 16) | ((u32)(u8)(c3) << 24 )) + + +#endif // __IRR_TYPES_H_INCLUDED__ + + diff --git a/include/NoIrrlicht/vector3d.h b/include/NoIrrlicht/vector3d.h new file mode 100644 index 0000000..8cc887a --- /dev/null +++ b/include/NoIrrlicht/vector3d.h @@ -0,0 +1,287 @@ +// Copyright (C) 2002-2007 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __IRR_POINT_3D_H_INCLUDED__ +#define __IRR_POINT_3D_H_INCLUDED__ + +#include "irrMath.h" + +namespace irr +{ +namespace core +{ + + //! 3d vector template class with lots of operators and methods. + template + class vector3d + { + public: + + vector3d() : X(0), Y(0), Z(0) {} + vector3d(T nx, T ny, T nz) : X(nx), Y(ny), Z(nz) {} + vector3d(const vector3d& other) : X(other.X), Y(other.Y), Z(other.Z) {} + + // operators + + vector3d operator-() const { return vector3d(-X, -Y, -Z); } + + vector3d& operator=(const vector3d& other) { X = other.X; Y = other.Y; Z = other.Z; return *this; } + + vector3d operator+(const vector3d& other) const { return vector3d(X + other.X, Y + other.Y, Z + other.Z); } + vector3d& operator+=(const vector3d& other) { X+=other.X; Y+=other.Y; Z+=other.Z; return *this; } + + vector3d operator-(const vector3d& other) const { return vector3d(X - other.X, Y - other.Y, Z - other.Z); } + vector3d& operator-=(const vector3d& other) { X-=other.X; Y-=other.Y; Z-=other.Z; return *this; } + + vector3d operator*(const vector3d& other) const { return vector3d(X * other.X, Y * other.Y, Z * other.Z); } + vector3d& operator*=(const vector3d& other) { X*=other.X; Y*=other.Y; Z*=other.Z; return *this; } + vector3d operator*(const T v) const { return vector3d(X * v, Y * v, Z * v); } + vector3d& operator*=(const T v) { X*=v; Y*=v; Z*=v; return *this; } + + vector3d operator/(const vector3d& other) const { return vector3d(X / other.X, Y / other.Y, Z / other.Z); } + vector3d& operator/=(const vector3d& other) { X/=other.X; Y/=other.Y; Z/=other.Z; return *this; } + vector3d operator/(const T v) const { T i=(T)1.0/v; return vector3d(X * i, Y * i, Z * i); } + vector3d& operator/=(const T v) { T i=(T)1.0/v; X*=i; Y*=i; Z*=i; return *this; } + + bool operator<=(const vector3d&other) const { return X<=other.X && Y<=other.Y && Z<=other.Z;}; + bool operator>=(const vector3d&other) const { return X>=other.X && Y>=other.Y && Z>=other.Z;}; + bool operator<(const vector3d&other) const { return X(const vector3d&other) const { return X>other.X && Y>other.Y && Z>other.Z;}; + + //! use week float compare + //bool operator==(const vector3d& other) const { return other.X==X && other.Y==Y && other.Z==Z; } + //bool operator!=(const vector3d& other) const { return other.X!=X || other.Y!=Y || other.Z!=Z; } + + bool operator==(const vector3d& other) const + { + return this->equals(other); + } + + bool operator!=(const vector3d& other) const + { + return !this->equals(other); + } + + // functions + + //! returns if this vector equals the other one, taking floating point rounding errors into account + bool equals(const vector3d& other, const T tolerance = (T)ROUNDING_ERROR_32 ) const + { + return core::equals(X, other.X, tolerance) && + core::equals(Y, other.Y, tolerance) && + core::equals(Z, other.Z, tolerance); + } + + vector3d& set(const T nx, const T ny, const T nz) {X=nx; Y=ny; Z=nz; return *this;} + vector3d& set(const vector3d& p) {X=p.X; Y=p.Y; Z=p.Z;return *this;} + + //! Returns length of the vector. + T getLength() const { return (T) sqrt((f64)(X*X + Y*Y + Z*Z)); } + + //! Returns squared length of the vector. + /** This is useful because it is much faster than + getLength(). */ + T getLengthSQ() const { return X*X + Y*Y + Z*Z; } + + //! Returns the dot product with another vector. + T dotProduct(const vector3d& other) const + { + return X*other.X + Y*other.Y + Z*other.Z; + } + + //! Returns distance from another point. + /** Here, the vector is interpreted as point in 3 dimensional space. */ + T getDistanceFrom(const vector3d& other) const + { + return vector3d(X - other.X, Y - other.Y, Z - other.Z).getLength(); + } + + //! Returns squared distance from another point. + /** Here, the vector is interpreted as point in 3 dimensional space. */ + T getDistanceFromSQ(const vector3d& other) const + { + return vector3d(X - other.X, Y - other.Y, Z - other.Z).getLengthSQ(); + } + + //! Calculates the cross product with another vector + //! \param p: vector to multiply with. + //! \return Crossproduct of this vector with p. + vector3d crossProduct(const vector3d& p) const + { + return vector3d(Y * p.Z - Z * p.Y, Z * p.X - X * p.Z, X * p.Y - Y * p.X); + } + + //! Returns if this vector interpreted as a point is on a line between two other points. + /** It is assumed that the point is on the line. */ + //! \param begin: Beginning vector to compare between. + //! \param end: Ending vector to compare between. + //! \return True if this vector is between begin and end. False if not. + bool isBetweenPoints(const vector3d& begin, const vector3d& end) const + { + T f = (end - begin).getLengthSQ(); + return getDistanceFromSQ(begin) < f && + getDistanceFromSQ(end) < f; + } + + //! Normalizes the vector. In case of the 0 vector the result + //! is still 0, otherwise the length of the vector will be 1. + //! Todo: 64 Bit template doesnt work.. need specialized template + vector3d& normalize() + { + T l = X*X + Y*Y + Z*Z; + if (l == 0) + return *this; + l = (T) reciprocal_squareroot ( (f32)l ); + X *= l; + Y *= l; + Z *= l; + return *this; + } + + //! Sets the length of the vector to a new value + vector3d& setLength(T newlength) + { + normalize(); + return (*this *= newlength); + } + + //! Inverts the vector. + vector3d& invert() + { + X *= -1.0f; + Y *= -1.0f; + Z *= -1.0f; + return *this; + } + + //! Rotates the vector by a specified number of degrees around the Y + //! axis and the specified center. + //! \param degrees: Number of degrees to rotate around the Y axis. + //! \param center: The center of the rotation. + void rotateXZBy(f64 degrees, const vector3d& center=vector3d()) + { + degrees *= DEGTORAD64; + T cs = (T)cos(degrees); + T sn = (T)sin(degrees); + X -= center.X; + Z -= center.Z; + set(X*cs - Z*sn, Y, X*sn + Z*cs); + X += center.X; + Z += center.Z; + } + + //! Rotates the vector by a specified number of degrees around the Z + //! axis and the specified center. + //! \param degrees: Number of degrees to rotate around the Z axis. + //! \param center: The center of the rotation. + void rotateXYBy(f64 degrees, const vector3d& center=vector3d()) + { + degrees *= DEGTORAD64; + T cs = (T)cos(degrees); + T sn = (T)sin(degrees); + X -= center.X; + Y -= center.Y; + set(X*cs - Y*sn, X*sn + Y*cs, Z); + X += center.X; + Y += center.Y; + } + + //! Rotates the vector by a specified number of degrees around the X + //! axis and the specified center. + //! \param degrees: Number of degrees to rotate around the X axis. + //! \param center: The center of the rotation. + void rotateYZBy(f64 degrees, const vector3d& center=vector3d()) + { + degrees *= DEGTORAD64; + T cs = (T)cos(degrees); + T sn = (T)sin(degrees); + Z -= center.Z; + Y -= center.Y; + set(X, Y*cs - Z*sn, Y*sn + Z*cs); + Z += center.Z; + Y += center.Y; + } + + //! Returns interpolated vector. + /** \param other: other vector to interpolate between + \param d: value between 0.0f and 1.0f. */ + vector3d getInterpolated(const vector3d& other, const T d) const + { + const T inv = (T) 1.0 - d; + return vector3d(other.X*inv + X*d, other.Y*inv + Y*d, other.Z*inv + Z*d); + } + + //! Returns interpolated vector. ( quadratic ) + /** \param v2: second vector to interpolate with + \param v3: third vector to interpolate with + \param d: value between 0.0f and 1.0f. */ + vector3d getInterpolated_quadratic(const vector3d& v2, const vector3d& v3, const T d) const + { + // this*(1-d)*(1-d) + 2 * v2 * (1-d) + v3 * d * d; + const T inv = (T) 1.0 - d; + const T mul0 = inv * inv; + const T mul1 = (T) 2.0 * d * inv; + const T mul2 = d * d; + + return vector3d ( X * mul0 + v2.X * mul1 + v3.X * mul2, + Y * mul0 + v2.Y * mul1 + v3.Y * mul2, + Z * mul0 + v2.Z * mul1 + v3.Z * mul2); + } + + //! Gets the Y and Z rotations of a vector. + /** Thanks to Arras on the Irrlicht forums to add this method. + \return A vector representing the rotation in degrees of + this vector. The Z component of the vector will always be 0. */ + vector3d getHorizontalAngle() const + { + vector3d angle; + + angle.Y = (T)atan2(X, Z); + angle.Y *= (f32)RADTODEG64; + + if (angle.Y < 0.0f) angle.Y += 360.0f; + if (angle.Y >= 360.0f) angle.Y -= 360.0f; + + const f32 z1 = sqrtf(X*X + Z*Z); + + angle.X = (T)atan2f(z1, (f32)Y); + angle.X *= RADTODEG; + angle.X -= 90.0f; + + if (angle.X < 0.0f) angle.X += 360.0f; + if (angle.X >= 360.0f) angle.X -= 360.0f; + + return angle; + } + + //! Fills an array of 4 values with the vector data (usually floats). + /** Useful for setting in shader constants for example. The fourth value + will always be 0. */ + void getAs4Values(T* array) const + { + array[0] = X; + array[1] = Y; + array[2] = Z; + array[3] = 0; + } + + // member variables + + T X, Y, Z; + }; + + + //! Typedef for a f32 3d vector. + typedef vector3d vector3df; + //! Typedef for an integer 3d vector. + typedef vector3d vector3di; + + template + vector3d operator*(const S scalar, const vector3d& vector) { return vector*scalar; } + +} // end namespace core +} // end namespace irr + +#endif + diff --git a/include/SPacket.h b/include/SPacket.h new file mode 100644 index 0000000..6d9d1e9 --- /dev/null +++ b/include/SPacket.h @@ -0,0 +1,166 @@ +#ifndef NET_PACKET_H +#define NET_PACKET_H + +#ifdef COMPILE_WITH_IRRLICHT +#include +#endif + +#ifndef IRRLICHT_SDK_VERSION +#include "NoIrrlicht/NoIrrlicht.h" +#endif + +#ifndef s64 +typedef signed long long s64; +#endif + +#ifndef u64 +typedef signed long long u64; +#endif + +#include + +namespace irr +{ +namespace net +{ + +/// An SOutPacket class, used for sending packets. +class SOutPacket +{ + public: + SOutPacket(); + SOutPacket(const c8* buff,const u32 buff_size); + + /// Adds data to the packet. + SOutPacket& operator << (const c8 data); + /// Adds data to the packet. + SOutPacket& operator << (const u16 data); + /// Adds data to the packet. + SOutPacket& operator << (const u32 data); + /// Adds data to the packet. + SOutPacket& operator << (const u8 data); + /// Adds data to the packet. + SOutPacket& operator << (const s16 data); + /// Adds data to the packet. + SOutPacket& operator << (const s32 data); + /// Adds data to the packet. + SOutPacket& operator << (const f32 data); + /// Adds data to the packet. + SOutPacket& operator << (const f64 data); + /// Adds data to the packet. + SOutPacket& operator << (const core::vector3df& data); + /// Adds data to the packet. + SOutPacket& operator << (const c8* string); + /// Adds data to the packet. + SOutPacket& operator << (const core::stringc& string); + /// Adds data to the packet. + SOutPacket& operator << (const std::string& string); + /// Adds data to the packet. + SOutPacket& operator << (const core::stringw& string); + + /// Appends another SOutPacket to the packet. + SOutPacket& operator << (const SOutPacket& other); + + /// Clears the data in the packet. (Resets the write position) + void clearData(); + + /// Gets the data in the packet. + c8* getData(); + + /// Gets the data in the packet. + const c8* getConstData(); + + /// Returns the size in bytes of the packet. + u32 getSize(); + + /// Compresses the packet using zlib compression. + void compressPacket(); + + /// Decompresses the packet using zlib decompression. + void deCompressPacket(); + + /// Encrypts a packet using AES encryption. + void encryptPacket(const c8 key[16]); + + /// Decrypts a packet using AES decryption. + void decryptPacket(const c8 key[16]); + private: + void enlargeBuffer(const u32 size); + core::array buff; +}; + +/// An SInPacket class, used for handling recieved packets. +class SInPacket +{ + public: + SInPacket(const c8* buff, const u32 size); + + void setNewData(const c8* buffer, const u32 size); + + /// Gets the next item in the packet based on the size of the variable. + void operator >> (c8& data); + /// Gets the next item in the packet based on the size of the variable. + void operator >> (u16& data); + /// Gets the next item in the packet based on the size of the variable. + void operator >> (u32& data); + /// Gets the next item in the packet based on the size of the variable. + void operator >> (u8& data); + /// Gets the next item in the packet based on the size of the variable. + void operator >> (s16& data); + /// Gets the next item in the packet based on the size of the variable. + void operator >> (s32& data); + /// Gets the next item in the packet based on the size of the variable. + void operator >> (f32& data); + /// Gets the next item in the packet based on the size of the variable. + void operator >> (f64& data); + /// Gets the next item in the packet based on the size of the variable. + void operator >> (core::vector3df& data); + /// Gets the next item in the packet based on the size of the variable. + void operator >> (char* string); + /// Gets the next item in the packet based on the size of the variable. + void operator >> (core::stringc& string); + /// Gets the next item in the packet based on the size of the variable. + void operator >> (std::string& string); + /// Gets the next item in the packet based on the size of the variable. + void operator >> (core::stringw& string); + + /// Gets the data in the packet. + c8* getData(); + + /// Gets the data in the packet. + const c8* getConstData(); + + /// Resets the read position. + void resetPos(); + + /// Returns the player ID of the player that sent this packet. (Only for servers) + u16 getPlayerId() const; + + // Used internally by irrNetLite to set the player ID. + void setPlayerId(u16 playernumber); + + /// Compresses the packet using zlib compression. + void compressPacket(); + + /// Decompresses the packet using zlib decompression. + void deCompressPacket(); + + /// Encrypts a packet using AES encryption. + void encryptPacket(const c8 key[16]); + + /// Decrypts a packet using AES decryption. + void decryptPacket(const c8 key[16]); + + /// Returns the size in bytes of the packet. + u32 getSize(); + + private: + u32 pos; + core::array buff; + u16 playerid; +}; + +} // Close Net Namespace +} // Close Irr namespace + +#endif diff --git a/include/irrNet.h b/include/irrNet.h new file mode 100644 index 0000000..a0b63e6 --- /dev/null +++ b/include/irrNet.h @@ -0,0 +1,28 @@ +#ifndef IRRNET_H +#define IRRNET_H +#include "SPacket.h" +#include "INetManager.h" +#endif + +// Copyright(C) Ahmed Hilali 2007 + +/* License: + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgement in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be clearly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + */ + diff --git a/lib/libirrnet.a b/lib/libirrnet.a new file mode 100644 index 0000000..20fe24f Binary files /dev/null and b/lib/libirrnet.a differ diff --git a/source/CMakeLists.txt b/source/CMakeLists.txt new file mode 100644 index 0000000..ce6dc8f --- /dev/null +++ b/source/CMakeLists.txt @@ -0,0 +1,57 @@ +cmake_minimum_required(VERSION 2.6) + +project(enet) + +# The "configure" step. +include(CheckFunctionExists) +include(CheckStructHasMember) +include(CheckTypeSize) +check_function_exists("fcntl" HAS_FCNTL) +check_function_exists("poll" HAS_POLL) +check_function_exists("gethostbyname_r" HAS_GETHOSTBYNAME_R) +check_function_exists("gethostbyaddr_r" HAS_GETHOSTBYADDR_R) +check_function_exists("inet_pton" HAS_INET_PTON) +check_function_exists("inet_ntop" HAS_INET_NTOP) +check_struct_has_member("struct msghdr" "msg_flags" "sys/types.h;sys/socket.h" HAS_MSGHDR_FLAGS) +set(CMAKE_EXTRA_INCLUDE_FILES "sys/types.h" "sys/socket.h") +check_type_size("socklen_t" HAS_SOCKLEN_T BUILTIN_TYPES_ONLY) +unset(CMAKE_EXTRA_INCLUDE_FILES) + +if(HAS_FCNTL) + add_definitions(-DHAS_FCNTL=1) +endif() +if(HAS_POLL) + add_definitions(-DHAS_POLL=1) +endif() +if(HAS_GETHOSTBYNAME_R) + add_definitions(-DHAS_GETHOSTBYNAME_R=1) +endif() +if(HAS_GETHOSTBYADDR_R) + add_definitions(-DHAS_GETHOSTBYADDR_R=1) +endif() +if(HAS_INET_PTON) + add_definitions(-DHAS_INET_PTON=1) +endif() +if(HAS_INET_NTOP) + add_definitions(-DHAS_INET_NTOP=1) +endif() +if(HAS_MSGHDR_FLAGS) + add_definitions(-DHAS_MSGHDR_FLAGS=1) +endif() +if(HAS_SOCKLEN_T) + add_definitions(-DHAS_SOCKLEN_T=1) +endif() + +include_directories(${PROJECT_SOURCE_DIR}/include) + +add_library(enet STATIC + callbacks.c + compress.c + host.c + list.c + packet.c + peer.c + protocol.c + unix.c + win32.c + ) diff --git a/source/CNetManager.cpp b/source/CNetManager.cpp new file mode 100644 index 0000000..1b7e750 --- /dev/null +++ b/source/CNetManager.cpp @@ -0,0 +1,463 @@ +#include "CNetManager.h" +#include + +namespace irr +{ + namespace net + { + CNetManager::CNetManager(INetCallback* handler, u32 port, const SNetParams& params) : + pHandler(handler), netIterations(10000), netParams(params), verbose(0), + globPacketRelay(false), connectionStatus(EICS_PENDING) + { + if (enet_initialize() != 0) + std::cout << "irrNetLite: An error occurred while initializing ENet.\n"; + + connectionStatus = setUpServer(port) ? EICS_ESTABLISHED : EICS_FAILED; + } + + CNetManager::CNetManager(INetCallback* handler, const c8* addressc, + const u32 port, const SNetParams& params) : + pHandler(handler), netIterations(10000), netParams(params), verbose(0), + globPacketRelay(false), connectionStatus(EICS_PENDING) + { + if (enet_initialize() != 0) + std::cout << "irrNetLite: An error occurred while initializing ENet.\n"; + + if(!setUpClient(addressc, port)) + connectionStatus = EICS_FAILED; + } + + CNetManager::~CNetManager(void) + { + if(host) + enet_host_destroy(host); + + enet_deinitialize(); + } + + bool CNetManager::setUpClient(const c8* addressc, const u32 port) + { + mode = ENM_CLIENT; + + if(verbose) + std::cout << "irrNetLite: Creating client!" << std::endl; + + host = enet_host_create(NULL, 1,2, netParams.downBandwidth / 8, netParams.upBandwidth / 8); + + ENetEvent event; + + enet_address_set_host(&address, addressc); + address.port = port; + + if(verbose) + std::cout << "irrNetLite: Connecting to " + << addressc << ":" << port << std::endl; + + // Sets up two channels. + peer = enet_host_connect(host, &address, 2, 0); + + if(peer == NULL) + { + std::cout << "irrNetLite: Error: Could not resolve server address. Connection failed.\n"; + return false; + } + + if(!( enet_host_service(host, &event, netParams.connectionTimeout) > 0 && + event.type == ENET_EVENT_TYPE_CONNECT)) + { + enet_peer_reset(peer); + + std::cout << "irrNetLite: Error: Connection timed out. Connection failed.\n"; + return false; + } + + while(enet_host_service(host, &event, netParams.connectionTimeout) > 0) + { + if(event.channelID == 1 && event.type == ENET_EVENT_TYPE_RECEIVE) + { + enet_uint8* buff = event.packet->data; + + u8 packiden = 0; + memcpy((char*)&packiden, buff, 1); + + if(packiden == 4) + { + memcpy((char*)&playerID, buff+1, 2); + + if(playerID == 0) + { + std::cout << "irrNetLite: Error: Null player ID recieved. Server likely full."; + enet_peer_reset(event.peer); + return false; + } + + if(verbose) + std::cout << "irrNetLite: Player ID is " << playerID << ".\n"; + + u8 packid = 3; + ENetPacket* packet = enet_packet_create(&packid, 1, ENET_PACKET_FLAG_RELIABLE); + enet_host_broadcast(host, 1, packet); + + return true; + } + } + } + + std::cout << "irrNetLite: Error: Failed to recieve Player ID. Connection failed.\n"; + return false; + } + + bool CNetManager::setUpServer(const u32 port) + { + mode = ENM_SERVER; + netParams.maxClients++; + + address.host = ENET_HOST_ANY; + address.port = port; + + if(verbose) + std::cout << "irrNetLite: Creating server!\n"; + + host = enet_host_create(&address, netParams.maxClients,2, 0,0); + + if(host == NULL) + { + std::cout << "irrNetLite: Error: An error occurred while trying to create an ENet server host.\n"; + return false; + } + + players.resize(netParams.maxClients, 0); + + + + return true; + } + + void CNetManager::setGlobalPacketRelay(bool relay) + { + globPacketRelay = relay; + } + + void CNetManager::update(const u32 timeOut) + { + if(connectionStatus == EICS_FAILED) + return; + + + if(mode == ENM_CLIENT) + { + ENetEvent event; + + for(u32 i = 0; i < netIterations;i++) + { + if(!(enet_host_service(host, &event, i ? 1 : timeOut) > 0)) + break; + + switch (event.type) + { + case ENET_EVENT_TYPE_RECEIVE: + { + enet_uint8* buff = event.packet->data; + + if(event.channelID == 1) + { + u8 packiden = 0; + memcpy((char*)&packiden,buff,1); + + if(packiden == 3) + { + connectionStatus = EICS_ESTABLISHED; + if(pHandler) pHandler->onConnect(0); + } + } + else + { + if(verbose) + std::cout << "irrNetLite: A packet of length " + << event.packet->dataLength + << " was received.\n"; + + SInPacket inpacket((c8*)buff, (u32)event.packet->dataLength); + + if(pHandler) + pHandler->handlePacket(inpacket); + } + + buff = 0; + enet_packet_destroy(event.packet); + break; + } + case ENET_EVENT_TYPE_DISCONNECT: + std::cout << "irrNetLite: Connection to server lost.\n"; + + event.peer->data = 0; + connectionStatus = EICS_FAILED; + + if(pHandler) + pHandler->onDisconnect(0); + default: + break; + } + } + + } + else // (mode == ENM_SERVER) + { + ENetEvent event; + + for(u32 i = 0;i < netIterations;i++) + { + if(!(enet_host_service (host, &event, i ? 1 : timeOut) > 0)) + break; + + switch (event.type) + { + case ENET_EVENT_TYPE_CONNECT: + { + if(verbose) + std::cout << "irrNetLite: A new client connected from " + << event.peer->address.host << ":" + << event.peer->address.port << std::endl; + + u16 pID = 1; + + while(pID < netParams.maxClients && players[pID] != 0) + pID++; + + if(pID >= netParams.maxClients) + { + if(verbose) + std::cout << "irrNetLite: Warning: Client rejected. Too many clients." + << std::endl; + + pID = 0; + } + else + { + event.peer->data = players[pID] = new SPeerData(pID, event.peer); + } + + c8 buffer[3]; + u8 packid = 4; + memcpy(buffer, (char*)&packid, 1); + memcpy(buffer+1, (char*)&pID, 2); + ENetPacket* packet; + packet = enet_packet_create(buffer, 3, ENET_PACKET_FLAG_RELIABLE); + enet_peer_send(event.peer, 1, packet); + enet_host_flush(host); + + if(pID == 0) enet_peer_reset(event.peer); + + break; + } + case ENET_EVENT_TYPE_RECEIVE: + { + enet_uint8* buff = event.packet->data; + + if(event.channelID == 1) + { + u8 packiden = 0; + memcpy((char*)&packiden, buff, 1); + + if(packiden == 3) + { + ENetPacket* packet = enet_packet_create(&packiden, 1, ENET_PACKET_FLAG_RELIABLE); + enet_peer_send(event.peer, 1, packet); + SPeerData* currentPeer = reinterpret_cast(event.peer->data); + if(currentPeer && pHandler) pHandler->onConnect(currentPeer->playerID); + } + } + else + { + SPeerData* currentPeer = reinterpret_cast(event.peer->data); + + if(currentPeer) + { + SInPacket inPacket((c8*)buff, (u32)event.packet->dataLength); + inPacket.setPlayerId(currentPeer->playerID); + + if(verbose) + std::cout << "irrNetLite: A packet of length " + << event.packet->dataLength + << " from player number " + << currentPeer->playerID + << " was received.\n"; + + if(pHandler) + pHandler->handlePacket(inPacket); + + if(globPacketRelay) + { + SOutPacket relayPacket((c8*)buff, (u32)event.packet->dataLength); + + const u32 playersSize = (u32)players.size(); + for(u32 i = 0;i < playersSize;++i) + if(players[i] && players[i] != currentPeer) + sendOutPacket(relayPacket, i); + } + } + } + + buff = 0; + enet_packet_destroy(event.packet); + break; + } + case ENET_EVENT_TYPE_DISCONNECT: + { + SPeerData* pData = reinterpret_cast(event.peer->data); + + if(pData) + { + if(verbose) + std::cout << "irrNetLite: Player number " + << pData->playerID + << " disconnected.\n"; + + if(pHandler) pHandler->onDisconnect(pData->playerID); + + players[pData->playerID] = 0; + delete pData; + event.peer->data = 0; + } + } + default: + break; + } + } + } + } + + void CNetManager::setVerbose(bool isverbose) + { + verbose = isverbose; + } + + ENetPeer* CNetManager::getPlayerById(u16 id) + { + if(id < players.size() && players[id] && players[id]->playerID == id) + return players[id]->enetPeer; + + return 0; + } + + ENetPeer* CNetManager::getPeer() + { + if(connectionStatus == EICS_ESTABLISHED) + return &host->peers[0]; + else + return 0; + } + + const u32 CNetManager::getPing() + { + if(getPeer()) + return getPeer()->roundTripTime; + else + return 0; + } + + const u32 CNetManager::getPeerCount() + { + return (u32)host->peerCount; + } + + const u16 CNetManager::getPlayerNumber() + { + return playerID; + } + + ENetHost* CNetManager::getHost() + { + return host; + } + + E_IRRNET_CONNECTION_STATUS CNetManager::getConnectionStatus() + { + return connectionStatus; + } + + void CNetManager::kickClient(const u16 playerId, bool hardKick = false) + { + ENetPeer* currentPeer = getPlayerById(playerId); + + if(currentPeer) + hardKick ? enet_peer_disconnect_now(currentPeer,0) : + enet_peer_disconnect(currentPeer,0); + } + + const u32 CNetManager::getClientAddress(const u16 playerId) + { + ENetPeer* currentPeer = getPlayerById(playerId); + + if(currentPeer) + return currentPeer->address.host; + + return 0; + } + + void CNetManager::sendOutPacket(SOutPacket& outpacket) + { + ENetPacket* packet = enet_packet_create((char*)outpacket.getData(), outpacket.getSize(), + ENET_PACKET_FLAG_RELIABLE); + + enet_host_broadcast(host, 0, packet); + } + + void CNetManager::sendOutPacket(SOutPacket& outpacket, const u16 playerId) + { + ENetPacket* packet = enet_packet_create ((char*)outpacket.getData(), outpacket.getSize(), + ENET_PACKET_FLAG_RELIABLE); + ENetPeer* currentPeer = getPlayerById(playerId); + + if(currentPeer && currentPeer->state == ENET_PEER_STATE_CONNECTED) + enet_peer_send(currentPeer, 0, packet); + } + + void CNetManager::sendOutPacketUnreliable(SOutPacket& outpacket) + { + ENetPacket* packet = enet_packet_create((char*)outpacket.getData(), outpacket.getSize(), 0); + enet_host_broadcast(host, 0, packet); + } + + void CNetManager::sendOutPacketUnreliable(SOutPacket& outpacket, const u16 playerId) + { + ENetPacket* packet = enet_packet_create((char*)outpacket.getData(), outpacket.getSize(), 0); + ENetPeer* currentPeer = getPlayerById(playerId); + + if(currentPeer && currentPeer->state == ENET_PEER_STATE_CONNECTED) + enet_peer_send(currentPeer, 0, packet); + } + + extern INetManager* createIrrNetClient(INetCallback* callback, const c8* addressc, const u32 port, const SNetParams& params) + { + return new irr::net::CNetManager(callback, addressc, port, params); + } + extern INetManager* createIrrNetServer(INetCallback* callback, const u32 port, const SNetParams& params) + { + return new irr::net::CNetManager(callback, port, params); + } + + } // Close Net Namespace +} // Close Irr namespace + +// Copyright(C) Ahmed Hilali 2007 + +/* License: + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any damages +arising from the use of this software. + +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it +freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not +claim that you wrote the original software. If you use this software +in a product, an acknowledgement in the product documentation would be +appreciated but is not required. +2. Altered source versions must be clearly marked as such, and must not be +misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. + +*/ diff --git a/source/CNetManager.d b/source/CNetManager.d new file mode 100644 index 0000000..84dd56d --- /dev/null +++ b/source/CNetManager.d @@ -0,0 +1,10 @@ +CNetManager.o: CNetManager.cpp ../include/CNetManager.h \ + ../include/INetManager.h ../include/SPacket.h \ + ../include/NoIrrlicht/NoIrrlicht.h ../include/NoIrrlicht/irrTypes.h \ + ../include/NoIrrlicht/irrArray.h ../include/NoIrrlicht/heapsort.h \ + ../include/NoIrrlicht/irrAllocator.h ../include/NoIrrlicht/irrString.h \ + ../include/NoIrrlicht/irrMath.h ../include/NoIrrlicht/IrrCompileConfig.h \ + ../include/NoIrrlicht/vector3d.h ../enet/include/enet/enet.h \ + ../enet/include/enet/unix.h ../enet/include/enet/types.h \ + ../enet/include/enet/protocol.h ../enet/include/enet/list.h \ + ../enet/include/enet/callbacks.h diff --git a/source/CNetManager.o b/source/CNetManager.o new file mode 100644 index 0000000..b9ede93 Binary files /dev/null and b/source/CNetManager.o differ diff --git a/source/Makefile b/source/Makefile new file mode 100644 index 0000000..0b96ac5 --- /dev/null +++ b/source/Makefile @@ -0,0 +1,56 @@ +VERSION = 2.0 + +ZLIBDIR=../zlib +ENETDIR=../enet +IRRNETDIR=1 + +ZLIBOBJ = $(ZLIBDIR)/adler32.o $(ZLIBDIR)/compress.o $(ZLIBDIR)/crc32.o $(ZLIBDIR)/deflate.o $(ZLIBDIR)/infback.o $(ZLIBDIR)/inffast.o $(ZLIBDIR)/inflate.o $(ZLIBDIR)/inftrees.o $(ZLIBDIR)/trees.o $(ZLIBDIR)/uncompr.o $(ZLIBDIR)/zutil.o +#ENETOBJ = $(ENETDIR)/host.o $(ENETDIR)/list.o $(ENETDIR)/memory.o $(ENETDIR)/packet.o $(ENETDIR)/peer.o $(ENETDIR)/protocol.o $(ENETDIR)/unix.o $(ENETDIR)/win32.o +ENETOBJ = $(ENETDIR)/host.o $(ENETDIR)/list.o $(ENETDIR)/callbacks.o $(ENETDIR)/packet.o $(ENETDIR)/peer.o $(ENETDIR)/protocol.o $(ENETDIR)/unix.o $(ENETDIR)/win32.o +IRRNETOBJ = CNetManager.o SPacket.o +LINKOBJ := $(IRRNETOBJ) $(ENETOBJ) $(ZLIBOBJ) + +############### +#Compiler flags +#CXXINCS = -I../../include -I../$(ENETDIR)/include/ -Izlib +CXXINCS = -I../include -I./$(ENETDIR)/include/ -I./NoIrrlicht/ -Izlib +CPPFLAGS = $(CXXINCS) +CXXFLAGS = -Wall -fexpensive-optimizations -O3 + +ifdef PROFILE +CXXFLAGS += -pg +endif +CFLAGS := -fexpensive-optimizations -O3 + +#Linux specific options +STATIC_LIB = libirrnet.a +LIB_PATH = ../lib/$(STATIC_LIB) +INSTALL_DIR = /usr/local/lib +staticlib install: SYSTEM = Linux +staticlib: LDFLAGS = --no-export-all-symbols --add-stdcall-alias +#################### +all linux: staticlib + +$(STATIC_LIB): $(LINKOBJ) + $(AR) rs $@ $^ + +# Copies static lib into /lib/Linux +staticlib: $(STATIC_LIB) + mv $^ $(LIB_PATH) + +# Create dependency files for automatic recompilation +%.d:%.cpp + $(CXX) $(CPPFLAGS) -MM -MF $@ $< + +-include $(LINKOBJ:.o=.d) + +clean: + $(RM) $(LINKOBJ) $(SHARED_LIB).$(VERSION) $(STATIC_LIB) $(LINKOBJ:.o=.d) + +#withirrlicht: +#CXXINCS += -Iirrlicht/include -DCOMPILE_WITH_IRRLICHT + +#all staticlib clean +# +#.PHONY: all staticlib clean +# diff --git a/source/ReadMe.txt b/source/ReadMe.txt new file mode 100644 index 0000000..252a38d --- /dev/null +++ b/source/ReadMe.txt @@ -0,0 +1,51 @@ +IrrNetLite V2.0 - Lite Enet Framework +------------------------------------- + +irrNetLite is an lite enet wrapper with a clean C++ interface. +Please look at Tutorial.cpp for a quick introduction to coding with irrNetLite. + +switch(YourQuestions) +{ +Why irrNetLite?: + Enet is a portable, robust and reliable UDP implementation, but unfortunately + it comes with an ugly C-style interface that can be rather difficult to integrate + with a large scale application (Or to look at in general.). irrNetLite makes the + experience a whole lot better by imploying OO-style interfaces for packet handling + and connection callbacks and a sprinkle here and there of synctatic sugar (Operator + overloading, etc). irrNetLite also implements some useful features not present in + vanilla Enet (Namely compression and encryption), in the same easy to use manner. + +Is there a connection to Irrlicht?: +What are all these header files?: +Do you have something against the std lib?: irrNetLite V1.0 was originally based off irrNet. irrNet was a network library + for integration of Enet and Irrlicht to create a persistant multi-user + enviroment. irrNet was dependant on Irrlicht. irrNetLite however, has + no dependancy whatsoever on Irrlicht being included or linked in. I do however + like some of the Irrlicht typedefs and helper structures, so those are included + amongst the header files, but by no means do you have to use them in your + application. I do recommend using the typedefs, as it is important to maintain + more precise typing (unsigned/signed) when sending data over a network due + to deferring architecture defaults. +} + +LICENSE +----------- + + Copyright (C) 2008 Ahmed Hilali + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgement in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be clearly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + diff --git a/source/SPacket.cpp b/source/SPacket.cpp new file mode 100644 index 0000000..55bd1c0 --- /dev/null +++ b/source/SPacket.cpp @@ -0,0 +1,477 @@ +#include "SPacket.h" +#include "zlib.h" +#include "CEncryption.h" + +uchar CEncryption::expKey[4 * Nb * (Nr + 1)] = {}; + +namespace irr +{ +namespace net +{ + +SOutPacket::SOutPacket() {} + +SOutPacket::SOutPacket(const c8* buff,const u32 buff_size) +{ + this->buff.set_used(buff_size); + memcpy(this->buff.pointer(),buff,buff_size); +} + +void SOutPacket::clearData() +{ + buff.clear(); +} + +c8* SOutPacket::getData() +{ + return (c8*)buff.pointer(); +} + +const c8* SOutPacket::getConstData() +{ + return (const c8*)buff.const_pointer(); +} + +u32 SOutPacket::getSize() +{ + return buff.size(); +} + +void SOutPacket::enlargeBuffer(const u32 size) +{ + const u32 newSize = buff.size() + size; + if(buff.allocated_size() < newSize) + buff.reallocate(newSize * 2); + + buff.set_used(newSize); +} + +SOutPacket& SOutPacket::operator << (const c8 data) +{ + buff.push_back(data); + return *this; +} + +SOutPacket& SOutPacket::operator << (const u16 data) +{ + enlargeBuffer(2); + memcpy(buff.pointer() + buff.size() - 2, &data, 2); + return *this; +} + +SOutPacket& SOutPacket::operator << (const u32 data) +{ + enlargeBuffer(4); + memcpy(buff.pointer() + buff.size() - 4, &data, 4); + return *this; +} + +SOutPacket& SOutPacket::operator << (const u8 data) +{ + buff.push_back(data); + return *this; +} + +SOutPacket& SOutPacket::operator << (const s16 data) +{ + enlargeBuffer(2); + memcpy(buff.pointer() + buff.size() - 2, &data, 2); + return *this; +} + +SOutPacket& SOutPacket::operator << (const s32 data) +{ + enlargeBuffer(4); + memcpy(buff.pointer() + buff.size() - 4, &data, 4); + return *this; +} + +SOutPacket& SOutPacket::operator << (const f32 data) +{ + enlargeBuffer(4); + memcpy(buff.pointer() + buff.size() - 4, &data, 4); + return *this; +} + +SOutPacket& SOutPacket::operator << (const f64 data) +{ + enlargeBuffer(8); + memcpy(buff.pointer() + buff.size() - 8, &data, 8); + return *this; +} + +SOutPacket& SOutPacket::operator << (const core::vector3df& data) +{ + enlargeBuffer(12); + memcpy(buff.pointer() + buff.size() - 12, &data.X, 12); + return *this; +} + +SOutPacket& SOutPacket::operator << (const c8* string) +{ + u16 tmp = (u16)strlen(string); + + enlargeBuffer(2); + memcpy(buff.pointer() + buff.size() - 2, &tmp, 2); + + enlargeBuffer(tmp); + memcpy(buff.pointer() + buff.size() - tmp, string, tmp); + return *this; +} + +SOutPacket& SOutPacket::operator << (const core::stringc& string) +{ + u16 tmp = string.size(); + + enlargeBuffer(2); + memcpy(buff.pointer() + buff.size() - 2, &tmp, 2); + + enlargeBuffer(tmp); + memcpy(buff.pointer() + buff.size() - tmp, &string[0], tmp); + return *this; +} + +SOutPacket& SOutPacket::operator << (const std::string& string) +{ + u16 tmp = (u16)string.size(); + + enlargeBuffer(2); + memcpy(buff.pointer() + buff.size() - 2, &tmp, 2); + + enlargeBuffer(tmp); + memcpy(buff.pointer() + buff.size() - tmp, &string[0], tmp); + return *this; +} + +SOutPacket& SOutPacket::operator << (const core::stringw& string) +{ + const u16 tmp = string.size(); + + enlargeBuffer(2); + memcpy(buff.pointer() + buff.size() - 2, &tmp, 2); + + enlargeBuffer(1); + const u8 wCharSize = sizeof(wchar_t); + memcpy(buff.pointer() + buff.size() - 1, &wCharSize, 1); + + const u32 wcharByteSize = (tmp * sizeof(wchar_t)); + enlargeBuffer(wcharByteSize); + memcpy(buff.pointer() + buff.size() - wcharByteSize, &string[0], wcharByteSize); + return *this; +} + +SOutPacket& SOutPacket::operator << (const SOutPacket& other) +{ + enlargeBuffer(other.buff.size()); + memcpy(buff.pointer() + buff.size() - other.buff.size(), other.buff.const_pointer(), other.buff.size()); + + return *this; +} + +void SOutPacket::compressPacket() +{ + const u32 compBound = compressBound(buff.size()) + 4; + core::array newBuff(compBound); + + const u32 currSize = buff.size(); + memcpy(newBuff.pointer(), &currSize, 4); + + uLongf destLen = compBound; + compress((Bytef*)newBuff.pointer() + 4, &destLen, (Bytef*)buff.pointer(), buff.size()); + newBuff.set_used(destLen + 4); + + buff = newBuff; +} + +void SOutPacket::deCompressPacket() +{ + u32 newSize = 0; + memcpy((void*)&newSize, buff.pointer(), 4); + + core::array newBuff; + newBuff.set_used(newSize); + + uLongf destLen = newSize; + uncompress((Bytef*)newBuff.pointer(), &destLen, (Bytef*)buff.pointer() + 4, buff.size() - 4); + newBuff.set_used(destLen); + + buff = newBuff; +} + +void SOutPacket::encryptPacket(const c8 key[16]) +{ + CEncryption::SetEncryptionKey((u8*)&key[0]); + core::array tmpbuff; + const u32 newSize = buff.size() + (16 - (buff.size() % 16)); + tmpbuff.set_used(newSize); + buff.set_used(newSize); + + for(u32 i = 0;i < newSize;i+=16) + CEncryption::Encrypt((u8*)buff.pointer() + i, (u8*)tmpbuff.pointer() + i); + + buff = tmpbuff; +} + +void SOutPacket::decryptPacket(const c8 key[16]) +{ + CEncryption::SetEncryptionKey((u8*)&key[0]); + const u32 newSize = buff.size(); + core::array tmpbuff; + tmpbuff.set_used(newSize); + + for(u32 i = 0;i < newSize;i+=16) + CEncryption::Decrypt((u8*)buff.pointer() + i, (u8*)tmpbuff.pointer() + i); + + buff = tmpbuff; +} + +SInPacket::SInPacket(const c8* buff, const u32 size) : pos(0), playerid(0) +{ + SInPacket::buff.set_used(size); + memcpy(SInPacket::buff.pointer(), buff, size); +} + + +void SInPacket::setNewData(const c8* buffer, const u32 size) +{ + buff.set_used(size); + memcpy(buff.pointer(), buffer, size); + pos = 0; +} + +void SInPacket::setPlayerId(u16 playernumber) +{ + playerid = playernumber; +} + +void SInPacket::operator >> (c8 &data) +{ + memcpy(&data,getData()+pos,1); + pos++; +} + +void SInPacket::operator >> (f32 &data) +{ + memcpy(&data,getData()+pos,4); + pos+=4; +} + +void SInPacket::operator >> (f64 &data) +{ + memcpy(&data,getData()+pos,8); + pos+=8; +} + +void SInPacket::operator >> (u16 &data) +{ + memcpy(&data,getData()+pos,2); + pos+=2; +} + +void SInPacket::operator >> (u32 &data) +{ + memcpy(&data,getData()+pos,4); + pos+=4; +} + +void SInPacket::operator >> (u8 &data) +{ + memcpy(&data,getData()+pos,1); + pos++; +} + +void SInPacket::operator >> (s16 &data) +{ + memcpy(&data,getData()+pos,2); + pos+=2; +} + +void SInPacket::operator >> (s32 &data) +{ + memcpy(&data,getData()+pos,4); + pos+=4; +} + +void SInPacket::operator >> (core::vector3df &data) +{ + memcpy(&data.X,getData()+pos,12); + pos+=12; +} + +void SInPacket::operator >> (char *string) +{ + u16 sz; + memcpy(&sz,getData()+pos,2); + pos+=2; + + memcpy(string,getData()+pos,sz); + pos += sz; + + string[sz] = '\0'; +} + +void SInPacket::operator >> (core::stringc& string) +{ + u16 sz; + memcpy(&sz, getData() + pos, 2); + pos+=2; + + char* tempBuff = new char[sz + 1]; + memcpy(tempBuff, getData() + pos, sz); + tempBuff[sz] = '\0'; + string = tempBuff; + + delete [] tempBuff; + + pos += sz; +} + +void SInPacket::operator >> (std::string& string) +{ + u16 sz; + memcpy(&sz, getData() + pos, 2); + pos+=2; + + char* tempBuff = new char[sz + 1]; + memcpy(tempBuff, getData() + pos, sz); + tempBuff[sz] = '\0'; + string = tempBuff; + + delete [] tempBuff; + + pos += sz; +} + +void SInPacket::operator >> (core::stringw& string) +{ + u16 sz; + memcpy(&sz,getData()+pos,2); + pos+=2; + + u8 wCharSize; + memcpy(&wCharSize,getData()+pos,1); + pos+=1; + + wchar_t* tempBuff = new wchar_t[sz + 1]; + const u32 wcharByteSize = (sz * sizeof(wchar_t)); + + if(wCharSize != sizeof(wchar_t)) + { + if(wCharSize > sizeof(wchar_t)) + { + for(u32 i = 0;i < sz;i++) + { + tempBuff[i] = 0; + memcpy(&tempBuff[i],getData()+pos,sizeof(wchar_t)); + + pos += wCharSize; + } + } + else + { + for(u32 i = 0;i < sz;i++) + { + tempBuff[i] = 0; + memcpy(&tempBuff[i],getData()+pos,wCharSize); + + pos += wCharSize; + } + } + } + else + { + memcpy(tempBuff, getData() + pos, wcharByteSize); + } + + tempBuff[sz] = '\0'; + string = tempBuff; + + delete [] tempBuff; + + pos += wcharByteSize; +} + +u16 SInPacket::getPlayerId() const +{ + return playerid; +} + +void SInPacket::resetPos() +{ + pos = 0; +} + +c8* SInPacket::getData() +{ + return (c8*)buff.pointer(); +} + +const c8* SInPacket::getConstData() +{ + return (const c8*)buff.const_pointer(); +} + +void SInPacket::compressPacket() +{ + const u32 compBound = compressBound(buff.size()) + 4; + core::array newBuff(compBound); + + const u32 currSize = buff.size(); + memcpy(newBuff.pointer(), &currSize, 4); + + uLongf destLen = compBound; + compress((Bytef*)newBuff.pointer() + 4, &destLen, (Bytef*)buff.pointer(), buff.size()); + newBuff.set_used(destLen + 4); + + buff = newBuff; +} + +void SInPacket::deCompressPacket() +{ + u32 newSize = 0; + memcpy((void*)&newSize, buff.pointer(), 4); + + core::array newBuff; + newBuff.set_used(newSize); + + uLongf destLen = newSize; + uncompress((Bytef*)newBuff.pointer(), &destLen, (Bytef*)buff.pointer() + 4, buff.size() - 4); + newBuff.set_used(destLen); + + buff = newBuff; +} + +void SInPacket::encryptPacket(const c8 key[16]) +{ + CEncryption::SetEncryptionKey((u8*)&key[0]); + core::array tmpbuff; + const u32 newSize = buff.size() + (16 - (buff.size() % 16)); + tmpbuff.set_used(newSize); + buff.set_used(newSize); + + for(u32 i = 0;i < newSize;i+=16) + CEncryption::Encrypt((u8*)buff.pointer() + i, (u8*)tmpbuff.pointer() + i); + + buff = tmpbuff; +} + +void SInPacket::decryptPacket(const c8 key[16]) +{ + CEncryption::SetEncryptionKey((u8*)&key[0]); + const u32 newSize = buff.size(); + core::array tmpbuff; + tmpbuff.set_used(newSize); + + for(u32 i = 0;i < newSize;i+=16) + CEncryption::Decrypt((u8*)buff.pointer() + i, (u8*)tmpbuff.pointer() + i); + + buff = tmpbuff; +} + +u32 SInPacket::getSize() +{ + return buff.size(); +} + +} // Close Net Namespace +} // Close Irr namespace diff --git a/source/SPacket.d b/source/SPacket.d new file mode 100644 index 0000000..42c4c95 --- /dev/null +++ b/source/SPacket.d @@ -0,0 +1,6 @@ +SPacket.o: SPacket.cpp ../include/SPacket.h \ + ../include/NoIrrlicht/NoIrrlicht.h ../include/NoIrrlicht/irrTypes.h \ + ../include/NoIrrlicht/irrArray.h ../include/NoIrrlicht/heapsort.h \ + ../include/NoIrrlicht/irrAllocator.h ../include/NoIrrlicht/irrString.h \ + ../include/NoIrrlicht/irrMath.h ../include/NoIrrlicht/IrrCompileConfig.h \ + ../include/NoIrrlicht/vector3d.h ../include/CEncryption.h diff --git a/source/SPacket.o b/source/SPacket.o new file mode 100644 index 0000000..794917f Binary files /dev/null and b/source/SPacket.o differ diff --git a/zlib b/zlib new file mode 160000 index 0000000..cacf7f1 --- /dev/null +++ b/zlib @@ -0,0 +1 @@ +Subproject commit cacf7f1d4e3d44d871b605da3b647f07d718623f