Initial commit.

This commit is contained in:
rna88 2018-03-10 20:07:10 -08:00
commit 18b7ce6bc9
38 changed files with 5735 additions and 0 deletions

6
.gitmodules vendored Normal file
View File

@ -0,0 +1,6 @@
[submodule "zlib"]
path = zlib
url = https://github.com/madler/zlib
[submodule "enet"]
path = enet
url = https://github.com/rna88/enet

27
README.md Normal file
View File

@ -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.

1
enet Submodule

@ -0,0 +1 @@
Subproject commit 7900e72b709798ac285431bf1860014c6e1caf91

View File

@ -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

252
examples/Example1/main.cpp Normal file
View File

@ -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 <irrNet.h>
#include <iostream>
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;
}

View File

@ -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

230
examples/Example2/main.cpp Normal file
View File

@ -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 <irrNet.h>
#include <iostream>
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<u32> 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;
}

View File

@ -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

177
examples/Tutorial/main.cpp Normal file
View File

@ -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 <irrNet.h>
#include <iostream>
// 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;
}

BIN
examples/bin/Example1 Executable file

Binary file not shown.

BIN
examples/bin/Example2 Executable file

Binary file not shown.

BIN
examples/bin/Tutorial Executable file

Binary file not shown.

15
examples/linux_compile_all.sh Executable file
View File

@ -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

411
include/CEncryption.h Normal file
View File

@ -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 <string.h>
#include <memory.h>
// 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)];
};

120
include/CNetManager.h Normal file
View File

@ -0,0 +1,120 @@
#ifndef IRRNET_CNM_H
#define IRRNET_CNM_H
#include <wchar.h>
#include <iostream>
#include <string>
#include <vector>
#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<SPeerData*> 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.
*/

242
include/INetManager.h Normal file
View File

@ -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.
*/

View File

@ -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 <stdio.h> // 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__

View File

@ -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

View File

@ -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<class T>
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<class T>
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

View File

@ -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 <new>
#include <memory.h>
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<typename T>
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<typename T>
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

View File

@ -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 T, typename TAlloc = irrAllocator<T> >
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<T>& 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<used; ++i)
allocator.destruct(&data[i]);
allocator.deallocate(data);
}
}
//! Reallocates the array, make it bigger or smaller.
//! \param new_size: New size of array.
void reallocate(u32 new_size)
{
T* old_data = data;
data = allocator.allocate(new_size); //new T[new_size];
allocated = new_size;
// copy old data
s32 end = used < new_size ? used : new_size;
for (s32 i=0; i<end; ++i)
{
// data[i] = old_data[i];
allocator.construct(&data[i], old_data[i]);
}
// destruct old data
for (u32 j=0; j<used; ++j)
allocator.destruct(&old_data[j]);
if (allocated < used)
used = allocated;
allocator.deallocate(old_data); //delete [] old_data;
}
//! Adds an element at back of array. If the array is too small to
//! add this new element it is made bigger.
//! \param element: Element to add at the back of the array.
void push_back(const T& element)
{
if (used + 1 > 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<used)
allocator.destruct(&data[i]);
allocator.construct(&data[i], data[i-1]); // data[i] = data[i-1];
}
if (used > 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<used; ++i)
allocator.destruct(&data[i]);
allocator.deallocate(data); // delete [] data;
data = 0;
used = 0;
allocated = 0;
is_sorted = true;
}
//! Sets pointer to new array, using this as new workspace.
//! \param newPointer: Pointer to new array of elements.
//! \param size: Size of the new array.
void set_pointer(T* newPointer, u32 size)
{
for (u32 i=0; i<used; ++i)
allocator.destruct(&data[i]);
allocator.deallocate(data); // delete [] data;
data = newPointer;
allocated = size;
used = size;
is_sorted = false;
}
//! Sets if the array should delete the memory it used.
//! \param f: If true, the array frees the allocated memory in its
//! destructor, otherwise not. The default is true.
void set_free_when_destroyed(bool f)
{
free_when_destroyed = f;
}
//! Sets the size of the array and adds some new elements if necessary.
/** Please note: This is only secure when using it with simple types, because
no default constructor will be called for the added new elements.
\param usedNow: Amount of elements now used. */
void set_used(u32 usedNow)
{
if (allocated < usedNow)
reallocate(usedNow);
used = usedNow;
}
//! Assignment operator
void operator=(const array<T>& other)
{
if (data)
{
for (u32 i=0; i<used; ++i)
allocator.destruct(&data[i]);
allocator.deallocate(data); // delete [] data;
}
//if (allocated < other.allocated)
if (other.allocated == 0)
data = 0;
else
data = allocator.allocate(other.allocated); // new T[other.allocated];
used = other.used;
free_when_destroyed = other.free_when_destroyed;
is_sorted = other.is_sorted;
allocated = other.allocated;
for (u32 i=0; i<other.used; ++i)
allocator.construct(&data[i], other.data[i]); // data[i] = other.data[i];
}
// equality operator
bool operator == (const array<T>& other) const
{
if (used != other.used)
return false;
for (u32 i=0; i<other.used; ++i)
if (data[i] != other[i])
return false;
return true;
}
// inequality operator
bool operator != (const array<T>& 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<used; ++i)
if (element == data[i])
return (s32)i;
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_reverse_search(const T& element) const
{
for (s32 i=used-1; 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; ++i)
{
allocator.destruct(&data[i-1]);
allocator.construct(&data[i-1], data[i]); // data[i-1] = data[i];
}
allocator.destruct(&data[used-1]);
--used;
}
//! Erases some elements from the array. may be slow, because all elements
//! following after the erased element have to be copied.
//! \param index: Index of the first element to be erased.
//! \param count: Amount of elements to be erased.
void erase(u32 index, s32 count)
{
_IRR_DEBUG_BREAK_IF(index>=used || count<1 || index+count>used) // access violation
u32 i;
for (i=index; i<index+count; ++i)
allocator.destruct(&data[i]);
for (i=index+count; i<used; ++i)
{
if (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

View File

@ -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 <math.h>
#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<class T>
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<class T>
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<class T>
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<class T>
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<class T>
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<class T>
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 <class T>
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

View File

@ -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 <stdio.h>
#include <string.h>
#include <stdlib.h>
namespace irr
{
namespace core
{
//! Very simple string class with some useful features.
/** string<c8> and string<wchar_t> work both with unicode AND ascii,
so you can assign unicode to string<c8> and ascii to string<wchar_t>
(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 <typename T, typename TAlloc = irrAllocator<T> >
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<T>& 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 <class B>
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<length; ++l)
array[l] = (T)c[l];
array[length] = 0;
}
//! Constructor for unicode and ascii strings
template <class B>
string(const B* const c)
: array(0), allocated(0), used(0)
{
*this = c;
}
//! destructor
~string()
{
allocator.deallocate(array); // delete [] array;
}
//! Assignment operator
string<T>& operator=(const string<T>& 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<used; ++i, ++p)
array[i] = *p;
return *this;
}
//! Assignment operator for strings, ascii and unicode
template <class B>
string<T>& 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<len; ++l)
array[l] = (T)c[l];
allocator.deallocate(oldArray); // delete [] oldArray;
return *this;
}
//! Add operator for other strings
string<T> operator+(const string<T>& other) const
{
string<T> str(*this);
str.append(other);
return str;
}
//! Add operator for strings, ascii and unicode
template <class B>
string<T> operator+(const B* const c) const
{
string<T> 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<T>& 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<T>& 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<T>& 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<used; ++i)
array[i] = ansi_lower ( array[i] );
}
//! Makes the string upper case.
void make_upper()
{
const T a = (T)'a';
const T z = (T)'z';
const T diff = (T)'A' - a;
for (u32 i=0; i<used; ++i)
{
if (array[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<T>& 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<T>& 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<T>& 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<len; ++l)
array[l+used] = *(other+l);
used += len;
}
//! Appends a string to this string
/** \param other: String to append. */
void append(const string<T>& other)
{
--used;
u32 len = other.size()+1;
if (used + len > allocated)
reallocate(used + len);
for (u32 l=0; l<len; ++l)
array[used+l] = other[l];
used += len;
}
//! Appends a string of the length l to this string.
/** \param other: other String to append to this string.
\param length: How much characters of the other string to add to this one. */
void append(const string<T>& other, u32 length)
{
if (other.size() < length)
{
append(other);
return;
}
if (used + length > allocated)
reallocate(used + length);
--used;
for (u32 l=0; l<length; ++l)
array[l+used] = other[l];
used += length;
// ensure proper termination
array[used]=0;
++used;
}
//! Reserves some memory.
/** \param count: Amount of characters to reserve. */
void reserve(u32 count)
{
if (count < allocated)
return;
reallocate(count);
}
//! finds first occurrence of character in string
/** \param c: Character to search for.
\return Returns position where the character has been found,
or -1 if not found. */
s32 findFirst(T c) const
{
for (u32 i=0; i<used; ++i)
if (array[i] == c)
return i;
return -1;
}
//! finds first occurrence of a character of a list in string
/** \param c: List of characters to find. For example if the method
should find the first 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 findFirstChar(const T* const c, u32 count) const
{
if (!c)
return -1;
for (u32 i=0; i<used; ++i)
for (u32 j=0; j<count; ++j)
if (array[i] == c[j])
return i;
return -1;
}
//! Finds first position of a character not in a given list.
/** \param c: List of characters not to find. For example if the method
should find the first occurrence of a character not '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 the character has been found,
or -1 if not found. */
template <class B>
s32 findFirstCharNotInList(const B* const c, u32 count) const
{
for (u32 i=0; i<used-1; ++i)
{
u32 j;
for (j=0; j<count; ++j)
if (array[i] == c[j])
break;
if (j==count)
return i;
}
return -1;
}
//! Finds last position of a character not in a given list.
/** \param c: List of characters not to find. For example if the method
should find the first occurrence of a character not '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 the character has been found,
or -1 if not found. */
template <class B>
s32 findLastCharNotInList(const B* const c, u32 count) const
{
for (s32 i=(s32)(used-2); i>=0; --i)
{
u32 j;
for (j=0; j<count; ++j)
if (array[i] == c[j])
break;
if (j==count)
return i;
}
return -1;
}
//! finds next occurrence of character in string
/** \param c: Character to search for.
\param startPos: Position in string to start searching.
\return Returns position where the character has been found,
or -1 if not found. */
s32 findNext(T c, u32 startPos) const
{
for (u32 i=startPos; i<used; ++i)
if (array[i] == c)
return i;
return -1;
}
//! finds last occurrence of character in string
//! \param c: Character to search for.
//! \param start: start to search reverse ( default = -1, on end )
//! \return Returns position where the character has been found,
//! or -1 if not found.
s32 findLast(T c, s32 start = -1) const
{
start = core::clamp ( start < 0 ? (s32)(used) - 1 : start, 0, (s32)(used) - 1 );
for (s32 i=start; i>=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<count; ++j)
if (array[i] == c[j])
return i;
return -1;
}
//! finds another string in this string
//! \param str: Another string
//! \return Returns positions where the string has been found,
//! or -1 if not found.
template <class B>
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<used-len; ++i)
{
u32 j=0;
while(str[j] && array[i+j] == str[j])
++j;
if (!str[j])
return i;
}
}
return -1;
}
//! Returns a substring
//! \param begin: Start of substring.
//! \param length: Length of substring.
string<T> subString(u32 begin, s32 length) const
{
if ((length+begin) > size())
length = size()-begin;
if (length <= 0)
return string<T>("");
string<T> o;
o.reserve(length+1);
for (s32 i=0; i<length; ++i)
o.array[i] = array[i+begin];
o.array[length] = 0;
o.used = o.allocated;
return o;
}
string<T>& operator += (T c)
{
append(c);
return *this;
}
string<T>& operator += (const T* const c)
{
append(c);
return *this;
}
string<T>& operator += (const string<T>& other)
{
append(other);
return *this;
}
string<T>& operator += (const int i)
{
append(string<T>(i));
return *this;
}
string<T>& operator += (const unsigned int i)
{
append(string<T>(i));
return *this;
}
string<T>& operator += (const long i)
{
append(string<T>(i));
return *this;
}
string<T>& operator += (const unsigned long& i)
{
append(string<T>(i));
return *this;
}
string<T>& operator += (const double i)
{
append(string<T>(i));
return *this;
}
string<T>& operator += (const float i)
{
append(string<T>(i));
return *this;
}
//! replaces all characters of a special type with another one
void replace(T toReplace, T replaceWith)
{
for (u32 i=0; i<used; ++i)
if (array[i] == toReplace)
array[i] = replaceWith;
}
//! trims the string.
/** Removes whitespace from begin and end of the string. */
string<T>& 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<used; ++i)
array[i-1] = array[i];
--used;
}
private:
/*
T toLower(const T& t) const
{
if (t>=(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<amount; ++i)
array[i] = old_array[i];
if (allocated < used)
used = allocated;
allocator.deallocate(old_array); // delete [] old_array;
}
//--- member variables
T* array;
u32 allocated;
u32 used;
TAlloc allocator;
};
//! Typedef for character strings
typedef string<c8> stringc;
//! Typedef for wide character strings
typedef string<wchar_t> stringw;
} // end namespace core
} // end namespace irr
#endif

View File

@ -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 <wchar.h>
#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 <stdlib.h>
#include <crtdbg.h>
#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__

View File

@ -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 T>
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<T>& other) : X(other.X), Y(other.Y), Z(other.Z) {}
// operators
vector3d<T> operator-() const { return vector3d<T>(-X, -Y, -Z); }
vector3d<T>& operator=(const vector3d<T>& other) { X = other.X; Y = other.Y; Z = other.Z; return *this; }
vector3d<T> operator+(const vector3d<T>& other) const { return vector3d<T>(X + other.X, Y + other.Y, Z + other.Z); }
vector3d<T>& operator+=(const vector3d<T>& other) { X+=other.X; Y+=other.Y; Z+=other.Z; return *this; }
vector3d<T> operator-(const vector3d<T>& other) const { return vector3d<T>(X - other.X, Y - other.Y, Z - other.Z); }
vector3d<T>& operator-=(const vector3d<T>& other) { X-=other.X; Y-=other.Y; Z-=other.Z; return *this; }
vector3d<T> operator*(const vector3d<T>& other) const { return vector3d<T>(X * other.X, Y * other.Y, Z * other.Z); }
vector3d<T>& operator*=(const vector3d<T>& other) { X*=other.X; Y*=other.Y; Z*=other.Z; return *this; }
vector3d<T> operator*(const T v) const { return vector3d<T>(X * v, Y * v, Z * v); }
vector3d<T>& operator*=(const T v) { X*=v; Y*=v; Z*=v; return *this; }
vector3d<T> operator/(const vector3d<T>& other) const { return vector3d<T>(X / other.X, Y / other.Y, Z / other.Z); }
vector3d<T>& operator/=(const vector3d<T>& other) { X/=other.X; Y/=other.Y; Z/=other.Z; return *this; }
vector3d<T> operator/(const T v) const { T i=(T)1.0/v; return vector3d<T>(X * i, Y * i, Z * i); }
vector3d<T>& operator/=(const T v) { T i=(T)1.0/v; X*=i; Y*=i; Z*=i; return *this; }
bool operator<=(const vector3d<T>&other) const { return X<=other.X && Y<=other.Y && Z<=other.Z;};
bool operator>=(const vector3d<T>&other) const { return X>=other.X && Y>=other.Y && Z>=other.Z;};
bool operator<(const vector3d<T>&other) const { return X<other.X && Y<other.Y && Z<other.Z;};
bool operator>(const vector3d<T>&other) const { return X>other.X && Y>other.Y && Z>other.Z;};
//! use week float compare
//bool operator==(const vector3d<T>& other) const { return other.X==X && other.Y==Y && other.Z==Z; }
//bool operator!=(const vector3d<T>& other) const { return other.X!=X || other.Y!=Y || other.Z!=Z; }
bool operator==(const vector3d<T>& other) const
{
return this->equals(other);
}
bool operator!=(const vector3d<T>& 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<T>& 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<T>& set(const T nx, const T ny, const T nz) {X=nx; Y=ny; Z=nz; return *this;}
vector3d<T>& set(const vector3d<T>& 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<T>& 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<T>& other) const
{
return vector3d<T>(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<T>& other) const
{
return vector3d<T>(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<T> crossProduct(const vector3d<T>& p) const
{
return vector3d<T>(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<T>& begin, const vector3d<T>& 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<T>& 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<T>& setLength(T newlength)
{
normalize();
return (*this *= newlength);
}
//! Inverts the vector.
vector3d<T>& 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<T>& center=vector3d<T>())
{
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<T>& center=vector3d<T>())
{
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<T>& center=vector3d<T>())
{
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<T> getInterpolated(const vector3d<T>& other, const T d) const
{
const T inv = (T) 1.0 - d;
return vector3d<T>(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<T> getInterpolated_quadratic(const vector3d<T>& v2, const vector3d<T>& 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<T> ( 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<T> getHorizontalAngle() const
{
vector3d<T> 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<f32> vector3df;
//! Typedef for an integer 3d vector.
typedef vector3d<s32> vector3di;
template<class S, class T>
vector3d<T> operator*(const S scalar, const vector3d<T>& vector) { return vector*scalar; }
} // end namespace core
} // end namespace irr
#endif

166
include/SPacket.h Normal file
View File

@ -0,0 +1,166 @@
#ifndef NET_PACKET_H
#define NET_PACKET_H
#ifdef COMPILE_WITH_IRRLICHT
#include <irrlicht.h>
#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 <string>
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<c8> 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<c8> buff;
u16 playerid;
};
} // Close Net Namespace
} // Close Irr namespace
#endif

28
include/irrNet.h Normal file
View File

@ -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.
*/

BIN
lib/libirrnet.a Normal file

Binary file not shown.

57
source/CMakeLists.txt Normal file
View File

@ -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
)

463
source/CNetManager.cpp Normal file
View File

@ -0,0 +1,463 @@
#include "CNetManager.h"
#include <iostream>
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<SPeerData*>(event.peer->data);
if(currentPeer && pHandler) pHandler->onConnect(currentPeer->playerID);
}
}
else
{
SPeerData* currentPeer = reinterpret_cast<SPeerData*>(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<SPeerData*>(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.
*/

10
source/CNetManager.d Normal file
View File

@ -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

BIN
source/CNetManager.o Normal file

Binary file not shown.

56
source/Makefile Normal file
View File

@ -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
#

51
source/ReadMe.txt Normal file
View File

@ -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.

477
source/SPacket.cpp Normal file
View File

@ -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<c8> 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<c8> 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<c8> 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<c8> 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<c8> 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<c8> 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<c8> 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<c8> 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

6
source/SPacket.d Normal file
View File

@ -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

BIN
source/SPacket.o Normal file

Binary file not shown.

1
zlib Submodule

@ -0,0 +1 @@
Subproject commit cacf7f1d4e3d44d871b605da3b647f07d718623f