add clock, change exceptions, add network exceptions, fix some crashes

This commit is contained in:
Eduardo Bart 2011-12-01 20:25:32 -02:00
parent 4afbe43e6f
commit d5e15d1f06
54 changed files with 442 additions and 274 deletions

View File

@ -33,7 +33,7 @@ FIND_PACKAGE(PCHSupport REQUIRED)
# choose a default build type if not specified # choose a default build type if not specified
IF(NOT CMAKE_BUILD_TYPE) IF(NOT CMAKE_BUILD_TYPE)
SET(CMAKE_BUILD_TYPE ReleaseWithDebInfo) SET(CMAKE_BUILD_TYPE Debug)
ENDIF(NOT CMAKE_BUILD_TYPE) ENDIF(NOT CMAKE_BUILD_TYPE)
MESSAGE(STATUS "BUILD TYPE: " ${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 "-std=gnu++0x -pipe ${CXX_WARNS}")
SET(CMAKE_CXX_FLAGS_DEBUG "-O0 -g3 -ggdb3 -fno-inline") SET(CMAKE_CXX_FLAGS_DEBUG "-O0 -g3 -ggdb3 -fno-inline")
SET(CMAKE_CXX_FLAGS_RELEASE "-O2") 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") SET(CMAKE_CXX_LINK_FLAGS "-static-libgcc -static-libstdc++ -Wl,--as-needed")
ENDIF(CMAKE_COMPILER_IS_GNUCXX) ENDIF(CMAKE_COMPILER_IS_GNUCXX)
@ -112,12 +112,14 @@ SET(SOURCES
# framework core # framework core
src/framework/core/logger.cpp 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/resourcemanager.cpp
src/framework/core/eventdispatcher.cpp src/framework/core/eventdispatcher.cpp
src/framework/core/modulemanager.cpp src/framework/core/modulemanager.cpp
src/framework/core/module.cpp src/framework/core/module.cpp
src/framework/core/engine.cpp src/framework/core/engine.cpp
src/framework/core/clock.cpp
# framework graphics # framework graphics
src/framework/graphics/font.cpp src/framework/graphics/font.cpp

View File

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

View File

@ -47,7 +47,7 @@ local function tryLogin(charInfo, tries)
end end
-- save last used character -- save last used character
Configs.set('lastUsedCharacter', charInfo.characterName) ConfigManager.set('lastUsedCharacter', charInfo.characterName)
end end
-- public functions -- public functions
@ -75,7 +75,7 @@ function CharacterList.create(characters, premDays)
label.worldHost = worldHost label.worldHost = worldHost
label.worldPort = worldIp 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) characterList:focusChild(label, ActiveFocusReason)
end end
end end

View File

@ -11,8 +11,8 @@ local function clearAccountFields()
enterGame:getChildById('accountNameLineEdit'):clearText() enterGame:getChildById('accountNameLineEdit'):clearText()
enterGame:getChildById('accountPasswordLineEdit'):clearText() enterGame:getChildById('accountPasswordLineEdit'):clearText()
enterGame:getChildById('accountNameLineEdit'):focus() enterGame:getChildById('accountNameLineEdit'):focus()
Configs.set('account', nil) ConfigManager.set('account', nil)
Configs.set('password', nil) ConfigManager.set('password', nil)
end end
local function onError(protocol, error) local function onError(protocol, error)
@ -30,9 +30,9 @@ end
local function onCharacterList(protocol, characters, premDays) local function onCharacterList(protocol, characters, premDays)
if enterGame:getChildById('rememberPasswordBox'):isChecked() then if enterGame:getChildById('rememberPasswordBox'):isChecked() then
Configs.set('account', EnterGame.account) ConfigManager.set('account', EnterGame.account)
Configs.set('password', EnterGame.password) ConfigManager.set('password', EnterGame.password)
Configs.set('autologin', tostring(enterGame:getChildById('autoLoginBox'):isChecked())) ConfigManager.set('autologin', tostring(enterGame:getChildById('autoLoginBox'):isChecked()))
else else
clearAccountFields() clearAccountFields()
end end
@ -40,9 +40,9 @@ local function onCharacterList(protocol, characters, premDays)
loadBox:destroy() loadBox:destroy()
CharacterList.create(characters, premDays) CharacterList.create(characters, premDays)
local lastMotdNumber = tonumber(Configs.get("motd")) local lastMotdNumber = tonumber(ConfigManager.get("motd"))
if motdNumber and motdNumber ~= lastMotdNumber then if motdNumber and motdNumber ~= lastMotdNumber then
Configs.set("motd", motdNumber) ConfigManager.set("motd", motdNumber)
local motdBox = displayInfoBox("Message of the day", motdMessage) local motdBox = displayInfoBox("Message of the day", motdMessage)
motdBox.onOk = CharacterList.show motdBox.onOk = CharacterList.show
CharacterList.hide() CharacterList.hide()
@ -53,11 +53,11 @@ end
function EnterGame.create() function EnterGame.create()
enterGame = UI.display('entergame.otui') enterGame = UI.display('entergame.otui')
local account = Configs.get('account') local account = ConfigManager.get('account')
local password = Configs.get('password') local password = ConfigManager.get('password')
local host = Configs.get('host') local host = ConfigManager.get('host')
local port = tonumber(Configs.get('port')) local port = tonumber(ConfigManager.get('port'))
local autologin = toboolean(Configs.get('autologin')) local autologin = toboolean(ConfigManager.get('autologin'))
enterGame:getChildById('accountNameLineEdit'):setText(account) enterGame:getChildById('accountNameLineEdit'):setText(account)
enterGame:getChildById('accountPasswordLineEdit'):setText(password) enterGame:getChildById('accountPasswordLineEdit'):setText(password)
@ -93,8 +93,8 @@ function EnterGame.doLogin()
EnterGame.port = enterGame:getChildById('serverPortLineEdit'):getText() EnterGame.port = enterGame:getChildById('serverPortLineEdit'):getText()
EnterGame.hide() EnterGame.hide()
Configs.set('host', EnterGame.host) ConfigManager.set('host', EnterGame.host)
Configs.set('port', EnterGame.port) ConfigManager.set('port', EnterGame.port)
local protocolLogin = ProtocolLogin.create() local protocolLogin = ProtocolLogin.create()
protocolLogin.onError = onError protocolLogin.onError = onError

View File

@ -6,8 +6,8 @@ local fpsEnabled = false
local vsyncEnabled = false local vsyncEnabled = false
function getConfig(name, default) function getConfig(name, default)
if Configs.exists(name) then if ConfigManager.exists(name) then
local val = string.trim(Configs.get(name)) local val = string.trim(ConfigManager.get(name))
if val == 'true' or val == 'false' then if val == 'true' or val == 'false' then
return toboolean(val) return toboolean(val)
else else
@ -15,7 +15,7 @@ function getConfig(name, default)
end end
else else
if default ~= nil then if default ~= nil then
Configs.set(name, default) ConfigManager.set(name, default)
return default return default
else else
return nil return nil
@ -24,7 +24,7 @@ function getConfig(name, default)
end end
function setConfig(name, value) function setConfig(name, value)
Configs.set(name, tostring(value)) ConfigManager.set(name, tostring(value))
end end
-- private functions -- private functions

View File

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

View File

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

View File

@ -20,14 +20,14 @@
* THE SOFTWARE. * THE SOFTWARE.
*/ */
#include "configs.h" #include "configmanager.h"
#include "resourcemanager.h" #include "resourcemanager.h"
#include <framework/otml/otml.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; m_fileName = file;
@ -39,13 +39,13 @@ bool Configs::load(const std::string& file)
for(const OTMLNodePtr& child : doc->children()) for(const OTMLNodePtr& child : doc->children())
m_confsMap[child->tag()] = child->value(); m_confsMap[child->tag()] = child->value();
return true; return true;
} catch(std::exception& e) { } catch(Exception& e) {
logError("could not load configurations: ", e.what()); logError("could not load configurations: ", e.what());
return false; return false;
} }
} }
bool Configs::save() bool ConfigManager::save()
{ {
OTMLDocumentPtr doc = OTMLDocument::create(); OTMLDocumentPtr doc = OTMLDocument::create();
for(auto it : m_confsMap) { for(auto it : m_confsMap) {

View File

@ -25,7 +25,7 @@
#include "declarations.h" #include "declarations.h"
class Configs class ConfigManager
{ {
public: public:
bool load(const std::string& file); bool load(const std::string& file);
@ -40,6 +40,6 @@ private:
std::map<std::string, std::string> m_confsMap; std::map<std::string, std::string> m_confsMap;
}; };
extern Configs g_configs; extern ConfigManager g_configs;
#endif #endif

View File

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

View File

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

View File

@ -22,44 +22,42 @@
#include "eventdispatcher.h" #include "eventdispatcher.h"
#include <framework/platform/platform.h> #include <framework/core/clock.h>
EventDispatcher g_dispatcher; EventDispatcher g_dispatcher;
void EventDispatcher::init() void EventDispatcher::flush()
{ {
// nothing to do poll();
}
void EventDispatcher::terminate() m_eventList.clear();
{
// clean scheduled events
while(!m_scheduledEventList.empty()) while(!m_scheduledEventList.empty())
m_scheduledEventList.pop(); m_scheduledEventList.pop();
} }
void EventDispatcher::poll() void EventDispatcher::poll()
{ {
while(!m_eventList.empty()) {
m_eventList.front()();
m_eventList.pop_front();
}
while(!m_scheduledEventList.empty()) { while(!m_scheduledEventList.empty()) {
if(g_platform.getTicks() < m_scheduledEventList.top().ticks) if(g_clock.ticks() < m_scheduledEventList.top().ticks)
break; break;
SimpleCallback callback = std::move(m_scheduledEventList.top().callback); SimpleCallback callback = std::move(m_scheduledEventList.top().callback);
m_scheduledEventList.pop(); m_scheduledEventList.pop();
callback(); callback();
} }
while(!m_eventList.empty()) {
m_eventList.front()();
m_eventList.pop_front();
}
} }
void EventDispatcher::scheduleEvent(const SimpleCallback& callback, int delay) 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) if(pushFront)
m_eventList.push_front(callback); m_eventList.push_front(callback);

View File

@ -35,19 +35,10 @@ struct ScheduledEvent {
class EventDispatcher class EventDispatcher
{ {
public: public:
/// Initialize dispatcher void flush();
void init();
/// Cleanup scheduled events
void terminate();
/// Execute scheduled events
void poll(); void poll();
/// Add an event
void addEvent(const SimpleCallback& callback, bool pushFront = false); void addEvent(const SimpleCallback& callback, bool pushFront = false);
/// Schedule an event
void scheduleEvent(const SimpleCallback& callback, int delay); void scheduleEvent(const SimpleCallback& callback, int delay);
private: private:

View File

@ -57,28 +57,29 @@ void Module::discover(const OTMLNodePtr& moduleNode)
bool Module::load() bool Module::load()
{ {
try {
for(const std::string& depName : m_dependencies) { for(const std::string& depName : m_dependencies) {
ModulePtr dep = g_modules.getModule(depName); ModulePtr dep = g_modules.getModule(depName);
if(!dep) if(!dep) {
throw std::runtime_error(Fw::mkstr("could not find module dependency '", depName ,"'")); logError("Unable to load module '", m_name, "' because dependency '", depName, "' was not found");
return false;
}
if(!dep->isLoaded() && !dep->load()) if(!dep->isLoaded() && !dep->load()) {
throw std::runtime_error(Fw::mkstr("dependency '", depName, "' has failed to load")); logError("Unable to load module '", m_name, "' because dependency '", depName, "' has failed to laod");
return false;
}
} }
if(m_loadCallback) { if(m_loadCallback) {
m_loaded = m_loadCallback(); m_loaded = m_loadCallback();
if(!m_loaded) if(!m_loaded) {
throw std::runtime_error("module onLoad event returned false"); logError("Unable to load module '", m_name, "' because its onLoad event returned false");
return false;
}
} }
logInfo("Loaded module '", m_name, "'"); logInfo("Loaded module '", m_name, "'");
return true; return true;
} catch(std::exception& e) {
logError("failed to load module '", m_name, "': ", e.what());
return false;
}
} }
void Module::unload() void Module::unload()

View File

@ -36,14 +36,14 @@ public:
bool load(); bool load();
void unload(); void unload();
bool isLoaded() const { return m_loaded; } bool isLoaded() { return m_loaded; }
std::string getDescription() const { return m_description; } std::string getDescription() { return m_description; }
std::string getName() const { return m_name; } std::string getName() { return m_name; }
std::string getAuthor() const { return m_author; } std::string getAuthor() { return m_author; }
std::string getWebsite() const { return m_website; } std::string getWebsite() { return m_website; }
std::string getVersion() const { return m_version; } std::string getVersion() { return m_version; }
bool autoLoad() const { return m_autoLoad; } bool autoLoad() { return m_autoLoad; }
private: private:
bool m_loaded; bool m_loaded;

View File

@ -56,13 +56,13 @@ bool ModuleManager::discoverModule(const std::string& file)
std::string name = moduleNode->valueAt("name"); std::string name = moduleNode->valueAt("name");
if(getModule(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 = ModulePtr(new Module(name));
module->discover(moduleNode); module->discover(moduleNode);
m_modules.push_back(module); m_modules.push_back(module);
} catch(std::exception& e) { } catch(Exception& e) {
logError("failed to load module from '", file, "': ", e.what()); logError("Unable to discover module from file '", file, "': ", e.what());
return false; return false;
} }
return true; return true;

View File

@ -107,7 +107,7 @@ void ResourceManager::loadFile(const std::string& fileName, std::iostream& out)
PHYSFS_file* file = PHYSFS_openRead(fullPath.c_str()); PHYSFS_file* file = PHYSFS_openRead(fullPath.c_str());
if(!file) { if(!file) {
out.clear(std::ios::failbit); 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 { } else {
int fileSize = PHYSFS_fileLength(file); int fileSize = PHYSFS_fileLength(file);
if(fileSize > 0) { if(fileSize > 0) {

View File

@ -30,6 +30,7 @@
#include <cassert> #include <cassert>
#include <ctime> #include <ctime>
#include <cmath> #include <cmath>
#include <unistd.h>
// common STL headers // common STL headers
#include <iostream> #include <iostream>
@ -53,6 +54,7 @@
#include <iomanip> #include <iomanip>
#include <unordered_map> #include <unordered_map>
#include <random> #include <random>
#include <chrono>
// boost utilities // boost utilities
#include <boost/algorithm/string.hpp> #include <boost/algorithm/string.hpp>

View File

@ -79,8 +79,6 @@ BorderImagePtr BorderImage::loadFromOTML(const OTMLNodePtr& borderImageNode)
// load texture // load texture
std::string source = borderImageNode->at("source")->value(); std::string source = borderImageNode->at("source")->value();
TexturePtr texture = g_textures.getTexture(source); TexturePtr texture = g_textures.getTexture(source);
if(!texture)
throw OTMLException(borderImageNode, "could not load border-image texture");
// load basic border confs // load basic border confs
size = texture->getSize(); size = texture->getSize();

View File

@ -37,8 +37,6 @@ void Font::load(const OTMLNodePtr& fontNode)
// load font texture // load font texture
m_texture = g_textures.getTexture(textureName); 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")) { if(OTMLNodePtr node = fontNode->get("fixed-glyph-width")) {
for(int glyph = m_firstGlyph; glyph < 256; ++glyph) for(int glyph = m_firstGlyph; glyph < 256; ++glyph)

View File

@ -44,7 +44,7 @@ bool FontManager::importFont(std::string fontFile)
std::string name = fontNode->valueAt("name"); std::string name = fontNode->valueAt("name");
if(fontExists(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)); FontPtr font(new Font(name));
font->load(fontNode); font->load(fontNode);
@ -55,8 +55,8 @@ bool FontManager::importFont(std::string fontFile)
m_defaultFont = font; m_defaultFont = font;
return true; return true;
} catch(std::exception& e) { } catch(Exception& e) {
logError("could not load font from '", fontFile, "': ", e.what()); logError("Unable to load font from file '", fontFile, "': ", e.what());
return false; return false;
} }
} }

View File

@ -43,8 +43,6 @@ void Image::loadFromOTML(const OTMLNodePtr& imageNode)
// load texture // load texture
m_texture = g_textures.getTexture(source); 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())); m_textureCoords = imageNode->valueAt("coords", Rect(Point(0,0),m_texture->getSize()));
// enable texture bilinear filter // enable texture bilinear filter

View File

@ -46,14 +46,14 @@ TexturePtr TextureManager::getTexture(const std::string& textureFile)
try { try {
// currently only png textures are supported // currently only png textures are supported
if(!boost::ends_with(textureFile, ".png")) 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 // load texture file data
std::stringstream fin; std::stringstream fin;
g_resources.loadFile(textureFile, fin); g_resources.loadFile(textureFile, fin);
texture = loadPNG(fin); texture = loadPNG(fin);
} catch(std::exception& e) { } catch(Exception& e) {
logError("unable to load texture '",textureFile,"': ", e.what()); Fw::throwException("unable to load texture '", textureFile, "': ", e.what());
} }
} }

View File

@ -25,7 +25,7 @@
#include <framework/ui/ui.h> #include <framework/ui/ui.h>
#include <framework/net/protocol.h> #include <framework/net/protocol.h>
#include <framework/core/eventdispatcher.h> #include <framework/core/eventdispatcher.h>
#include <framework/core/configs.h> #include <framework/core/configmanager.h>
#include <framework/platform/platform.h> #include <framework/platform/platform.h>
#include <framework/otml/otml.h> #include <framework/otml/otml.h>
#include <framework/graphics/graphics.h> #include <framework/graphics/graphics.h>
@ -152,10 +152,10 @@ void LuaInterface::registerFunctions()
g_lua.registerClass<Protocol>(); g_lua.registerClass<Protocol>();
// ConfigManager // ConfigManager
g_lua.registerClass<Configs>(); g_lua.registerClass<ConfigManager>();
g_lua.bindClassStaticFunction<Configs>("set", std::bind(&Configs::set, &g_configs, _1, _2)); g_lua.bindClassStaticFunction<ConfigManager>("set", std::bind(&ConfigManager::set, &g_configs, _1, _2));
g_lua.bindClassStaticFunction<Configs>("get", std::bind(&Configs::get, &g_configs, _1)); g_lua.bindClassStaticFunction<ConfigManager>("get", std::bind(&ConfigManager::get, &g_configs, _1));
g_lua.bindClassStaticFunction<Configs>("exists", std::bind(&Configs::exists, &g_configs, _1)); g_lua.bindClassStaticFunction<ConfigManager>("exists", std::bind(&ConfigManager::exists, &g_configs, _1));
// Logger // Logger
g_lua.registerClass<Logger>(); g_lua.registerClass<Logger>();

View File

@ -545,7 +545,7 @@ void LuaInterface::createLuaState()
// creates lua state // creates lua state
L = luaL_newstate(); L = luaL_newstate();
if(!L) if(!L)
throw std::runtime_error("failed to create lua state"); logFatal("Unable to create lua state");
// load lua standard libraries // load lua standard libraries
luaL_openlibs(L); luaL_openlibs(L);

View File

@ -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++," throw LuaException("attempt to call an expired lua function from C++,"
"did you forget to hold a reference for that function?", 0); "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()); 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++," throw LuaException("attempt to call an expired lua function from C++,"
"did you forget to hold a reference for that function?", 0); "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()); logError("lua function callback failed: ", e.what());
} }
return Ret(); return Ret();

View File

@ -35,7 +35,7 @@ void InputMessage::reset()
uint8 InputMessage::getU8(bool peek) uint8 InputMessage::getU8(bool peek)
{ {
assert(canRead(1)); checkRead(1);
uint8 v = m_buffer[m_readPos]; uint8 v = m_buffer[m_readPos];
if(!peek) if(!peek)
@ -46,7 +46,7 @@ uint8 InputMessage::getU8(bool peek)
uint16 InputMessage::getU16(bool peek) uint16 InputMessage::getU16(bool peek)
{ {
assert(canRead(2)); checkRead(2);
uint16 v = *(uint16_t*)(m_buffer + m_readPos); uint16 v = *(uint16_t*)(m_buffer + m_readPos);
if(!peek) if(!peek)
@ -57,7 +57,7 @@ uint16 InputMessage::getU16(bool peek)
uint32 InputMessage::getU32(bool peek) uint32 InputMessage::getU32(bool peek)
{ {
assert(canRead(4)); checkRead(4);
uint32 v = *(uint32*)(m_buffer + m_readPos); uint32 v = *(uint32*)(m_buffer + m_readPos);
if(!peek) if(!peek)
@ -68,7 +68,7 @@ uint32 InputMessage::getU32(bool peek)
uint64 InputMessage::getU64(bool peek) uint64 InputMessage::getU64(bool peek)
{ {
assert(canRead(8)); checkRead(8);
uint64 v = *(uint64*)(m_buffer + m_readPos); uint64 v = *(uint64*)(m_buffer + m_readPos);
if(!peek) if(!peek)
@ -80,7 +80,7 @@ uint64 InputMessage::getU64(bool peek)
std::string InputMessage::getString() std::string InputMessage::getString()
{ {
uint16 stringLength = getU16(); uint16 stringLength = getU16();
assert(canRead(stringLength)); checkRead(stringLength);
char* v = (char*)(m_buffer + m_readPos); char* v = (char*)(m_buffer + m_readPos);
m_readPos += stringLength; m_readPos += stringLength;
return std::string(v, stringLength); return std::string(v, stringLength);
@ -92,3 +92,10 @@ bool InputMessage::canRead(int bytes)
return false; return false;
return true; return true;
} }
void InputMessage::checkRead(int bytes)
{
if(!canRead(bytes))
throw NetworkException("InputMessage eof reached");
}

View File

@ -24,6 +24,7 @@
#define INPUTMESSAGE_H #define INPUTMESSAGE_H
#include "declarations.h" #include "declarations.h"
#include "networkexception.h"
class InputMessage class InputMessage
{ {
@ -56,6 +57,7 @@ public:
private: private:
bool canRead(int bytes); bool canRead(int bytes);
void checkRead(int bytes);
uint16 m_readPos; uint16 m_readPos;
uint16 m_messageSize; uint16 m_messageSize;

View File

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

View File

@ -35,7 +35,7 @@ void OutputMessage::reset()
void OutputMessage::addU8(uint8 value) void OutputMessage::addU8(uint8 value)
{ {
assert(canWrite(1)); checkWrite(1);
m_buffer[m_writePos] = value; m_buffer[m_writePos] = value;
m_writePos += 1; m_writePos += 1;
m_messageSize += 1; m_messageSize += 1;
@ -43,7 +43,7 @@ void OutputMessage::addU8(uint8 value)
void OutputMessage::addU16(uint16 value) void OutputMessage::addU16(uint16 value)
{ {
assert(canWrite(2)); checkWrite(2);
*(uint16_t*)(m_buffer + m_writePos) = value; *(uint16_t*)(m_buffer + m_writePos) = value;
m_writePos += 2; m_writePos += 2;
m_messageSize += 2; m_messageSize += 2;
@ -51,7 +51,7 @@ void OutputMessage::addU16(uint16 value)
void OutputMessage::addU32(uint32 value) void OutputMessage::addU32(uint32 value)
{ {
assert(canWrite(4)); checkWrite(4);
*(uint32*)(m_buffer + m_writePos) = value; *(uint32*)(m_buffer + m_writePos) = value;
m_writePos += 4; m_writePos += 4;
m_messageSize += 4; m_messageSize += 4;
@ -59,7 +59,7 @@ void OutputMessage::addU32(uint32 value)
void OutputMessage::addU64(uint64 value) void OutputMessage::addU64(uint64 value)
{ {
assert(canWrite(8)); checkWrite(8);
*(uint64*)(m_buffer + m_writePos) = value; *(uint64*)(m_buffer + m_writePos) = value;
m_writePos += 8; m_writePos += 8;
m_messageSize += 8; m_messageSize += 8;
@ -68,7 +68,9 @@ void OutputMessage::addU64(uint64 value)
void OutputMessage::addString(const char* value) void OutputMessage::addString(const char* value)
{ {
size_t stringLength = strlen(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); addU16(stringLength);
strcpy((char*)(m_buffer + m_writePos), value); strcpy((char*)(m_buffer + m_writePos), value);
m_writePos += stringLength; m_writePos += stringLength;
@ -82,7 +84,9 @@ void OutputMessage::addString(const std::string &value)
void OutputMessage::addPaddingBytes(int bytes, uint8 byte) 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); memset((void*)&m_buffer[m_writePos], byte, bytes);
m_writePos += bytes; m_writePos += bytes;
m_messageSize += bytes; m_messageSize += bytes;
@ -94,3 +98,9 @@ bool OutputMessage::canWrite(int bytes)
return false; return false;
return true; return true;
} }
void OutputMessage::checkWrite(int bytes)
{
if(!canWrite(bytes))
throw NetworkException("OutputMessage max buffer size reached");
}

View File

@ -24,6 +24,7 @@
#define OUTPUTMESSAGE_H #define OUTPUTMESSAGE_H
#include "declarations.h" #include "declarations.h"
#include "networkexception.h"
class OutputMessage class OutputMessage
{ {
@ -56,6 +57,7 @@ public:
private: private:
bool canWrite(int bytes); bool canWrite(int bytes);
void checkWrite(int bytes);
uint16 m_writePos; uint16 m_writePos;
uint16 m_messageSize; uint16 m_messageSize;

View File

@ -107,14 +107,15 @@ void Protocol::internalRecvData(uint8* buffer, uint16 size)
if(m_checksumEnabled) { if(m_checksumEnabled) {
uint32 checksum = getAdlerChecksum(m_inputMessage.getBuffer() + InputMessage::DATA_POS, m_inputMessage.getMessageSize() - InputMessage::CHECKSUM_LENGTH); uint32 checksum = getAdlerChecksum(m_inputMessage.getBuffer() + InputMessage::DATA_POS, m_inputMessage.getMessageSize() - InputMessage::CHECKSUM_LENGTH);
if(m_inputMessage.getU32() != checksum) { if(m_inputMessage.getU32() != checksum) {
// error logTraceError("got a network message with invalid checksum");
logError("got a network message with invalid checksum");
return; return;
} }
} }
if(m_xteaEncryptionEnabled) if(m_xteaEncryptionEnabled) {
xteaDecrypt(m_inputMessage); if(!xteaDecrypt(m_inputMessage))
return;
}
onRecv(m_inputMessage); onRecv(m_inputMessage);
} }
@ -133,7 +134,7 @@ bool Protocol::xteaDecrypt(InputMessage& inputMessage)
{ {
uint16 messageSize = inputMessage.getMessageSize() - InputMessage::CHECKSUM_LENGTH; uint16 messageSize = inputMessage.getMessageSize() - InputMessage::CHECKSUM_LENGTH;
if(messageSize % 8 != 0) { if(messageSize % 8 != 0) {
logError("invalid encrypted network message"); logTraceError("invalid encrypted network message");
return false; return false;
} }
@ -156,7 +157,7 @@ bool Protocol::xteaDecrypt(InputMessage& inputMessage)
int tmp = inputMessage.getU16(); int tmp = inputMessage.getU16();
if(tmp > inputMessage.getMessageSize() - 4) { if(tmp > inputMessage.getMessageSize() - 4) {
logError("invalid decrypted a network message"); logTraceError("invalid decrypted a network message");
return false; return false;
} }

View File

@ -65,9 +65,11 @@ void Rsa::setKey(const char* p, const char* q, const char* d)
mpz_clear(pm1); mpz_clear(pm1);
mpz_clear(qm1); 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_t plain, c;
mpz_init2(plain, 1024); mpz_init2(plain, 1024);
@ -92,11 +94,13 @@ bool Rsa::encrypt(char* msg, int32_t size, const char* key)
mpz_clear(plain); mpz_clear(plain);
mpz_clear(e); mpz_clear(e);
mpz_clear(mod); mpz_clear(mod);
return true;
} }
bool Rsa::decrypt(char* msg, int32_t size) bool Rsa::decrypt(char* msg, int32_t size)
{ {
if(!m_keySet)
return false;
mpz_t c,v1,v2,u2,tmp; mpz_t c,v1,v2,u2,tmp;
mpz_init2(c, 1024); mpz_init2(c, 1024);
mpz_init2(v1, 1024); mpz_init2(v1, 1024);
@ -130,6 +134,5 @@ bool Rsa::decrypt(char* msg, int32_t size)
mpz_clear(v2); mpz_clear(v2);
mpz_clear(u2); mpz_clear(u2);
mpz_clear(tmp); mpz_clear(tmp);
return true; return true;
} }

View File

@ -34,7 +34,7 @@ public:
void setKey(const char* p, const char* q, const char* d); void setKey(const char* p, const char* q, const char* d);
bool decrypt(char* msg, int32_t size); 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: protected:
bool m_keySet; bool m_keySet;

View File

@ -36,11 +36,6 @@ public:
/// Poll platform input/window events /// Poll platform input/window events
void poll(); void poll();
void updateTicks();
/// Get current time in milliseconds since last application init
int getTicks() { return m_lastTicks; }
/// Sleep in current thread /// Sleep in current thread
void sleep(ulong ms); void sleep(ulong ms);
@ -84,9 +79,6 @@ public:
std::string getAppUserDir(); std::string getAppUserDir();
void displayFatalError(const std::string& message); void displayFatalError(const std::string& message);
private:
int m_lastTicks;
}; };
extern Platform g_platform; extern Platform g_platform;

View File

@ -370,9 +370,6 @@ void Platform::init(PlatformListener* platformListener, const char *appName)
x11.atomWindowState = XInternAtom(x11.display, "_NET_WM_STATE", False); x11.atomWindowState = XInternAtom(x11.display, "_NET_WM_STATE", False);
x11.atomWindowMaximizedVert = XInternAtom(x11.display, "_NET_WM_STATE_MAXIMIZED_VERT", False); x11.atomWindowMaximizedVert = XInternAtom(x11.display, "_NET_WM_STATE_MAXIMIZED_VERT", False);
x11.atomWindowMaximizedHorz = XInternAtom(x11.display, "_NET_WM_STATE_MAXIMIZED_HORZ", False); x11.atomWindowMaximizedHorz = XInternAtom(x11.display, "_NET_WM_STATE_MAXIMIZED_HORZ", False);
// force first tick
updateTicks();
} }
void Platform::terminate() 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) bool Platform::createWindow(int x, int y, int width, int height, int minWidth, int minHeight, bool maximized)
{ {
static int attrList[] = { static int attrList[] = {
@ -729,11 +706,11 @@ void Platform::setWindowIcon(const std::string& pngIcon)
Atom property = XInternAtom(x11.display, "_NET_WM_ICON", 0); 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())) 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); free_apng(&apng);
} else } else
logError("could not load app icon"); logError("Couldn't load app icon");
} }
void Platform::destroyWindow() void Platform::destroyWindow()
@ -835,7 +812,7 @@ const char *Platform::getClipboardText()
XFlush(x11.display); XFlush(x11.display);
// hack to wait SelectioNotify event, otherwise we will get wrong clipboard pastes // hack to wait SelectioNotify event, otherwise we will get wrong clipboard pastes
sleep(100); usleep(100 * 1000);
// check for data // check for data
Atom type; Atom type;

View File

@ -24,7 +24,7 @@
#include "uitranslator.h" #include "uitranslator.h"
#include <framework/graphics/font.h> #include <framework/graphics/font.h>
#include <framework/otml/otmlnode.h> #include <framework/otml/otmlnode.h>
#include <framework/platform/platform.h> #include <framework/core/clock.h>
#include <framework/graphics/graphics.h> #include <framework/graphics/graphics.h>
UIFrameCounter::UIFrameCounter() UIFrameCounter::UIFrameCounter()
@ -32,7 +32,7 @@ UIFrameCounter::UIFrameCounter()
m_focusable = false; m_focusable = false;
m_phantom = true; m_phantom = true;
m_align = Fw::AlignLeft; m_align = Fw::AlignLeft;
m_lastFrameTicks = g_platform.getTicks(); m_lastFrameTicks = g_clock.ticks();
m_frameCount = 0; m_frameCount = 0;
} }
@ -40,7 +40,7 @@ void UIFrameCounter::render()
{ {
UIWidget::render(); UIWidget::render();
int now = g_platform.getTicks(); int now = g_clock.ticks();
if(now - m_lastFrameTicks >= 1000) { if(now - m_lastFrameTicks >= 1000) {
m_fpsText = Fw::mkstr("FPS: ", m_frameCount); m_fpsText = Fw::mkstr("FPS: ", m_frameCount);
m_lastFrameTicks = now; m_lastFrameTicks = now;

View File

@ -24,6 +24,7 @@
#include <framework/graphics/font.h> #include <framework/graphics/font.h>
#include <framework/graphics/graphics.h> #include <framework/graphics/graphics.h>
#include <framework/platform/platform.h> #include <framework/platform/platform.h>
#include <framework/core/clock.h>
#include <framework/otml/otmlnode.h> #include <framework/otml/otmlnode.h>
UILineEdit::UILineEdit() UILineEdit::UILineEdit()
@ -55,7 +56,7 @@ void UILineEdit::render()
assert(m_cursorPos <= textLength); assert(m_cursorPos <= textLength);
// draw every 333ms // draw every 333ms
const int delay = 333; const int delay = 333;
int ticks = g_platform.getTicks(); int ticks = g_clock.ticks();
if(ticks - m_cursorTicks <= delay) { if(ticks - m_cursorTicks <= delay) {
Rect cursorRect; Rect cursorRect;
// when cursor is at 0 or is the first visible element // 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() void UILineEdit::blinkCursor()
{ {
m_cursorTicks = g_platform.getTicks(); m_cursorTicks = g_clock.ticks();
} }

View File

@ -110,8 +110,8 @@ bool UIManager::importStyles(const std::string& file)
for(const OTMLNodePtr& styleNode : doc->children()) for(const OTMLNodePtr& styleNode : doc->children())
importStyleFromOTML(styleNode); importStyleFromOTML(styleNode);
return true; return true;
} catch(std::exception& e) { } catch(Exception& e) {
logError("failed to import ui styles from '", file, "':\n", e.what()); logError("Failed to import UI styles from '", file, "': ", e.what());
return false; return false;
} }
} }
@ -153,8 +153,11 @@ OTMLNodePtr UIManager::getStyle(const std::string& styleName)
} }
auto it = m_styles.find(styleName); auto it = m_styles.find(styleName);
if(it == m_styles.end()) if(it == m_styles.end()) {
throw std::runtime_error(Fw::mkstr("style '", styleName, "' is not a defined style")); logError("Unable to retrive style '", styleName, "': not a defined style");
return nullptr;
}
return m_styles[styleName]; return m_styles[styleName];
} }
@ -171,14 +174,14 @@ UIWidgetPtr UIManager::loadUI(const std::string& file, const UIWidgetPtr& parent
importStyleFromOTML(node); importStyleFromOTML(node);
else { else {
if(widget) 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); widget = loadWidgetFromOTML(node, parent);
} }
} }
return widget; return widget;
} catch(std::exception& e) { } catch(Exception& e) {
logError("failed to load ui from '", file, "':\n", e.what()); logError("Failed to load UI from '", file, "': ", e.what());
return nullptr; return nullptr;
} }
} }

View File

@ -142,6 +142,8 @@ void UIWidget::setFocusable(bool focusable)
void UIWidget::setStyle(const std::string& styleName) void UIWidget::setStyle(const std::string& styleName)
{ {
OTMLNodePtr styleNode = g_ui.getStyle(styleName); OTMLNodePtr styleNode = g_ui.getStyle(styleName);
if(!styleNode)
return;
applyStyle(styleNode); applyStyle(styleNode);
m_style = styleNode; m_style = styleNode;
updateStyle(); updateStyle();
@ -331,7 +333,7 @@ UIWidgetPtr UIWidget::backwardsGetWidgetById(const std::string& id)
void UIWidget::focusChild(const UIWidgetPtr& child, Fw::FocusReason reason) void UIWidget::focusChild(const UIWidgetPtr& child, Fw::FocusReason reason)
{ {
if(child && !hasChild(child)) { 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; return;
} }
@ -440,7 +442,7 @@ void UIWidget::removeChild(const UIWidgetPtr& child)
if(focusAnother && !m_focusedChild) if(focusAnother && !m_focusedChild)
focusPreviousChild(Fw::ActiveFocusReason); focusPreviousChild(Fw::ActiveFocusReason);
} else } 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) void UIWidget::focusNextChild(Fw::FocusReason reason)
@ -774,8 +776,8 @@ void UIWidget::applyStyle(const OTMLNodePtr& styleNode)
try { try {
onStyleApply(styleNode); onStyleApply(styleNode);
callLuaField("onStyleApply", styleNode); callLuaField("onStyleApply", styleNode);
} catch(std::exception& e) { } catch(Exception& e) {
logError("failed to apply widget '", m_id, "' style: ", e.what()); logError("Failed to apply style to widget '", m_id, "' style: ", e.what());
} }
} }

View File

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

View File

@ -29,22 +29,11 @@
#include <sstream> #include <sstream>
#include <exception> #include <exception>
#include <cxxabi.h> #include <cxxabi.h>
#include <chrono>
#include <unistd.h>
#include "types.h" #include "types.h"
#include "exception.h"
namespace Fw { 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 // read utilities for istream
inline uint8 getU8(std::istream& in) { inline uint8 getU8(std::istream& in) {
uint8 tmp; uint8 tmp;
@ -197,9 +186,9 @@ inline bool cast(const bool& in, std::string& out) {
} }
// used by safe_cast // used by safe_cast
class BadCast : public std::bad_cast { class CastException : public Exception {
public: public:
virtual ~BadCast() throw() { } virtual ~CastException() throw() { }
template<class T, class R> template<class T, class R>
void setWhat() { void setWhat() {
m_what = mkstr("failed to cast value of type '", demangleType<T>(), 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 safeCast(const T& t) {
R r; R r;
if(!cast(t, r)) { if(!cast(t, r)) {
BadCast e; CastException e;
e.setWhat<T,R>(); e.setWhat<T,R>();
throw e; throw e;
} }
@ -231,7 +220,7 @@ template<typename R, typename T>
R unsafeCast(const T& t, R def = R()) { R unsafeCast(const T& t, R def = R()) {
try { try {
return safeCast<R,T>(t); return safeCast<R,T>(t);
} catch(BadCast& e) { } catch(CastException& e) {
println("CAST ERROR: ", e.what()); println("CAST ERROR: ", e.what());
return def; return def;
} }
@ -268,6 +257,11 @@ inline std::string ip2str(uint32 ip) {
return std::string(host); return std::string(host);
} }
template<typename... T>
void throwException(const T&... args) {
throw Exception(Fw::mkstr(args...));
}
} }
// shortcut for Fw::dump // shortcut for Fw::dump

View File

@ -27,16 +27,16 @@
#include "tile.h" #include "tile.h"
#include "item.h" #include "item.h"
#include <framework/platform/platform.h>
#include <framework/graphics/graphics.h> #include <framework/graphics/graphics.h>
#include <framework/core/eventdispatcher.h> #include <framework/core/eventdispatcher.h>
#include <framework/core/clock.h>
Creature::Creature() : Thing() Creature::Creature() : Thing()
{ {
m_healthPercent = 0; m_healthPercent = 0;
m_showSquareColor = false; m_showSquareColor = false;
m_direction = Otc::South; m_direction = Otc::South;
m_walkTimePerPixel = 1000.0/32.0;
m_walking = false; m_walking = false;
@ -201,7 +201,7 @@ void Creature::walk(const Position& position, bool inverse)
m_walkTimePerPixel = walkTime / 32.0; m_walkTimePerPixel = walkTime / 32.0;
if(!sameWalk) if(!sameWalk)
m_walkStartTicks = g_platform.getTicks(); m_walkStartTicks = g_clock.ticks();
updateWalk(); updateWalk();
} }
} }
@ -210,7 +210,7 @@ void Creature::updateWalk()
{ {
const ThingType& type = getType(); const ThingType& type = getType();
if(m_walking) { 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); int totalPixelsWalked = std::min((int)round(elapsedTicks / m_walkTimePerPixel), 32);
if(m_inverseWalking) { if(m_inverseWalking) {
@ -240,7 +240,10 @@ void Creature::updateWalk()
} }
int totalWalkTileTicks = (int)m_walkTimePerPixel*32 * 0.5; 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); g_dispatcher.scheduleEvent(std::bind(&Creature::updateWalk, asCreature()), m_walkTimePerPixel);
if(totalPixelsWalked == 32) if(totalPixelsWalked == 32)
@ -250,17 +253,19 @@ void Creature::updateWalk()
void Creature::cancelWalk(Otc::Direction direction) void Creature::cancelWalk(Otc::Direction direction)
{ {
m_walking = false; if(m_walking) {
m_walkStartTicks = 0;
m_walkOffset.x = 0;
m_walkOffset.y = 0;
m_direction = direction;
auto self = asCreature(); auto self = asCreature();
g_dispatcher.scheduleEvent([=]() { g_dispatcher.scheduleEvent([=]() {
if(!self->m_walking) if(!self->m_walking)
self->m_animation = 0; self->m_animation = 0;
}, m_walkTimePerPixel * 2); }, m_walkTimePerPixel * 2);
}
m_walking = false;
m_walkStartTicks = 0;
m_walkOffset.x = 0;
m_walkOffset.y = 0;
m_direction = direction;
} }
void Creature::setName(const std::string& name) void Creature::setName(const std::string& name)

View File

@ -24,7 +24,7 @@
#include "thingstype.h" #include "thingstype.h"
#include "map.h" #include "map.h"
#include "tile.h" #include "tile.h"
#include <framework/platform/platform.h> #include <framework/core/clock.h>
#include <framework/core/eventdispatcher.h> #include <framework/core/eventdispatcher.h>
Effect::Effect() : Thing() Effect::Effect() : Thing()
@ -34,7 +34,7 @@ Effect::Effect() : Thing()
void Effect::draw(const Point& p) 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()) { if(animationPhase < getAnimationPhases()) {
m_animation = animationPhase; m_animation = animationPhase;
@ -44,7 +44,7 @@ void Effect::draw(const Point& p)
void Effect::startAnimation() void Effect::startAnimation()
{ {
m_animationStartTicks = g_platform.getTicks(); m_animationStartTicks = g_clock.ticks();
// schedule removal // schedule removal
auto self = asEffect(); auto self = asEffect();

View File

@ -24,12 +24,12 @@
#include "thingstype.h" #include "thingstype.h"
#include "spritemanager.h" #include "spritemanager.h"
#include "thing.h" #include "thing.h"
#include <framework/platform/platform.h> #include <framework/core/clock.h>
Item::Item() : Thing() Item::Item() : Thing()
{ {
m_data = 0; m_data = 0;
m_lastTicks = g_platform.getTicks(); m_lastTicks = g_clock.ticks();
} }
void Item::draw(const Point& p) void Item::draw(const Point& p)
@ -37,7 +37,7 @@ void Item::draw(const Point& p)
const ThingType& type = getType(); const ThingType& type = getType();
if(type.dimensions[ThingType::AnimationPhases] > 1) 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++) for(int b = 0; b < type.dimensions[ThingType::Layers]; b++)
internalDraw(p, b); internalDraw(p, b);

View File

@ -24,7 +24,7 @@
#include "thingstype.h" #include "thingstype.h"
#include "map.h" #include "map.h"
#include "tile.h" #include "tile.h"
#include <framework/platform/platform.h> #include <framework/core/clock.h>
#include <framework/core/eventdispatcher.h> #include <framework/core/eventdispatcher.h>
Missile::Missile() : Thing() Missile::Missile() : Thing()
@ -34,7 +34,7 @@ Missile::Missile() : Thing()
void Missile::draw(const Point& p) 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); 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.x *= 32;
m_positionDelta.y *= 32; m_positionDelta.y *= 32;
m_startTicks = g_platform.getTicks(); m_startTicks = g_clock.ticks();
// schedule removal // schedule removal
auto self = asMissile(); auto self = asMissile();

View File

@ -40,8 +40,8 @@ bool SpriteManager::load(const std::string& file)
m_spritesCount = Fw::getU16(m_fin); m_spritesCount = Fw::getU16(m_fin);
m_sprites.resize(m_spritesCount); m_sprites.resize(m_spritesCount);
return true; return true;
} catch(std::exception& e) { } catch(Exception& e) {
logError("faile to load sprites from '", file, "': ", e.what()); logError("Failed to load sprites from '", file, "': ", e.what());
return false; return false;
} }
} }

View File

@ -48,8 +48,8 @@ bool ThingsType::load(const std::string& file)
} }
return true; return true;
} catch(std::exception& e) { } catch(Exception& e) {
logError("failed to load dat from '", file, "': ", e.what()); logError("Failed to load dat from '", file, "': ", e.what());
return false; return false;
} }
} }
@ -116,7 +116,14 @@ ThingType& ThingsType::getThingType(uint16 id, Categories category)
if(category == Item) if(category == Item)
id -= 100; 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]; return m_things[category][id];
} }

View File

@ -27,6 +27,13 @@
struct ThingType struct ThingType
{ {
ThingType() {
// fill default values
dimensions.fill(0);
properties.fill(false);
parameters.fill(0);
}
enum Dimensions { enum Dimensions {
Width = 0, Width = 0,
Height, Height,

View File

@ -43,8 +43,6 @@
void OTClient::registerLuaFunctions() void OTClient::registerLuaFunctions()
{ {
using namespace std::placeholders;
g_lua.bindGlobalFunction("exit", std::bind(&OTClient::exit, &g_client)); g_lua.bindGlobalFunction("exit", std::bind(&OTClient::exit, &g_client));
g_lua.bindGlobalFunction("setOnClose", std::bind(&OTClient::setOnClose, &g_client, _1)); g_lua.bindGlobalFunction("setOnClose", std::bind(&OTClient::setOnClose, &g_client, _1));
g_lua.bindGlobalFunction("importDat", std::bind(&ThingsType::load, &g_thingsType, _1)); g_lua.bindGlobalFunction("importDat", std::bind(&ThingsType::load, &g_thingsType, _1));

View File

@ -35,9 +35,9 @@
void ProtocolGame::parseMessage(InputMessage& msg) void ProtocolGame::parseMessage(InputMessage& msg)
{ {
try {
while(!msg.eof()) { while(!msg.eof()) {
uint8 opt = msg.getU8(); uint8 opt = msg.getU8();
//dump << "protocol id:" << (int)opt;
switch(opt) { switch(opt) {
case Otc::GameServerInitGame: case Otc::GameServerInitGame:
@ -251,10 +251,13 @@ void ProtocolGame::parseMessage(InputMessage& msg)
//case Otc::GameServerObjectInfo: //case Otc::GameServerObjectInfo:
//case Otc::GameServerPlayerInventory: //case Otc::GameServerPlayerInventory:
default: default:
logError("UNKNOWN PACKET OPT BYTE: 0x", std::hex, opt); Fw::throwException("unknown opt byte ", opt);
break; break;
} }
} }
} catch(Exception& e) {
logTraceError(e.what());
}
} }
void ProtocolGame::parsePlayerLogin(InputMessage& msg) void ProtocolGame::parsePlayerLogin(InputMessage& msg)
@ -738,7 +741,7 @@ void ProtocolGame::parseCreatureSpeak(InputMessage& msg)
case Otc::SpeakPrivateRed: case Otc::SpeakPrivateRed:
break; break;
default: default:
logTraceDebug("Unknown speak type.", (int)type); logTraceError("unknown speak type ", type);
break; break;
} }
@ -811,7 +814,7 @@ void ProtocolGame::parseCancelWalk(InputMessage& msg)
void ProtocolGame::parseFloorChangeUp(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(); Position pos = g_map.getCentralPosition();
pos.z--; pos.z--;
@ -830,7 +833,7 @@ void ProtocolGame::parseFloorChangeUp(InputMessage& msg)
void ProtocolGame::parseFloorChangeDown(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(); Position pos = g_map.getCentralPosition();
pos.z++; pos.z++;
@ -982,13 +985,13 @@ void ProtocolGame::setTileDescription(InputMessage& msg, Position position)
g_map.cleanTile(position); g_map.cleanTile(position);
int stackPos = 0; int stackPos = 0;
while(1){ while(true) {
uint16 inspectTileId = msg.getU16(true); uint16 inspectTileId = msg.getU16(true);
if(inspectTileId >= 0xFF00) if(inspectTileId >= 0xFF00)
return; return;
else { else {
if(stackPos >= 10) if(stackPos >= 10)
logWarning("Too many things!"); logTraceWarning("too many things");
ThingPtr thing = internalGetThing(msg); ThingPtr thing = internalGetThing(msg);
g_map.addThing(thing, position, 255); g_map.addThing(thing, position, 255);

View File

@ -52,8 +52,7 @@ void ProtocolGame::sendLoginPacket(uint32 timestamp, uint8 unknown)
oMsg.addPaddingBytes(128 - (29 + m_accountName.length() + m_characterName.length() + m_accountPassword.length())); oMsg.addPaddingBytes(128 - (29 + m_accountName.length() + m_characterName.length() + m_accountPassword.length()));
// encrypt with RSA // encrypt with RSA
if(!Rsa::encrypt((char*)oMsg.getBuffer() + 6 + oMsg.getMessageSize() - 128, 128, Otc::OtservPublicRSA)) Rsa::encrypt((char*)oMsg.getBuffer() + 6 + oMsg.getMessageSize() - 128, 128, Otc::OtservPublicRSA);
return;
send(oMsg); send(oMsg);

View File

@ -53,6 +53,7 @@ void ProtocolLogin::onConnect()
void ProtocolLogin::onRecv(InputMessage& inputMessage) void ProtocolLogin::onRecv(InputMessage& inputMessage)
{ {
try {
while(!inputMessage.eof()) { while(!inputMessage.eof()) {
uint8 opt = inputMessage.getU8(); uint8 opt = inputMessage.getU8();
switch(opt) { switch(opt) {
@ -68,8 +69,14 @@ void ProtocolLogin::onRecv(InputMessage& inputMessage)
case Otc::LoginServerCharacterList: case Otc::LoginServerCharacterList:
parseCharacterList(inputMessage); parseCharacterList(inputMessage);
break; break;
default:
Fw::throwException("unknown opt byte ", opt);
break;
} }
} }
} catch(Exception& e) {
logTraceError(e.what());
}
disconnect(); disconnect();
} }
@ -104,14 +111,10 @@ void ProtocolLogin::sendLoginPacket()
// complete the 128 bytes for rsa encryption with zeros // complete the 128 bytes for rsa encryption with zeros
oMsg.addPaddingBytes(128 - (21 + m_accountName.length() + m_accountPassword.length())); oMsg.addPaddingBytes(128 - (21 + m_accountName.length() + m_accountPassword.length()));
Rsa::encrypt((char*)oMsg.getBuffer() + InputMessage::DATA_POS + oMsg.getMessageSize() - 128, 128, Otc::OtservPublicRSA);
if(!Rsa::encrypt((char*)oMsg.getBuffer() + InputMessage::DATA_POS + oMsg.getMessageSize() - 128, 128, Otc::OtservPublicRSA))
return;
send(oMsg); send(oMsg);
enableXteaEncryption(); enableXteaEncryption();
recv(); recv();
} }

View File

@ -23,17 +23,17 @@
#include "otclient.h" #include "otclient.h"
#include <framework/core/modulemanager.h> #include <framework/core/modulemanager.h>
#include <framework/core/configs.h> #include <framework/core/configmanager.h>
#include <framework/core/resourcemanager.h> #include <framework/core/resourcemanager.h>
#include <framework/core/eventdispatcher.h> #include <framework/core/eventdispatcher.h>
#include <framework/core/clock.h>
#include <framework/luascript/luainterface.h> #include <framework/luascript/luainterface.h>
#include <framework/platform/platform.h>
#include <framework/graphics/graphics.h> #include <framework/graphics/graphics.h>
#include <framework/graphics/fontmanager.h> #include <framework/graphics/fontmanager.h>
#include <framework/ui/uimanager.h> #include <framework/ui/uimanager.h>
#include <framework/ui/uiwidget.h> #include <framework/ui/uiwidget.h>
#include <framework/net/connection.h> #include <framework/net/connection.h>
#include <framework/platform/platform.h>
#include <otclient/net/protocolgame.h> #include <otclient/net/protocolgame.h>
#include <otclient/core/game.h> #include <otclient/core/game.h>
#include <otclient/core/map.h> #include <otclient/core/map.h>
@ -79,9 +79,6 @@ void OTClient::init(std::vector<std::string> args)
// initialize graphics // initialize graphics
g_graphics.init(); g_graphics.init();
// initialize event dispatcher
g_dispatcher.init();
// initialize the ui // initialize the ui
g_ui.init(); g_ui.init();
@ -105,7 +102,7 @@ void OTClient::init(std::vector<std::string> args)
void OTClient::run() void OTClient::run()
{ {
int frameTicks = g_platform.getTicks(); int frameTicks = g_clock.ticks();
int lastPollTicks = frameTicks; int lastPollTicks = frameTicks;
int frameCount = 0; int frameCount = 0;
@ -113,7 +110,7 @@ void OTClient::run()
m_running = true; m_running = true;
if(g_ui.getRootWidget()->getChildCount() == 0) { 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; m_stopping = true;
} }
@ -122,8 +119,7 @@ void OTClient::run()
while(!m_stopping) { while(!m_stopping) {
//g_platform.sleep(150); //g_platform.sleep(150);
g_platform.updateTicks(); frameTicks = g_clock.updateTicks();
frameTicks = g_platform.getTicks();
// poll events every POLL_CYCLE_DELAY // poll events every POLL_CYCLE_DELAY
// this delay exists to avoid massive polling thus increasing framerate // this delay exists to avoid massive polling thus increasing framerate
@ -147,7 +143,7 @@ void OTClient::run()
g_platform.swapBuffers(); g_platform.swapBuffers();
} else { } else {
// sleeps until next poll to avoid massive cpu usage // 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 // terminate network
Connection::terminate(); Connection::terminate();
// terminate dispatcher // flush remaining dispatcher events
g_dispatcher.terminate(); g_dispatcher.flush();
// terminate graphics // terminate graphics
g_graphics.terminate(); g_graphics.terminate();
@ -257,7 +253,7 @@ void OTClient::saveConfigurations()
// saves user configuration // saves user configuration
if(!g_configs.save()) 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() void OTClient::onClose()