Browse Source

base block registry, cleanup, improved network (hton, ntoh, only
unsigned), data access from Stream moved into DataVector(rule of 5
compliant)

Kajetan Johannes Hammerle 4 years ago
parent
commit
899de1ca31

+ 2 - 24
common/block/Block.cpp

@@ -1,32 +1,10 @@
-#include <iostream>
-
 #include "common/block/Block.h"
 
-using namespace std;
-
-BlockId Block::idCounter = 0;
-
-Block::Block()
-{
-    id = idCounter++;
-    cout << "Block " << id << endl;
-}
-
-Block::~Block()
+Block::Block(BlockId id) : id(id)
 {
 }
 
 BlockId Block::getId() const
 {
     return id;
-}
-
-bool Block::isEmpty() const
-{
-    return false;
-}
-
-bool Block::isBlockingFace(Face& f) const
-{
-    return !isEmpty();
-}
+}

+ 5 - 10
common/block/Block.h

@@ -1,23 +1,18 @@
 #ifndef BLOCK_H
 #define BLOCK_H
 
-#include "common/utils/Face.h"
+#include <cstdint>
 
-typedef unsigned short BlockId;
+typedef uint16_t BlockId;
 
 class Block
 {
 public:
-    Block();
-    virtual ~Block();
-    
+    Block(BlockId id);
     BlockId getId() const;
-    
-    virtual bool isEmpty() const;
-    virtual bool isBlockingFace(Face& f) const;
+
 private:
-    static BlockId idCounter;
-    BlockId id;
+    const BlockId id;
 };
 
 #endif

+ 0 - 15
common/block/BlockAir.cpp

@@ -1,15 +0,0 @@
-#include "common/block/BlockAir.h"
-
-BlockAir::BlockAir()
-{
-}
-
-BlockAir::~BlockAir()
-{
-}
-
-bool BlockAir::isEmpty() const
-{
-    return true;
-}
-

+ 0 - 18
common/block/BlockAir.h

@@ -1,18 +0,0 @@
-#ifndef BLOCKAIR_H
-#define BLOCKAIR_H
-
-#include "common/block/Block.h"
-
-class BlockAir : public Block
-{
-public:
-    BlockAir();
-    virtual ~BlockAir();
-    
-    bool isEmpty() const override;
-private:
-
-};
-
-#endif
-

+ 24 - 0
common/block/BlockRegistry.cpp

@@ -0,0 +1,24 @@
+#include "BlockRegistry.h"
+
+Block BlockRegistry::NULL_BLOCK(0);
+
+BlockRegistry::BlockRegistry() : idCounter(1)
+{
+    
+}
+
+const Block& BlockRegistry::getBlock(const std::string& name) const
+{
+    const std::unordered_map<std::string, Block>::const_iterator& iter = registry.find(name);
+    if(iter == registry.end())
+    {
+        return NULL_BLOCK;
+    }    
+    return iter->second;
+}
+
+const Block& BlockRegistry::getBlock(BlockId id) const
+{
+    return NULL_BLOCK;
+}
+

+ 24 - 0
common/block/BlockRegistry.h

@@ -0,0 +1,24 @@
+#ifndef BLOCKREGISTRY_H
+#define BLOCKREGISTRY_H
+
+#include <unordered_map>
+
+#include "common/block/Block.h"
+
+class BlockRegistry
+{
+public:
+    static Block NULL_BLOCK;
+    
+    BlockRegistry();
+    
+    const Block& getBlock(const std::string&) const;
+    const Block& getBlock(BlockId id) const;
+    
+private:
+    std::unordered_map<std::string, Block> registry;
+    BlockId idCounter;
+};
+
+#endif
+

+ 0 - 46
common/block/Blocks.cpp

@@ -1,46 +0,0 @@
-#include "common/block/Blocks.h"
-
-const int BlockRegistry::BLOCK_AMOUNT = 4;
-const Block* BlockRegistry::BLOCKS[BLOCK_AMOUNT];
-
-const BlockAir Blocks::AIR;
-const Block Blocks::GRASS;
-const Block Blocks::DIRT;
-const Block Blocks::STONE;
-
-BlockRegistry::BlockRegistry()
-{
-}
-
-void BlockRegistry::registerBlock(const Block& block)
-{
-    BlockId id = block.getId();
-    if(id >= 0 && id < BLOCK_AMOUNT && BLOCKS[id] == nullptr)
-    {
-        BLOCKS[id] = &block;
-    }
-}
-
-const Block& BlockRegistry::getBlockFromId(BlockId id)
-{
-    return *BLOCKS[(id >= 0 && id < BLOCK_AMOUNT && BLOCKS[id] != nullptr) * id];
-}
-
-void BlockRegistry::init()
-{
-    for(int i = 0; i < BLOCK_AMOUNT; i++)
-    {
-        BLOCKS[i] = nullptr;
-    }
-}
-
-void BlockRegistry::registerBlocks()
-{
-    init();
-    
-    registerBlock(Blocks::AIR);
-    registerBlock(Blocks::GRASS);
-    registerBlock(Blocks::DIRT);
-    registerBlock(Blocks::STONE);
-}
-

+ 0 - 31
common/block/Blocks.h

@@ -1,31 +0,0 @@
-#ifndef BLOCKS_H
-#define BLOCKS_H
-
-#include "common/block/Block.h"
-#include "common/block/BlockAir.h"
-
-class BlockRegistry
-{
-public:
-    static const Block& getBlockFromId(BlockId id);
-    static void registerBlocks();
-    
-private:
-    BlockRegistry();
-    static void init();
-    static void registerBlock(const Block& block);
-    
-    static const int BLOCK_AMOUNT;
-    static const Block* BLOCKS[];
-};
-
-namespace Blocks
-{
-    extern const BlockAir AIR;
-    extern const Block GRASS;
-    extern const Block DIRT;
-    extern const Block STONE;
-}
-
-#endif
-

+ 39 - 176
common/stream/Stream.cpp

@@ -1,62 +1,41 @@
-#include <iostream>
-#include <stdexcept>
-#include <iostream>
 #include <cstring>
-
-#include <sys/socket.h>
+#include <netinet/in.h>
 
 #include "common/stream/Stream.h"
 
-Stream::Stream(size_t minSize) : dataLength(getSize(minSize)), 
-        data(new unsigned char[dataLength]), writeIndex(0), readIndex(0)
+Stream::Stream() : error(false), writeIndex(0), readIndex(0)
 {
 }
 
-Stream::~Stream()
+Stream::Stream(size_t capacity) : data(capacity), error(false), writeIndex(0), readIndex(0)
 {
-    delete[] data;
 }
 
-size_t Stream::getSize(size_t minSize) const
+bool Stream::hasData() const
 {
-    size_t size = 1;
-    while(size < minSize && size <= MAX_SIZE)
-    {
-        size <<= 1;
-    }
-    return size;
+    return readIndex < writeIndex;
 }
 
-bool Stream::hasData() const
+bool Stream::hasError() const
 {
-    return readIndex < writeIndex;
+    return error;
 }
 
-bool Stream::resize(size_t minSize)
+void Stream::clearError()
 {
-    if(minSize > MAX_SIZE)
-    {
-        return true;
-    }
-    size_t newSize = getSize(minSize);
-    //cout << "resize from " << dataLength << " to " << newSize << endl;
-    unsigned char* newData = new unsigned char[newSize];
-    memcpy(newData, data, writeIndex);
-    delete[] data;
-    data = newData;
-    dataLength = newSize;
-    return false;
+    error = false;
 }
 
 void Stream::write(const void* writeData, size_t length)
 {
-    if(writeIndex + length > dataLength && resize(writeIndex + length))
+    if(data.write(writeIndex, writeData, length))
+    {
+        writeIndex += length;
+    }
+    else
     {
-        std::cout << "write over max stream size" << std::endl;
-        return;
+        error = true;
     }
-    memcpy(data + writeIndex, writeData, length);
-    writeIndex += length;
 }
 
 void Stream::write(const char* writeData)
@@ -64,181 +43,65 @@ void Stream::write(const char* writeData)
     write(writeData, strlen(writeData));
 }
 
-void Stream::writeChar(char c)
-{
-    write(&c, sizeof(char));
-}
-
-void Stream::writeShort(int16_t s)
-{
-    write(&s, sizeof(short));
-}
-
-void Stream::writeInt(int32_t i)
-{
-    write(&i, sizeof(int));
-}
-
-void Stream::writeLong(int64_t l)
-{
-    write(&l, sizeof(long));
-}
-
 void Stream::writeUnsignedChar(uint8_t uc)
 {
-    write(&uc, sizeof(unsigned char));
+    write(&uc, sizeof(uint8_t));
 }
 
 void Stream::writeUnsignedShort(uint16_t us)
 {
-    write(&us, sizeof(unsigned short));
+    us = htons(us);
+    write(&us, sizeof(uint16_t));
 }
 
 void Stream::writeUnsignedInt(uint32_t ui)
 {
-    write(&ui, sizeof(unsigned int));
+    ui = htonl(ui);
+    write(&ui, sizeof(uint32_t));
 }
 
-void Stream::writeUnsignedLong(uint64_t ul)
+void Stream::read(void* buffer, size_t length)
 {
-    write(&ul, sizeof(unsigned long));
-}
-
-bool Stream::read(void* buffer, size_t length)
-{
-    if(readIndex + length > writeIndex)
+    if(readIndex + length <= writeIndex && data.read(readIndex, buffer, length))
     {
-        std::cout << "read over stream data length" << std::endl;
-        return true;
+        readIndex += length;
     }
-    memcpy(buffer, data + readIndex, length);
-    readIndex += length;
-    return false;
-}
-
-char Stream::readChar(char error)
-{
-    char c;
-    if(read(&c, sizeof(char)))
+    else
     {
-        return error;
+        error = true;
     }
-    return c;
 }
 
-int16_t Stream::readShort(int16_t error)
-{
-    short s;
-    if(read(&s, sizeof(short)))
-    {
-        return error;
-    }
-    return s;
-}
-
-int32_t Stream::readInt(int32_t error)
-{
-    int i;
-    if(read(&i, sizeof(int)))
-    {
-        return error;
-    }
-    return i;
-}
-
-int64_t Stream::readLong(int64_t error)
-{
-    long l;
-    if(read(&l, sizeof(long)))
-    {
-        return error;
-    }
-    return l;
-}
-
-unsigned char Stream::readUnsignedChar(unsigned char error)
+uint8_t Stream::readUnsignedChar()
 {
     unsigned char uc;
-    if(read(&uc, sizeof(unsigned char)))
-    {
-        return error;
-    }
+    read(&uc, sizeof(unsigned char));
     return uc;
 }
 
-uint16_t Stream::readUnsignedShort(uint16_t error)
+uint16_t Stream::readUnsignedShort()
 {
-    unsigned short us;
-    if(read(&us, sizeof(unsigned short)))
-    {
-        return error;
-    }
+    uint16_t us;
+    read(&us, sizeof(uint16_t));
+    us = ntohs(us);
     return us;
 }
 
-uint32_t Stream::readUnsignedInt(uint32_t error)
+uint32_t Stream::readUnsignedInt()
 {
-    unsigned int ui;
-    if(read(&ui, sizeof(unsigned int)))
-    {
-        return error;
-    }
+    uint32_t ui;
+    read(&ui, sizeof(uint32_t));
+    ui = ntohl(ui);
     return ui;
 }
 
-uint64_t Stream::readUnsignedLong(uint64_t error)
-{
-    unsigned long ul;
-    if(read(&ul, sizeof(unsigned long)))
-    {
-        return error;
-    }
-    return ul;
-}
-
-void Stream::readSocket(int socket)
+bool Stream::readSocket(int socket)
 {
-    writeIndex = 0;
     readIndex = 0;
-    
-    size_t bufferOffset = 0;
-    ssize_t freeSpace = dataLength - writeIndex;
-    
-    while(true)
-    {
-        ssize_t readLength = recv(socket, data + bufferOffset, freeSpace, MSG_DONTWAIT);        
-        if(readLength <= 0)
-        {
-            break;
-        }
-        writeIndex += readLength;
-        if(readLength < freeSpace)
-        {    
-            break;
-        }
-        else
-        {
-            resize(dataLength + 1);
-            freeSpace = dataLength - writeIndex;
-            bufferOffset += readLength;
-        }
-    }
+    return data.readSocket(socket, writeIndex);
 }
 
-void Stream::sendToSocket(int socket)
+void Stream::sendToSocket(int socket) const
 {
-    size_t bufferOffset = 0;
-    size_t sendLength = writeIndex;
-    
-    while(sendLength > 0)
-    {
-        ssize_t writtenLength = send(socket, data + bufferOffset, sendLength, MSG_NOSIGNAL);
-        if(writtenLength == -1)
-        {
-            perror("Cannot send data");
-            return;
-        }
-        sendLength -= writtenLength;
-        bufferOffset += writtenLength;
-    }
+    data.sendToSocket(socket, writeIndex);
 }

+ 16 - 32
common/stream/Stream.h

@@ -2,55 +2,39 @@
 #define STREAM_H
 
 #include <cstddef>
+#include <cstdint>
 
-#include <stdint.h>
+#include "common/utils/DataVector.h"
 
 class Stream
 {
 public:
-    Stream(size_t minSize = 1);
-    virtual ~Stream();
-    Stream(const Stream& other) = delete;
-    Stream& operator=(const Stream& other) = delete;
+    Stream();
+    Stream(size_t capacity);
 
-    void readSocket(int socket);
-    void sendToSocket(int socket);
+    bool readSocket(int socket);
+    void sendToSocket(int socket) const;
     
     bool hasData() const;
+    bool hasError() const;
+    void clearError();
     
     void write(const void* writeData, size_t length);
     void write(const char* writeData);
-    void writeChar(char c);
-    void writeShort(int16_t s);
-    void writeInt(int32_t i);
-    void writeLong(int64_t l);
     void writeUnsignedChar(uint8_t uc);
     void writeUnsignedShort(uint16_t us);
     void writeUnsignedInt(uint32_t ui);
-    void writeUnsignedLong(uint64_t ul);
     
-    bool read(void* buffer, size_t length);
-    char readChar(char error);
-    int16_t readShort(int16_t error);
-    int32_t readInt(int32_t error);
-    int64_t readLong(int64_t error);
-    unsigned char readUnsignedChar(unsigned char error);
-    uint16_t readUnsignedShort(uint16_t error);
-    uint32_t readUnsignedInt(uint32_t error);
-    uint64_t readUnsignedLong(uint64_t error);
+    void read(void* buffer, size_t length);
+    uint8_t readUnsignedChar();
+    uint16_t readUnsignedShort();
+    uint32_t readUnsignedInt();
     
 private:
-    bool resize(size_t minSize);
-    size_t getSize(size_t minSize) const;
-    
-    // limit to 50 mbyte
-    static constexpr size_t MAX_SIZE = 1024 * 1024 * 50;
-    
-    size_t dataLength; 
-    unsigned char* data;
-    
-    size_t writeIndex = 0;
-    size_t readIndex = 0;
+    DataVector data;
+    bool error;
+    size_t writeIndex;
+    size_t readIndex;
 };
 
 #endif

+ 150 - 0
common/utils/DataVector.cpp

@@ -0,0 +1,150 @@
+#include <cstring>
+#include <iostream>
+#include <thread>
+
+#include <errno.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <poll.h>
+
+#include "DataVector.h"
+
+DataVector::DataVector(size_t capacity) : capacity(capacity), data(new char[capacity])
+{
+    memset(data, 0, capacity);
+}
+
+DataVector::DataVector(const DataVector& orig) : capacity(orig.capacity), data(new char[capacity])
+{
+    memcpy(data, orig.data, capacity);
+}
+
+DataVector::DataVector(DataVector&& other) : capacity(other.capacity), data(other.data)
+{
+    other.capacity = 0;
+    other.data = nullptr;
+}
+
+DataVector::~DataVector()
+{
+    delete[] data;
+}
+
+DataVector& DataVector::operator=(const DataVector& other)
+{
+    if(this != &other)
+    {
+        delete[] data;
+        capacity = other.capacity;
+        data = new char[capacity];
+        memcpy(data, other.data, capacity);
+    }
+    return *this;
+}
+
+DataVector& DataVector::operator=(DataVector&& other)
+{
+    if(this != &other)
+    {
+        capacity = other.capacity;
+        data = other.data;
+        other.capacity = 0;
+        other.data = nullptr;
+    }
+    return *this;
+}
+
+bool DataVector::read(size_t fromIndex, void* buffer, size_t length) const
+{
+    if(fromIndex + length >= capacity)
+    {
+        return false;
+    }
+    memcpy(buffer, data + fromIndex, length);
+    return true;
+}
+
+bool DataVector::write(size_t toIndex, const void* writeData, size_t length)
+{
+    if(toIndex + length >= capacity)
+    {
+        return false;
+    }
+    memcpy(data + toIndex, writeData, length);
+    return true;
+}
+
+bool DataVector::readSocket(int socket, size_t& readBytes)
+{
+    readBytes = 0;
+    
+    uint32_t packetSize = 0;
+    ssize_t readLength = recv(socket, &packetSize, 4, 0);
+    if(readLength != 4)
+    {
+        return false;
+    }
+    packetSize = ntohl(packetSize);
+    if(packetSize > capacity)
+    {
+        return false;
+    }
+            
+    size_t bytesLeft = packetSize;
+    
+    while(true)
+    {
+        ssize_t readLength = recv(socket, data + readBytes, bytesLeft, MSG_DONTWAIT);
+        if(readLength < 0) // an error occurred
+        {
+            if(errno == EAGAIN || errno == EWOULDBLOCK)
+            {
+                struct pollfd fds;
+                fds.fd = socket;
+                fds.events = POLLIN;
+                fds.revents = 0;
+                if(poll(&fds, 1, 3000) <= 0)
+                {
+                    // client took to long to send the full packet
+                    readBytes = 0;
+                    return false;
+                }
+                continue;
+            }
+            // a real error occurred
+            perror("cannot receive data");
+            return true;
+        }
+        else if(readLength == 0) // socket closed / shutdown
+        {
+            return true;
+        }
+        else
+        {
+            readBytes += readLength;
+            bytesLeft -= readLength;
+            if(bytesLeft == 0) // packet fully read
+            {
+                return true;
+            }
+        }
+    }
+}
+
+void DataVector::sendToSocket(int socket, size_t toIndex) const
+{
+    size_t bufferOffset = 0;
+    size_t sendLength = toIndex;
+    
+    while(sendLength > 0)
+    {
+        ssize_t writtenLength = send(socket, data + bufferOffset, sendLength, MSG_NOSIGNAL);
+        if(writtenLength == -1)
+        {
+            perror("cannot send data");
+            return;
+        }
+        sendLength -= writtenLength;
+        bufferOffset += writtenLength;
+    }
+}

+ 29 - 0
common/utils/DataVector.h

@@ -0,0 +1,29 @@
+#ifndef DATAVECTOR_H
+#define DATAVECTOR_H
+
+#include <cstddef>
+
+class DataVector final
+{
+public:
+    DataVector(size_t capacity = 5 * 1024 * 1024);
+    DataVector(const DataVector& orig);
+    DataVector(DataVector&& other);
+    ~DataVector();
+    
+    DataVector& operator=(const DataVector& other);
+    DataVector& operator=(DataVector&& other);
+    
+    bool read(size_t fromIndex, void* buffer, size_t length) const;
+    bool write(size_t toIndex, const void* data, size_t length);
+    
+    bool readSocket(int socket, size_t& readBytes);
+    void sendToSocket(int socket, size_t toIndex) const;
+    
+private:
+    size_t capacity;
+    char* data;
+};
+
+#endif
+

+ 2 - 2
meson.build

@@ -2,11 +2,11 @@ project('cubes plus plus', 'cpp')
 
 #sourcesCommon = ['common/stream/Stream.cpp', 'common/utils/Face.cpp', 'common/block/Block.cpp', 'common/block/Blocks.cpp', 'common/block/BlockAir.cpp', 'common/world/Chunk.cpp', 'common/world/World.cpp']
 
-sourcesCommon = ['common/stream/Stream.cpp']
+sourcesCommon = ['common/stream/Stream.cpp', 'common/block/BlockRegistry.cpp','common/block/Block.cpp', 'common/utils/DataVector.cpp']
 
 sourcesServer = ['server/Main.cpp', 'server/GameServer.cpp', 'server/network/Server.cpp', 'server/commands/CommandManager.cpp', 'server/commands/CommandUtils.cpp', 'server/commands/GeneralCommands.cpp']
 
-sourcesClient = ['client/Main.cpp', 'client/engine/Clock.cpp', 'client/engine/DirectRenderer.cpp', 'client/engine/KeyManager.cpp', 'client/engine/Mesh.cpp', 'client/engine/MouseManager.cpp', 'client/engine/Shader.cpp', 'client/engine/Texture.cpp', 'client/engine/Utils.cpp', 'client/engine/Wrapper.cpp', 'client/engine/shader/ShaderProgram.cpp', 'client/engine/shader/WorldShader.cpp', 'client/engine/shader/FramebufferRectangle.cpp', 'client/engine/shader/SSAOShader.cpp', 'client/engine/shader/SSAOBlurShader.cpp', 'client/engine/shader/WorldPostShader.cpp', 'client/engine/shader/OverlayShader.cpp', 'client/GameClient.cpp', 'client/rendering/ChunkRenderer.cpp', 'client/rendering/ClientChunkProvider.cpp', 'client/rendering/block/BlockRenderer.cpp', 'client/rendering/block/BlockRenderers.cpp', 'client/rendering/entity/EntityRenderer.cpp', 'client/rendering/gui/GUI.cpp', 'client/rendering/gui/StartMenu.cpp', 'client/math/Matrix3D.cpp', 'client/math/Matrix3DStack.cpp', 'client/math/StackOverflow.cpp', 'client/math/StackUnderflow.cpp', 'client/math/Vector3D.cpp', 'client/math/Plane3D.cpp', 'client/math/Camera3D.cpp', 'client/network/Client.cpp', 'client/network/ClientListener.cpp']
+#sourcesClient = ['client/Main.cpp', 'client/engine/Clock.cpp', 'client/engine/DirectRenderer.cpp', 'client/engine/KeyManager.cpp', 'client/engine/Mesh.cpp', 'client/engine/MouseManager.cpp', 'client/engine/Shader.cpp', 'client/engine/Texture.cpp', 'client/engine/Utils.cpp', 'client/engine/Wrapper.cpp', 'client/engine/shader/ShaderProgram.cpp', 'client/engine/shader/WorldShader.cpp', 'client/engine/shader/FramebufferRectangle.cpp', 'client/engine/shader/SSAOShader.cpp', 'client/engine/shader/SSAOBlurShader.cpp', 'client/engine/shader/WorldPostShader.cpp', 'client/engine/shader/OverlayShader.cpp', 'client/GameClient.cpp', 'client/rendering/ChunkRenderer.cpp', 'client/rendering/ClientChunkProvider.cpp', 'client/rendering/block/BlockRenderer.cpp', 'client/rendering/block/BlockRenderers.cpp', 'client/rendering/entity/EntityRenderer.cpp', 'client/rendering/gui/GUI.cpp', 'client/rendering/gui/StartMenu.cpp', 'client/math/Matrix3D.cpp', 'client/math/Matrix3DStack.cpp', 'client/math/StackOverflow.cpp', 'client/math/StackUnderflow.cpp', 'client/math/Vector3D.cpp', 'client/math/Plane3D.cpp', 'client/math/Camera3D.cpp', 'client/network/Client.cpp', 'client/network/ClientListener.cpp']
 
 sourcesTest = ['tests/Main.cpp', 'server/commands/CommandUtils.cpp']
 

+ 3 - 1
server/GameServer.cpp

@@ -52,7 +52,9 @@ void GameServer::onClientPackage(int socket, Stream& in) const
     std::string s = "";
     while(in.hasData())
     {
-        s = in.readChar('_') + s;
+        char c;
+        in.read(&c, 1);
+        s = c + s;
     }
 
     Stream answer;

+ 3 - 2
server/commands/CommandManager.cpp

@@ -26,10 +26,11 @@ void CommandManager::execute(IGameServer& gs, ICommandSource& cs, const std::str
         return;
     }
 
-    if(commands.find(command) == commands.end())
+    const std::unordered_map<std::string, Command>::const_iterator& iter = commands.find(command);
+    if(iter == commands.end())
     {
         std::cout << "Unknown command: '" << command << "'" << std::endl;
         return;
     }
-    commands.begin()->second(gs, cs, args);
+    iter->second(gs, cs, args);
 }

+ 4 - 2
server/commands/CommandManager.h

@@ -9,14 +9,16 @@
 class CommandManager
 {
 public:
+    typedef void (*Command) (IGameServer&, ICommandSource&, const std::vector<std::string>&);
+    
     CommandManager();
     
     void execute(IGameServer& gs, ICommandSource& cs, const std::string& rawCommand) const;
 
 private:
-    std::unordered_map<std::string, void (*) (IGameServer& gs, ICommandSource&, const std::vector<std::string>&)> commands;
+    std::unordered_map<std::string, Command> commands;
     
-    void registerCommand(const std::string& name, void (*command) (IGameServer& gs, ICommandSource&, const std::vector<std::string>&));
+    void registerCommand(const std::string& name, Command command);
 };
 
 #endif

+ 15 - 16
server/network/Server.cpp

@@ -92,6 +92,10 @@ Server::~Server()
         {
             if(clients[i].socket != -1)
             {
+                if(shutdown(clients[i].socket, SHUT_RDWR))
+                {
+                    printError("cannot shutdown client socket");
+                }
                 if(close(clients[i].socket) == -1)
                 {
                     printError("cannot close client socket");
@@ -144,7 +148,7 @@ void Server::listenForClients()
             if(clientSocket >= 0)
             {
                 //std::cout << inet_ntoa(clientSocketData.sin_addr) << ":" << (int) ntohs(clientSocketData.sin_port) << std::endl;
-                if(addClientThreadsafe(clientSocket))
+                if(addClient(clientSocket))
                 {
                     if(close(clientSocket) == -1)
                     {
@@ -166,16 +170,9 @@ void Server::listenForClients()
     }
 }
 
-bool Server::addClientThreadsafe(int clientSocket)
-{
-    clientMutex.lock();
-    bool b = addClient(clientSocket);
-    clientMutex.unlock();
-    return b;
-}
-
 bool Server::addClient(int clientSocket)
 {
+    std::lock_guard<std::mutex> lg(clientMutex);
     if(clientAmount >= maxClients)
     {
         serverListener.onFullServerClientConnect(clientSocket);
@@ -257,12 +254,14 @@ void Server::listenOnClient(ConnectedClient& cc)
     serverListener.onClientDisconnect(cc.socket);
     
     // reset slot for another client
-    clientMutex.lock();
-    if(close(cc.socket) == -1)
+    if(shouldRun)
     {
-        perror("cannot close socket of client");
+        std::lock_guard<std::mutex> lg(clientMutex);
+        if(close(cc.socket) == -1)
+        {
+            printError("cannot close socket of client");
+        }
+        cc.socket = -1;
+        clientAmount--;
     }
-    cc.socket = -1;
-    clientAmount--;
-    clientMutex.unlock();
-}
+}

+ 0 - 1
server/network/Server.h

@@ -25,7 +25,6 @@ public:
 private:
     void printError(const char* message) const;
     void listenForClients();
-    bool addClientThreadsafe(int clientSocket);
     bool addClient(int clientSocket);
     void listenOnClient(ConnectedClient& cc);