From d5e15d1f06fedc135f9f6b8db02746b3ba2887d2 Mon Sep 17 00:00:00 2001
From: Eduardo Bart <edub4rt@gmail.com>
Date: Thu, 1 Dec 2011 20:25:32 -0200
Subject: [PATCH] add clock, change exceptions, add network exceptions, fix
 some crashes

---
 CMakeLists.txt                                |  8 ++--
 cmake/FindOpenGLES.cmake                      | 10 ----
 modules/entergame/characterlist.lua           |  4 +-
 modules/entergame/entergame.lua               | 28 +++++------
 modules/options/options.lua                   |  8 ++--
 src/framework/core/clock.cpp                  | 42 ++++++++++++++++
 src/framework/core/clock.h                    | 48 +++++++++++++++++++
 .../core/{configs.cpp => configmanager.cpp}   | 10 ++--
 .../core/{configs.h => configmanager.h}       |  4 +-
 src/framework/core/engine.cpp                 | 24 ++++++++++
 src/framework/core/engine.h                   | 33 +++++++++++++
 src/framework/core/eventdispatcher.cpp        | 28 +++++------
 src/framework/core/eventdispatcher.h          | 11 +----
 src/framework/core/module.cpp                 | 37 +++++++-------
 src/framework/core/module.h                   | 14 +++---
 src/framework/core/modulemanager.cpp          |  6 +--
 src/framework/core/resourcemanager.cpp        |  2 +-
 src/framework/global.h                        |  2 +
 src/framework/graphics/borderimage.cpp        |  2 -
 src/framework/graphics/font.cpp               |  2 -
 src/framework/graphics/fontmanager.cpp        |  6 +--
 src/framework/graphics/image.cpp              |  2 -
 src/framework/graphics/texturemanager.cpp     |  6 +--
 src/framework/luascript/luafunctions.cpp      | 10 ++--
 src/framework/luascript/luainterface.cpp      |  2 +-
 src/framework/luascript/luavaluecasts.h       |  4 +-
 src/framework/net/inputmessage.cpp            | 17 +++++--
 src/framework/net/inputmessage.h              |  2 +
 src/framework/net/networkexception.h          | 12 +++++
 src/framework/net/outputmessage.cpp           | 22 ++++++---
 src/framework/net/outputmessage.h             |  2 +
 src/framework/net/protocol.cpp                | 13 ++---
 src/framework/net/rsa.cpp                     |  9 ++--
 src/framework/net/rsa.h                       |  2 +-
 src/framework/platform/platform.h             |  8 ----
 src/framework/platform/x11platform.cpp        | 29 ++---------
 src/framework/ui/uiframecounter.cpp           |  6 +--
 src/framework/ui/uilineedit.cpp               |  5 +-
 src/framework/ui/uimanager.cpp                | 17 ++++---
 src/framework/ui/uiwidget.cpp                 | 10 ++--
 src/framework/util/exception.h                | 19 ++++++++
 src/framework/util/tools.h                    | 26 ++++------
 src/otclient/core/creature.cpp                | 27 ++++++-----
 src/otclient/core/effect.cpp                  |  6 +--
 src/otclient/core/item.cpp                    |  6 +--
 src/otclient/core/missile.cpp                 |  6 +--
 src/otclient/core/spritemanager.cpp           |  4 +-
 src/otclient/core/thingstype.cpp              | 13 +++--
 src/otclient/core/thingtype.h                 |  7 +++
 src/otclient/luascript/luafunctions.cpp       |  2 -
 src/otclient/net/protocolgameparse.cpp        | 23 +++++----
 src/otclient/net/protocolgamesend.cpp         |  3 +-
 src/otclient/net/protocollogin.cpp            | 43 +++++++++--------
 src/otclient/otclient.cpp                     | 24 ++++------
 54 files changed, 442 insertions(+), 274 deletions(-)
 delete mode 100644 cmake/FindOpenGLES.cmake
 create mode 100644 src/framework/core/clock.cpp
 create mode 100644 src/framework/core/clock.h
 rename src/framework/core/{configs.cpp => configmanager.cpp} (92%)
 rename src/framework/core/{configs.h => configmanager.h} (96%)
 create mode 100644 src/framework/core/engine.cpp
 create mode 100644 src/framework/core/engine.h
 create mode 100644 src/framework/net/networkexception.h
 create mode 100644 src/framework/util/exception.h

diff --git a/CMakeLists.txt b/CMakeLists.txt
index fc8abf20..d990ea49 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -33,7 +33,7 @@ FIND_PACKAGE(PCHSupport REQUIRED)
 
 # choose a default build type if not specified
 IF(NOT CMAKE_BUILD_TYPE)
-    SET(CMAKE_BUILD_TYPE ReleaseWithDebInfo)
+    SET(CMAKE_BUILD_TYPE Debug)
 ENDIF(NOT CMAKE_BUILD_TYPE)
 MESSAGE(STATUS "BUILD TYPE: " ${CMAKE_BUILD_TYPE})
 
@@ -43,7 +43,7 @@ IF(CMAKE_COMPILER_IS_GNUCXX)
     SET(CMAKE_CXX_FLAGS "-std=gnu++0x -pipe ${CXX_WARNS}")
     SET(CMAKE_CXX_FLAGS_DEBUG "-O0 -g3 -ggdb3 -fno-inline")
     SET(CMAKE_CXX_FLAGS_RELEASE "-O2")
-    SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O1 -g -fno-inline")
+    SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O1 -g -ggdb -fno-inline")
     SET(CMAKE_CXX_LINK_FLAGS "-static-libgcc -static-libstdc++ -Wl,--as-needed")
 ENDIF(CMAKE_COMPILER_IS_GNUCXX)
 
@@ -112,12 +112,14 @@ SET(SOURCES
 
     # framework core
     src/framework/core/logger.cpp
-    src/framework/core/configs.cpp
+    src/framework/core/clock.cpp
+    src/framework/core/configmanager.cpp
     src/framework/core/resourcemanager.cpp
     src/framework/core/eventdispatcher.cpp
     src/framework/core/modulemanager.cpp
     src/framework/core/module.cpp
     src/framework/core/engine.cpp
+    src/framework/core/clock.cpp
 
     # framework graphics
     src/framework/graphics/font.cpp
diff --git a/cmake/FindOpenGLES.cmake b/cmake/FindOpenGLES.cmake
deleted file mode 100644
index 34afa737..00000000
--- a/cmake/FindOpenGLES.cmake
+++ /dev/null
@@ -1,10 +0,0 @@
-# Try to find the OpenGLES librairy
-#  OPENGLES_FOUND - system has OpenGLES
-#  OPENGLES_INCLUDE_DIR - the OpenGLES include directory
-#  OPENGLES_LIBRARY - the OpenGLES library
-
-FIND_PATH(OPENGLES_INCLUDE_DIR gl2.h PATH_SUFFIXES GLES2)
-FIND_LIBRARY(OPENGLES_LIBRARY NAMES GLESv2)
-INCLUDE(FindPackageHandleStandardArgs)
-FIND_PACKAGE_HANDLE_STANDARD_ARGS(OpenGLES DEFAULT_MSG OPENGLES_LIBRARY OPENGLES_INCLUDE_DIR)
-MARK_AS_ADVANCED(OPENGLES_LIBRARY OPENGLES_INCLUDE_DIR)
\ No newline at end of file
diff --git a/modules/entergame/characterlist.lua b/modules/entergame/characterlist.lua
index c9dc7388..17f00414 100644
--- a/modules/entergame/characterlist.lua
+++ b/modules/entergame/characterlist.lua
@@ -47,7 +47,7 @@ local function tryLogin(charInfo, tries)
   end
 
   -- save last used character
-  Configs.set('lastUsedCharacter', charInfo.characterName)
+  ConfigManager.set('lastUsedCharacter', charInfo.characterName)
 end
 
 -- public functions
@@ -75,7 +75,7 @@ function CharacterList.create(characters, premDays)
     label.worldHost = worldHost
     label.worldPort = worldIp
 
-    if i == 1 or Configs.get('lastUsedCharacter') == characterName then
+    if i == 1 or ConfigManager.get('lastUsedCharacter') == characterName then
       characterList:focusChild(label, ActiveFocusReason)
     end
   end
diff --git a/modules/entergame/entergame.lua b/modules/entergame/entergame.lua
index 8336940b..3d0fcbad 100644
--- a/modules/entergame/entergame.lua
+++ b/modules/entergame/entergame.lua
@@ -11,8 +11,8 @@ local function clearAccountFields()
   enterGame:getChildById('accountNameLineEdit'):clearText()
   enterGame:getChildById('accountPasswordLineEdit'):clearText()
   enterGame:getChildById('accountNameLineEdit'):focus()
-  Configs.set('account', nil)
-  Configs.set('password', nil)
+  ConfigManager.set('account', nil)
+  ConfigManager.set('password', nil)
 end
 
 local function onError(protocol, error)
@@ -30,9 +30,9 @@ end
 
 local function onCharacterList(protocol, characters, premDays)
   if enterGame:getChildById('rememberPasswordBox'):isChecked() then
-    Configs.set('account', EnterGame.account)
-    Configs.set('password', EnterGame.password)
-    Configs.set('autologin', tostring(enterGame:getChildById('autoLoginBox'):isChecked()))
+    ConfigManager.set('account', EnterGame.account)
+    ConfigManager.set('password', EnterGame.password)
+    ConfigManager.set('autologin', tostring(enterGame:getChildById('autoLoginBox'):isChecked()))
   else
     clearAccountFields()
   end
@@ -40,9 +40,9 @@ local function onCharacterList(protocol, characters, premDays)
   loadBox:destroy()
   CharacterList.create(characters, premDays)
 
-  local lastMotdNumber = tonumber(Configs.get("motd"))
+  local lastMotdNumber = tonumber(ConfigManager.get("motd"))
   if motdNumber and motdNumber ~= lastMotdNumber then
-    Configs.set("motd", motdNumber)
+    ConfigManager.set("motd", motdNumber)
     local motdBox = displayInfoBox("Message of the day", motdMessage)
     motdBox.onOk = CharacterList.show
     CharacterList.hide()
@@ -53,11 +53,11 @@ end
 function EnterGame.create()
   enterGame = UI.display('entergame.otui')
 
-  local account = Configs.get('account')
-  local password = Configs.get('password')
-  local host = Configs.get('host')
-  local port = tonumber(Configs.get('port'))
-  local autologin = toboolean(Configs.get('autologin'))
+  local account = ConfigManager.get('account')
+  local password = ConfigManager.get('password')
+  local host = ConfigManager.get('host')
+  local port = tonumber(ConfigManager.get('port'))
+  local autologin = toboolean(ConfigManager.get('autologin'))
 
   enterGame:getChildById('accountNameLineEdit'):setText(account)
   enterGame:getChildById('accountPasswordLineEdit'):setText(password)
@@ -93,8 +93,8 @@ function EnterGame.doLogin()
   EnterGame.port = enterGame:getChildById('serverPortLineEdit'):getText()
   EnterGame.hide()
 
-  Configs.set('host', EnterGame.host)
-  Configs.set('port', EnterGame.port)
+  ConfigManager.set('host', EnterGame.host)
+  ConfigManager.set('port', EnterGame.port)
 
   local protocolLogin = ProtocolLogin.create()
   protocolLogin.onError = onError
diff --git a/modules/options/options.lua b/modules/options/options.lua
index b1517666..ec2d1b48 100644
--- a/modules/options/options.lua
+++ b/modules/options/options.lua
@@ -6,8 +6,8 @@ local fpsEnabled = false
 local vsyncEnabled = false
 
 function getConfig(name, default)
-  if Configs.exists(name) then
-    local val = string.trim(Configs.get(name))
+  if ConfigManager.exists(name) then
+    local val = string.trim(ConfigManager.get(name))
     if val == 'true' or val == 'false' then
       return toboolean(val)
     else
@@ -15,7 +15,7 @@ function getConfig(name, default)
     end
   else
     if default ~= nil then
-      Configs.set(name, default)
+      ConfigManager.set(name, default)
       return default
     else
       return nil
@@ -24,7 +24,7 @@ function getConfig(name, default)
 end
 
 function setConfig(name, value)
-  Configs.set(name, tostring(value))
+  ConfigManager.set(name, tostring(value))
 end
 
 -- private functions
diff --git a/src/framework/core/clock.cpp b/src/framework/core/clock.cpp
new file mode 100644
index 00000000..e8e93e0f
--- /dev/null
+++ b/src/framework/core/clock.cpp
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2010-2011 OTClient <https://github.com/edubart/otclient>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "clock.h"
+
+Clock g_clock;
+
+Clock::Clock()
+{
+    m_startupTime = std::chrono::high_resolution_clock::now();
+}
+
+int Clock::updateTicks()
+{
+    auto timeNow = std::chrono::high_resolution_clock::now();
+    m_currentTicks = std::chrono::duration_cast<std::chrono::milliseconds>(timeNow - m_startupTime).count();
+    return m_currentTicks;
+}
+
+void Clock::sleep(int ms)
+{
+    usleep(ms * 1000);
+}
diff --git a/src/framework/core/clock.h b/src/framework/core/clock.h
new file mode 100644
index 00000000..5926f5d2
--- /dev/null
+++ b/src/framework/core/clock.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2010-2011 OTClient <https://github.com/edubart/otclient>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef CLOCK_H
+#define CLOCK_H
+
+#include "declarations.h"
+
+class Clock
+{
+public:
+    Clock();
+
+    int updateTicks();
+    void sleep(int ms);
+
+    int ticks() { return m_currentTicks; }
+    int ticksElapsed(int prevTicks) { return ticks() - prevTicks; }
+    int ticksFor(int delay) { return ticks() + delay; }
+
+private:
+    int m_currentTicks;
+    std::chrono::system_clock::time_point m_startupTime;
+};
+
+extern Clock g_clock;
+
+#endif
+
diff --git a/src/framework/core/configs.cpp b/src/framework/core/configmanager.cpp
similarity index 92%
rename from src/framework/core/configs.cpp
rename to src/framework/core/configmanager.cpp
index eba1e67b..83b3cbf8 100644
--- a/src/framework/core/configs.cpp
+++ b/src/framework/core/configmanager.cpp
@@ -20,14 +20,14 @@
  * THE SOFTWARE.
  */
 
-#include "configs.h"
+#include "configmanager.h"
 #include "resourcemanager.h"
 
 #include <framework/otml/otml.h>
 
-Configs g_configs;
+ConfigManager g_configs;
 
-bool Configs::load(const std::string& file)
+bool ConfigManager::load(const std::string& file)
 {
     m_fileName = file;
 
@@ -39,13 +39,13 @@ bool Configs::load(const std::string& file)
         for(const OTMLNodePtr& child : doc->children())
             m_confsMap[child->tag()] = child->value();
         return true;
-    } catch(std::exception& e) {
+    } catch(Exception& e) {
         logError("could not load configurations: ", e.what());
         return false;
     }
 }
 
-bool Configs::save()
+bool ConfigManager::save()
 {
     OTMLDocumentPtr doc = OTMLDocument::create();
     for(auto it : m_confsMap) {
diff --git a/src/framework/core/configs.h b/src/framework/core/configmanager.h
similarity index 96%
rename from src/framework/core/configs.h
rename to src/framework/core/configmanager.h
index 496b9ece..75635bf6 100644
--- a/src/framework/core/configs.h
+++ b/src/framework/core/configmanager.h
@@ -25,7 +25,7 @@
 
 #include "declarations.h"
 
-class Configs
+class ConfigManager
 {
 public:
     bool load(const std::string& file);
@@ -40,6 +40,6 @@ private:
     std::map<std::string, std::string> m_confsMap;
 };
 
-extern Configs g_configs;
+extern ConfigManager g_configs;
 
 #endif
diff --git a/src/framework/core/engine.cpp b/src/framework/core/engine.cpp
new file mode 100644
index 00000000..4023427f
--- /dev/null
+++ b/src/framework/core/engine.cpp
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2010-2011 OTClient <https://github.com/edubart/otclient>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "engine.h"
+
diff --git a/src/framework/core/engine.h b/src/framework/core/engine.h
new file mode 100644
index 00000000..64b28a72
--- /dev/null
+++ b/src/framework/core/engine.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2010-2011 OTClient <https://github.com/edubart/otclient>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef ENGINE_H
+#define ENGINE_H
+
+#include "declarations.h"
+
+class Engine
+{
+};
+
+#endif
+
diff --git a/src/framework/core/eventdispatcher.cpp b/src/framework/core/eventdispatcher.cpp
index c88a2f33..a2692113 100644
--- a/src/framework/core/eventdispatcher.cpp
+++ b/src/framework/core/eventdispatcher.cpp
@@ -22,44 +22,42 @@
 
 #include "eventdispatcher.h"
 
-#include <framework/platform/platform.h>
+#include <framework/core/clock.h>
 
 EventDispatcher g_dispatcher;
 
-void EventDispatcher::init()
+void EventDispatcher::flush()
 {
-    // nothing to do
-}
+    poll();
 
-void EventDispatcher::terminate()
-{
-    // clean scheduled events
+    m_eventList.clear();
     while(!m_scheduledEventList.empty())
         m_scheduledEventList.pop();
 }
 
 void EventDispatcher::poll()
 {
-    while(!m_eventList.empty()) {
-        m_eventList.front()();
-        m_eventList.pop_front();
-    }
-
     while(!m_scheduledEventList.empty()) {
-        if(g_platform.getTicks() < m_scheduledEventList.top().ticks)
+        if(g_clock.ticks() < m_scheduledEventList.top().ticks)
             break;
         SimpleCallback callback = std::move(m_scheduledEventList.top().callback);
         m_scheduledEventList.pop();
         callback();
     }
+
+    while(!m_eventList.empty()) {
+        m_eventList.front()();
+        m_eventList.pop_front();
+    }
 }
 
 void EventDispatcher::scheduleEvent(const SimpleCallback& callback, int delay)
 {
-    m_scheduledEventList.push(ScheduledEvent(g_platform.getTicks() + delay, callback));
+    assert(delay >= 0);
+    m_scheduledEventList.push(ScheduledEvent(g_clock.ticksFor(delay), callback));
 }
 
-void EventDispatcher::addEvent(const SimpleCallback& callback, bool pushFront /* = false */)
+void EventDispatcher::addEvent(const SimpleCallback& callback, bool pushFront)
 {
     if(pushFront)
         m_eventList.push_front(callback);
diff --git a/src/framework/core/eventdispatcher.h b/src/framework/core/eventdispatcher.h
index 2cee89a7..03de23ad 100644
--- a/src/framework/core/eventdispatcher.h
+++ b/src/framework/core/eventdispatcher.h
@@ -35,19 +35,10 @@ struct ScheduledEvent {
 class EventDispatcher
 {
 public:
-    /// Initialize dispatcher
-    void init();
-
-    /// Cleanup scheduled events
-    void terminate();
-
-    /// Execute scheduled events
+    void flush();
     void poll();
 
-    /// Add an event
     void addEvent(const SimpleCallback& callback, bool pushFront = false);
-
-    /// Schedule an event
     void scheduleEvent(const SimpleCallback& callback, int delay);
 
 private:
diff --git a/src/framework/core/module.cpp b/src/framework/core/module.cpp
index b6956116..3719891d 100644
--- a/src/framework/core/module.cpp
+++ b/src/framework/core/module.cpp
@@ -57,28 +57,29 @@ void Module::discover(const OTMLNodePtr& moduleNode)
 
 bool Module::load()
 {
-    try {
-        for(const std::string& depName : m_dependencies) {
-            ModulePtr dep = g_modules.getModule(depName);
-            if(!dep)
-                throw std::runtime_error(Fw::mkstr("could not find module dependency '", depName ,"'"));
-
-            if(!dep->isLoaded() && !dep->load())
-                throw std::runtime_error(Fw::mkstr("dependency '", depName, "' has failed to load"));
+    for(const std::string& depName : m_dependencies) {
+        ModulePtr dep = g_modules.getModule(depName);
+        if(!dep) {
+            logError("Unable to load module '", m_name, "' because dependency '", depName, "' was not found");
+            return false;
         }
 
-        if(m_loadCallback) {
-            m_loaded = m_loadCallback();
-            if(!m_loaded)
-                throw std::runtime_error("module onLoad event returned false");
+        if(!dep->isLoaded() && !dep->load()) {
+            logError("Unable to load module '", m_name, "' because dependency '", depName, "' has failed to laod");
+            return false;
         }
-
-        logInfo("Loaded module '", m_name, "'");
-        return true;
-    } catch(std::exception& e) {
-        logError("failed to load module '", m_name, "': ", e.what());
-        return false;
     }
+
+    if(m_loadCallback) {
+        m_loaded = m_loadCallback();
+        if(!m_loaded) {
+            logError("Unable to load module '", m_name, "' because its onLoad event returned false");
+            return false;
+        }
+    }
+
+    logInfo("Loaded module '", m_name, "'");
+    return true;
 }
 
 void Module::unload()
diff --git a/src/framework/core/module.h b/src/framework/core/module.h
index 2efb18cf..6d988ef9 100644
--- a/src/framework/core/module.h
+++ b/src/framework/core/module.h
@@ -36,14 +36,14 @@ public:
     bool load();
     void unload();
 
-    bool isLoaded() const { return m_loaded; }
+    bool isLoaded() { return m_loaded; }
 
-    std::string getDescription() const { return m_description; }
-    std::string getName() const { return m_name; }
-    std::string getAuthor() const { return m_author; }
-    std::string getWebsite() const { return m_website; }
-    std::string getVersion() const { return m_version; }
-    bool autoLoad() const { return m_autoLoad; }
+    std::string getDescription() { return m_description; }
+    std::string getName() { return m_name; }
+    std::string getAuthor() { return m_author; }
+    std::string getWebsite() { return m_website; }
+    std::string getVersion() { return m_version; }
+    bool autoLoad() { return m_autoLoad; }
 
 private:
     bool m_loaded;
diff --git a/src/framework/core/modulemanager.cpp b/src/framework/core/modulemanager.cpp
index cd09bedf..a9154347 100644
--- a/src/framework/core/modulemanager.cpp
+++ b/src/framework/core/modulemanager.cpp
@@ -56,13 +56,13 @@ bool ModuleManager::discoverModule(const std::string& file)
 
         std::string name = moduleNode->valueAt("name");
         if(getModule(name))
-            throw OTMLException(moduleNode, "a module with the same name is already discovered, did you duplicate module names?");
+            Fw::throwException("module '", name, "' already exists, cannot have duplicate module names");
 
         module = ModulePtr(new Module(name));
         module->discover(moduleNode);
         m_modules.push_back(module);
-    } catch(std::exception& e) {
-        logError("failed to load module from '", file, "': ", e.what());
+    } catch(Exception& e) {
+        logError("Unable to discover module from file '", file, "': ", e.what());
         return false;
     }
     return true;
diff --git a/src/framework/core/resourcemanager.cpp b/src/framework/core/resourcemanager.cpp
index 3dd2539e..148cfc23 100644
--- a/src/framework/core/resourcemanager.cpp
+++ b/src/framework/core/resourcemanager.cpp
@@ -107,7 +107,7 @@ void ResourceManager::loadFile(const std::string& fileName, std::iostream& out)
     PHYSFS_file* file = PHYSFS_openRead(fullPath.c_str());
     if(!file) {
         out.clear(std::ios::failbit);
-        throw std::runtime_error(Fw::mkstr("failed to load file '", fullPath.c_str(), "': ", PHYSFS_getLastError()));
+        Fw::throwException("failed to load file '", fullPath.c_str(), "': ", PHYSFS_getLastError());
     } else {
         int fileSize = PHYSFS_fileLength(file);
         if(fileSize > 0) {
diff --git a/src/framework/global.h b/src/framework/global.h
index 2d8e874a..9821b6b1 100644
--- a/src/framework/global.h
+++ b/src/framework/global.h
@@ -30,6 +30,7 @@
 #include <cassert>
 #include <ctime>
 #include <cmath>
+#include <unistd.h>
 
 // common STL headers
 #include <iostream>
@@ -53,6 +54,7 @@
 #include <iomanip>
 #include <unordered_map>
 #include <random>
+#include <chrono>
 
 // boost utilities
 #include <boost/algorithm/string.hpp>
diff --git a/src/framework/graphics/borderimage.cpp b/src/framework/graphics/borderimage.cpp
index a27a2081..2fa82dca 100644
--- a/src/framework/graphics/borderimage.cpp
+++ b/src/framework/graphics/borderimage.cpp
@@ -79,8 +79,6 @@ BorderImagePtr BorderImage::loadFromOTML(const OTMLNodePtr& borderImageNode)
     // load texture
     std::string source = borderImageNode->at("source")->value();
     TexturePtr texture = g_textures.getTexture(source);
-    if(!texture)
-        throw OTMLException(borderImageNode, "could not load border-image texture");
 
     // load basic border confs
     size = texture->getSize();
diff --git a/src/framework/graphics/font.cpp b/src/framework/graphics/font.cpp
index abe0d820..20d2fa20 100644
--- a/src/framework/graphics/font.cpp
+++ b/src/framework/graphics/font.cpp
@@ -37,8 +37,6 @@ void Font::load(const OTMLNodePtr& fontNode)
 
     // load font texture
     m_texture = g_textures.getTexture(textureName);
-    if(!m_texture)
-        throw std::runtime_error("failed to load texture for font");
 
     if(OTMLNodePtr node = fontNode->get("fixed-glyph-width")) {
         for(int glyph = m_firstGlyph; glyph < 256; ++glyph)
diff --git a/src/framework/graphics/fontmanager.cpp b/src/framework/graphics/fontmanager.cpp
index b1cb04ce..9137b2c6 100644
--- a/src/framework/graphics/fontmanager.cpp
+++ b/src/framework/graphics/fontmanager.cpp
@@ -44,7 +44,7 @@ bool FontManager::importFont(std::string fontFile)
 
         std::string name = fontNode->valueAt("name");
         if(fontExists(name))
-            throw std::runtime_error("a font with the same name is already imported, did you duplicate font names?");
+            Fw::throwException("font '", name, "' already exists, cannot have duplicate font names");
 
         FontPtr font(new Font(name));
         font->load(fontNode);
@@ -55,8 +55,8 @@ bool FontManager::importFont(std::string fontFile)
             m_defaultFont = font;
 
         return true;
-    } catch(std::exception& e) {
-        logError("could not load font from '", fontFile, "': ", e.what());
+    } catch(Exception& e) {
+        logError("Unable to load font from file '", fontFile, "': ", e.what());
         return false;
     }
 }
diff --git a/src/framework/graphics/image.cpp b/src/framework/graphics/image.cpp
index 0eb4a003..146f0016 100644
--- a/src/framework/graphics/image.cpp
+++ b/src/framework/graphics/image.cpp
@@ -43,8 +43,6 @@ void Image::loadFromOTML(const OTMLNodePtr& imageNode)
 
     // load texture
     m_texture = g_textures.getTexture(source);
-    if(!m_texture)
-        throw OTMLException(imageNode, "could not load image texture");
     m_textureCoords = imageNode->valueAt("coords", Rect(Point(0,0),m_texture->getSize()));
 
     // enable texture bilinear filter
diff --git a/src/framework/graphics/texturemanager.cpp b/src/framework/graphics/texturemanager.cpp
index 2caa3b67..d78732ed 100644
--- a/src/framework/graphics/texturemanager.cpp
+++ b/src/framework/graphics/texturemanager.cpp
@@ -46,14 +46,14 @@ TexturePtr TextureManager::getTexture(const std::string& textureFile)
         try {
             // currently only png textures are supported
             if(!boost::ends_with(textureFile, ".png"))
-                throw std::runtime_error("texture file format no supported");
+                Fw::throwException("texture file format no supported");
 
             // load texture file data
             std::stringstream fin;
             g_resources.loadFile(textureFile, fin);
             texture = loadPNG(fin);
-        } catch(std::exception& e) {
-            logError("unable to load texture '",textureFile,"': ", e.what());
+        } catch(Exception& e) {
+            Fw::throwException("unable to load texture '", textureFile, "': ", e.what());
         }
     }
 
diff --git a/src/framework/luascript/luafunctions.cpp b/src/framework/luascript/luafunctions.cpp
index 6a7d321b..44822c7f 100644
--- a/src/framework/luascript/luafunctions.cpp
+++ b/src/framework/luascript/luafunctions.cpp
@@ -25,7 +25,7 @@
 #include <framework/ui/ui.h>
 #include <framework/net/protocol.h>
 #include <framework/core/eventdispatcher.h>
-#include <framework/core/configs.h>
+#include <framework/core/configmanager.h>
 #include <framework/platform/platform.h>
 #include <framework/otml/otml.h>
 #include <framework/graphics/graphics.h>
@@ -152,10 +152,10 @@ void LuaInterface::registerFunctions()
     g_lua.registerClass<Protocol>();
 
     // ConfigManager
-    g_lua.registerClass<Configs>();
-    g_lua.bindClassStaticFunction<Configs>("set", std::bind(&Configs::set, &g_configs, _1, _2));
-    g_lua.bindClassStaticFunction<Configs>("get", std::bind(&Configs::get, &g_configs, _1));
-    g_lua.bindClassStaticFunction<Configs>("exists", std::bind(&Configs::exists, &g_configs, _1));
+    g_lua.registerClass<ConfigManager>();
+    g_lua.bindClassStaticFunction<ConfigManager>("set", std::bind(&ConfigManager::set, &g_configs, _1, _2));
+    g_lua.bindClassStaticFunction<ConfigManager>("get", std::bind(&ConfigManager::get, &g_configs, _1));
+    g_lua.bindClassStaticFunction<ConfigManager>("exists", std::bind(&ConfigManager::exists, &g_configs, _1));
 
     // Logger
     g_lua.registerClass<Logger>();
diff --git a/src/framework/luascript/luainterface.cpp b/src/framework/luascript/luainterface.cpp
index bf91a2e8..80f47135 100644
--- a/src/framework/luascript/luainterface.cpp
+++ b/src/framework/luascript/luainterface.cpp
@@ -545,7 +545,7 @@ void LuaInterface::createLuaState()
     // creates lua state
     L = luaL_newstate();
     if(!L)
-        throw std::runtime_error("failed to create lua state");
+        logFatal("Unable to create lua state");
 
     // load lua standard libraries
     luaL_openlibs(L);
diff --git a/src/framework/luascript/luavaluecasts.h b/src/framework/luascript/luavaluecasts.h
index 124f6f40..99c97325 100644
--- a/src/framework/luascript/luavaluecasts.h
+++ b/src/framework/luascript/luavaluecasts.h
@@ -168,7 +168,7 @@ bool luavalue_cast(int index, std::function<void(Args...)>& func) {
                     throw LuaException("attempt to call an expired lua function from C++,"
                                        "did you forget to hold a reference for that function?", 0);
                 }
-            } catch(std::exception& e) {
+            } catch(LuaException& e) {
                 logError("lua function callback failed: ", e.what());
             }
         };
@@ -202,7 +202,7 @@ luavalue_cast(int index, std::function<Ret(Args...)>& func) {
                     throw LuaException("attempt to call an expired lua function from C++,"
                                        "did you forget to hold a reference for that function?", 0);
                 }
-            } catch(std::exception& e) {
+            } catch(LuaException& e) {
                 logError("lua function callback failed: ", e.what());
             }
             return Ret();
diff --git a/src/framework/net/inputmessage.cpp b/src/framework/net/inputmessage.cpp
index 9b86218f..d0b37c90 100644
--- a/src/framework/net/inputmessage.cpp
+++ b/src/framework/net/inputmessage.cpp
@@ -35,7 +35,7 @@ void InputMessage::reset()
 
 uint8 InputMessage::getU8(bool peek)
 {
-    assert(canRead(1));
+    checkRead(1);
     uint8 v = m_buffer[m_readPos];
 
     if(!peek)
@@ -46,7 +46,7 @@ uint8 InputMessage::getU8(bool peek)
 
 uint16 InputMessage::getU16(bool peek)
 {
-    assert(canRead(2));
+    checkRead(2);
     uint16 v = *(uint16_t*)(m_buffer + m_readPos);
 
     if(!peek)
@@ -57,7 +57,7 @@ uint16 InputMessage::getU16(bool peek)
 
 uint32 InputMessage::getU32(bool peek)
 {
-    assert(canRead(4));
+    checkRead(4);
     uint32 v = *(uint32*)(m_buffer + m_readPos);
 
     if(!peek)
@@ -68,7 +68,7 @@ uint32 InputMessage::getU32(bool peek)
 
 uint64 InputMessage::getU64(bool peek)
 {
-    assert(canRead(8));
+    checkRead(8);
     uint64 v = *(uint64*)(m_buffer + m_readPos);
 
     if(!peek)
@@ -80,7 +80,7 @@ uint64 InputMessage::getU64(bool peek)
 std::string InputMessage::getString()
 {
     uint16 stringLength = getU16();
-    assert(canRead(stringLength));
+    checkRead(stringLength);
     char* v = (char*)(m_buffer + m_readPos);
     m_readPos += stringLength;
     return std::string(v, stringLength);
@@ -92,3 +92,10 @@ bool InputMessage::canRead(int bytes)
         return false;
     return true;
 }
+
+void InputMessage::checkRead(int bytes)
+{
+    if(!canRead(bytes))
+        throw NetworkException("InputMessage eof reached");
+}
+
diff --git a/src/framework/net/inputmessage.h b/src/framework/net/inputmessage.h
index f8f02148..8746cbf1 100644
--- a/src/framework/net/inputmessage.h
+++ b/src/framework/net/inputmessage.h
@@ -24,6 +24,7 @@
 #define INPUTMESSAGE_H
 
 #include "declarations.h"
+#include "networkexception.h"
 
 class InputMessage
 {
@@ -56,6 +57,7 @@ public:
 
 private:
     bool canRead(int bytes);
+    void checkRead(int bytes);
 
     uint16 m_readPos;
     uint16 m_messageSize;
diff --git a/src/framework/net/networkexception.h b/src/framework/net/networkexception.h
new file mode 100644
index 00000000..c96a20da
--- /dev/null
+++ b/src/framework/net/networkexception.h
@@ -0,0 +1,12 @@
+#ifndef NETWORKEXCEPTION_H
+#define NETWORKEXCEPTION_H
+
+#include "declarations.h"
+
+class NetworkException : public Exception
+{
+public:
+    NetworkException(const std::string& what) : Exception(what) { }
+};
+
+#endif
diff --git a/src/framework/net/outputmessage.cpp b/src/framework/net/outputmessage.cpp
index 95a6b1fa..c1164ccc 100644
--- a/src/framework/net/outputmessage.cpp
+++ b/src/framework/net/outputmessage.cpp
@@ -35,7 +35,7 @@ void OutputMessage::reset()
 
 void OutputMessage::addU8(uint8 value)
 {
-    assert(canWrite(1));
+    checkWrite(1);
     m_buffer[m_writePos] = value;
     m_writePos += 1;
     m_messageSize += 1;
@@ -43,7 +43,7 @@ void OutputMessage::addU8(uint8 value)
 
 void OutputMessage::addU16(uint16 value)
 {
-    assert(canWrite(2));
+    checkWrite(2);
     *(uint16_t*)(m_buffer + m_writePos) = value;
     m_writePos += 2;
     m_messageSize += 2;
@@ -51,7 +51,7 @@ void OutputMessage::addU16(uint16 value)
 
 void OutputMessage::addU32(uint32 value)
 {
-    assert(canWrite(4));
+    checkWrite(4);
     *(uint32*)(m_buffer + m_writePos) = value;
     m_writePos += 4;
     m_messageSize += 4;
@@ -59,7 +59,7 @@ void OutputMessage::addU32(uint32 value)
 
 void OutputMessage::addU64(uint64 value)
 {
-    assert(canWrite(8));
+    checkWrite(8);
     *(uint64*)(m_buffer + m_writePos) = value;
     m_writePos += 8;
     m_messageSize += 8;
@@ -68,7 +68,9 @@ void OutputMessage::addU64(uint64 value)
 void OutputMessage::addString(const char* value)
 {
     size_t stringLength = strlen(value);
-    assert(stringLength < 0xFFFF && canWrite(stringLength + 2));
+    if(stringLength > 65535)
+        throw NetworkException("[OutputMessage::addString] string length > 65535");
+    checkWrite(stringLength + 2);
     addU16(stringLength);
     strcpy((char*)(m_buffer + m_writePos), value);
     m_writePos += stringLength;
@@ -82,7 +84,9 @@ void OutputMessage::addString(const std::string &value)
 
 void OutputMessage::addPaddingBytes(int bytes, uint8 byte)
 {
-    assert(canWrite(bytes) && bytes >= 0);
+    if(bytes <= 0)
+        return;
+    checkWrite(bytes);
     memset((void*)&m_buffer[m_writePos], byte, bytes);
     m_writePos += bytes;
     m_messageSize += bytes;
@@ -94,3 +98,9 @@ bool OutputMessage::canWrite(int bytes)
         return false;
     return true;
 }
+
+void OutputMessage::checkWrite(int bytes)
+{
+    if(!canWrite(bytes))
+        throw NetworkException("OutputMessage max buffer size reached");
+}
diff --git a/src/framework/net/outputmessage.h b/src/framework/net/outputmessage.h
index 0b5e7b53..bfcb8b93 100644
--- a/src/framework/net/outputmessage.h
+++ b/src/framework/net/outputmessage.h
@@ -24,6 +24,7 @@
 #define OUTPUTMESSAGE_H
 
 #include "declarations.h"
+#include "networkexception.h"
 
 class OutputMessage
 {
@@ -56,6 +57,7 @@ public:
 
 private:
     bool canWrite(int bytes);
+    void checkWrite(int bytes);
 
     uint16 m_writePos;
     uint16 m_messageSize;
diff --git a/src/framework/net/protocol.cpp b/src/framework/net/protocol.cpp
index 014b6b20..afa904df 100644
--- a/src/framework/net/protocol.cpp
+++ b/src/framework/net/protocol.cpp
@@ -107,14 +107,15 @@ void Protocol::internalRecvData(uint8* buffer, uint16 size)
     if(m_checksumEnabled) {
         uint32 checksum = getAdlerChecksum(m_inputMessage.getBuffer() + InputMessage::DATA_POS, m_inputMessage.getMessageSize() - InputMessage::CHECKSUM_LENGTH);
         if(m_inputMessage.getU32() != checksum) {
-            // error
-            logError("got a network message with invalid checksum");
+            logTraceError("got a network message with invalid checksum");
             return;
         }
     }
 
-    if(m_xteaEncryptionEnabled)
-        xteaDecrypt(m_inputMessage);
+    if(m_xteaEncryptionEnabled) {
+        if(!xteaDecrypt(m_inputMessage))
+            return;
+    }
 
     onRecv(m_inputMessage);
 }
@@ -133,7 +134,7 @@ bool Protocol::xteaDecrypt(InputMessage& inputMessage)
 {
     uint16 messageSize = inputMessage.getMessageSize() - InputMessage::CHECKSUM_LENGTH;
     if(messageSize % 8 != 0) {
-        logError("invalid encrypted network message");
+        logTraceError("invalid encrypted network message");
         return false;
     }
 
@@ -156,7 +157,7 @@ bool Protocol::xteaDecrypt(InputMessage& inputMessage)
 
     int tmp = inputMessage.getU16();
     if(tmp > inputMessage.getMessageSize() - 4) {
-        logError("invalid decrypted a network message");
+        logTraceError("invalid decrypted a network message");
         return false;
     }
 
diff --git a/src/framework/net/rsa.cpp b/src/framework/net/rsa.cpp
index 910f0661..a69c297b 100644
--- a/src/framework/net/rsa.cpp
+++ b/src/framework/net/rsa.cpp
@@ -65,9 +65,11 @@ void Rsa::setKey(const char* p, const char* q, const char* d)
 
     mpz_clear(pm1);
     mpz_clear(qm1);
+
+    m_keySet = true;
 }
 
-bool Rsa::encrypt(char* msg, int32_t size, const char* key)
+void Rsa::encrypt(char* msg, int32_t size, const char* key)
 {
     mpz_t plain, c;
     mpz_init2(plain, 1024);
@@ -92,11 +94,13 @@ bool Rsa::encrypt(char* msg, int32_t size, const char* key)
     mpz_clear(plain);
     mpz_clear(e);
     mpz_clear(mod);
-    return true;
 }
 
 bool Rsa::decrypt(char* msg, int32_t size)
 {
+    if(!m_keySet)
+        return false;
+
     mpz_t c,v1,v2,u2,tmp;
     mpz_init2(c, 1024);
     mpz_init2(v1, 1024);
@@ -130,6 +134,5 @@ bool Rsa::decrypt(char* msg, int32_t size)
     mpz_clear(v2);
     mpz_clear(u2);
     mpz_clear(tmp);
-
     return true;
 }
diff --git a/src/framework/net/rsa.h b/src/framework/net/rsa.h
index 7029e1a6..b7a97a6f 100644
--- a/src/framework/net/rsa.h
+++ b/src/framework/net/rsa.h
@@ -34,7 +34,7 @@ public:
 
     void setKey(const char* p, const char* q, const char* d);
     bool decrypt(char* msg, int32_t size);
-    static bool encrypt(char* msg, int32_t size, const char* key);
+    static void encrypt(char* msg, int32_t size, const char* key);
 
 protected:
     bool m_keySet;
diff --git a/src/framework/platform/platform.h b/src/framework/platform/platform.h
index 1ac0020f..c6e892b0 100644
--- a/src/framework/platform/platform.h
+++ b/src/framework/platform/platform.h
@@ -36,11 +36,6 @@ public:
     /// Poll platform input/window events
     void poll();
 
-    void updateTicks();
-
-    /// Get current time in milliseconds since last application init
-    int getTicks() { return m_lastTicks; }
-
     /// Sleep in current thread
     void sleep(ulong ms);
 
@@ -84,9 +79,6 @@ public:
     std::string getAppUserDir();
 
     void displayFatalError(const std::string& message);
-
-private:
-    int m_lastTicks;
 };
 
 extern Platform g_platform;
diff --git a/src/framework/platform/x11platform.cpp b/src/framework/platform/x11platform.cpp
index b375587b..7e0180cb 100644
--- a/src/framework/platform/x11platform.cpp
+++ b/src/framework/platform/x11platform.cpp
@@ -370,9 +370,6 @@ void Platform::init(PlatformListener* platformListener, const char *appName)
     x11.atomWindowState = XInternAtom(x11.display, "_NET_WM_STATE", False);
     x11.atomWindowMaximizedVert = XInternAtom(x11.display, "_NET_WM_STATE_MAXIMIZED_VERT", False);
     x11.atomWindowMaximizedHorz = XInternAtom(x11.display, "_NET_WM_STATE_MAXIMIZED_HORZ", False);
-
-    // force first tick
-    updateTicks();
 }
 
 void Platform::terminate()
@@ -585,26 +582,6 @@ void Platform::poll()
     }
 }
 
-void Platform::updateTicks()
-{
-    static timeval tv;
-    static ulong firstTick = 0;
-
-    gettimeofday(&tv, 0);
-    if(!firstTick)
-        firstTick = tv.tv_sec;
-
-    m_lastTicks = ((tv.tv_sec - firstTick) * 1000) + (tv.tv_usec / 1000);
-}
-
-void Platform::sleep(ulong miliseconds)
-{
-    timespec tv;
-    tv.tv_sec  = miliseconds / 1000;
-    tv.tv_nsec = (miliseconds % 1000) * 1000000;
-    nanosleep(&tv, NULL);
-}
-
 bool Platform::createWindow(int x, int y, int width, int height, int minWidth, int minHeight, bool maximized)
 {
     static int attrList[] = {
@@ -729,11 +706,11 @@ void Platform::setWindowIcon(const std::string& pngIcon)
 
         Atom property = XInternAtom(x11.display, "_NET_WM_ICON", 0);
         if(!XChangeProperty(x11.display, x11.window, property, XA_CARDINAL, 32, PropModeReplace, (const unsigned char*)&iconData[0], iconData.size()))
-            logError("could not set app icon");
+            logError("Couldn't set app icon");
 
         free_apng(&apng);
     } else
-        logError("could not load app icon");
+        logError("Couldn't load app icon");
 }
 
 void Platform::destroyWindow()
@@ -835,7 +812,7 @@ const char *Platform::getClipboardText()
         XFlush(x11.display);
 
         // hack to wait SelectioNotify event, otherwise we will get wrong clipboard pastes
-        sleep(100);
+        usleep(100 * 1000);
 
         // check for data
         Atom type;
diff --git a/src/framework/ui/uiframecounter.cpp b/src/framework/ui/uiframecounter.cpp
index 0df02ab8..33bc404c 100644
--- a/src/framework/ui/uiframecounter.cpp
+++ b/src/framework/ui/uiframecounter.cpp
@@ -24,7 +24,7 @@
 #include "uitranslator.h"
 #include <framework/graphics/font.h>
 #include <framework/otml/otmlnode.h>
-#include <framework/platform/platform.h>
+#include <framework/core/clock.h>
 #include <framework/graphics/graphics.h>
 
 UIFrameCounter::UIFrameCounter()
@@ -32,7 +32,7 @@ UIFrameCounter::UIFrameCounter()
     m_focusable = false;
     m_phantom = true;
     m_align = Fw::AlignLeft;
-    m_lastFrameTicks = g_platform.getTicks();
+    m_lastFrameTicks = g_clock.ticks();
     m_frameCount = 0;
 }
 
@@ -40,7 +40,7 @@ void UIFrameCounter::render()
 {
     UIWidget::render();
 
-    int now = g_platform.getTicks();
+    int now = g_clock.ticks();
     if(now - m_lastFrameTicks >= 1000) {
         m_fpsText = Fw::mkstr("FPS: ", m_frameCount);
         m_lastFrameTicks = now;
diff --git a/src/framework/ui/uilineedit.cpp b/src/framework/ui/uilineedit.cpp
index 62b71372..7e8cf097 100644
--- a/src/framework/ui/uilineedit.cpp
+++ b/src/framework/ui/uilineedit.cpp
@@ -24,6 +24,7 @@
 #include <framework/graphics/font.h>
 #include <framework/graphics/graphics.h>
 #include <framework/platform/platform.h>
+#include <framework/core/clock.h>
 #include <framework/otml/otmlnode.h>
 
 UILineEdit::UILineEdit()
@@ -55,7 +56,7 @@ void UILineEdit::render()
         assert(m_cursorPos <= textLength);
         // draw every 333ms
         const int delay = 333;
-        int ticks = g_platform.getTicks();
+        int ticks = g_clock.ticks();
         if(ticks - m_cursorTicks <= delay) {
             Rect cursorRect;
             // when cursor is at 0 or is the first visible element
@@ -447,5 +448,5 @@ bool UILineEdit::onMousePress(const Point& mousePos, Fw::MouseButton button)
 
 void UILineEdit::blinkCursor()
 {
-    m_cursorTicks = g_platform.getTicks();
+    m_cursorTicks = g_clock.ticks();
 }
diff --git a/src/framework/ui/uimanager.cpp b/src/framework/ui/uimanager.cpp
index 492bd980..2725a8fa 100644
--- a/src/framework/ui/uimanager.cpp
+++ b/src/framework/ui/uimanager.cpp
@@ -110,8 +110,8 @@ bool UIManager::importStyles(const std::string& file)
         for(const OTMLNodePtr& styleNode : doc->children())
             importStyleFromOTML(styleNode);
         return true;
-    } catch(std::exception& e) {
-        logError("failed to import ui styles from '", file, "':\n", e.what());
+    } catch(Exception& e) {
+        logError("Failed to import UI styles from '", file, "': ", e.what());
         return false;
     }
 }
@@ -153,8 +153,11 @@ OTMLNodePtr UIManager::getStyle(const std::string& styleName)
     }
 
     auto it = m_styles.find(styleName);
-    if(it == m_styles.end())
-        throw std::runtime_error(Fw::mkstr("style '", styleName, "' is not a defined style"));
+    if(it == m_styles.end()) {
+        logError("Unable to retrive style '", styleName, "': not a defined style");
+        return nullptr;
+    }
+
     return m_styles[styleName];
 }
 
@@ -171,14 +174,14 @@ UIWidgetPtr UIManager::loadUI(const std::string& file, const UIWidgetPtr& parent
                 importStyleFromOTML(node);
             else {
                 if(widget)
-                    throw std::runtime_error("cannot have multiple main widgets in .otui files");
+                    Fw::throwException("cannot have multiple main widgets in otui files");
                 widget = loadWidgetFromOTML(node, parent);
             }
         }
 
         return widget;
-    } catch(std::exception& e) {
-        logError("failed to load ui from '", file, "':\n", e.what());
+    } catch(Exception& e) {
+        logError("Failed to load UI from '", file, "': ", e.what());
         return nullptr;
     }
 }
diff --git a/src/framework/ui/uiwidget.cpp b/src/framework/ui/uiwidget.cpp
index 165bb3cf..2ed4f8c1 100644
--- a/src/framework/ui/uiwidget.cpp
+++ b/src/framework/ui/uiwidget.cpp
@@ -142,6 +142,8 @@ void UIWidget::setFocusable(bool focusable)
 void UIWidget::setStyle(const std::string& styleName)
 {
     OTMLNodePtr styleNode = g_ui.getStyle(styleName);
+    if(!styleNode)
+        return;
     applyStyle(styleNode);
     m_style = styleNode;
     updateStyle();
@@ -331,7 +333,7 @@ UIWidgetPtr UIWidget::backwardsGetWidgetById(const std::string& id)
 void UIWidget::focusChild(const UIWidgetPtr& child, Fw::FocusReason reason)
 {
     if(child && !hasChild(child)) {
-        logError("attempt to focus an unknown child in a UIWidget");
+        logError("Attempt to focus an unknown child in a UIWidget");
         return;
     }
 
@@ -440,7 +442,7 @@ void UIWidget::removeChild(const UIWidgetPtr& child)
         if(focusAnother && !m_focusedChild)
             focusPreviousChild(Fw::ActiveFocusReason);
     } else
-        logError("attempt to remove an unknown child from a UIWidget");
+        logError("Attempt to remove an unknown child from a UIWidget");
 }
 
 void UIWidget::focusNextChild(Fw::FocusReason reason)
@@ -774,8 +776,8 @@ void UIWidget::applyStyle(const OTMLNodePtr& styleNode)
     try {
         onStyleApply(styleNode);
         callLuaField("onStyleApply", styleNode);
-    } catch(std::exception& e) {
-        logError("failed to apply widget '", m_id, "' style: ", e.what());
+    } catch(Exception& e) {
+        logError("Failed to apply style to widget '", m_id, "' style: ", e.what());
     }
 }
 
diff --git a/src/framework/util/exception.h b/src/framework/util/exception.h
new file mode 100644
index 00000000..c0561670
--- /dev/null
+++ b/src/framework/util/exception.h
@@ -0,0 +1,19 @@
+#ifndef EXCEPTION_H
+#define EXCEPTION_H
+
+#include <exception>
+
+class Exception : public std::exception
+{
+public:
+    Exception() { }
+    Exception(const std::string& what) : m_what(what) { }
+    virtual ~Exception() throw() { };
+
+    virtual const char* what() const throw() { return m_what.c_str(); }
+
+protected:
+    std::string m_what;
+};
+
+#endif
diff --git a/src/framework/util/tools.h b/src/framework/util/tools.h
index bb1b3579..159cd1fc 100644
--- a/src/framework/util/tools.h
+++ b/src/framework/util/tools.h
@@ -29,22 +29,11 @@
 #include <sstream>
 #include <exception>
 #include <cxxabi.h>
-#include <chrono>
-#include <unistd.h>
 #include "types.h"
+#include "exception.h"
 
 namespace Fw {
 
-inline int getTicks() {
-    static auto firstTick = std::chrono::high_resolution_clock::now();
-    auto tickNow = std::chrono::high_resolution_clock::now();
-    return std::chrono::duration_cast<std::chrono::milliseconds>(tickNow - firstTick).count();
-}
-
-inline void sleep(int ms) {
-    usleep(ms);
-}
-
 // read utilities for istream
 inline uint8 getU8(std::istream& in) {
     uint8 tmp;
@@ -197,9 +186,9 @@ inline bool cast(const bool& in, std::string& out) {
 }
 
 // used by safe_cast
-class BadCast : public std::bad_cast {
+class CastException : public Exception {
 public:
-    virtual ~BadCast() throw() { }
+    virtual ~CastException() throw() { }
     template<class T, class R>
     void setWhat() {
         m_what = mkstr("failed to cast value of type '", demangleType<T>(),
@@ -217,7 +206,7 @@ template<typename R, typename T>
 R safeCast(const T& t) {
     R r;
     if(!cast(t, r)) {
-        BadCast e;
+        CastException e;
         e.setWhat<T,R>();
         throw e;
     }
@@ -231,7 +220,7 @@ template<typename R, typename T>
 R unsafeCast(const T& t, R def = R()) {
     try {
         return safeCast<R,T>(t);
-    } catch(BadCast& e) {
+    } catch(CastException& e) {
         println("CAST ERROR: ", e.what());
         return def;
     }
@@ -268,6 +257,11 @@ inline std::string ip2str(uint32 ip) {
     return std::string(host);
 }
 
+template<typename... T>
+void throwException(const T&... args) {
+    throw Exception(Fw::mkstr(args...));
+}
+
 }
 
 // shortcut for Fw::dump
diff --git a/src/otclient/core/creature.cpp b/src/otclient/core/creature.cpp
index 55c606b9..2b574f30 100644
--- a/src/otclient/core/creature.cpp
+++ b/src/otclient/core/creature.cpp
@@ -27,16 +27,16 @@
 #include "tile.h"
 #include "item.h"
 
-#include <framework/platform/platform.h>
 #include <framework/graphics/graphics.h>
 #include <framework/core/eventdispatcher.h>
-
+#include <framework/core/clock.h>
 
 Creature::Creature() : Thing()
 {
     m_healthPercent = 0;
     m_showSquareColor = false;
     m_direction = Otc::South;
+    m_walkTimePerPixel = 1000.0/32.0;
 
     m_walking = false;
 
@@ -201,7 +201,7 @@ void Creature::walk(const Position& position, bool inverse)
 
         m_walkTimePerPixel = walkTime / 32.0;
         if(!sameWalk)
-            m_walkStartTicks = g_platform.getTicks();
+            m_walkStartTicks = g_clock.ticks();
         updateWalk();
     }
 }
@@ -210,7 +210,7 @@ void Creature::updateWalk()
 {
     const ThingType& type = getType();
     if(m_walking) {
-        int elapsedTicks = g_platform.getTicks() - m_walkStartTicks;
+        int elapsedTicks = g_clock.ticks() - m_walkStartTicks;
         int totalPixelsWalked = std::min((int)round(elapsedTicks / m_walkTimePerPixel), 32);
 
         if(m_inverseWalking) {
@@ -240,7 +240,10 @@ void Creature::updateWalk()
         }
 
         int totalWalkTileTicks = (int)m_walkTimePerPixel*32 * 0.5;
-        m_animation = (g_platform.getTicks() % totalWalkTileTicks) / (totalWalkTileTicks / (type.dimensions[ThingType::AnimationPhases] - 1)) + 1;
+        if(type.dimensions[ThingType::AnimationPhases] > 0)
+            m_animation = (g_clock.ticks() % totalWalkTileTicks) / (totalWalkTileTicks / (type.dimensions[ThingType::AnimationPhases] - 1)) + 1;
+        else
+            m_animation = 0;
         g_dispatcher.scheduleEvent(std::bind(&Creature::updateWalk, asCreature()), m_walkTimePerPixel);
 
         if(totalPixelsWalked == 32)
@@ -250,17 +253,19 @@ void Creature::updateWalk()
 
 void Creature::cancelWalk(Otc::Direction direction)
 {
+    if(m_walking) {
+        auto self = asCreature();
+        g_dispatcher.scheduleEvent([=]() {
+            if(!self->m_walking)
+                self->m_animation = 0;
+        }, m_walkTimePerPixel * 2);
+    }
+
     m_walking = false;
     m_walkStartTicks = 0;
     m_walkOffset.x = 0;
     m_walkOffset.y = 0;
     m_direction = direction;
-
-    auto self = asCreature();
-    g_dispatcher.scheduleEvent([=]() {
-        if(!self->m_walking)
-            self->m_animation = 0;
-    }, m_walkTimePerPixel * 2);
 }
 
 void Creature::setName(const std::string& name)
diff --git a/src/otclient/core/effect.cpp b/src/otclient/core/effect.cpp
index e75c51c7..33a3aca8 100644
--- a/src/otclient/core/effect.cpp
+++ b/src/otclient/core/effect.cpp
@@ -24,7 +24,7 @@
 #include "thingstype.h"
 #include "map.h"
 #include "tile.h"
-#include <framework/platform/platform.h>
+#include <framework/core/clock.h>
 #include <framework/core/eventdispatcher.h>
 
 Effect::Effect() : Thing()
@@ -34,7 +34,7 @@ Effect::Effect() : Thing()
 
 void Effect::draw(const Point& p)
 {
-    int animationPhase = (g_platform.getTicks() - m_animationStartTicks) / TICKS_PER_FRAME;
+    int animationPhase = (g_clock.ticks() - m_animationStartTicks) / TICKS_PER_FRAME;
 
     if(animationPhase < getAnimationPhases()) {
         m_animation = animationPhase;
@@ -44,7 +44,7 @@ void Effect::draw(const Point& p)
 
 void Effect::startAnimation()
 {
-    m_animationStartTicks = g_platform.getTicks();
+    m_animationStartTicks = g_clock.ticks();
 
     // schedule removal
     auto self = asEffect();
diff --git a/src/otclient/core/item.cpp b/src/otclient/core/item.cpp
index ad825566..6f55f3ee 100644
--- a/src/otclient/core/item.cpp
+++ b/src/otclient/core/item.cpp
@@ -24,12 +24,12 @@
 #include "thingstype.h"
 #include "spritemanager.h"
 #include "thing.h"
-#include <framework/platform/platform.h>
+#include <framework/core/clock.h>
 
 Item::Item() : Thing()
 {
     m_data = 0;
-    m_lastTicks = g_platform.getTicks();
+    m_lastTicks = g_clock.ticks();
 }
 
 void Item::draw(const Point& p)
@@ -37,7 +37,7 @@ void Item::draw(const Point& p)
     const ThingType& type = getType();
 
     if(type.dimensions[ThingType::AnimationPhases] > 1)
-        m_animation = (g_platform.getTicks() % (TICKS_PER_FRAME * type.dimensions[ThingType::AnimationPhases])) / TICKS_PER_FRAME;
+        m_animation = (g_clock.ticks() % (TICKS_PER_FRAME * type.dimensions[ThingType::AnimationPhases])) / TICKS_PER_FRAME;
 
     for(int b = 0; b < type.dimensions[ThingType::Layers]; b++)
         internalDraw(p, b);
diff --git a/src/otclient/core/missile.cpp b/src/otclient/core/missile.cpp
index ea9ead9d..7eac599c 100644
--- a/src/otclient/core/missile.cpp
+++ b/src/otclient/core/missile.cpp
@@ -24,7 +24,7 @@
 #include "thingstype.h"
 #include "map.h"
 #include "tile.h"
-#include <framework/platform/platform.h>
+#include <framework/core/clock.h>
 #include <framework/core/eventdispatcher.h>
 
 Missile::Missile() : Thing()
@@ -34,7 +34,7 @@ Missile::Missile() : Thing()
 
 void Missile::draw(const Point& p)
 {
-    float time = (g_platform.getTicks() - m_startTicks) / m_duration;
+    float time = (g_clock.ticks() - m_startTicks) / m_duration;
     internalDraw(p + Point(m_positionDelta.x * time, m_positionDelta.y * time), 0);
 }
 
@@ -108,7 +108,7 @@ void Missile::setPath(const Position& fromPosition, const Position& toPosition)
     m_positionDelta.x *= 32;
     m_positionDelta.y *= 32;
 
-    m_startTicks = g_platform.getTicks();
+    m_startTicks = g_clock.ticks();
 
     // schedule removal
     auto self = asMissile();
diff --git a/src/otclient/core/spritemanager.cpp b/src/otclient/core/spritemanager.cpp
index 149791eb..076572a6 100644
--- a/src/otclient/core/spritemanager.cpp
+++ b/src/otclient/core/spritemanager.cpp
@@ -40,8 +40,8 @@ bool SpriteManager::load(const std::string& file)
         m_spritesCount = Fw::getU16(m_fin);
         m_sprites.resize(m_spritesCount);
         return true;
-    } catch(std::exception& e) {
-        logError("faile to load sprites from '", file, "': ", e.what());
+    } catch(Exception& e) {
+        logError("Failed to load sprites from '", file, "': ", e.what());
         return false;
     }
 }
diff --git a/src/otclient/core/thingstype.cpp b/src/otclient/core/thingstype.cpp
index 6f591a0b..dbcb88f3 100644
--- a/src/otclient/core/thingstype.cpp
+++ b/src/otclient/core/thingstype.cpp
@@ -48,8 +48,8 @@ bool ThingsType::load(const std::string& file)
         }
 
         return true;
-    } catch(std::exception& e) {
-        logError("failed to load dat from '", file, "': ", e.what());
+    } catch(Exception& e) {
+        logError("Failed to load dat from '", file, "': ", e.what());
         return false;
     }
 }
@@ -116,7 +116,14 @@ ThingType& ThingsType::getThingType(uint16 id, Categories category)
     if(category == Item)
         id -= 100;
 
-    assert(id < m_things[category].size());
+    //assert(id < m_things[category].size());
+
+    // assert wrokground
+    if(id >= m_things[category].size()) {
+        //logTraceErrorOnce("got an invalid type");
+        static ThingType emptyType;
+        return emptyType;
+    }
 
     return m_things[category][id];
 }
diff --git a/src/otclient/core/thingtype.h b/src/otclient/core/thingtype.h
index 46dd515a..56cafdf4 100644
--- a/src/otclient/core/thingtype.h
+++ b/src/otclient/core/thingtype.h
@@ -27,6 +27,13 @@
 
 struct ThingType
 {
+    ThingType() {
+        // fill default values
+        dimensions.fill(0);
+        properties.fill(false);
+        parameters.fill(0);
+    }
+
     enum Dimensions {
         Width = 0,
         Height,
diff --git a/src/otclient/luascript/luafunctions.cpp b/src/otclient/luascript/luafunctions.cpp
index 37d6b53e..8b3b1472 100644
--- a/src/otclient/luascript/luafunctions.cpp
+++ b/src/otclient/luascript/luafunctions.cpp
@@ -43,8 +43,6 @@
 
 void OTClient::registerLuaFunctions()
 {
-    using namespace std::placeholders;
-
     g_lua.bindGlobalFunction("exit", std::bind(&OTClient::exit, &g_client));
     g_lua.bindGlobalFunction("setOnClose", std::bind(&OTClient::setOnClose, &g_client, _1));
     g_lua.bindGlobalFunction("importDat", std::bind(&ThingsType::load, &g_thingsType, _1));
diff --git a/src/otclient/net/protocolgameparse.cpp b/src/otclient/net/protocolgameparse.cpp
index dbef2856..28ea4d88 100644
--- a/src/otclient/net/protocolgameparse.cpp
+++ b/src/otclient/net/protocolgameparse.cpp
@@ -35,11 +35,11 @@
 
 void ProtocolGame::parseMessage(InputMessage& msg)
 {
-    while(!msg.eof()) {
-        uint8 opt = msg.getU8();
-        //dump << "protocol id:" << (int)opt;
+    try {
+        while(!msg.eof()) {
+            uint8 opt = msg.getU8();
 
-        switch(opt) {
+            switch(opt) {
             case Otc::GameServerInitGame:
                 parsePlayerLogin(msg);
                 break;
@@ -251,9 +251,12 @@ void ProtocolGame::parseMessage(InputMessage& msg)
             //case Otc::GameServerObjectInfo:
             //case Otc::GameServerPlayerInventory:
             default:
-                logError("UNKNOWN PACKET OPT BYTE: 0x", std::hex, opt);
+                Fw::throwException("unknown opt byte ", opt);
                 break;
+            }
         }
+    } catch(Exception& e) {
+        logTraceError(e.what());
     }
 }
 
@@ -738,7 +741,7 @@ void ProtocolGame::parseCreatureSpeak(InputMessage& msg)
         case Otc::SpeakPrivateRed:
             break;
         default:
-            logTraceDebug("Unknown speak type.", (int)type);
+            logTraceError("unknown speak type ", type);
             break;
     }
 
@@ -811,7 +814,7 @@ void ProtocolGame::parseCancelWalk(InputMessage& msg)
 
 void ProtocolGame::parseFloorChangeUp(InputMessage& msg)
 {
-    logDebug("[ProtocolGame::parseFloorChangeUp]: This function has never been tested.");
+    logTraceDebug("this function has never been tested.");
 
     Position pos = g_map.getCentralPosition();
     pos.z--;
@@ -830,7 +833,7 @@ void ProtocolGame::parseFloorChangeUp(InputMessage& msg)
 
 void ProtocolGame::parseFloorChangeDown(InputMessage& msg)
 {
-    logDebug("[ProtocolGame::parseFloorChangeDown]: This function has never been tested.");
+    logTraceDebug("this function has never been tested.");
 
     Position pos = g_map.getCentralPosition();
     pos.z++;
@@ -982,13 +985,13 @@ void ProtocolGame::setTileDescription(InputMessage& msg, Position position)
     g_map.cleanTile(position);
 
     int stackPos = 0;
-    while(1){
+    while(true) {
         uint16 inspectTileId = msg.getU16(true);
         if(inspectTileId >= 0xFF00)
             return;
         else {
             if(stackPos >= 10)
-                logWarning("Too many things!");
+                logTraceWarning("too many things");
 
             ThingPtr thing = internalGetThing(msg);
             g_map.addThing(thing, position, 255);
diff --git a/src/otclient/net/protocolgamesend.cpp b/src/otclient/net/protocolgamesend.cpp
index 3df83f04..ebd4b914 100644
--- a/src/otclient/net/protocolgamesend.cpp
+++ b/src/otclient/net/protocolgamesend.cpp
@@ -52,8 +52,7 @@ void ProtocolGame::sendLoginPacket(uint32 timestamp, uint8 unknown)
     oMsg.addPaddingBytes(128 - (29 + m_accountName.length() + m_characterName.length() + m_accountPassword.length()));
 
     // encrypt with RSA
-    if(!Rsa::encrypt((char*)oMsg.getBuffer() + 6 + oMsg.getMessageSize() - 128, 128, Otc::OtservPublicRSA))
-        return;
+    Rsa::encrypt((char*)oMsg.getBuffer() + 6 + oMsg.getMessageSize() - 128, 128, Otc::OtservPublicRSA);
 
     send(oMsg);
 
diff --git a/src/otclient/net/protocollogin.cpp b/src/otclient/net/protocollogin.cpp
index 5ac4313d..bbd4bb3d 100644
--- a/src/otclient/net/protocollogin.cpp
+++ b/src/otclient/net/protocollogin.cpp
@@ -53,22 +53,29 @@ void ProtocolLogin::onConnect()
 
 void ProtocolLogin::onRecv(InputMessage& inputMessage)
 {
-    while(!inputMessage.eof()) {
-        uint8 opt = inputMessage.getU8();
-        switch(opt) {
-        case Otc::LoginServerError:
-            parseError(inputMessage);
-            break;
-        case Otc::LoginServerMotd:
-            parseMOTD(inputMessage);
-            break;
-        case Otc::LoginServerUpdateNeeded:
-            callLuaField("onError", "Client needs update.");
-            break;
-        case Otc::LoginServerCharacterList:
-            parseCharacterList(inputMessage);
-            break;
+    try {
+        while(!inputMessage.eof()) {
+            uint8 opt = inputMessage.getU8();
+            switch(opt) {
+            case Otc::LoginServerError:
+                parseError(inputMessage);
+                break;
+            case Otc::LoginServerMotd:
+                parseMOTD(inputMessage);
+                break;
+            case Otc::LoginServerUpdateNeeded:
+                callLuaField("onError", "Client needs update.");
+                break;
+            case Otc::LoginServerCharacterList:
+                parseCharacterList(inputMessage);
+                break;
+            default:
+                Fw::throwException("unknown opt byte ", opt);
+                break;
+            }
         }
+    } catch(Exception& e) {
+        logTraceError(e.what());
     }
     disconnect();
 }
@@ -104,14 +111,10 @@ void ProtocolLogin::sendLoginPacket()
 
     // complete the 128 bytes for rsa encryption with zeros
     oMsg.addPaddingBytes(128 - (21 + m_accountName.length() + m_accountPassword.length()));
-
-    if(!Rsa::encrypt((char*)oMsg.getBuffer() + InputMessage::DATA_POS + oMsg.getMessageSize() - 128, 128, Otc::OtservPublicRSA))
-        return;
+    Rsa::encrypt((char*)oMsg.getBuffer() + InputMessage::DATA_POS + oMsg.getMessageSize() - 128, 128, Otc::OtservPublicRSA);
 
     send(oMsg);
-
     enableXteaEncryption();
-
     recv();
 }
 
diff --git a/src/otclient/otclient.cpp b/src/otclient/otclient.cpp
index 80d31a24..5a392e18 100644
--- a/src/otclient/otclient.cpp
+++ b/src/otclient/otclient.cpp
@@ -23,17 +23,17 @@
 #include "otclient.h"
 
 #include <framework/core/modulemanager.h>
-#include <framework/core/configs.h>
+#include <framework/core/configmanager.h>
 #include <framework/core/resourcemanager.h>
 #include <framework/core/eventdispatcher.h>
+#include <framework/core/clock.h>
 #include <framework/luascript/luainterface.h>
-#include <framework/platform/platform.h>
 #include <framework/graphics/graphics.h>
 #include <framework/graphics/fontmanager.h>
 #include <framework/ui/uimanager.h>
 #include <framework/ui/uiwidget.h>
 #include <framework/net/connection.h>
-
+#include <framework/platform/platform.h>
 #include <otclient/net/protocolgame.h>
 #include <otclient/core/game.h>
 #include <otclient/core/map.h>
@@ -79,9 +79,6 @@ void OTClient::init(std::vector<std::string> args)
     // initialize graphics
     g_graphics.init();
 
-    // initialize event dispatcher
-    g_dispatcher.init();
-
     // initialize the ui
     g_ui.init();
 
@@ -105,7 +102,7 @@ void OTClient::init(std::vector<std::string> args)
 
 void OTClient::run()
 {
-    int frameTicks = g_platform.getTicks();
+    int frameTicks = g_clock.ticks();
     int lastPollTicks = frameTicks;
     int frameCount = 0;
 
@@ -113,7 +110,7 @@ void OTClient::run()
     m_running = true;
 
     if(g_ui.getRootWidget()->getChildCount() == 0) {
-        logError("there is no root widgets to display, the app will close");
+        logError("There is no root widgets to display, the app will close");
         m_stopping = true;
     }
 
@@ -122,8 +119,7 @@ void OTClient::run()
 
     while(!m_stopping) {
         //g_platform.sleep(150);
-        g_platform.updateTicks();
-        frameTicks = g_platform.getTicks();
+        frameTicks = g_clock.updateTicks();
 
         // poll events every POLL_CYCLE_DELAY
         // this delay exists to avoid massive polling thus increasing framerate
@@ -147,7 +143,7 @@ void OTClient::run()
             g_platform.swapBuffers();
         } else {
             // sleeps until next poll to avoid massive cpu usage
-            Fw::sleep(POLL_CYCLE_DELAY+1);
+            g_clock.sleep(POLL_CYCLE_DELAY+1);
         }
     }
 
@@ -177,8 +173,8 @@ void OTClient::terminate()
     // terminate network
     Connection::terminate();
 
-    // terminate dispatcher
-    g_dispatcher.terminate();
+    // flush remaining dispatcher events
+    g_dispatcher.flush();
 
     // terminate graphics
     g_graphics.terminate();
@@ -257,7 +253,7 @@ void OTClient::saveConfigurations()
 
     // saves user configuration
     if(!g_configs.save())
-        logError("configurations are lost because it couldn't be saved");
+        logError("Configurations are lost because it couldn't be saved");
 }
 
 void OTClient::onClose()