changeset 7:45b3c770803c

Misc: switch to lower case (part 2)
author David Demelier <markand@malikania.fr>
date Wed, 23 Mar 2016 17:11:39 +0100
parents 13650239e6c2
children e33b246ac2d3
files docs/doxygen/CMakeLists.txt docs/doxygen/Doxyfile.in libclient/CMakeLists.txt libclient/malikania/animation.h libclient/malikania/animator.cpp libclient/malikania/animator.h libclient/malikania/backend/sdl/font-backend.cpp libclient/malikania/backend/sdl/font-backend.h libclient/malikania/backend/sdl/image-backend.cpp libclient/malikania/backend/sdl/image-backend.h libclient/malikania/backend/sdl/window-backend.cpp libclient/malikania/backend/sdl/window-backend.h libclient/malikania/client-resources-loader.cpp libclient/malikania/client-resources-loader.h libclient/malikania/color.cpp libclient/malikania/color.h libclient/malikania/font.cpp libclient/malikania/font.h libclient/malikania/image.cpp libclient/malikania/image.h libclient/malikania/label.cpp libclient/malikania/label.h libclient/malikania/line.h libclient/malikania/point.h libclient/malikania/rectangle.h libclient/malikania/size.h libclient/malikania/sprite.cpp libclient/malikania/sprite.h libclient/malikania/window.cpp libclient/malikania/window.h libcommon/CMakeLists.txt libcommon/malikania/application.cpp libcommon/malikania/application.h libcommon/malikania/backend/sdl/common-sdl.cpp libcommon/malikania/backend/sdl/common-sdl.h libcommon/malikania/common-config.h libcommon/malikania/elapsed-timer.cpp libcommon/malikania/elapsed-timer.h libcommon/malikania/game.h libcommon/malikania/id.h libcommon/malikania/json.cpp libcommon/malikania/json.h libcommon/malikania/resources-loader.cpp libcommon/malikania/resources-loader.h libcommon/malikania/resources-locator.cpp libcommon/malikania/resources-locator.h libcommon/malikania/util.cpp libcommon/malikania/util.h tests/libclient/animation/main.cpp tests/libclient/color/main.cpp tests/libclient/font/main.cpp tests/libclient/image/main.cpp tests/libclient/line/main.cpp tests/libclient/point/main.cpp tests/libclient/rectangle/main.cpp tests/libclient/size/main.cpp tests/libclient/sprite/main.cpp tests/libcommon/elapsed-timer/main.cpp tests/libserver/id/main.cpp
diffstat 59 files changed, 5632 insertions(+), 87 deletions(-) [+]
line wrap: on
line diff
--- a/docs/doxygen/CMakeLists.txt	Wed Mar 23 09:49:51 2016 +0100
+++ b/docs/doxygen/CMakeLists.txt	Wed Mar 23 17:11:39 2016 +0100
@@ -25,7 +25,7 @@
 	set(DOXYGEN_HAVE_DOT YES)
 	set(DOXYGEN_DOT_PATH \"${DOXYGEN_DOT_EXECUTABLE}\")
 else ()
-	set(DOXYGEN_HAVE_DOT NOsc)
+	set(DOXYGEN_HAVE_DOT NO)
 	set(DOXYGEN_DOT_PATH)
 endif ()
 
--- a/docs/doxygen/Doxyfile.in	Wed Mar 23 09:49:51 2016 +0100
+++ b/docs/doxygen/Doxyfile.in	Wed Mar 23 17:11:39 2016 +0100
@@ -163,7 +163,9 @@
 # will be relative from the directory where doxygen is started.
 # This tag requires that the tag FULL_PATH_NAMES is set to YES.
 
-STRIP_FROM_PATH        =
+STRIP_FROM_PATH        = libclient/malikania \
+                         libcommon/malikania \
+                         libserver/malikania
 
 # The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the
 # path mentioned in the documentation of a class, which tells the reader which
@@ -172,7 +174,7 @@
 # specify the list of include paths that are normally passed to the compiler
 # using the -I flag.
 
-STRIP_FROM_INC_PATH    =
+STRIP_FROM_INC_PATH    = @CMAKE_SOURCE_DIR@/libclient
 
 # If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but
 # less readable) file names. This can be useful is your file systems doesn't
@@ -806,7 +808,8 @@
 # Note that relative paths are relative to the directory from which doxygen is
 # run.
 
-EXCLUDE                =
+EXCLUDE                = libclient/malikania/backend \
+                         libcommon/malikania/backend
 
 # The EXCLUDE_SYMLINKS tag can be used to select whether or not files or
 # directories that are symbolic links (a Unix file system feature) are excluded
--- a/libclient/CMakeLists.txt	Wed Mar 23 09:49:51 2016 +0100
+++ b/libclient/CMakeLists.txt	Wed Mar 23 17:11:39 2016 +0100
@@ -18,37 +18,37 @@
 
 set(
 	HEADERS
-	${CMAKE_CURRENT_SOURCE_DIR}/malikania/Animation.h
-	${CMAKE_CURRENT_SOURCE_DIR}/malikania/Animator.h
-	${CMAKE_CURRENT_SOURCE_DIR}/malikania/ClientResourcesLoader.h
-	${CMAKE_CURRENT_SOURCE_DIR}/malikania/Color.h
-	${CMAKE_CURRENT_SOURCE_DIR}/malikania/Font.h
-	${CMAKE_CURRENT_SOURCE_DIR}/malikania/Image.h
-	${CMAKE_CURRENT_SOURCE_DIR}/malikania/Label.h
-	${CMAKE_CURRENT_SOURCE_DIR}/malikania/Line.h
-	${CMAKE_CURRENT_SOURCE_DIR}/malikania/Point.h
-	${CMAKE_CURRENT_SOURCE_DIR}/malikania/Rectangle.h
-	${CMAKE_CURRENT_SOURCE_DIR}/malikania/Size.h
-	${CMAKE_CURRENT_SOURCE_DIR}/malikania/Sprite.h
-	${CMAKE_CURRENT_SOURCE_DIR}/malikania/Window.h
-	${CMAKE_CURRENT_SOURCE_DIR}/malikania/${WITH_BACKEND_DIRECTORY}/FontBackend.h
-	${CMAKE_CURRENT_SOURCE_DIR}/malikania/${WITH_BACKEND_DIRECTORY}/ImageBackend.h
-	${CMAKE_CURRENT_SOURCE_DIR}/malikania/${WITH_BACKEND_DIRECTORY}/WindowBackend.h
+	${CMAKE_CURRENT_SOURCE_DIR}/malikania/animation.h
+	${CMAKE_CURRENT_SOURCE_DIR}/malikania/animator.h
+	${CMAKE_CURRENT_SOURCE_DIR}/malikania/client-resources-loader.h
+	${CMAKE_CURRENT_SOURCE_DIR}/malikania/color.h
+	${CMAKE_CURRENT_SOURCE_DIR}/malikania/font.h
+	${CMAKE_CURRENT_SOURCE_DIR}/malikania/image.h
+	${CMAKE_CURRENT_SOURCE_DIR}/malikania/label.h
+	${CMAKE_CURRENT_SOURCE_DIR}/malikania/line.h
+	${CMAKE_CURRENT_SOURCE_DIR}/malikania/point.h
+	${CMAKE_CURRENT_SOURCE_DIR}/malikania/rectangle.h
+	${CMAKE_CURRENT_SOURCE_DIR}/malikania/size.h
+	${CMAKE_CURRENT_SOURCE_DIR}/malikania/sprite.h
+	${CMAKE_CURRENT_SOURCE_DIR}/malikania/window.h
+	${CMAKE_CURRENT_SOURCE_DIR}/malikania/${WITH_BACKEND_DIRECTORY}/font-backend.h
+	${CMAKE_CURRENT_SOURCE_DIR}/malikania/${WITH_BACKEND_DIRECTORY}/image-backend.h
+	${CMAKE_CURRENT_SOURCE_DIR}/malikania/${WITH_BACKEND_DIRECTORY}/window-backend.h
 )
 
 set(
 	SOURCES
-	${CMAKE_CURRENT_SOURCE_DIR}/malikania/Animator.cpp
-	${CMAKE_CURRENT_SOURCE_DIR}/malikania/ClientResourcesLoader.cpp
-	${CMAKE_CURRENT_SOURCE_DIR}/malikania/Color.cpp
-	${CMAKE_CURRENT_SOURCE_DIR}/malikania/Font.cpp
-	${CMAKE_CURRENT_SOURCE_DIR}/malikania/Image.cpp
-	${CMAKE_CURRENT_SOURCE_DIR}/malikania/Label.cpp
-	${CMAKE_CURRENT_SOURCE_DIR}/malikania/Sprite.cpp
-	${CMAKE_CURRENT_SOURCE_DIR}/malikania/Window.cpp
-	${CMAKE_CURRENT_SOURCE_DIR}/malikania/${WITH_BACKEND_DIRECTORY}/FontBackend.cpp
-	${CMAKE_CURRENT_SOURCE_DIR}/malikania/${WITH_BACKEND_DIRECTORY}/ImageBackend.cpp
-	${CMAKE_CURRENT_SOURCE_DIR}/malikania/${WITH_BACKEND_DIRECTORY}/WindowBackend.cpp
+	${CMAKE_CURRENT_SOURCE_DIR}/malikania/animator.cpp
+	${CMAKE_CURRENT_SOURCE_DIR}/malikania/client-resources-loader.cpp
+	${CMAKE_CURRENT_SOURCE_DIR}/malikania/color.cpp
+	${CMAKE_CURRENT_SOURCE_DIR}/malikania/font.cpp
+	${CMAKE_CURRENT_SOURCE_DIR}/malikania/image.cpp
+	${CMAKE_CURRENT_SOURCE_DIR}/malikania/label.cpp
+	${CMAKE_CURRENT_SOURCE_DIR}/malikania/sprite.cpp
+	${CMAKE_CURRENT_SOURCE_DIR}/malikania/window.cpp
+	${CMAKE_CURRENT_SOURCE_DIR}/malikania/${WITH_BACKEND_DIRECTORY}/font-backend.cpp
+	${CMAKE_CURRENT_SOURCE_DIR}/malikania/${WITH_BACKEND_DIRECTORY}/image-backend.cpp
+	${CMAKE_CURRENT_SOURCE_DIR}/malikania/${WITH_BACKEND_DIRECTORY}/window-backend.cpp
 )
 
 find_package(SDL2 REQUIRED)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libclient/malikania/animation.h	Wed Mar 23 17:11:39 2016 +0100
@@ -0,0 +1,154 @@
+/*
+ * animation.h -- animation description
+ *
+ * Copyright (c) 2013-2016 Malikania Authors
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef MALIKANIA_ANIMATION_H
+#define MALIKANIA_ANIMATION_H
+
+/**
+ * @file animation.h
+ * @brief Describe an animation.
+ */
+
+#include <cassert>
+#include <cstdint>
+#include <memory>
+#include <vector>
+
+#include "sprite.h"
+
+namespace malikania {
+
+class Window;
+
+/**
+ * @class AnimationFrame
+ * @brief Animation frame description.
+ *
+ * A frame is a duration before switching to the next sprite cell. It is currently implemented as a class for future
+ * usage.
+ */
+class AnimationFrame {
+private:
+	std::uint16_t m_delay;
+
+public:
+	/**
+	 * Construct a frame.
+	 *
+	 * @param delay the optional delay
+	 */
+	inline AnimationFrame(std::uint16_t delay = 100) noexcept
+		: m_delay(delay)
+	{
+	}
+
+	/**
+	 * Get the the delay.
+	 *
+	 * @return the delay
+	 */
+	inline std::uint16_t delay() const noexcept
+	{
+		return m_delay;
+	}
+};
+
+/**
+ * @brief List of frames.
+ */
+using AnimationFrames = std::vector<AnimationFrame>;
+
+/**
+ * @class Animation
+ * @brief Animation description.
+ *
+ * An animation is a sprite with a set of frames containing a delay for showing all sprites in a specific amount of
+ * time.
+ *
+ * Because an animation contains an image, a state (time, current cell) it must be constructed with an Animator object
+ * so the user is able to use the same animation on different parts of the screen without having to duplicate
+ * resources.
+ *
+ * @see Animator
+ */
+class Animation {
+private:
+	Sprite m_sprite;
+	AnimationFrames m_frames;
+
+public:
+	/**
+	 * Create an animation.
+	 *
+	 * @param sprite the sprite image
+	 * @param frames the frames to show
+	 */
+	inline Animation(Sprite sprite, AnimationFrames frames) noexcept
+		: m_sprite(std::move(sprite))
+		, m_frames(std::move(frames))
+	{
+	}
+
+	/**
+	 * Get the underlying sprite.
+	 *
+	 * @return the sprite
+	 */
+	inline const Sprite &sprite() const noexcept
+	{
+		return m_sprite;
+	}
+
+	/**
+	 * Overloaded function.
+	 *
+	 * @return the sprite
+	 */
+	inline Sprite &sprite() noexcept
+	{
+		return m_sprite;
+	}
+
+	/**
+	 * Get the frames.
+	 *
+	 * @return the frames
+	 */
+	inline const AnimationFrames &frames() const noexcept
+	{
+		return m_frames;
+	}
+
+	/**
+	 * Access a frame.
+	 *
+	 * @pre index < number of frames
+	 * @param index the index
+	 * @return the frame
+	 */
+	inline const AnimationFrame &operator[](unsigned index) const noexcept
+	{
+		assert(index < m_frames.size());
+
+		return m_frames[index];
+	}
+};
+
+} // !malikania
+
+#endif // !MALIKANIA_ANIMATION_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libclient/malikania/animator.cpp	Wed Mar 23 17:11:39 2016 +0100
@@ -0,0 +1,53 @@
+/*
+ * animator.cpp -- animation drawing object
+ *
+ * Copyright (c) 2013-2016 Malikania Authors
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "animation.h"
+#include "animator.h"
+
+namespace malikania {
+
+Animator::Animator(Animation &animation) noexcept
+	: m_animation(animation)
+{
+}
+
+void Animator::update() noexcept
+{
+	unsigned total = m_animation.sprite().rows() * m_animation.sprite().columns();
+
+	if (m_current >= total) {
+		return;
+	}
+
+	if (m_timer.elapsed() >= m_animation[m_current].delay()) {
+		m_current ++;
+		m_timer.reset();
+	}
+}
+
+void Animator::draw(Window &window, const Point &point)
+{
+	// TODO: assert ?
+	if (m_current >= m_animation.sprite().rows() * m_animation.sprite().columns()) {
+		return;
+	}
+
+	m_animation.sprite().draw(window, m_current, point);
+}
+
+} // !malikania
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libclient/malikania/animator.h	Wed Mar 23 17:11:39 2016 +0100
@@ -0,0 +1,74 @@
+/*
+ * animator.h -- animation drawing object
+ *
+ * Copyright (c) 2013-2016 Malikania Authors
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef MALIKANIA_ANIMATOR_H
+#define MALIKANIA_ANIMATOR_H
+
+/**
+ * @file animator.h
+ * @brief Draw animations.
+ */
+
+#include <malikania/elapsed-timer.h>
+
+namespace malikania {
+
+class Animation;
+class Position;
+class Window;
+
+/**
+ * @class Animator
+ * @brief Object for drawing animations.
+ *
+ * The animator contains an animation and a state.
+ */
+class Animator {
+private:
+	Animation &m_animation;
+	ElapsedTimer m_timer;
+	unsigned m_current{0};
+
+public:
+	/**
+	 * Construct an animator.
+	 *
+	 * @pre animation must not be null
+	 * @param animation the animation
+	 */
+	Animator(Animation &animation) noexcept;
+
+	/**
+	 * Update the animator state.
+	 *
+	 * This function should be called in the main loop to update the cell to draw before calling draw().
+	 */
+	void update() noexcept;
+
+	/**
+	 * Draw the animation.
+	 *
+	 * @param window the window
+	 * @param position the position in the window
+	 */
+	void draw(Window &window, const Point &position);
+};
+
+} // !malikania
+
+#endif // !MALIKANIA_ANIMATOR_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libclient/malikania/backend/sdl/font-backend.cpp	Wed Mar 23 17:11:39 2016 +0100
@@ -0,0 +1,57 @@
+/*
+ * font-backend.cpp -- font object (SDL2 implementation)
+ *
+ * Copyright (c) 2013-2016 Malikania Authors
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <malikania/Size.h>
+#include <malikania/Font.h>
+
+#include <malikania/backend/sdl/common-sdl.h>
+
+#include "font-backend.h"
+
+using namespace std::string_literals;
+
+namespace malikania {
+
+Font::Backend::Backend(std::string data, unsigned size)
+	: m_font(nullptr, nullptr)
+{
+	auto rw = sdl::RWFromBinary(std::move(data));
+
+	if (rw == nullptr) {
+		throw std::runtime_error(SDL_GetError());
+	}
+
+	m_font = Handle(TTF_OpenFontRW(rw, true, size), TTF_CloseFont);
+
+	if (m_font == NULL) {
+		throw std::runtime_error(TTF_GetError());
+	}
+}
+
+Size Font::Backend::clip(const Font &, const std::string &text) const
+{
+	int width, height;
+
+	if (TTF_SizeUTF8(m_font.get(), text.c_str(), &width, &height) != 0) {
+		throw std::runtime_error(SDL_GetError());
+	}
+
+	return Size((unsigned)width, (unsigned)height);
+}
+
+} // !malikania
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libclient/malikania/backend/sdl/font-backend.h	Wed Mar 23 17:11:39 2016 +0100
@@ -0,0 +1,53 @@
+/*
+ * font-backend.h -- font object (SDL2 implementation)
+ *
+ * Copyright (c) 2013-2016 Malikania Authors
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef MALIKANIA_FONT_BACKEND_H
+#define MALIKANIA_FONT_BACKEND_H
+
+#include <memory>
+
+#include <SDL.h>
+#include <SDL_ttf.h>
+
+#include <malikania/font.h>
+
+namespace malikania {
+
+class Font;
+class Size;
+
+class Font::Backend {
+private:
+	using Handle = std::unique_ptr<TTF_Font, void (*)(TTF_Font*)>;
+
+	Handle m_font;
+
+public:
+	Backend(std::string data, unsigned size);
+
+	inline TTF_Font *font() noexcept
+	{
+		return m_font.get();
+	}
+
+	Size clip(const Font &self, const std::string &text) const;
+};
+
+} // !malikania
+
+#endif // !MALIKANIA_FONT_BACKEND_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libclient/malikania/backend/sdl/image-backend.cpp	Wed Mar 23 17:11:39 2016 +0100
@@ -0,0 +1,99 @@
+/*
+ * image-backend.cpp -- image object (SDL2 implementation)
+ *
+ * Copyright (c) 2013-2016 Malikania Authors
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <SDL_image.h>
+
+#include <malikania/backend/sdl/common-sdl.h>
+
+#include "image-backend.h"
+#include "window-backend.h"
+
+using namespace std::string_literals;
+
+namespace malikania {
+
+Image::Backend::Backend(Image &, Window &window, std::string data)
+	: m_texture(nullptr, nullptr)
+{
+	/* Initialize the texture */
+	auto rw = sdl::RWFromBinary(std::move(data));
+
+	if (rw == nullptr) {
+		throw std::runtime_error(SDL_GetError());
+	}
+
+	m_texture = Handle(IMG_LoadTexture_RW(window.backend().renderer(), rw, true), SDL_DestroyTexture);
+
+	if (m_texture == nullptr) {
+		throw std::runtime_error(SDL_GetError());
+	}
+
+	/* Store the size */
+	int width, height;
+
+	if (SDL_QueryTexture(m_texture.get(), nullptr, nullptr, &width, &height) < 0) {
+		throw std::runtime_error(SDL_GetError());
+	}
+
+	m_size = Size((unsigned)width, (unsigned)height);
+}
+
+void Image::Backend::draw(Window &window, const Point &point)
+{
+	SDL_Rect target;
+
+	target.x = (int)point.x();
+	target.y = (int)point.y();
+	target.w = (int)m_size.width();
+	target.h = (int)m_size.height();
+
+	if (SDL_RenderCopy(window.backend().renderer(), m_texture.get(), nullptr, &target) < 0) {
+		throw std::runtime_error(SDL_GetError());
+	}
+}
+
+void Image::Backend::draw(Window &window, const Rectangle &source, const Rectangle &target)
+{
+	SDL_Rect sr, st;
+
+	sr.x = source.x();
+	sr.y = source.y();
+	sr.w = (int)source.width();
+	sr.h = (int)source.height();
+
+	st.x = target.x();
+	st.y = target.y();
+	st.w = (int)target.width();
+	st.h = (int)target.height();
+
+	/* Readjust .w, .h if null */
+	if (source.isNull()) {
+		sr.w = (int)m_size.width();
+		sr.h = (int)m_size.height();
+	}
+	if (target.isNull()) {
+		st.w = (int)m_size.width();
+		st.h = (int)m_size.height();
+	}
+
+	if (SDL_RenderCopy(window.backend().renderer(), m_texture.get(), &sr, &st) < 0) {
+		throw std::runtime_error(SDL_GetError());
+	}
+}
+
+} // !malikania
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libclient/malikania/backend/sdl/image-backend.h	Wed Mar 23 17:11:39 2016 +0100
@@ -0,0 +1,63 @@
+/*
+ * image-backend.h -- image object (SDL2 implementation)
+ *
+ * Copyright (c) 2013-2016 Malikania Authors
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef MALIKANIA_IMAGE_BACKEND_H
+#define MALIKANIA_IMAGE_BACKEND_H
+
+#include <memory>
+
+#include <SDL.h>
+
+#include <malikania/size.h>
+#include <malikania/image.h>
+
+namespace malikania {
+
+class Image;
+class Point;
+class Rectangle;
+class Window;
+
+class Image::Backend {
+private:
+	using Handle = std::unique_ptr<SDL_Texture, void (*)(SDL_Texture *)>;
+
+	Handle m_texture;
+	Size m_size;
+
+public:
+	Backend(Image &self, Window &window, std::string data);
+
+	inline SDL_Texture *texture() noexcept
+	{
+		return m_texture.get();
+	}
+
+	inline const Size &size() const noexcept
+	{
+		return m_size;
+	}
+
+	void draw(Window &window, const Point &position);
+
+	void draw(Window &window, const Rectangle &source, const Rectangle &target);
+};
+
+} // !malikania
+
+#endif // !MALIKANIA_IMAGE_BACKEND_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libclient/malikania/backend/sdl/window-backend.cpp	Wed Mar 23 17:11:39 2016 +0100
@@ -0,0 +1,244 @@
+/*
+ * window-backend.cpp -- window object (SDL2 implementation)
+ *
+ * Copyright (c) 2013-2016 Malikania Authors
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <SDL.h>
+#include <SDL_ttf.h>
+
+#include <stdexcept>
+
+#include "font-backend.h"
+#include "window-backend.h"
+
+namespace malikania {
+
+Window::Backend::Backend(Window &, unsigned width, unsigned height)
+	: m_window(nullptr, nullptr)
+	, m_renderer(nullptr, nullptr)
+{
+	SDL_SetMainReady();
+	SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO);
+
+	m_window = WindowHandle(
+		SDL_CreateWindow("Malikania", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, width, height, SDL_WINDOW_OPENGL),
+		SDL_DestroyWindow
+	);
+
+	if (m_window == nullptr) {
+		throw std::runtime_error(SDL_GetError());
+	}
+
+	// Create renderer
+	m_renderer = RendererHandle(
+		SDL_CreateRenderer(m_window.get(), -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC),
+		SDL_DestroyRenderer
+	);
+
+	if (m_renderer == nullptr) {
+		throw std::runtime_error(SDL_GetError());
+	}
+
+	if (TTF_Init() == -1) {
+		throw std::runtime_error(TTF_GetError());
+	}
+}
+
+void Window::Backend::processEvents(Window &window)
+{
+	SDL_Event event;
+
+	while (SDL_PollEvent(&event)) {
+		switch (event.type) {
+		case SDL_KEYUP:
+			window.onKeyUp(event.key.keysym.sym);
+			break;
+		// TODO continue implemanting all event possible
+		case SDL_KEYDOWN:
+			window.onKeyDown(event.key.keysym.sym);
+			break;
+		case SDL_QUIT:
+			window.close();
+			break;
+		default:
+			break;
+		}
+	}
+}
+
+void Window::Backend::clear()
+{
+	SDL_RenderClear(m_renderer.get());
+}
+
+void Window::Backend::update()
+{
+	// TO AUDIT
+#if 0
+	for (Refresh function : m_refreshList) {
+		function();
+	}
+#endif
+}
+
+void Window::Backend::present()
+{
+	SDL_RenderPresent(m_renderer.get());
+}
+
+Size Window::Backend::resolution()
+{
+	SDL_DisplayMode current;
+	int width = 0;
+	int height = 0;
+	for (int i = 0; i < SDL_GetNumVideoDisplays(); i++) {
+		int error = SDL_GetCurrentDisplayMode(i, &current);
+		if (error == 0) {
+			// Get the last one
+			// TODO test with only one display mode, but we have to test with more than that
+			width = current.w;
+			height = current.h;
+		} else {
+			throw std::runtime_error("Could not get display mode for video display" + std::string(SDL_GetError()));
+		}
+	}
+
+	return Size((unsigned)width, (unsigned)height);
+}
+
+void Window::Backend::setDrawingColor(const Color &color)
+{
+	int error = SDL_SetRenderDrawColor(m_renderer.get(), color.red(), color.green(), color.blue(), color.alpha());
+	if (error != 0) {
+		throw std::runtime_error("Couldn't set drawing color" + std::string(SDL_GetError()));
+	}
+}
+
+void Window::Backend::drawLine(const Line &line)
+{
+	if (SDL_RenderDrawLine(m_renderer.get(), line.x1(), line.y1(), line.x2(), line.y2()) != 0) {
+		throw std::runtime_error(SDL_GetError());
+	}
+}
+
+void Window::Backend::drawLines(const std::vector<Point> &points)
+{
+	std::vector<SDL_Point> sdlPoints(points.size());
+
+	for (unsigned i = 0; i < points.size(); ++i) {
+		sdlPoints[i] = SDL_Point{points[i].x(), points[i].y()};
+	}
+
+	if (SDL_RenderDrawLines(m_renderer.get(), sdlPoints.data(), sdlPoints.size()) != 0) {
+		throw std::runtime_error(SDL_GetError());
+	}
+}
+
+void Window::Backend::drawPoint(const Point &point)
+{
+	if (SDL_RenderDrawPoint(m_renderer.get(), point.x(), point.y()) != 0) {
+		throw std::runtime_error(SDL_GetError());
+	}
+}
+
+void Window::Backend::drawPoints(const std::vector<Point> &points)
+{
+	std::vector<SDL_Point> sdlPoints(points.size());
+
+	for (unsigned i = 0; i < points.size(); ++i) {
+		sdlPoints[i] = SDL_Point{points[i].x(), points[i].y()};
+	}
+
+	if (SDL_RenderDrawPoints(m_renderer.get(), sdlPoints.data(), sdlPoints.size()) != 0) {
+		throw std::runtime_error(SDL_GetError());
+	}
+}
+
+// TODO: not sure to keep this signature (add fillRect probably)
+void Window::Backend::drawRectangle(const Rectangle &rectangle, bool filled, const malikania::Color &fillColor)
+{
+	SDL_Rect rect{rectangle.x(), rectangle.y(), (int)rectangle.width(), (int)rectangle.height()};
+	int error = SDL_RenderDrawRect(m_renderer.get(), &rect);
+	if (error != 0) {
+		throw std::runtime_error(SDL_GetError());
+	}
+	if (filled) {
+		this->setDrawingColor(fillColor);
+		error = SDL_RenderFillRect(m_renderer.get(), &rect);
+		if (error != 0) {
+			throw std::runtime_error(SDL_GetError());
+		}
+	}
+}
+
+// TODO: same as above
+void Window::Backend::drawRectangles(const std::vector<Rectangle> &rectangles, bool filled, std::vector<Color> fillColors)
+{
+	std::vector<SDL_Rect> sdlRects(rectangles.size());
+
+	for (unsigned i = 0; i < rectangles.size(); ++i) {
+		sdlRects[i] = SDL_Rect{rectangles[i].x(), rectangles[i].y(), (int)rectangles[i].width(), (int)rectangles[i].height()};
+	}
+
+	if (SDL_RenderDrawRects(m_renderer.get(), sdlRects.data(), sdlRects.size()) != 0) {
+		throw std::runtime_error(SDL_GetError());
+	}
+
+	if (filled) {
+		if (rectangles.size() != fillColors.size()) {
+			throw std::runtime_error("Couldn't fill rectangles, rectangles size and fillColors size are not the same");
+		}
+
+		int j = 0;
+		for (Color fillColor : fillColors) {
+			this->setDrawingColor(fillColor);
+
+			if (SDL_RenderFillRect(m_renderer.get(), &sdlRects[j++]) != 0) {
+				throw std::runtime_error("Couldn't fill rectangle" + std::string(SDL_GetError()));
+			}
+		}
+	}
+}
+
+// TODO: merge this into only one function and test results.
+void Window::Backend::drawText(const std::string &text, Font &font, const Rectangle &rectangle)
+{
+	SDL_Color color = {0, 0, 0, 255};
+	SDL_Surface* message = TTF_RenderUTF8_Blended(font.backend().font(), text.c_str(), color);
+	SDL_Texture* texture = SDL_CreateTextureFromSurface(m_renderer.get(), message);
+	SDL_Rect rect{rectangle.x(), rectangle.y(), (int)rectangle.width(), (int)rectangle.height()};
+
+	SDL_RenderCopy(m_renderer.get(), texture, nullptr, &rect);
+	SDL_FreeSurface(message);
+}
+
+void Window::Backend::drawText(const std::string &text, Font &font, const Point &point)
+{
+	SDL_Color color = {0, 0, 0, 0};
+	SDL_GetRenderDrawColor(m_renderer.get(), &color.r, &color.g, &color.b, &color.a);
+	SDL_Surface* message = TTF_RenderUTF8_Blended(font.backend().font(), text.c_str(), color);
+	SDL_Texture* textTexture = SDL_CreateTextureFromSurface(m_renderer.get(), message);
+	SDL_Rect rect{point.x(), point.y(), message->w, message->h};
+
+	SDL_RenderCopy(m_renderer.get(), textTexture, nullptr, &rect);
+	SDL_FreeSurface(message);
+}
+
+void Window::Backend::close()
+{
+}
+
+} // !malikania
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libclient/malikania/backend/sdl/window-backend.h	Wed Mar 23 17:11:39 2016 +0100
@@ -0,0 +1,76 @@
+/*
+ * window-backend.h -- window object (SDL2 implementation)
+ *
+ * Copyright (c) 2013-2016 Malikania Authors
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef MALIKANIA_WINDOW_BACKEND_H
+#define MALIKANIA_WINDOW_BACKEND_H
+
+#include <memory>
+#include <vector>
+
+#include <SDL.h>
+
+#include <malikania/color.h>
+#include <malikania/font.h>
+#include <malikania/line.h>
+#include <malikania/point.h>
+#include <malikania/rectangle.h>
+#include <malikania/size.h>
+#include <malikania/window.h>
+
+namespace malikania {
+
+class Window;
+
+class Window::Backend {
+private:
+	using WindowHandle = std::unique_ptr<SDL_Window, void (*)(SDL_Window *)>;
+	using RendererHandle = std::unique_ptr<SDL_Renderer, void (*)(SDL_Renderer *)>;
+
+	WindowHandle m_window;
+	RendererHandle m_renderer;
+
+public:
+	Backend(Window &self, unsigned width, unsigned height);
+
+	void close();
+	void processEvents(Window &window);
+	void clear();
+	void update();
+	void present();
+	Size resolution();
+
+	// Drawing functions
+	void setDrawingColor(const Color &color);
+	void drawLine(const Line &line);
+	void drawLines(const std::vector<Point> &points);
+	void drawPoint(const Point &point);
+	void drawPoints(const std::vector<Point> &points);
+	void drawRectangle(const Rectangle &rectangle, bool filled, const Color &fillColor);
+	void drawRectangles(const std::vector<Rectangle> &rectangles, bool filled, std::vector<Color> fillColors);
+	void drawText(const std::string &text, Font &font, const Rectangle &rectangle);
+	void drawText(const std::string &text, Font &font, const Point &point);
+
+	inline SDL_Renderer *renderer() noexcept
+	{
+		return m_renderer.get();
+	}
+};
+
+} // !malikania
+
+#endif // !MALIKANIA_WINDOW_BACKEND_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libclient/malikania/client-resources-loader.cpp	Wed Mar 23 17:11:39 2016 +0100
@@ -0,0 +1,119 @@
+/*
+ * client-resources-loader.cpp -- load shared resources files for the client
+ *
+ * Copyright (c) 2013-2016 Malikania Authors
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <cassert>
+
+#include "animation.h"
+#include "client-resources-loader.h"
+#include "size.h"
+#include "sprite.h"
+
+namespace malikania {
+
+Size ClientResourcesLoader::requireSize(const std::string &id, const json::Value &object, const std::string &property) const
+{
+	assert(object.isObject());
+
+	auto it = object.find(property);
+
+	if (it == object.end() || !it->isArray()) {
+		throw std::runtime_error(id + ": missing '" + property + "' property (array expected)");
+	}
+	if (it->size() != 2) {
+		throw std::runtime_error(id + ": property '" + property + "' must have two values");
+	}
+	if (!(*it)[0].isInt() || !(*it)[1].isInt()) {
+		throw std::runtime_error(id + ": property '" + property + "' must have to integer values");
+	}
+
+	return Size((*it)[0].toInt(), (*it)[1].toInt());
+}
+
+Size ClientResourcesLoader::getSize(const std::string &, const json::Value &object, const std::string &key) const noexcept
+{
+	assert(object.isObject());
+
+	auto it = object.find(key);
+
+	if (it == object.end() || !it->isArray() || it->size() != 2 || !(*it)[0].isInt() || !(*it)[1].isInt()) {
+		return Size();
+	}
+
+	return Size((*it)[0].toInt(), (*it)[1].toInt());
+}
+
+Image ClientResourcesLoader::loadImage(const std::string &id)
+{
+	return Image(m_window, locator().read(id));
+}
+
+Sprite ClientResourcesLoader::loadSprite(const std::string &id)
+{
+	json::Value value = json::fromString(locator().read(id));
+
+	if (!value.isObject()) {
+		throw std::runtime_error(id + ": not a JSON object");
+	}
+
+	return Sprite(
+		loadImage(requireString(id, value, "image")),
+		requireSize(id, value, "cell"),
+		getSize(id, value, "size"),
+		getSize(id, value, "space"),
+		getSize(id, value, "margin")
+	);
+}
+
+Animation ClientResourcesLoader::loadAnimation(const std::string &id)
+{
+	json::Value value = json::fromString(locator().read(id));
+
+	if (!value.isObject()) {
+		throw std::runtime_error(id + ": not a JSON object");
+	}
+
+	Sprite sprite = loadSprite(requireString(id, value, "sprite"));
+
+	/* Load all frames */
+	json::Value property = value["frames"];
+
+	if (!property.isArray()) {
+		throw std::runtime_error(id + ": missing 'frames' property (array expected)");
+	}
+
+	AnimationFrames frames;
+
+	for (auto it = property.begin(); it != property.end(); ++it) {
+		if (!it->isObject()) {
+			throw std::runtime_error(id + ": frame " + std::to_string(it.index()) + ": not a JSON object");
+		}
+
+		auto delay = it->find("delay");
+
+		if (delay == it->end() || !delay->isInt()) {
+			throw std::runtime_error(id + ": frame " + std::to_string(it.index()) +
+			     ": missing 'delay' property (int expected)");
+		}
+
+		frames.emplace_back(delay->toInt());
+	}
+
+	return Animation(std::move(sprite), std::move(frames));
+}
+
+} // !malikania
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libclient/malikania/client-resources-loader.h	Wed Mar 23 17:11:39 2016 +0100
@@ -0,0 +1,112 @@
+/*
+ * client-resources-loader.h -- load shared resources files for the client
+ *
+ * Copyright (c) 2013-2016 Malikania Authors
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef MALIKANIA_CLIENT_RESOURCES_LOADER_H
+#define MALIKANIA_CLIENT_RESOURCES_LOADER_H
+
+#include <malikania/resources-loader.h>
+
+#include "animation.h"
+#include "image.h"
+#include "size.h"
+#include "sprite.h"
+
+namespace malikania {
+
+class Window;
+
+/**
+ * @class ClientResourcesLoader
+ * @brief Load client resources.
+ */
+class ClientResourcesLoader : public ResourcesLoader {
+private:
+	Window &m_window;
+
+protected:
+	/**
+	 * Require a size object from an object property.
+	 *
+	 * The size is an array of two integers (e.g. [ 1, 2 ]).
+	 *
+	 * @pre object.isObject()
+	 * @param id the resource id
+	 * @param object the object
+	 * @param property the property
+	 * @return the size
+	 * @throw std::runtime_error if the property is not a size
+	 */
+	Size requireSize(const std::string &id, const json::Value &object, const std::string &property) const;
+
+	/**
+	 * Get a size object or a default one if not present or invalid.
+	 *
+	 * @pre object.isObject()
+	 * @param id the resource id
+	 * @param object the object
+	 * @param property the property
+	 * @return the size or default one
+	 */
+	Size getSize(const std::string &id, const json::Value &object, const std::string &property) const noexcept;
+
+public:
+	/**
+	 * Client resources loader constructor.
+	 *
+	 * The window is required because some of the resources require it.
+	 *
+	 * @param window the window
+	 * @param locator the resources locator
+	 */
+	inline ClientResourcesLoader(Window &window, ResourcesLocator &locator)
+		: ResourcesLoader(locator)
+		, m_window(window)
+	{
+	}
+
+	/**
+	 * Load an image.
+	 *
+	 * @param id the resource id
+	 * @return the image
+	 * @throw std::runtime_error on errors
+	 */
+	virtual Image loadImage(const std::string &id);
+
+	/**
+	 * Load a sprite.
+	 *
+	 * @param id the resource id
+	 * @return the sprite
+	 * @throw std::runtime_error on errors
+	 */
+	virtual Sprite loadSprite(const std::string &id);
+
+	/**
+	 * Load an animation.
+	 *
+	 * @param id the resource id
+	 * @return the animation
+	 * @throw std::runtime_error on errors
+	 */
+	virtual Animation loadAnimation(const std::string &id);
+};
+
+} // !malikania
+
+#endif // !MALIKANIA_CLIENT_RESOURCES_LOADER_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libclient/malikania/color.cpp	Wed Mar 23 17:11:39 2016 +0100
@@ -0,0 +1,236 @@
+/*
+ * color.cpp -- color description
+ *
+ * Copyright (c) 2013-2016 Malikania Authors
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <unordered_map>
+#include <cctype>
+
+#include "color.h"
+
+namespace malikania {
+
+namespace {
+
+constexpr unsigned rgb(std::uint8_t r, std::uint8_t g, std::uint8_t b) noexcept
+{
+	return (0xff000000 | (r << 16) | (g << 8) | b);
+}
+
+/*
+ * Convert hexadecimal value to the correct number.
+ */
+std::uint8_t value(char digit)
+{
+	if (std::isdigit(digit)) {
+		return digit - '0';
+	}
+	if ((digit = std::toupper(digit)) < 'A' || digit > 'F') {
+		throw std::invalid_argument("invalid hexadecimal value: " + std::to_string(digit));
+	}
+
+	return digit - 55;
+}
+
+inline std::uint8_t value(char digit1, char digit2)
+{
+	return ((value(digit1) << 4) & 0xf0) | value(digit2);
+}
+
+const std::unordered_map<std::string, std::uint32_t> colors{
+	{ "aliceblue",		rgb(240, 248, 255)	},
+	{ "antiquewhite",	rgb(250, 235, 215)	},
+	{ "aqua",		rgb( 0, 255, 255)	},
+	{ "aquamarine",		rgb(127, 255, 212)	},
+	{ "azure",		rgb(240, 255, 255)	},
+	{ "beige",		rgb(245, 245, 220)	},
+	{ "bisque",		rgb(255, 228, 196)	},
+	{ "black",		rgb( 0, 0, 0)		},
+	{ "blanchedalmond",	rgb(255, 235, 205)	},
+	{ "blue",		rgb( 0, 0, 255)		},
+	{ "blueviolet",		rgb(138, 43, 226)	},
+	{ "brown",		rgb(165, 42, 42)	},
+	{ "burlywood",		rgb(222, 184, 135)	},
+	{ "cadetblue",		rgb( 95, 158, 160)	},
+	{ "chartreuse",		rgb(127, 255, 0)	},
+	{ "chocolate",		rgb(210, 105, 30)	},
+	{ "coral",		rgb(255, 127, 80)	},
+	{ "cornflowerblue",	rgb(100, 149, 237)	},
+	{ "cornsilk",		rgb(255, 248, 220)	},
+	{ "crimson",		rgb(220, 20, 60)	},
+	{ "cyan",		rgb( 0, 255, 255)	},
+	{ "darkblue",		rgb( 0, 0, 139)		},
+	{ "darkcyan",		rgb( 0, 139, 139)	},
+	{ "darkgoldenrod",	rgb(184, 134, 11)	},
+	{ "darkgray",		rgb(169, 169, 169)	},
+	{ "darkgreen",		rgb( 0, 100, 0)		},
+	{ "darkgrey",		rgb(169, 169, 169)	},
+	{ "darkkhaki",		rgb(189, 183, 107)	},
+	{ "darkmagenta",	rgb(139, 0, 139)	},
+	{ "darkolivegreen",	rgb( 85, 107, 47)	},
+	{ "darkorange",		rgb(255, 140, 0)	},
+	{ "darkorchid",		rgb(153, 50, 204)	},
+	{ "darkred",		rgb(139, 0, 0)		},
+	{ "darksalmon",		rgb(233, 150, 122)	},
+	{ "darkseagreen",	rgb(143, 188, 143)	},
+	{ "darkslateblue",	rgb( 72, 61, 139)	},
+	{ "darkslategray",	rgb( 47, 79, 79)	},
+	{ "darkslategrey",	rgb( 47, 79, 79)	},
+	{ "darkturquoise",	rgb( 0, 206, 209)	},
+	{ "darkviolet",		rgb(148, 0, 211)	},
+	{ "deeppink",		rgb(255, 20, 147)	},
+	{ "deepskyblue",	rgb( 0, 191, 255)	},
+	{ "dimgray",		rgb(105, 105, 105)	},
+	{ "dimgrey",		rgb(105, 105, 105)	},
+	{ "dodgerblue",		rgb( 30, 144, 255)	},
+	{ "firebrick",		rgb(178, 34, 34)	},
+	{ "floralwhite",	rgb(255, 250, 240)	},
+	{ "forestgreen",	rgb( 34, 139, 34)	},
+	{ "fuchsia",		rgb(255, 0, 255)	},
+	{ "gainsboro",		rgb(220, 220, 220)	},
+	{ "ghostwhite",		rgb(248, 248, 255)	},
+	{ "gold",		rgb(255, 215, 0)	},
+	{ "goldenrod",		rgb(218, 165, 32)	},
+	{ "gray",		rgb(128, 128, 128)	},
+	{ "green",		rgb( 0, 128, 0)		},
+	{ "greenyellow",	rgb(173, 255, 47)	},
+	{ "grey",		rgb(128, 128, 128)	},
+	{ "honeydew",		rgb(240, 255, 240)	},
+	{ "hotpink",		rgb(255, 105, 180)	},
+	{ "indianred",		rgb(205, 92, 92)	},
+	{ "indigo",		rgb( 75, 0, 130)	},
+	{ "ivory",		rgb(255, 255, 240)	},
+	{ "khaki",		rgb(240, 230, 140)	},
+	{ "lavender",		rgb(230, 230, 250)	},
+	{ "lavenderblush",	rgb(255, 240, 245)	},
+	{ "lawngreen",		rgb(124, 252, 0)	},
+	{ "lemonchiffon",	rgb(255, 250, 205)	},
+	{ "lightblue",		rgb(173, 216, 230)	},
+	{ "lightcoral",		rgb(240, 128, 128)	},
+	{ "lightcyan",		rgb(224, 255, 255)	},
+	{ "lightgoldenrodyellow", rgb(250, 250, 210)	},
+	{ "lightgray",		rgb(211, 211, 211)	},
+	{ "lightgreen",		rgb(144, 238, 144)	},
+	{ "lightgrey",		rgb(211, 211, 211)	},
+	{ "lightpink",		rgb(255, 182, 193)	},
+	{ "lightsalmon",	rgb(255, 160, 122)	},
+	{ "lightseagreen",	rgb( 32, 178, 170)	},
+	{ "lightskyblue",	rgb(135, 206, 250)	},
+	{ "lightslategray",	rgb(119, 136, 153)	},
+	{ "lightslategrey",	rgb(119, 136, 153)	},
+	{ "lightsteelblue",	rgb(176, 196, 222)	},
+	{ "lightyellow",	rgb(255, 255, 224)	},
+	{ "lime",		rgb( 0, 255, 0)		},
+	{ "limegreen",		rgb( 50, 205, 50)	},
+	{ "linen",		rgb(250, 240, 230)	},
+	{ "magenta",		rgb(255, 0, 255)	},
+	{ "maroon",		rgb(128, 0, 0)		},
+	{ "mediumaquamarine",	rgb(102, 205, 170)	},
+	{ "mediumblue",		rgb( 0, 0, 205)		},
+	{ "mediumorchid",	rgb(186, 85, 211)	},
+	{ "mediumpurple",	rgb(147, 112, 219)	},
+	{ "mediumseagreen",	rgb( 60, 179, 113)	},
+	{ "mediumslateblue",	rgb(123, 104, 238)	},
+	{ "mediumspringgreen",	rgb( 0, 250, 154)	},
+	{ "mediumturquoise",	rgb( 72, 209, 204)	},
+	{ "mediumvioletred",	rgb(199, 21, 133)	},
+	{ "midnightblue",	rgb( 25, 25, 112)	},
+	{ "mintcream",		rgb(245, 255, 250)	},
+	{ "mistyrose",		rgb(255, 228, 225)	},
+	{ "moccasin",		rgb(255, 228, 181)	},
+	{ "navajowhite",	rgb(255, 222, 173)	},
+	{ "navy",		rgb( 0, 0, 128)		},
+	{ "oldlace",		rgb(253, 245, 230)	},
+	{ "olive",		rgb(128, 128, 0)	},
+	{ "olivedrab",		rgb(107, 142, 35)	},
+	{ "orange",		rgb(255, 165, 0)	},
+	{ "orangered",		rgb(255, 69, 0)		},
+	{ "orchid",		rgb(218, 112, 214)	},
+	{ "palegoldenrod",	rgb(238, 232, 170)	},
+	{ "palegreen",		rgb(152, 251, 152)	},
+	{ "paleturquoise",	rgb(175, 238, 238)	},
+	{ "palevioletred",	rgb(219, 112, 147)	},
+	{ "papayawhip",		rgb(255, 239, 213)	},
+	{ "peachpuff",		rgb(255, 218, 185)	},
+	{ "peru",		rgb(205, 133, 63)	},
+	{ "pink",		rgb(255, 192, 203)	},
+	{ "plum",		rgb(221, 160, 221)	},
+	{ "powderblue",		rgb(176, 224, 230)	},
+	{ "purple",		rgb(128, 0, 128)	},
+	{ "red",		rgb(255, 0, 0)		},
+	{ "rosybrown",		rgb(188, 143, 143)	},
+	{ "royalblue",		rgb( 65, 105, 225)	},
+	{ "saddlebrown",	rgb(139, 69, 19)	},
+	{ "salmon",		rgb(250, 128, 114)	},
+	{ "sandybrown",		rgb(244, 164, 96)	},
+	{ "seagreen",		rgb( 46, 139, 87)	},
+	{ "seashell",		rgb(255, 245, 238)	},
+	{ "sienna",		rgb(160, 82, 45)	},
+	{ "silver",		rgb(192, 192, 192)	},
+	{ "skyblue",		rgb(135, 206, 235)	},
+	{ "slateblue",		rgb(106, 90, 205)	},
+	{ "slategray",		rgb(112, 128, 144)	},
+	{ "slategrey",		rgb(112, 128, 144)	},
+	{ "snow",		rgb(255, 250, 250)	},
+	{ "springgreen",	rgb( 0, 255, 127)	},
+	{ "steelblue",		rgb( 70, 130, 180)	},
+	{ "tan",		rgb(210, 180, 140)	},
+	{ "teal",		rgb( 0, 128, 128)	},
+	{ "thistle",		rgb(216, 191, 216)	},
+	{ "tomato",		rgb(255, 99, 71)	},
+	{ "transparent",	0			},
+	{ "turquoise",		rgb( 64, 224, 208)	},
+	{ "violet",		rgb(238, 130, 238)	},
+	{ "wheat",		rgb(245, 222, 179)	},
+	{ "white",		rgb(255, 255, 255)	},
+	{ "whitesmoke",		rgb(245, 245, 245)	},
+	{ "yellow",		rgb(255, 255, 0)	},
+	{ "yellowgreen",	rgb(154, 205, 50)	}
+};
+
+} // !namespace
+
+Color::Color(const std::string &name)
+{
+	if (!name.empty()) {
+		/* Parse #rrggbb or #rgb */
+		if (name[0] == '#') {
+			if (name.length() == 7) {
+				m_red   = value(name[1], name[2]);
+				m_green = value(name[3], name[4]);
+				m_blue  = value(name[5], name[6]);
+			} else if (name.length() == 4) {
+				m_red   = value(name[1], name[1]);
+				m_green = value(name[2], name[2]);
+				m_blue  = value(name[3], name[3]);
+			} else {
+				throw std::invalid_argument{"invalid format"};
+			}
+		} else {
+			/* Name lookup */
+			auto it = colors.find(name);
+
+			if (it == colors.end()) {
+				throw std::invalid_argument{name + " is not a valid color"};
+			}
+
+			/* Assign the color to *this */
+			*this = it->second;
+		}
+	}
+}
+
+} // !malikania
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libclient/malikania/color.h	Wed Mar 23 17:11:39 2016 +0100
@@ -0,0 +1,126 @@
+/*
+ * color.h -- color description
+ *
+ * Copyright (c) 2013-2016 Malikania Authors
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef MALIKANIA_COLOR_H
+#define MALIKANIA_COLOR_H
+
+#include <cstdint>
+#include <string>
+
+namespace malikania {
+
+/**
+ * @class Color
+ * @brief Color description
+ */
+class Color {
+private:
+	std::uint8_t m_red{0};
+	std::uint8_t m_green{0};
+	std::uint8_t m_blue{0};
+	std::uint8_t m_alpha{255};
+
+public:
+	/**
+	 * Default color to black.
+	 */
+	inline Color() noexcept = default;
+
+	/**
+	 * Constructor with all fields.
+	 *
+	 * @param red the red value
+	 * @param green the green value
+	 * @param blue the blue value
+	 * @param alpha the alpha value
+	 */
+	inline Color(std::uint8_t red, std::uint8_t green, std::uint8_t blue, std::uint8_t alpha) noexcept
+		: m_red(red)
+		, m_green(green)
+		, m_blue(blue)
+		, m_alpha(alpha)
+	{
+	}
+
+	/**
+	 * Constructor with an hexadecimal value.
+	 *
+	 * @param hex the color
+	 */
+	inline Color(std::uint32_t hex) noexcept
+		: m_red((hex >> 16) & 0xff)
+		, m_green((hex >> 8) & 0xff)
+		, m_blue(hex & 0xff)
+		, m_alpha((hex >> 24) & 0xff)
+	{
+	}
+
+	/**
+	 * Construct a color from #rrggbb or name.
+	 *
+	 * See the SVG this [list](http://www.december.com/html/spec/colorsvg.html) for supported names.
+	 *
+	 * @param name the color name
+	 * @throw std::invalid_argument if the color does not exist or is invalid
+	 */
+	Color(const std::string &name);
+
+	/**
+	 * Get the red value.
+	 *
+	 * @return the value
+	 */
+	inline std::uint8_t red() const noexcept
+	{
+		return m_red;
+	}
+
+	/**
+	 * Get the green value.
+	 *
+	 * @return the value
+	 */
+	inline std::uint8_t green() const noexcept
+	{
+		return m_green;
+	}
+
+	/**
+	 * Get the blue value.
+	 *
+	 * @return the value
+	 */
+	inline std::uint8_t blue() const noexcept
+	{
+		return m_blue;
+	}
+
+	/**
+	 * Get the alpha value.
+	 *
+	 * @return the value
+	 */
+	inline std::uint8_t alpha() const noexcept
+	{
+		return m_alpha;
+	}
+};
+
+} // !malikania
+
+#endif // !MALIKANIA_COLOR_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libclient/malikania/font.cpp	Wed Mar 23 17:11:39 2016 +0100
@@ -0,0 +1,40 @@
+/*
+ * font.cpp -- font object
+ *
+ * Copyright (c) 2013-2016 Malikania Authors
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "font-backend.h"
+
+namespace malikania {
+
+Font::Font(std::string data, unsigned size)
+	: m_backend(std::make_unique<Backend>(std::move(data), size))
+	, m_size(size)
+{
+}
+
+Font::Font(Font &&other) noexcept = default;
+
+Font::~Font() noexcept = default;
+
+Size Font::clip(const std::string &text) const
+{
+	return m_backend->clip(*this, text);
+}
+
+Font &Font::operator=(Font &&other) noexcept = default;
+
+} // !malikania
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libclient/malikania/font.h	Wed Mar 23 17:11:39 2016 +0100
@@ -0,0 +1,115 @@
+/*
+ * font.h -- font object
+ *
+ * Copyright (c) 2013-2016 Malikania Authors
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef MALIKANIA_FONT_H
+#define MALIKANIA_FONT_H
+
+/**
+ * @file Font.h
+ * @brief Fonts.
+ */
+
+#include <memory>
+#include <string>
+
+#include "size.h"
+
+namespace malikania {
+
+/**
+ * @class Font
+ * @brief Font object.
+ */
+class Font {
+private:
+	class Backend;
+
+	std::unique_ptr<Backend> m_backend;
+	unsigned m_size;
+
+public:
+	/**
+	 * Construct a font from binary data.
+	 *
+	 * @param data the raw data
+	 * @param size the size
+	 */
+	Font(std::string data, unsigned size);
+
+	/**
+	 * Default move constructor.
+	 *
+	 * @param other the other font
+	 */
+	Font(Font &&other) noexcept;
+
+	/**
+	 * Default destructor.
+	 */
+	virtual ~Font() noexcept;
+
+	/**
+	 * Get the font size.
+	 *
+	 * @return the font size
+	 */
+	inline unsigned size() const noexcept
+	{
+		return m_size;
+	}
+
+	/**
+	 * Get the underlying backend.
+	 *
+	 * @return the backend
+	 */
+	inline const Backend &backend() const noexcept
+	{
+		return *m_backend;
+	}
+
+	/**
+	 * Overloaded function.
+	 *
+	 * @return the backend
+	 */
+	inline Backend &backend() noexcept
+	{
+		return *m_backend;
+	}
+
+	/**
+	 * Get the clipping size required to draw the given text.
+	 *
+	 * @param text the text to clip
+	 * @return the required size
+	 */
+	Size clip(const std::string &text) const;
+
+	/**
+	 * Default move assignment operator.
+	 *
+	 * @param other the other font
+	 * @return this
+	 */
+	Font &operator=(Font &&other) noexcept;
+};
+
+} // !malikania
+
+#endif // MALIKANIA_FONT_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libclient/malikania/image.cpp	Wed Mar 23 17:11:39 2016 +0100
@@ -0,0 +1,49 @@
+/*
+ * image.cpp -- image object
+ *
+ * Copyright (c) 2013-2016 Malikania Authors
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "image-backend.h"
+
+namespace malikania {
+
+Image::Image(Window &window, std::string data)
+	: m_backend(std::make_unique<Backend>(*this, window, std::move(data)))
+{
+}
+
+Image::Image(Image &&) noexcept = default;
+
+Image::~Image() noexcept = default;
+
+const Size &Image::size() const noexcept
+{
+	return m_backend->size();
+}
+
+void Image::draw(Window &window, const Point &position)
+{
+	m_backend->draw(window, position);
+}
+
+void Image::draw(Window &window, const Rectangle &source, const Rectangle &target)
+{
+	m_backend->draw(window, source, target);
+}
+
+Image &Image::operator=(Image &&) noexcept = default;
+
+} // !malikania
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libclient/malikania/image.h	Wed Mar 23 17:11:39 2016 +0100
@@ -0,0 +1,124 @@
+/*
+ * image.h -- image object
+ *
+ * Copyright (c) 2013-2016 Malikania Authors
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef MALIKANIA_IMAGE_H
+#define MALIKANIA_IMAGE_H
+
+/**
+ * @file image.h
+ * @brief Images.
+ */
+
+#include <memory>
+#include <string>
+
+#include "point.h"
+#include "rectangle.h"
+#include "size.h"
+
+namespace malikania {
+
+class Window;
+
+/**
+ * @class Image
+ * @brief Image object.
+ */
+class Image {
+private:
+	class Backend;
+
+	std::unique_ptr<Backend> m_backend;
+
+public:
+	/**
+	 * Construct an image from the binary data.
+	 *
+	 * @param window the window
+	 * @param data the data
+	 */
+	Image(Window &window, std::string data);
+
+	/**
+	 * Default move constructor.
+	 *
+	 * @param other the other image
+	 */
+	Image(Image &&other) noexcept;
+
+	/**
+	 * Default destructor.
+	 */
+	~Image() noexcept;
+
+	/**
+	 * Overloaded function.
+	 *
+	 * @return the backend
+	 */
+	inline Backend &backend() noexcept
+	{
+		return *m_backend;
+	}
+
+	/**
+	 * Get the underlying backend.
+	 *
+	 * @return the backend
+	 */
+	inline const Backend &backend() const noexcept
+	{
+		return *m_backend;
+	}
+
+	/**
+	 * Get the image size.
+	 *
+	 * @return the size
+	 */
+	const Size &size() const noexcept;
+
+	/**
+	 * Draw the image to the window.
+	 *
+	 * @param window the window
+	 * @param position the position
+	 */
+	void draw(Window &window, const Point &position = {0, 0});
+
+	/**
+	 * Overloaded function.
+	 *
+	 * @param window the window
+	 * @param source the source to clip
+	 * @param target the target destination
+	 */
+	void draw(Window &window, const Rectangle &source, const Rectangle &target);
+
+	/**
+	 * Default move assignment operator.
+	 *
+	 * @param other the other image
+	 * @return this
+	 */
+	Image &operator=(Image &&image) noexcept;
+};
+
+} // !malikania
+
+#endif // !MALIKANIA_IMAGE_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libclient/malikania/label.cpp	Wed Mar 23 17:11:39 2016 +0100
@@ -0,0 +1,42 @@
+/*
+ * label.cpp -- GUI label
+ *
+ * Copyright (c) 2013-2016 Malikania Authors
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "label.h"
+
+namespace malikania {
+
+Label::Label(std::string text, std::shared_ptr<Font> font, Rectangle frame, Color textColor, Color backgroundColor)
+	: m_text(std::move(text))
+	, m_font(std::move(font))
+	, m_frame(std::move(frame))
+	, m_textColor(std::move(textColor))
+	, m_backgroundColor(std::move(backgroundColor))
+{
+}
+
+int Label::fontSize() const noexcept
+{
+	// TODO
+	return 12;
+}
+
+void Label::draw(Window &, const Rectangle &)
+{
+}
+
+}// !malikania
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libclient/malikania/label.h	Wed Mar 23 17:11:39 2016 +0100
@@ -0,0 +1,69 @@
+/*
+ * label.h -- GUI label
+ *
+ * Copyright (c) 2013-2016 Malikania Authors
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef MALIKANIA_LABEL_H
+#define MALIKANIA_LABEL_H
+
+#include "color.h"
+#include "font.h"
+#include "image.h"
+#include "rectangle.h"
+
+namespace malikania {
+
+class Window;
+
+class Label {
+private:
+	std::string m_text;
+	std::shared_ptr<Font> m_font;
+	Rectangle m_frame;
+	Color m_textColor;
+	Color m_backgroundColor;
+
+public:
+	Label(std::string text, std::shared_ptr<Font> font, Rectangle frame, Color textColor = {0, 0, 0, 255}, Color backgroundColor = {255, 255, 255, 0});
+
+	inline const std::string text() const noexcept
+	{
+		return m_text;
+	}
+
+	inline std::string text() noexcept
+	{
+		return m_text;
+	}
+
+	inline const std::shared_ptr<Font> &font() const noexcept
+	{
+		return m_font;
+	}
+
+	inline std::shared_ptr<Font> &font() noexcept
+	{
+		return m_font;
+	}
+
+	int fontSize() const noexcept;
+
+	void draw(Window &window, const Rectangle &rectangle);
+};
+
+}// !malikania
+
+#endif // !MALIKANIA_LABEL_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libclient/malikania/line.h	Wed Mar 23 17:11:39 2016 +0100
@@ -0,0 +1,126 @@
+/*
+ * line.h -- line description
+ *
+ * Copyright (c) 2013-2016 Malikania Authors
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef MALIKANIA_LINE_H
+#define MALIKANIA_LINE_H
+
+/**
+ * @file line.h
+ * @brief Line description.
+ */
+
+namespace malikania {
+
+/**
+ * @class Line
+ * @brief Line description.
+ *
+ * A line has an origin (x, y) and a destination (x, y).
+ */
+class Line {
+private:
+	int m_x1;
+	int m_y1;
+	int m_x2;
+	int m_y2;
+
+public:
+	/**
+	 * Construct a line.
+	 *
+	 * @param x1 the first x
+	 * @param y1 the first y
+	 * @param x2 the second x
+	 * @param y2 the second y
+	 */
+	inline Line(int x1 = 0, int y1 = 0, int x2 = 0, int y2 = 0) noexcept
+		: m_x1(x1)
+		, m_y1(y1)
+		, m_x2(x2)
+		, m_y2(y2)
+	{
+	}
+
+	/**
+	 * Get the first x.
+	 *
+	 * @return the x1
+	 */
+	inline int x1() const noexcept
+	{
+		return m_x1;
+	}
+
+	/**
+	 * Get the first y.
+	 *
+	 * @return the y1
+	 */
+	inline int y1() const noexcept
+	{
+		return m_y1;
+	}
+
+	/**
+	 * Get the second x.
+	 *
+	 * @return the x2
+	 */
+	inline int x2() const noexcept
+	{
+		return m_x2;
+	}
+
+	/**
+	 * Get the second y.
+	 *
+	 * @return the y2
+	 */
+	inline int y2() const noexcept
+	{
+		return m_y2;
+	}
+};
+
+/**
+ * Compare equality.
+ *
+ * @param l1 the first line
+ * @param l2 the second line
+ * @return true if they equal
+ */
+inline bool operator==(const Line &l1, const Line &l2) noexcept
+{
+	return l1.x1() == l2.x1() && l1.x2() == l2.x2() && l1.y1() == l2.y1() && l1.y2() == l2.y2();
+}
+
+/**
+ * Compare equality.
+ *
+ * @param l1 the first line
+ * @param l2 the second line
+ * @return false if they equal
+ */
+inline bool operator!=(const Line &l1, const Line &l2) noexcept
+{
+	return !(l1 == l2);
+}
+
+} // !malikania
+
+#endif // !MALIKANIA_LINE_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libclient/malikania/point.h	Wed Mar 23 17:11:39 2016 +0100
@@ -0,0 +1,98 @@
+/*
+ * point.h -- point description
+ *
+ * Copyright (c) 2013-2016 Malikania Authors
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef MALIKANIA_POINT_H
+#define MALIKANIA_POINT_H
+
+/**
+ * @file point.h
+ * @brief Point description.
+ */
+
+namespace malikania {
+
+/**
+ * @class Point
+ * @brief Point coordinate.
+ */
+class Point {
+private:
+	int m_x;
+	int m_y;
+
+public:
+	/**
+	 * Construct a point.
+	 *
+	 * @param x the x
+	 * @param y the y
+	 */
+	inline Point(int x = 0, int y = 0) noexcept
+		: m_x(x)
+		, m_y(y)
+	{
+	}
+
+	/**
+	 * Get the x position.
+	 *
+	 * @return the x
+	 */
+	inline int x() const noexcept
+	{
+		return m_x;
+	}
+
+	/**
+	 * Get the y position.
+	 *
+	 * @return the y
+	 */
+	inline int y() const noexcept
+	{
+		return m_y;
+	}
+};
+
+/**
+ * Compare equality.
+ *
+ * @param p1 the first point
+ * @param p2 the second point
+ * @return true if they equal
+ */
+inline bool operator==(const Point &p1, const Point &p2) noexcept
+{
+	return p1.x() == p2.x() && p1.y() == p2.y();
+}
+
+/**
+ * Compare equality.
+ *
+ * @param p1 the first point
+ * @param p2 the second point
+ * @return false if they equal
+ */
+inline bool operator!=(const Point &p1, const Point &p2) noexcept
+{
+	return !(p1 == p2);
+}
+
+} // !malikania
+
+#endif // !MALIKANIA_POINT_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libclient/malikania/rectangle.h	Wed Mar 23 17:11:39 2016 +0100
@@ -0,0 +1,138 @@
+/*
+ * rectangle.h -- rectangle description
+ *
+ * Copyright (c) 2013-2016 Malikania Authors
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef MALIKANIA_RECTANGLE_H
+#define MALIKANIA_RECTANGLE_H
+
+/**
+ * @file rectangle.h
+ * @brief Rectangle description.
+ */
+
+namespace malikania {
+
+/**
+ * @class Rectangle
+ * @brief Rectangle description.
+ *
+ * A rectangle has coordinates (x, y) and dimensions (width, height).
+ *
+ * They are commonly used for clipping images into the window.
+ */
+class Rectangle {
+private:
+	int m_x;
+	int m_y;
+	unsigned m_width;
+	unsigned m_height;
+
+public:
+	/**
+	 * Construct a rectangle.
+	 *
+	 * @param x the x position
+	 * @param y the y position
+	 * @param width the width
+	 * @param height the height
+	 */
+	inline Rectangle(int x = 0, int y = 0, unsigned width = 0, unsigned height = 0) noexcept
+		: m_x(x)
+		, m_y(y)
+		, m_width(width)
+		, m_height(height)
+	{
+	}
+
+	/**
+	 * Get the x position.
+	 *
+	 * @return the x position
+	 */
+	inline int x() const noexcept
+	{
+		return m_x;
+	}
+
+	/**
+	 * Get the y position.
+	 *
+	 * @return the y position
+	 */
+	inline int y() const noexcept
+	{
+		return m_y;
+	}
+
+	/**
+	 * Get the rectangle width.
+	 *
+	 * @return the width
+	 */
+	inline unsigned width() const noexcept
+	{
+		return m_width;
+	}
+
+	/**
+	 * Get the rectangle height.
+	 *
+	 * @return the height
+	 */
+	inline unsigned height() const noexcept
+	{
+		return m_height;
+	}
+
+	/**
+	 * Check if the rectangle has null dimensions.
+	 *
+	 * @return true if weight and height are 0
+	 */
+	inline bool isNull() const noexcept
+	{
+		return m_width == 0 && m_height == 0;
+	}
+};
+
+/**
+ * Compare equality.
+ *
+ * @param r1 the first rectangle
+ * @param r2 the second rectangle
+ * @return true if they equal
+ */
+inline bool operator==(const Rectangle &r1, const Rectangle &r2) noexcept
+{
+	return r1.x() == r2.x() && r1.y() == r2.y() && r1.width() == r2.width() && r1.height() == r2.height();
+}
+
+/**
+ * Compare equality.
+ *
+ * @param r1 the first rectangle
+ * @param r2 the second rectangle
+ * @return false if they equal
+ */
+inline bool operator!=(const Rectangle &r1, const Rectangle &r2) noexcept
+{
+	return !(r1 == r2);
+}
+
+} // !malikania
+
+#endif // !MALIKANIA_RECTANGLE_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libclient/malikania/size.h	Wed Mar 23 17:11:39 2016 +0100
@@ -0,0 +1,103 @@
+/*
+ * size.h -- size description
+ *
+ * Copyright (c) 2013-2016 Malikania Authors
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef MALIKANIA_SIZE_H
+#define MALIKANIA_SIZE_H
+
+namespace malikania {
+
+/**
+ * @class Size
+ * @brief Size description.
+ */
+class Size {
+private:
+	unsigned m_width;
+	unsigned m_height;
+
+public:
+	/**
+	 * Constructor.
+	 *
+	 * @param width the size width
+	 * @param height the size height
+	 */
+	inline Size(unsigned width = 0, unsigned height = 0) noexcept
+		: m_width(width)
+		, m_height(height)
+	{
+	}
+
+	/**
+	 * Get the width.
+	 *
+	 * @return the width
+	 */
+	inline unsigned width() const noexcept
+	{
+		return m_width;
+	}
+
+	/**
+	 * Get the height.
+	 *
+	 * @return the height
+	 */
+	inline unsigned height() const noexcept
+	{
+		return m_height;
+	}
+
+	/**
+	 * Check if the size is 0, 0.
+	 *
+	 * @return true if height and width are 0
+	 */
+	inline bool isNull() const noexcept
+	{
+		return m_height == 0 && m_width == 0;
+	}
+};
+
+/**
+ * Compare equality.
+ *
+ * @param s1 the first size
+ * @param s2 the second size
+ * @return true if they equal
+ */
+inline bool operator==(const Size &s1, const Size &s2) noexcept
+{
+	return s1.width() == s2.width() && s1.height() == s2.height();
+}
+
+/**
+ * Compare equality.
+ *
+ * @param s1 the first size
+ * @param s2 the second size
+ * @return false if they equal
+ */
+inline bool operator!=(const Size &s1, const Size &s2) noexcept
+{
+	return !(s1 == s2);
+}
+
+} // !malikania
+
+#endif // !MALIKANIA_SIZE_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libclient/malikania/sprite.cpp	Wed Mar 23 17:11:39 2016 +0100
@@ -0,0 +1,61 @@
+/*
+ * sprite.cpp -- image sprite
+ *
+ * Copyright (c) 2013-2016 Malikania Authors
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "sprite.h"
+
+namespace malikania {
+
+Sprite::Sprite(Image image, Size cell, Size size, Size space, Size margin) noexcept
+	: m_image(std::move(image))
+	, m_cell(std::move(cell))
+	, m_margin(std::move(margin))
+	, m_space(std::move(space))
+	, m_size(std::move(size))
+{
+	assert(m_cell.width() > 0);
+	assert(m_cell.height() > 0);
+
+	/* If size is not specified, take from image */
+	if (m_size.isNull()) {
+		m_size = m_image.size();
+	}
+
+	/* Compute number of cells */
+	m_rows = (m_size.height() - (margin.height() * 2) + m_space.height()) / (m_cell.height() + m_space.height());
+	m_columns = (m_size.width() - (m_margin.width() * 2) + m_space.width()) / (m_cell.width() + m_space.width());
+}
+
+void Sprite::draw(Window &window, unsigned cell, const Point &point)
+{
+	assert(cell < m_rows * m_columns);
+
+	/* Compute index in the grid */
+	unsigned hindex = (cell % m_columns);
+	unsigned vindex = (cell / m_columns);
+
+	/* Compute the pixel boundaries */
+	int x = m_margin.width() + (hindex * m_space.width()) + (hindex * m_cell.width());
+	int y = m_margin.height() + (vindex * m_space.height()) + (vindex * m_cell.height());
+
+	Rectangle source(x, y, m_cell.width(), m_cell.height());
+	Rectangle target(point.x(), point.y(), m_cell.width(), m_cell.height());
+
+	m_image.draw(window, source, target);
+}
+
+} // !malikania
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libclient/malikania/sprite.h	Wed Mar 23 17:11:39 2016 +0100
@@ -0,0 +1,146 @@
+/*
+ * sprite.h -- image sprite
+ *
+ * Copyright (c) 2013-2016 Malikania Authors
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef MALIKANIA_SPRITE_H
+#define MALIKANIA_SPRITE_H
+
+/**
+ * @file sprite.h
+ * @brief Sprite description.
+ */
+
+#include <malikania/json.h>
+
+#include "image.h"
+
+namespace malikania {
+
+class Point;
+class Window;
+
+/**
+ * @class Sprite
+ * @brief A Sprite is an image divided into cells.
+ */
+class Sprite {
+private:
+	Image m_image;
+	Size m_cell;
+	Size m_margin;
+	Size m_space;
+	Size m_size;
+	unsigned m_rows;
+	unsigned m_columns;
+
+public:
+	/**
+	 * Construct a sprite.
+	 *
+	 * @pre cell must not have height or width null
+	 * @param image the image to use
+	 * @param cell size of cell in the image
+	 * @param margin the optional space from borders
+	 * @param space the optional space between cells
+	 * @param size the sprite size (if 0, taken from the image)
+	 */
+	Sprite(Image image, Size cell, Size margin = { 0, 0 }, Size space = { 0, 0 }, Size size = { 0, 0 }) noexcept;
+
+	/**
+	 * Get the underlying image.
+	 *
+	 * @return the image
+	 */
+	inline const Image &image() const noexcept
+	{
+		return m_image;
+	}
+
+	/**
+	 * Overloaded function.
+	 *
+	 * @return the image
+	 */
+	inline Image &image() noexcept
+	{
+		return m_image;
+	}
+
+	/**
+	 * Get the cell size.
+	 *
+	 * @return the cell size
+	 */
+	inline const Size &cell() const noexcept
+	{
+		return m_cell;
+	}
+
+	/**
+	 * Get the margin size.
+	 *
+	 * @return the margin size
+	 */
+	inline const Size &margin() noexcept
+	{
+		return m_margin;
+	}
+
+	/**
+	 * Get the space size.
+	 *
+	 * @return the space size
+	 */
+	inline const Size &space() const noexcept
+	{
+		return m_space;
+	}
+
+	/**
+	 * Get the number of rows in the grid.
+	 *
+	 * @return the number of rows
+	 */
+	inline unsigned rows() const noexcept
+	{
+		return m_rows;
+	}
+
+	/**
+	 * Get the number of columns in the grid.
+	 *
+	 * @return the number of columns
+	 */
+	inline unsigned columns() const noexcept
+	{
+		return m_columns;
+	}
+
+	/**
+	 * Draw the sprite into the window at the specified position.
+	 *
+	 * @pre cell < rows() * columns()
+	 * @param window the window
+	 * @param cell the cell index
+	 * @param position the position in the window
+	 */
+	void draw(Window &window, unsigned cell, const Point &position);
+};
+
+} // !malikania
+
+#endif // !MALIKANIA_SPRITE_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libclient/malikania/window.cpp	Wed Mar 23 17:11:39 2016 +0100
@@ -0,0 +1,115 @@
+#include <stdexcept>
+
+#include "window-backend.h"
+
+namespace malikania {
+
+Window::Window(unsigned width, unsigned height)
+	: m_backend(std::make_unique<Backend>(*this, width, height))
+{
+}
+
+Window::Window(Window &&) noexcept = default;
+
+Window::~Window() noexcept = default;
+
+Size Window::getWindowResolution()
+{
+	return m_backend->resolution();
+}
+
+void Window::processEvent()
+{
+	m_backend->processEvents(*this);
+}
+
+void Window::clear()
+{
+	m_backend->clear();
+}
+
+void Window::update()
+{
+	m_backend->update();
+}
+
+void Window::present()
+{
+	m_backend->present();
+}
+
+void Window::close() noexcept
+{
+	m_isOpen = false;
+	m_backend->close();
+}
+
+void Window::setOnKeyUp(KeyUp function)
+{
+	m_keyUpList.push_back(std::move(function));
+}
+
+void Window::setOnKeyDown(KeyDown function)
+{
+	m_keyDownList.push_back(std::move(function));
+}
+
+void Window::setOnMouseMove(MouseMove function)
+{
+	m_mouseMoveList.push_back(std::move(function));
+}
+
+void Window::setOnRefresh(Refresh function)
+{
+	m_refreshList.push_back(std::move(function));
+}
+
+void Window::setDrawingColor(Color color)
+{
+	m_drawingColor = std::move(color);
+	m_backend->setDrawingColor(color);
+}
+
+void Window::drawLine(const Line &line)
+{
+	m_backend->drawLine(line);
+}
+
+void Window::drawLines(const std::vector<Point> &points)
+{
+	m_backend->drawLines(points);
+}
+
+void Window::drawPoint(const Point &point)
+{
+	m_backend->drawPoint(point);
+}
+
+void Window::drawPoints(const std::vector<Point> &points)
+{
+	m_backend->drawPoints(points);
+}
+
+void Window::drawRectangle(const Rectangle &rectangle, bool filled, Color fillColor)
+{
+	m_backend->drawRectangle(rectangle, filled, fillColor);
+}
+
+void Window::drawRectangles(const std::vector<Rectangle> &rectangles, bool filled, std::vector<Color> fillColors)
+{
+	m_backend->drawRectangles(rectangles, filled, fillColors);
+}
+
+void Window::drawText(const std::string &text, Font &font, const Rectangle &rectangle)
+{
+	m_backend->drawText(text, font, rectangle);
+}
+
+void Window::drawText(const std::string &text, Font &font, const Point &point)
+{
+	m_backend->drawText(text, font, point);
+}
+
+Window &Window::operator=(Window &&) noexcept = default;
+
+} // !malikania
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libclient/malikania/window.h	Wed Mar 23 17:11:39 2016 +0100
@@ -0,0 +1,133 @@
+#ifndef MALIKANIA_WINDOW_H
+#define MALIKANIA_WINDOW_H
+
+#include <functional>
+#include <vector>
+#include <string>
+#include <map>
+#include <memory>
+
+#include "line.h"
+#include "color.h"
+#include "font.h"
+#include "point.h"
+#include "rectangle.h"
+#include "size.h"
+
+namespace malikania {
+
+class Window {
+public:
+	using KeyUp = std::function<void (int)>;
+	using KeyDown = std::function<void (int)>;
+	using MouseMove = std::function<void (int, int)>;
+	using Refresh = std::function<void (void)>;
+	using KeyUpList = std::vector<KeyUp>;
+	using KeyDownList = std::vector<KeyDown>;
+	using MouseMoveList = std::vector<MouseMove>;
+	using RefreshList = std::vector<Refresh>;
+
+private:
+	class Backend;
+
+	std::unique_ptr<Backend> m_backend;
+
+	bool m_isOpen{true};
+	KeyUpList m_keyUpList;
+	KeyDownList m_keyDownList;
+	MouseMoveList m_mouseMoveList;
+	RefreshList m_refreshList;
+	Color m_drawingColor;
+
+	template <typename FuncList, typename... Args>
+	inline void notify(FuncList list, Args&&... args)
+	{
+		for (auto &f : list) {
+			f(std::forward<Args>(args)...);
+		}
+	}
+
+public:
+	Window(unsigned width = 640, unsigned height = 480);
+
+	Window(Window &&) noexcept;
+
+	virtual ~Window() noexcept;
+
+	inline const Backend &backend() const noexcept
+	{
+		return *m_backend;
+	}
+
+	inline Backend &backend() noexcept
+	{
+		return *m_backend;
+	}
+
+	Size getWindowResolution();
+
+	void processEvent();
+
+	void clear();
+
+	void update();
+
+	void present();
+
+	inline bool isOpen() noexcept
+	{
+		return m_isOpen;
+	}
+
+	void close() noexcept;
+
+	void setOnKeyUp(KeyUp function);
+	void setOnKeyDown(KeyDown function);
+	void setOnMouseMove(MouseMove function);
+	void setOnRefresh(Refresh function);
+
+	inline void onKeyUp(int key)
+	{
+		notify(m_keyUpList, key);
+	}
+
+	inline void onKeyDown(int key)
+	{
+		notify(m_keyDownList, key);
+	}
+
+	inline void onMouseMove(int x, int y)
+	{
+		notify(m_mouseMoveList, x, y);
+	}
+
+	inline Color drawingColor()
+	{
+		return m_drawingColor;
+	}
+
+	void setDrawingColor(Color color);
+
+	void drawLine(const Line &line);
+
+	void drawLines(const std::vector<Point> &points);
+
+	void drawPoint(const Point &point);
+
+	void drawPoints(const std::vector<Point> &points);
+
+	void drawRectangle(const Rectangle &rectangle, bool filled = false, Color fillColor = {255, 255, 255, 255});
+
+	void drawRectangles(const std::vector<Rectangle> &rectangles, bool filled = false
+		, std::vector<Color> fillColors = {{255, 255, 255, 255}});
+
+	void drawText(const std::string &text, Font &font, const Rectangle &rectangle);
+
+	void drawText(const std::string &text, Font &font, const Point &point);
+
+	Window &operator=(Window &&other) noexcept;
+};
+
+}// !malikania
+
+#endif // !_MALIKANIA_WINDOW_H_
--- a/libcommon/CMakeLists.txt	Wed Mar 23 09:49:51 2016 +0100
+++ b/libcommon/CMakeLists.txt	Wed Mar 23 17:11:39 2016 +0100
@@ -18,34 +18,32 @@
 
 set(
 	HEADERS
-	${CMAKE_CURRENT_SOURCE_DIR}/malikania/Application.h
-	${CMAKE_CURRENT_SOURCE_DIR}/malikania/Game.h
-	${CMAKE_CURRENT_SOURCE_DIR}/malikania/ElapsedTimer.h
-	${CMAKE_CURRENT_SOURCE_DIR}/malikania/Game.h
-	${CMAKE_CURRENT_SOURCE_DIR}/malikania/Id.h
-	${CMAKE_CURRENT_SOURCE_DIR}/malikania/Js.h
-	${CMAKE_CURRENT_SOURCE_DIR}/malikania/Json.h
-	${CMAKE_CURRENT_SOURCE_DIR}/malikania/ResourcesLoader.h
-	${CMAKE_CURRENT_SOURCE_DIR}/malikania/ResourcesLocator.h
-	${CMAKE_CURRENT_SOURCE_DIR}/malikania/Util.h
+	${CMAKE_CURRENT_SOURCE_DIR}/malikania/application.h
+	${CMAKE_CURRENT_SOURCE_DIR}/malikania/game.h
+	${CMAKE_CURRENT_SOURCE_DIR}/malikania/elapsed-timer.h
+	${CMAKE_CURRENT_SOURCE_DIR}/malikania/game.h
+	${CMAKE_CURRENT_SOURCE_DIR}/malikania/id.h
+	${CMAKE_CURRENT_SOURCE_DIR}/malikania/json.h
+	${CMAKE_CURRENT_SOURCE_DIR}/malikania/resources-loader.h
+	${CMAKE_CURRENT_SOURCE_DIR}/malikania/resources-locator.h
+	${CMAKE_CURRENT_SOURCE_DIR}/malikania/util.h
 )
 
 set(
 	SOURCES
-	${CMAKE_CURRENT_SOURCE_DIR}/malikania/Application.cpp
-	${CMAKE_CURRENT_SOURCE_DIR}/malikania/ElapsedTimer.cpp
-	${CMAKE_CURRENT_SOURCE_DIR}/malikania/Js.cpp
-	${CMAKE_CURRENT_SOURCE_DIR}/malikania/Json.cpp
-	${CMAKE_CURRENT_SOURCE_DIR}/malikania/ResourcesLoader.cpp
-	${CMAKE_CURRENT_SOURCE_DIR}/malikania/ResourcesLocator.cpp
-	${CMAKE_CURRENT_SOURCE_DIR}/malikania/Util.cpp
+	${CMAKE_CURRENT_SOURCE_DIR}/malikania/application.cpp
+	${CMAKE_CURRENT_SOURCE_DIR}/malikania/elapsed-timer.cpp
+	${CMAKE_CURRENT_SOURCE_DIR}/malikania/json.cpp
+	${CMAKE_CURRENT_SOURCE_DIR}/malikania/resources-loader.cpp
+	${CMAKE_CURRENT_SOURCE_DIR}/malikania/resources-locator.cpp
+	${CMAKE_CURRENT_SOURCE_DIR}/malikania/util.cpp
 )
 
 if (WITH_BACKEND_SDL)
 	find_package(SDL2 REQUIRED)
 
-	list(APPEND HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/malikania/backend/sdl/CommonSdl.h)
-	list(APPEND SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/malikania/backend/sdl/CommonSdl.cpp)
+	list(APPEND HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/malikania/backend/sdl/common-sdl.h)
+	list(APPEND SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/malikania/backend/sdl/common-sdl.cpp)
 	list(APPEND INCLUDES ${SDL2_INCLUDE_DIRS})
 	list(APPEND LIBRARIES ${SDL2_LIBRARIES})
 endif ()
@@ -59,18 +57,8 @@
 	TARGET libcommon
 	SOURCES ${HEADERS} ${SOURCES}
 	FLAGS "MALIKANIA_COMMON_BUILD"
-	PUBLIC_INCLUDES
-		${CMAKE_CURRENT_SOURCE_DIR}
-		${Jansson_INCLUDE_DIRS}
-		${ZIP_INCLUDE_DIRS}
-		${OPENSSL_INCLUDE_DIR}
-		${INCLUDES}
-	LIBRARIES
-		extern-jansson
-		${LIBRARIES}
-		${Jansson_LIBRARIES}
-		${ZIP_LIBRARIES}
-		${OPENSSL_LIBRARIES}
+	PUBLIC_INCLUDES ${CMAKE_CURRENT_SOURCE_DIR} ${INCLUDES}
+	LIBRARIES extern-jansson ${LIBRARIES}
 )
 
 set_target_properties(libcommon PROPERTIES PREFIX "")
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libcommon/malikania/application.cpp	Wed Mar 23 17:11:39 2016 +0100
@@ -0,0 +1,28 @@
+/*
+ * application.cpp -- main application class
+ *
+ * Copyright (c) 2013-2016 Malikania Authors
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "application.h"
+
+namespace malikania {
+
+Application::Application(int, char **)
+{
+	// TODO: find the executable path
+}
+
+} // !malikania
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libcommon/malikania/application.h	Wed Mar 23 17:11:39 2016 +0100
@@ -0,0 +1,51 @@
+/*
+ * application.h -- main application class
+ *
+ * Copyright (c) 2013-2016 Malikania Authors
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef MALIKANIA_APPLICATION_H
+#define MALIKANIA_APPLICATION_H
+
+/**
+ * @file application.h
+ * @brief Main class for the client or server
+ */
+
+namespace malikania {
+
+/**
+ * @class Application
+ * @brief Main class for argument parsing and executable path retrievement
+ */
+class Application {
+public:
+	/**
+	 * Construct the application.
+	 *
+	 * @param argc the argument count
+	 * @param argv the arguments
+	 */
+	Application(int argc, char **argv);
+
+	/**
+	 * Virtual destructor defaulted.
+	 */
+	virtual ~Application() = default;
+};
+
+} // !malikania
+
+#endif // !MALIKANIA_APPLICATION_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libcommon/malikania/backend/sdl/common-sdl.cpp	Wed Mar 23 17:11:39 2016 +0100
@@ -0,0 +1,153 @@
+/*
+ * CommonSdl.cpp -- common SDL2 related code
+ *
+ * Copyright (c) 2013-2016 Malikania Authors
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <cerrno>
+#include <cstdint>
+#include <cstring>
+#include <new>
+
+#include "common-sdl.h"
+
+namespace malikania {
+
+namespace sdl {
+
+namespace {
+
+/*
+ * RWFromBinary implementation
+ * ------------------------------------------------------------------
+ *
+ * A little bit inspired by official SDL_RWFromMem implementation, largely modified to match our conventions and the
+ * C++ code.
+ */
+
+class Buffer {
+public:
+	std::string m_data;
+	std::uint64_t m_position;
+	std::uint64_t m_length;
+
+	inline Buffer(std::string data) noexcept
+		: m_data(std::move(data))
+		, m_position(0U)
+		, m_length(m_data.length())
+	{
+	}
+};
+
+Sint64 size(SDL_RWops *ops)
+{
+	return reinterpret_cast<Buffer *>(ops->hidden.unknown.data1)->m_length;
+}
+
+Sint64 seek(SDL_RWops *ops, Sint64 offset, int whence)
+{
+	Buffer *data = reinterpret_cast<Buffer *>(ops->hidden.unknown.data1);
+	Sint64 position = data->m_position;
+
+	switch (whence) {
+	case RW_SEEK_SET:
+		position = offset;
+		break;
+	case RW_SEEK_CUR:
+		position = data->m_position + offset;
+		break;
+	case RW_SEEK_END:
+		position = data->m_length + offset;
+		break;
+	default:
+		break;
+	}
+
+	if (position < 0)
+		position = 0;
+	else if ((std::uint64_t)position > data->m_length)
+		position = data->m_length;
+
+	return (data->m_position = position);
+}
+
+size_t read(SDL_RWops *ops, void *dst, size_t size, size_t number)
+{
+	Buffer *data = reinterpret_cast<Buffer *>(ops->hidden.unknown.data1);
+	size_t total = number * size;
+	size_t avail = data->m_length - data->m_position;
+
+	if (number <= 0 || size <= 0 || ((total / number) != (size_t)size)) {
+		return 0;
+	}
+	if (total > avail) {
+		total = avail;
+	}
+
+	SDL_memcpy(dst, &data->m_data[data->m_position], total);
+
+	data->m_position += total;
+
+	return (total / size);
+}
+
+size_t write(SDL_RWops *, const void *, size_t, size_t)
+{
+	SDL_SetError("write not supported");
+
+	return -1;
+}
+
+int close(SDL_RWops *ops)
+{
+	if (ops != nullptr) {
+		delete reinterpret_cast<Buffer *>(ops->hidden.unknown.data1);
+		SDL_FreeRW(ops);
+	}
+
+	return 0;
+}
+
+} // !namespace
+
+SDL_RWops *RWFromBinary(std::string data) noexcept
+{
+	SDL_RWops *ops = SDL_AllocRW();
+
+	if (ops == nullptr) {
+		return nullptr;
+	}
+
+	ops->hidden.unknown.data1 = new (std::nothrow) Buffer(std::move(data));
+
+	if (ops->hidden.unknown.data1 == nullptr) {
+		SDL_SetError("%s", std::strerror(errno));
+		SDL_FreeRW(ops);
+		return nullptr;
+	}
+
+	ops->type = SDL_RWOPS_UNKNOWN;
+	ops->seek = seek;
+	ops->size = size;
+	ops->read = read;
+	ops->write = write;
+	ops->close = close;
+
+	return ops;
+}
+
+} // !sdl
+
+} // !malikania
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libcommon/malikania/backend/sdl/common-sdl.h	Wed Mar 23 17:11:39 2016 +0100
@@ -0,0 +1,49 @@
+/*
+ * CommonSdl.h -- common SDL2 related code
+ *
+ * Copyright (c) 2013-2016 Malikania Authors
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef MALIKANIA_COMMON_SDL_H
+#define MALIKANIA_COMMON_SDL_H
+
+#include <SDL.h>
+
+#include <string>
+
+namespace malikania {
+
+namespace sdl {
+
+/**
+ * Create a SDL_RWops that owns the binary data.
+ *
+ * This is a safe alternative to SDL_RWFromMem because it owns the memory pointed by data until it is closed. The
+ * data is moved so there are no copies.
+ *
+ * The stream has read-only support and can not write.
+ *
+ * Seeking past-the-end or past-the-begin readjust the position to the end or begin respectively.
+ *
+ * @param data the data
+ * @return the object or nullptr on errors
+ */
+SDL_RWops *RWFromBinary(std::string data) noexcept;
+
+} // !sdl
+
+} // !malikania
+
+#endif // !MALIKANIA_COMMON_SDL_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libcommon/malikania/common-config.h	Wed Mar 23 17:11:39 2016 +0100
@@ -0,0 +1,14 @@
+#ifndef COMMON_CONFIG_H
+#define COMMON_CONFIG_H
+
+#if defined(_WIN32)
+#  if defined(MALIKANIA_COMMON_BUILD)
+#    define MALIKANIA_COMMON_EXPORT __declspec(dllexport)
+#  else
+#    define MALIKANIA_COMMON_EXPORT __declspec(dllimport)
+#  endif
+#else
+#  define MALIKANIA_COMMON_EXPORT
+#endif
+
+#endif // !COMMON_CONFIG_H
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libcommon/malikania/elapsed-timer.cpp	Wed Mar 23 17:11:39 2016 +0100
@@ -0,0 +1,64 @@
+/*
+ * elapsed-timer.cpp -- measure elapsed time
+ *
+ * Copyright (c) 2013-2016 Malikania Authors
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "elapsed-timer.h"
+
+using std::chrono::duration_cast;
+using std::chrono::high_resolution_clock;
+using std::chrono::milliseconds;
+
+namespace malikania {
+
+ElapsedTimer::ElapsedTimer() noexcept
+{
+	m_last = high_resolution_clock::now();
+}
+
+void ElapsedTimer::pause() noexcept
+{
+	/*
+	 * When we put the timer on pause, do not forget to set the already
+	 * elapsed time.
+	 */
+	(void)elapsed();
+	m_paused = true;
+}
+
+void ElapsedTimer::restart() noexcept
+{
+	m_paused = false;
+	m_last = high_resolution_clock::now();
+}
+
+void ElapsedTimer::reset() noexcept
+{
+	m_elapsed = 0;
+	m_last = high_resolution_clock::now();
+}
+
+unsigned ElapsedTimer::elapsed() noexcept
+{
+	if (!m_paused) {
+		m_elapsed += duration_cast<milliseconds>(high_resolution_clock::now() - m_last).count();
+		m_last = high_resolution_clock::now();
+	}
+
+	return m_elapsed;
+}
+
+} // !malikania
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libcommon/malikania/elapsed-timer.h	Wed Mar 23 17:11:39 2016 +0100
@@ -0,0 +1,81 @@
+/*
+ * elapsed-timer.h -- measure elapsed time
+ *
+ * Copyright (c) 2013-2016 Malikania Authors
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef MALIKANIA_ELAPSED_TIMER_H
+#define MALIKANIA_ELAPSED_TIMER_H
+
+/**
+ * @file elapsed-timer.h
+ * @brief Measure elapsed time
+ */
+
+#include <chrono>
+
+namespace malikania {
+
+/**
+ * @class ElapsedTimer
+ * @brief Measure elapsed time
+ *
+ * This class provides an abstraction to measure elapsed time since the
+ * construction of the object.
+ *
+ * It uses std::chrono::high_resolution_clock for more precision and uses
+ * milliseconds only.
+ */
+class ElapsedTimer {
+public:
+	using TimePoint = std::chrono::time_point<std::chrono::high_resolution_clock>;
+
+private:
+	TimePoint m_last;
+	bool m_paused{false};
+	unsigned m_elapsed{0};
+
+public:
+	/**
+	 * Construct the elapsed timer, start counting.
+	 */
+	ElapsedTimer() noexcept;
+
+	/**
+	 * Put the timer on pause, the already elapsed time is stored.
+	 */
+	void pause() noexcept;
+
+	/**
+	 * Restart the timer, does not reset it.
+	 */
+	void restart() noexcept;
+
+	/**
+	 * Reset the timer to 0.
+	 */
+	void reset() noexcept;
+
+	/**
+	 * Get the number of elapsed milliseconds.
+	 *
+	 * @return the milliseconds
+	 */
+	unsigned elapsed() noexcept;
+};
+
+} // !malikania
+
+#endif // !MALIKANIA_ELAPSED_TIMER_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libcommon/malikania/game.h	Wed Mar 23 17:11:39 2016 +0100
@@ -0,0 +1,124 @@
+/*
+ * game.h -- basic game class
+ *
+ * Copyright (c) 2013-2016 Malikania Authors
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef MALIKANIA_GAME_H
+#define MALIKANIA_GAME_H
+
+#include <cassert>
+#include <string>
+#include <vector>
+
+namespace malikania {
+
+namespace json {
+
+class Document;
+
+} // !json
+
+/**
+ * @class Game
+ * @brief Basic game class.
+ */
+class Game {
+private:
+	std::string m_name;
+	std::string m_version;
+	std::string m_requires;
+	std::string m_license;
+	std::string m_author;
+
+public:
+	/**
+	 * Construct a game.
+	 *
+	 * @pre name must not be empty
+	 * @pre version must not be empty
+	 * @pre requires must not be empty
+	 * @param name the game name
+	 * @param version the version
+	 * @param requires the engine version required
+	 * @param license the license (Optional)
+	 * @param authors the authors (Optional)
+	 */
+	inline Game(std::string name, std::string version, std::string requires, std::string license, std::string author)
+		: m_name(std::move(name))
+		, m_version(std::move(version))
+		, m_requires(std::move(requires))
+		, m_license(std::move(license))
+		, m_author(std::move(author))
+	{
+		assert(!m_name.empty());
+		assert(!m_version.empty());
+		assert(!m_requires.empty());
+	}
+
+	/**
+	 * Get the game name.
+	 *
+	 * @return the name
+	 */
+	inline const std::string &name() const noexcept
+	{
+		return m_name;
+	}
+
+	/**
+	 * Get the author.
+	 *
+	 * @return the author
+	 */
+	inline const std::string &author() const noexcept
+	{
+		return m_author;
+	}
+
+	/**
+	 * Get the license.
+	 *
+	 * @return the license
+	 */
+	inline const std::string &license() const noexcept
+	{
+		return m_license;
+	}
+
+	/**
+	 * Get the license.
+	 *
+	 * @return the license
+	 */
+	inline const std::string &version() const noexcept
+	{
+		return m_version;
+	}
+
+	/**
+	 * Get the engine version required to run the game.
+	 *
+	 * @return the version required
+	 */
+	inline const std::string &requires() const noexcept
+	{
+		return m_requires;
+	}
+};
+
+} // !malikania
+
+#endif // !MALIKANIA_GAME_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libcommon/malikania/id.h	Wed Mar 23 17:11:39 2016 +0100
@@ -0,0 +1,176 @@
+/*
+ * id.h -- integer id generator
+ *
+ * Copyright (c) 2013-2016 Malikania Authors
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef MALIKANIA_COMMON_ID_H
+#define MALIKANIA_COMMON_ID_H
+
+/**
+ * @file id.h
+ * @brief Integer id generator
+ */
+
+#include <limits>
+#include <queue>
+#include <stdexcept>
+
+namespace malikania {
+
+/**
+ * @class IdGen
+ * @brief Integer id generator
+ *
+ * This class helps generating and release unique integer id that can be used anywhere. The ids are generated in a
+ * sequence and when an id is released it is reused instead of incrementing the next number.
+ *
+ * The template can use any integral integer but unsigned are preferred.
+ *
+ * The maximum number of id is equal to std::numeric_limits<T>::max - 1.
+ */
+template <typename T>
+class IdGen {
+private:
+	static_assert(std::numeric_limits<T>::is_integer, "IdGen requires integral types");
+
+	T m_current{0};
+	std::priority_queue<T> m_reusable;
+
+public:
+	/**
+	 * Get the next id for that player.
+	 *
+	 * @return the id
+	 * @throw std::out_of_range if no number is available
+	 */
+	T next();
+
+	/**
+	 * Release the player id.
+	 *
+	 * @param id the id not needed anymore
+	 */
+	inline void release(T id) noexcept
+	{
+		m_reusable.push(id);
+	}
+
+	/**
+	 * Reset the ids to 0 and remove the queue.
+	 */
+	void reset() noexcept;
+};
+
+template <typename T>
+T IdGen<T>::next()
+{
+	T id;
+
+	if (m_reusable.size() > 0) {
+		id = m_reusable.top();
+		m_reusable.pop();
+	} else {
+		if (m_current == std::numeric_limits<T>::max()) {
+			throw std::out_of_range("no id available");
+		}
+
+		id = m_current++;
+	}
+
+	return id;
+}
+
+template <typename T>
+void IdGen<T>::reset() noexcept
+{
+	m_current = 0;
+
+	while (!m_reusable.empty()) {
+		m_reusable.pop();
+	}
+}
+
+/**
+ * @class Id
+ * @brief RAII based id owner
+ *
+ * This class is similar to a std::lock_guard or std::unique_lock in a way that the id is acquired
+ * when the object is instanciated and released when destroyed.
+ *
+ * This class does not take ownership of the IdGen so it must still exists when the Id is destroyed.
+ */
+template <typename T>
+class Id {
+private:
+	IdGen<T> &m_gen;
+	T m_id;
+
+public:
+	/**
+	 * Construct a new Id and take the next number.
+	 *
+	 * @param gen the generator
+	 * @throw any exception if IdGen fails to give an id.
+	 */
+	inline Id(IdGen<T> &gen)
+		: m_gen(gen)
+		, m_id(m_gen.next())
+	{
+	}
+
+	/**
+	 * Construct an Id with an already taken number.
+	 *
+	 * @param gen the generator
+	 * @param id the id
+	 * @warning be sure that the id was taken from this generator
+	 */
+	Id(IdGen<T> &gen, T id)
+		: m_gen(gen)
+		, m_id(id)
+	{
+	}
+
+	/**
+	 * Destroy the id and release the number.
+	 */
+	~Id() noexcept
+	{
+		m_gen.release(m_id);
+	}
+
+	/**
+	 * Get the number id.
+	 *
+	 * @return the id
+	 */
+	inline T value() const noexcept
+	{
+		return m_id;
+	}
+
+	/**
+	 * Convert the id to the number.
+	 */
+	inline operator T() const noexcept
+	{
+		return m_id;
+	}
+};
+
+} // !malikania
+
+#endif // !MALIKANIA_COMMON_ID_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libcommon/malikania/json.cpp	Wed Mar 23 17:11:39 2016 +0100
@@ -0,0 +1,345 @@
+/*
+ * json.cpp -- C++14 JSON manipulation using jansson parser
+ *
+ * Copyright (c) 2015-2016 David Demelier <markand@malikania.fr>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <jansson.h>
+
+#include <sstream>
+
+#include "json.h"
+
+namespace malikania {
+
+namespace json {
+
+namespace {
+
+void readObject(Value &parent, json_t *object);
+void readArray(Value &parent, json_t *array);
+
+Value readValue(json_t *v)
+{
+	if (json_is_null(v))
+		return Value(nullptr);
+	if (json_is_string(v))
+		return Value(json_string_value(v));
+	if (json_is_real(v))
+		return Value(json_number_value(v));
+	if (json_is_integer(v))
+		return Value(static_cast<int>(json_integer_value(v)));
+	if (json_is_boolean(v))
+		return Value(json_boolean_value(v));
+	if (json_is_object(v)) {
+		Value object(Type::Object);
+
+		readObject(object, v);
+
+		return object;
+	}
+	if (json_is_array(v)) {
+		Value array(Type::Array);
+
+		readArray(array, v);
+
+		return array;
+	}
+
+	return Value();
+}
+
+void readObject(Value &parent, json_t *object)
+{
+	const char *key;
+	json_t *value;
+
+	json_object_foreach(object, key, value)
+		parent.insert(key, readValue(value));
+}
+
+void readArray(Value &parent, json_t *array)
+{
+	size_t index;
+	json_t *value;
+
+	json_array_foreach(array, index, value)
+		parent.append(readValue(value));
+}
+
+template <typename Func, typename... Args>
+Value convert(Func fn, Args&&... args)
+{
+	json_error_t error;
+	json_t *json = fn(std::forward<Args>(args)..., &error);
+
+	if (json == nullptr)
+		throw Error(error.text, error.source, error.line, error.column, error.position);
+
+	Value value;
+
+	if (json_is_object(json)) {
+		value = Value(Type::Object);
+		readObject(value, json);
+	} else {
+		value = Value(Type::Array);
+		readArray(value, json);
+	}
+
+	json_decref(json);
+
+	return value;
+}
+
+std::string indent(int param, int level)
+{
+	std::string str;
+
+	if (param < 0)
+		str = std::string(level, '\t');
+	else if (param > 0)
+		str = std::string(param * level, ' ');
+
+	return str;
+}
+
+} // !namespace
+
+void Value::copy(const Value &other)
+{
+	switch (other.m_type) {
+	case Type::Array:
+		new (&m_array) std::vector<Value>(other.m_array);
+		break;
+	case Type::Boolean:
+		m_boolean = other.m_boolean;
+		break;
+	case Type::Int:
+		m_integer = other.m_integer;
+		break;
+	case Type::Object:
+		new (&m_object) std::map<std::string, Value>(other.m_object);
+		break;
+	case Type::Real:
+		m_number = other.m_number;
+		break;
+	case Type::String:
+		new (&m_string) std::string(other.m_string);
+		break;
+	default:
+		break;
+	}
+
+	m_type = other.m_type;
+}
+
+void Value::move(Value &&other)
+{
+	switch (other.m_type) {
+	case Type::Array:
+		new (&m_array) std::vector<Value>(std::move(other.m_array));
+		break;
+	case Type::Boolean:
+		m_boolean = other.m_boolean;
+		break;
+	case Type::Int:
+		m_integer = other.m_integer;
+		break;
+	case Type::Object:
+		new (&m_object) std::map<std::string, Value>(std::move(other.m_object));
+		break;
+	case Type::Real:
+		m_number = other.m_number;
+		break;
+	case Type::String:
+		new (&m_string) std::string(std::move(other.m_string));
+		break;
+	default:
+		break;
+	}
+
+	m_type = other.m_type;
+}
+
+Value::Value(Type type)
+	: m_type(type)
+{
+	switch (m_type) {
+	case Type::Array:
+		new (&m_array) std::vector<Value>();
+		break;
+	case Type::Boolean:
+		m_boolean = false;
+		break;
+	case Type::Int:
+		m_integer = 0;
+		break;
+	case Type::Object:
+		new (&m_object) std::map<std::string, Value>();
+		break;
+	case Type::Real:
+		m_number = 0;
+		break;
+	case Type::String:
+		new (&m_string) std::string();
+		break;
+	default:
+		break;
+	}
+}
+
+Value::~Value()
+{
+	switch (m_type) {
+	case Type::Array:
+		m_array.~vector<Value>();
+		break;
+	case Type::Object:
+		m_object.~map<std::string, Value>();
+		break;
+	case Type::String:
+		m_string.~basic_string();
+		break;
+	default:
+		break;
+	}
+}
+
+std::string Value::toString(bool coerce) const
+{
+	std::string result;
+
+	if (m_type == Type::String)
+		result = m_string;
+	else if (coerce)
+		result = toJson();
+
+	return result;
+}
+
+std::string Value::toJson(int level, int current) const
+{
+	std::ostringstream oss;
+
+	switch (m_type) {
+	case Type::Array: {
+		oss << '[' << (level != 0 ? "\n" : "");
+
+		unsigned total = m_array.size();
+		unsigned i = 0;
+		for (const auto &v : m_array) {
+			oss << indent(level, current + 1) << v.toJson(level, current + 1);
+			oss << (++i < total ? "," : "");
+			oss << (level != 0 ? "\n" : "");
+		}
+
+		oss << (level != 0 ? indent(level, current) : "") << ']';
+		break;
+	}
+	case Type::Boolean:
+		oss << (m_boolean ? "true" : "false");
+		break;
+	case Type::Int:
+		oss << m_integer;
+		break;
+	case Type::Null:
+		oss << "null";
+		break;
+	case Type::Object: {
+		oss << '{' << (level != 0 ? "\n" : "");
+
+		unsigned total = m_object.size();
+		unsigned i = 0;
+		for (const auto &pair : m_object) {
+			oss << indent(level, current + 1);
+
+			/* Key and : */
+			oss << "\"" << pair.first << "\":" << (level != 0 ? " " : "");
+
+			/* Value */
+			oss << pair.second.toJson(level, current + 1);
+
+			/* Comma, new line if needed */
+			oss << (++i < total ? "," : "") << (level != 0 ? "\n" : "");
+		}
+
+		oss << (level != 0 ? indent(level, current) : "") << '}';
+		break;
+	}
+	case Type::Real:
+		oss << m_number;
+		break;
+	case Type::String:
+		oss << "\"" << escape(m_string) << "\"";
+		break;
+	default:
+		break;
+	}
+
+	return oss.str();
+}
+
+std::string escape(const std::string &value)
+{
+	std::string result;
+
+	for (auto it = value.begin(); it != value.end(); ++it) {
+		switch (*it) {
+		case '\\':
+			result += "\\\\";
+			break;
+		case '/':
+			result += "\\/";
+			break;
+		case '"':
+			result += "\\\"";
+			break;
+		case '\b':
+			result += "\\b";
+			break;
+		case '\f':
+			result += "\\f";
+			break;
+		case '\n':
+			result += "\\n";
+			break;
+		case '\r':
+			result += "\\r";
+			break;
+		case '\t':
+			result += "\\t";
+			break;
+		default:
+			result += *it;
+			break;
+		}
+	}
+
+	return result;
+}
+
+Value fromString(const std::string &buffer)
+{
+	return convert(json_loads, buffer.c_str(), 0);
+}
+
+Value fromFile(const std::string &path)
+{
+	return convert(json_load_file, path.c_str(), 0);
+}
+
+} // !json
+
+} // !malikania
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libcommon/malikania/json.h	Wed Mar 23 17:11:39 2016 +0100
@@ -0,0 +1,1200 @@
+/*
+ * json.h -- C++14 JSON manipulation using jansson parser
+ *
+ * Copyright (c) 2015-2016 David Demelier <markand@malikania.fr>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef MALIKANIA_JSON_H
+#define MALIKANIA_JSON_H
+
+/**
+ * @file json.h
+ * @brief Jansson C++14 wrapper
+ */
+
+#include <cassert>
+#include <exception>
+#include <initializer_list>
+#include <map>
+#include <string>
+#include <utility>
+#include <vector>
+
+namespace malikania {
+
+/**
+ * Json namespace.
+ */
+namespace json {
+
+/**
+ * @enum Type
+ * @brief Type of Value.
+ */
+enum class Type {
+	Array,		//!< Value is an array []
+	Boolean,	//!< Value is boolean
+	Int,		//!< Value is integer
+	Null,		//!< Value is defined to null
+	Object,		//!< Value is object {}
+	Real,		//!< Value is float
+	String		//!< Value is unicode string
+};
+
+/**
+ * @class Error
+ * @brief Error description.
+ */
+class Error : public std::exception {
+private:
+	std::string m_text;
+	std::string m_source;
+	int m_line;
+	int m_column;
+	int m_position;
+
+public:
+	/**
+	 * Create the error.
+	 *
+	 * @param text the text message
+	 * @param source the source (e.g. file name)
+	 * @param line the line number
+	 * @param column the column number
+	 * @param position the position
+	 */
+	inline Error(std::string text, std::string source, int line, int column, int position) noexcept
+		: m_text(std::move(text))
+		, m_source(std::move(source))
+		, m_line(line)
+		, m_column(column)
+		, m_position(position)
+	{
+	}
+
+	/**
+	 * Get the error message.
+	 *
+	 * @return the text
+	 */
+	inline const std::string &text() const noexcept
+	{
+		return m_text;
+	}
+
+	/**
+	 * Get the source (e.g. a file name).
+	 *
+	 * @return the source
+	 */
+	inline const std::string &source() const noexcept
+	{
+		return m_source;
+	}
+
+	/**
+	 * Get the line.
+	 *
+	 * @return the line
+	 */
+	inline int line() const noexcept
+	{
+		return m_line;
+	}
+
+	/**
+	 * Get the column.
+	 *
+	 * @return the column
+	 */
+	inline int column() const noexcept
+	{
+		return m_column;
+	}
+
+	/**
+	 * Get the position.
+	 *
+	 * @return the position
+	 */
+	inline int position() const noexcept
+	{
+		return m_position;
+	}
+
+	/**
+	 * Get the error message.
+	 *
+	 * @return the message
+	 */
+	const char *what() const noexcept override
+	{
+		return m_text.c_str();
+	}
+};
+
+/**
+ * @class Iterator
+ * @brief This is the base class for iterator and const_iterator
+ *
+ * This iterator works for both arrays and objects. Because of that purpose, it is only available
+ * as forward iterator.
+ *
+ * When iterator comes from an object, you can use key() otherwise you can use index().
+ */
+template <typename ValueType, typename ArrayIteratorType, typename ObjectIteratorType>
+class Iterator : public std::iterator<std::forward_iterator_tag, ValueType> {
+private:
+	friend class Value;
+
+	ValueType *m_parent{nullptr};
+	ArrayIteratorType m_ita;
+	ObjectIteratorType m_itm;
+
+	inline void increment()
+	{
+		if (m_parent->isObject())
+			m_itm++;
+		else
+			m_ita++;
+	}
+
+	inline Iterator(ValueType *parent, ObjectIteratorType it)
+		: m_parent(parent)
+		, m_itm(it)
+	{
+		assert(parent);
+	}
+
+	inline Iterator(ValueType *parent, ArrayIteratorType it)
+		: m_parent(parent)
+		, m_ita(it)
+	{
+		assert(parent);
+	}
+
+public:
+	/**
+	 * Default constructor.
+	 */
+	Iterator() = default;
+
+	/**
+	 * Get the iterator key (for objects).
+	 *
+	 * @pre iterator must be dereferenceable
+	 * @pre iterator must come from object
+	 * @return the key
+	 */
+	inline const std::string &key() const noexcept
+	{
+		assert(m_parent && m_parent->isObject());
+		assert(m_itm != m_parent->m_object.end());
+
+		return m_itm->first;
+	}
+
+	/**
+	 * Get the iterator position (for arrays).
+	 *
+	 * @pre iterator must be dereferenceable
+	 * @pre iterator must come from arrays
+	 * @return the index
+	 */
+	inline unsigned index() const noexcept
+	{
+		assert(m_parent && m_parent->isArray());
+		assert(m_ita != m_parent->m_array.end());
+
+		return std::distance(m_parent->m_array.begin(), m_ita);
+	}
+
+	/**
+	 * Dereference the iterator.
+	 *
+	 * @pre iterator be dereferenceable
+	 * @return the value
+	 */
+	inline ValueType &operator*() noexcept
+	{
+		assert(m_parent);
+		assert((m_parent->isArray()  && m_ita != m_parent->m_array.end()) ||
+		       (m_parent->isObject() && m_itm != m_parent->m_object.end()));
+
+		return (m_parent->m_type == Type::Object) ? m_itm->second : *m_ita;
+	}
+
+	/**
+	 * Dereference the iterator as a pointer.
+	 *
+	 * @pre iterator must be dereferenceable
+	 * @return the value
+	 */
+	inline ValueType *operator->() noexcept
+	{
+		assert(m_parent);
+		assert((m_parent->isArray()  && m_ita != m_parent->m_array.end()) ||
+		       (m_parent->isObject() && m_itm != m_parent->m_object.end()));
+
+		return (m_parent->m_type == Type::Object) ? &m_itm->second : &(*m_ita);
+	}
+
+	/**
+	 * Increment the iterator. (Prefix version).
+	 *
+	 * @pre iterator must be dereferenceable
+	 * @return *this;
+	 */
+	inline Iterator &operator++() noexcept
+	{
+		assert(m_parent);
+		assert((m_parent->isArray()  && m_ita != m_parent->m_array.end()) ||
+		       (m_parent->isObject() && m_itm != m_parent->m_object.end()));
+
+		increment();
+
+		return *this;
+	}
+
+	/**
+	 * Increment the iterator. (Postfix version).
+	 *
+	 * @pre iterator must be dereferenceable
+	 * @return *this;
+	 */
+	inline Iterator &operator++(int) noexcept
+	{
+		assert(m_parent);
+		assert((m_parent->isArray()  && m_ita != m_parent->m_array.end()) ||
+		       (m_parent->isObject() && m_itm != m_parent->m_object.end()));
+
+		increment();
+
+		return *this;
+	}
+
+	/**
+	 * Compare two iterators.
+	 *
+	 * @param it1 the first iterator
+	 * @param it2 the second iterator
+	 * @return true if they are same
+	 */
+	bool operator==(const Iterator &it) const noexcept
+	{
+		return m_parent == it.m_parent && m_itm == it.m_itm && m_ita == it.m_ita;
+	}
+
+	/**
+	 * Test if the iterator is different.
+	 *
+	 * @param it the iterator
+	 * @return true if they are different
+	 */
+	inline bool operator!=(const Iterator &it) const noexcept
+	{
+		return !(*this == it);
+	}
+};
+
+/**
+ * @class Value
+ * @brief Generic JSON value wrapper.
+ */
+class Value {
+private:
+	Type m_type{Type::Null};
+
+	union {
+		double m_number;
+		bool m_boolean;
+		int m_integer;
+		std::string m_string;
+		std::vector<Value> m_array;
+		std::map<std::string, Value> m_object;
+	};
+
+	void copy(const Value &);
+	void move(Value &&);
+	std::string toJson(int indent, int current) const;
+
+	friend class Iterator<Value, typename std::vector<Value>::iterator, typename std::map<std::string, Value>::iterator>;
+	friend class Iterator<const Value, typename std::vector<Value>::const_iterator, typename std::map<std::string, Value>::const_iterator>;
+
+public:
+	/**
+	 * Forward iterator.
+	 */
+	using iterator = Iterator<Value, typename std::vector<Value>::iterator, typename std::map<std::string, Value>::iterator>;
+
+	/**
+	 * Const forward iterator.
+	 */
+	using const_iterator = Iterator<const Value, typename std::vector<Value>::const_iterator, typename std::map<std::string, Value>::const_iterator>;
+
+	/**
+	 * Construct a null value.
+	 */
+	inline Value() noexcept
+	{
+	}
+
+	/**
+	 * Create a value with a specified type, this is usually only needed when you want to create an object or
+	 * an array.
+	 *
+	 * For any other types, initialize with sane default value.
+	 *
+	 * @param type the type
+	 */
+	Value(Type type);
+
+	/**
+	 * Construct a null value.
+	 */
+	inline Value(std::nullptr_t) noexcept
+		: m_type(Type::Null)
+	{
+	}
+
+	/**
+	 * Construct a boolean value.
+	 *
+	 * @param value the boolean value
+	 */
+	inline Value(bool value) noexcept
+		: m_type(Type::Boolean)
+		, m_boolean(value)
+	{
+	}
+
+	/**
+	 * Create value from integer.
+	 *
+	 * @param value the value
+	 */
+	inline Value(int value) noexcept
+		: m_type(Type::Int)
+		, m_integer(value)
+	{
+	}
+
+	/**
+	 * Construct a value from a C-string.
+	 *
+	 * @param value the C-string
+	 */
+	inline Value(const char *value)
+		: m_type(Type::String)
+	{
+		new (&m_string) std::string{value ? value : ""};
+	}
+
+	/**
+	 * Construct a number value.
+	 *
+	 * @param value the real value
+	 */
+	inline Value(double value) noexcept
+		: m_type(Type::Real)
+		, m_number(value)
+	{
+	}
+
+	/**
+	 * Construct a string value.
+	 *
+	 * @param value the string
+	 */
+	inline Value(std::string value) noexcept
+		: m_type(Type::String)
+	{
+		new (&m_string) std::string(std::move(value));
+	}
+
+	/**
+	 * Create an object from a map.
+	 *
+	 * @param values the values
+	 * @see fromObject
+	 */
+	inline Value(std::map<std::string, Value> values)
+		: Value(Type::Object)
+	{
+		for (const auto &pair : values)
+			insert(pair.first, pair.second);
+	}
+
+	/**
+	 * Create an array from a vector.
+	 *
+	 * @param values the values
+	 * @see fromArray
+	 */
+	inline Value(std::vector<Value> values)
+		: Value(Type::Array)
+	{
+		for (Value value : values)
+			append(std::move(value));
+	}
+
+	/**
+	 * Move constructor.
+	 *
+	 * @param other the value to move from
+	 */
+	inline Value(Value &&other)
+	{
+		move(std::move(other));
+	}
+
+	/**
+	 * Copy constructor.
+	 *
+	 * @param other the value to copy from
+	 */
+	inline Value(const Value &other)
+	{
+		copy(other);
+	}
+
+	/**
+	 * Copy operator.
+	 *
+	 * @param other the value to copy from
+	 * @return *this
+	 */
+	inline Value &operator=(const Value &other)
+	{
+		copy(other);
+
+		return *this;
+	}
+
+	/**
+	 * Move operator.
+	 *
+	 * @param other the value to move from
+	 */
+	inline Value &operator=(Value &&other)
+	{
+		move(std::move(other));
+
+		return *this;
+	}
+
+	/**
+	 * Destructor.
+	 */
+	~Value();
+
+	/**
+	 * Get an iterator to the beginning.
+	 *
+	 * @pre must be an array or object
+	 * @return the iterator
+	 */
+	inline iterator begin() noexcept
+	{
+		assert(isArray() || isObject());
+
+		return m_type == Type::Object ? iterator(this, m_object.begin()) : iterator(this, m_array.begin());
+	}
+
+	/**
+	 * Overloaded function.
+	 *
+	 * @pre must be an array or object
+	 * @return the iterator
+	 */
+	inline const_iterator begin() const noexcept
+	{
+		assert(isArray() || isObject());
+
+		return m_type == Type::Object ? const_iterator(this, m_object.begin()) : const_iterator(this, m_array.begin());
+	}
+
+	/**
+	 * Overloaded function.
+	 *
+	 * @pre must be an array or object
+	 * @return the iterator
+	 */
+	inline const_iterator cbegin() const noexcept
+	{
+		assert(isArray() || isObject());
+
+		return m_type == Type::Object ? const_iterator(this, m_object.cbegin()) : const_iterator(this, m_array.cbegin());
+	}
+
+	/**
+	 * Get an iterator to the end.
+	 *
+	 * @pre must be an array or object
+	 * @return the iterator
+	 */
+	inline iterator end() noexcept
+	{
+		assert(isArray() || isObject());
+
+		return m_type == Type::Object ? iterator(this, m_object.end()) : iterator(this, m_array.end());
+	}
+
+	/**
+	 * Get an iterator to the end.
+	 *
+	 * @pre must be an array or object
+	 * @return the iterator
+	 */
+	inline const_iterator end() const noexcept
+	{
+		assert(isArray() || isObject());
+
+		return m_type == Type::Object ? const_iterator(this, m_object.end()) : const_iterator(this, m_array.end());
+	}
+
+	/**
+	 * Get an iterator to the end.
+	 *
+	 * @pre must be an array or object
+	 * @return the iterator
+	 */
+	inline const_iterator cend() const noexcept
+	{
+		assert(isArray() || isObject());
+
+		return m_type == Type::Object ? const_iterator(this, m_object.cend()) : const_iterator(this, m_array.cend());
+	}
+
+	/**
+	 * Get the value type.
+	 *
+	 * @return the type
+	 */
+	inline Type typeOf() const noexcept
+	{
+		return m_type;
+	}
+
+	/**
+	 * Get the value as boolean.
+	 *
+	 * @return the value or false if not a boolean
+	 */
+	inline bool toBool() const noexcept
+	{
+		return m_type != Type::Boolean ? false : m_boolean;
+	}
+
+	/**
+	 * Get the value as integer.
+	 *
+	 * @return the value or 0 if not a integer
+	 */
+	inline int toInt() const noexcept
+	{
+		return m_type != Type::Int ? 0 : m_integer;
+	}
+
+	/**
+	 * Get the value as real.
+	 *
+	 * @return the value or 0 if not a real
+	 */
+	inline double toReal() const noexcept
+	{
+		return m_type != Type::Real ? 0 : m_number;
+	}
+
+	/**
+	 * Get the value as string.
+	 *
+	 * @param coerce set to true to coerce the value if not a string
+	 * @return the value or empty string if not a string
+	 */
+	std::string toString(bool coerce = false) const;
+
+	/**
+	 * Check if the value is boolean type.
+	 *
+	 * @return true if boolean
+	 */
+	inline bool isBool() const noexcept
+	{
+		return m_type == Type::Boolean;
+	}
+
+	/**
+	 * Check if the value is integer type.
+	 *
+	 * @return true if integer
+	 */
+	inline bool isInt() const noexcept
+	{
+		return m_type == Type::Int;
+	}
+
+	/**
+	 * Check if the value is object type.
+	 *
+	 * @return true if object
+	 */
+	inline bool isObject() const noexcept
+	{
+		return m_type == Type::Object;
+	}
+
+	/**
+	 * Check if the value is array type.
+	 *
+	 * @return true if array
+	 */
+	inline bool isArray() const noexcept
+	{
+		return m_type == Type::Array;
+	}
+
+	/**
+	 * Check if the value is integer or real type.
+	 *
+	 * @return true if integer or real
+	 * @see toInt
+	 * @see toReal
+	 */
+	inline bool isNumber() const noexcept
+	{
+		return m_type == Type::Real || m_type == Type::Int;
+	}
+
+	/**
+	 * Check if the value is real type.
+	 *
+	 * @return true if real
+	 */
+	inline bool isReal() const noexcept
+	{
+		return m_type == Type::Real;
+	}
+
+	/**
+	 * Check if the value is null type.
+	 *
+	 * @return true if null
+	 */
+	inline bool isNull() const noexcept
+	{
+		return m_type == Type::Null;
+	}
+
+	/**
+	 * Check if the value is string type.
+	 *
+	 * @return true if string
+	 */
+	inline bool isString() const noexcept
+	{
+		return m_type == Type::String;
+	}
+
+	/**
+	 * Get the array or object size.
+	 *
+	 * @pre must be an array or object
+	 * @return the size
+	 */
+	inline unsigned size() const noexcept
+	{
+		assert(isArray() || isObject());
+
+		if (m_type == Type::Object)
+			return m_object.size();
+
+		return m_array.size();
+	}
+
+	/**
+	 * Remove all the values.
+	 *
+	 * @pre must be an array or an object
+	 */
+	inline void clear() noexcept
+	{
+		assert(isArray() || isObject());
+
+		if (m_type == Type::Array)
+			m_array.clear();
+		else
+			m_object.clear();
+	}
+
+	/*
+	 * Array functions
+	 * ----------------------------------------------------------
+	 */
+
+	/**
+	 * Get the value at the specified position or the defaultValue if position is out of bounds.
+	 *
+	 * @param position the position
+	 * @param defaultValue the value replacement
+	 * @return the value or defaultValue
+	 */
+	template <typename DefaultValue>
+	inline Value valueOr(unsigned position, DefaultValue &&defaultValue) const
+	{
+		if (m_type != Type::Array || position >= m_array.size())
+			return defaultValue;
+
+		return m_array[position];
+	}
+
+	/**
+	 * Overloaded function with type check.
+	 *
+	 * @param position the position
+	 * @param type the requested type
+	 * @param defaultValue the value replacement
+	 * @return the value or defaultValue
+	 */
+	template <typename DefaultValue>
+	inline Value valueOr(unsigned position, Type type, DefaultValue &&defaultValue) const
+	{
+		if (m_type != Type::Array || position >= m_array.size() || m_array[position].typeOf() != type)
+			return defaultValue;
+
+		return m_array[position];
+	}
+
+	/**
+	 * Get a value at the specified index.
+	 *
+	 * @pre must be an array
+	 * @param position the position
+	 * @return the value
+	 * @throw std::out_of_range if out of bounds
+	 */
+	inline const Value &at(unsigned position) const
+	{
+		assert(isArray());
+
+		return m_array.at(position);
+	}
+
+	/**
+	 * Overloaded function.
+	 *
+	 * @pre must be an array
+	 * @param position the position
+	 * @return the value
+	 * @throw std::out_of_range if out of bounds
+	 */
+	inline Value &at(unsigned position)
+	{
+		assert(isArray());
+
+		return m_array.at(position);
+	}
+
+	/**
+	 * Get a value at the specified index.
+	 *
+	 * @pre must be an array
+	 * @pre position must be valid
+	 * @param position the position
+	 * @return the value
+	 */
+	inline const Value &operator[](unsigned position) const
+	{
+		assert(isArray());
+		assert(position < m_array.size());
+
+		return m_array[position];
+	}
+
+	/**
+	 * Overloaded function.
+	 *
+	 * @pre must be an array
+	 * @pre position must be valid
+	 * @param position the position
+	 * @return the value
+	 */
+	inline Value &operator[](unsigned position)
+	{
+		assert(isArray());
+		assert(position < m_array.size());
+
+		return m_array[position];
+	}
+
+	/**
+	 * Push a value to the beginning of the array.
+	 *
+	 * @pre must be an array
+	 * @param value the value to push
+	 */
+	inline void push(const Value &value)
+	{
+		assert(isArray());
+
+		m_array.insert(m_array.begin(), value);
+	}
+
+	/**
+	 * Overloaded function.
+	 *
+	 * @pre must be an array
+	 * @param value the value to push
+	 */
+	inline void push(Value &&value)
+	{
+		assert(isArray());
+
+		m_array.insert(m_array.begin(), std::move(value));
+	}
+
+	/**
+	 * Insert a value at the specified position.
+	 *
+	 * @pre must be an array
+	 * @pre position must be valid
+	 * @param position the position
+	 * @param value the value to push
+	 */
+	inline void insert(unsigned position, const Value &value)
+	{
+		assert(isArray());
+		assert(position <= m_array.size());
+
+		m_array.insert(m_array.begin() + position, value);
+	}
+
+	/**
+	 * Overloaded function.
+	 *
+	 * @pre must be an array
+	 * @pre position must be valid
+	 * @param position the position
+	 * @param value the value to push
+	 */
+	inline void insert(unsigned position, Value &&value)
+	{
+		assert(isArray());
+		assert(position <= m_array.size());
+
+		m_array.insert(m_array.begin() + position, std::move(value));
+	}
+
+	/**
+	 * Add a new value to the end.
+	 *
+	 * @pre must be an array
+	 * @param value the value to append
+	 */
+	inline void append(const Value &value)
+	{
+		assert(isArray());
+
+		m_array.push_back(value);
+	}
+
+	/**
+	 * Overloaded function.
+	 *
+	 * @pre must be an array
+	 * @param value the value to append
+	 */
+	inline void append(Value &&value)
+	{
+		assert(isArray());
+
+		m_array.push_back(std::move(value));
+	}
+
+	/**
+	 * Remove a value at the specified position.
+	 *
+	 * @pre must be an array
+	 * @pre position must be valid
+	 * @param position the position
+	 */
+	inline void erase(unsigned position)
+	{
+		assert(isArray());
+		assert(position < m_array.size());
+
+		m_array.erase(m_array.begin() + position);
+	}
+
+	/*
+	 * Object functions
+	 * ----------------------------------------------------------
+	 */
+
+	/**
+	 * Get the value at the specified key or the defaultValue if key is absent.
+	 *
+	 * @param name the name
+	 * @param defaultValue the value replacement
+	 * @return the value or defaultValue
+	 */
+	template <typename DefaultValue>
+	Value valueOr(const std::string &name, DefaultValue &&defaultValue) const
+	{
+		if (m_type != Type::Object)
+			return defaultValue;
+
+		auto it = m_object.find(name);
+
+		if (it == m_object.end())
+			return defaultValue;
+
+		return it->second;
+	}
+
+	/**
+	 * Overloaded function with type check.
+	 *
+	 * @param name the name
+	 * @param type the requested type
+	 * @param defaultValue the value replacement
+	 * @return the value or defaultValue
+	 */
+	template <typename DefaultValue>
+	Value valueOr(const std::string &name, Type type, DefaultValue &&defaultValue) const
+	{
+		if (m_type != Type::Object)
+			return defaultValue;
+
+		auto it = m_object.find(name);
+
+		if (it == m_object.end() || it->second.typeOf() != type)
+			return defaultValue;
+
+		return it->second;
+	}
+
+	/**
+	 * Get a value from the object.
+	 *
+	 * @pre must be an object
+	 * @param name the value key
+	 * @return the value
+	 * @throw std::out_of_range if not found
+	 */
+	inline const Value &at(const std::string &name) const
+	{
+		assert(isObject());
+
+		return m_object.at(name);
+	}
+
+	/**
+	 * Overloaded function.
+	 *
+	 * @pre must be an object
+	 * @param name the value key
+	 * @return the value
+	 * @throw std::out_of_range if not found
+	 */
+	inline Value &at(const std::string &name)
+	{
+		assert(isObject());
+
+		return m_object.at(name);
+	}
+
+	/**
+	 * Get a value from the object.
+	 *
+	 * @pre must be an object
+	 * @param name the value key
+	 * @return the value
+	 */
+	inline Value &operator[](const std::string &name)
+	{
+		assert(isObject());
+
+		return m_object[name];
+	}
+
+	/**
+	 * Find a value by key.
+	 *
+	 * @pre must be an object
+	 * @param key the property key
+	 * @return the iterator or past the end if not found
+	 */
+	inline iterator find(const std::string &key)
+	{
+		assert(isObject());
+
+		return iterator(this, m_object.find(key));
+	}
+
+	/**
+	 * Overloaded function.
+	 *
+	 * @pre must be an object
+	 * @param key the property key
+	 * @return the iterator or past the end if not found
+	 */
+	inline const_iterator find(const std::string &key) const
+	{
+		assert(isObject());
+
+		return const_iterator(this, m_object.find(key));
+	}
+
+	/**
+	 * Insert a new value.
+	 *
+	 * @pre must be an object
+	 * @param name the key
+	 * @param value the value
+	 */
+	inline void insert(std::string name, const Value &value)
+	{
+		assert(isObject());
+
+		m_object.insert({std::move(name), value});
+	}
+
+	/**
+	 * Overloaded function.
+	 *
+	 * @pre must be an object
+	 * @param name the key
+	 * @param value the value
+	 */
+	inline void insert(std::string name, Value &&value)
+	{
+		assert(isObject());
+
+		m_object.insert({std::move(name), std::move(value)});
+	}
+
+	/**
+	 * Check if a value exists.
+	 *
+	 * @pre must be an object
+	 * @param key the key value
+	 * @return true if exists
+	 */
+	inline bool contains(const std::string &key) const noexcept
+	{
+		assert(isObject());
+
+		return m_object.find(key) != m_object.end();
+	}
+
+	/**
+	 * Remove a value of the specified key.
+	 *
+	 * @pre must be an object
+	 * @param key the value key
+	 */
+	inline void erase(const std::string &key)
+	{
+		assert(isObject());
+
+		m_object.erase(key);
+	}
+
+	/**
+	 * Return this value as JSon representation.
+	 *
+	 * @param indent the indentation to use (0 == compact, < 0 == tabs, > 0 == number of spaces)
+	 * @return the string
+	 */
+	inline std::string toJson(int indent = 2) const
+	{
+		return toJson(indent, 0);
+	}
+};
+
+/**
+ * Escape the input.
+ *
+ * @param input the input
+ * @return the escaped string
+ */
+std::string escape(const std::string &input);
+
+/**
+ * Convenient function to create an empty array.
+ *
+ * @return an empty array
+ */
+inline Value array()
+{
+	return Value(Type::Array);
+}
+
+/**
+ * Convenient function for creating array from initializer list.
+ *
+ * @param values the values
+ * @return the array
+ */
+inline Value array(std::initializer_list<Value> values)
+{
+	return Value(std::vector<Value>(values.begin(), values.end()));
+}
+
+/**
+ * Convenient function to create an empty object.
+ *
+ * @return an empty object
+ */
+inline Value object()
+{
+	return Value(Type::Object);
+}
+
+/**
+ * Convenient function for creating object from initializer list.
+ *
+ * @param values the values
+ * @return the object
+ */
+inline Value object(std::initializer_list<std::pair<std::string, Value>> values)
+{
+	return Value(std::map<std::string, Value>(values.begin(), values.end()));
+}
+
+/**
+ * Construct a value from a buffer.
+ *
+ * @param data the JSON data
+ * @return the parsed value
+ * @throw Error on errors
+ */
+Value fromString(const std::string &data);
+
+/**
+ * Construct a value from a file.
+ *
+ * @param path the path to the file
+ * @return the parsed value
+ * @throw Error on errors
+ */
+Value fromFile(const std::string &path);
+
+} // !json
+
+} // !malikania
+
+#endif // !MALIKANIA_JSON_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libcommon/malikania/resources-loader.cpp	Wed Mar 23 17:11:39 2016 +0100
@@ -0,0 +1,109 @@
+/*
+ * resources-loader.cpp -- load shared resources files
+ *
+ * Copyright (c) 2013-2016 Malikania Authors
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <cassert>
+
+#include "game.h"
+#include "resources-loader.h"
+#include "resources-locator.h"
+
+namespace malikania {
+
+void ResourcesLoader::requires(const std::string &id,
+			       const json::Value &object,
+			       const std::unordered_map<std::string, json::Type> props) const
+{
+	assert(object.isObject());
+
+	for (const auto &pair : props) {
+		auto it = object.find(pair.first);
+
+		if (it == object.end() || it->typeOf() != pair.second) {
+			std::string msg = id + ": missing '" + pair.first + "' property (";
+
+			switch (pair.second) {
+			case json::Type::Array:
+				msg += "array";
+				break;
+			case json::Type::Boolean:
+				msg += "boolean";
+				break;
+			case json::Type::Int:
+				msg += "int";
+				break;
+			case json::Type::Object:
+				msg += "object";
+				break;
+			case json::Type::Real:
+				msg += "real";
+				break;
+			case json::Type::String:
+				msg += "string";
+				break;
+			default:
+				break;
+			}
+
+			msg += " expected)";
+
+			throw std::runtime_error(std::move(msg));
+		}
+	}
+}
+
+std::string ResourcesLoader::requireString(const std::string &id,
+					   const json::Value &object,
+					   const std::string &property) const
+{
+	assert(object.isObject());
+
+	auto it = object.find(property);
+
+	if (it == object.end() || !it->isString()) {
+		throw std::runtime_error(id + ": missing '" + property + "' property (string expected)");
+	}
+
+	return it->toString();
+}
+
+ResourcesLoader::ResourcesLoader(ResourcesLocator &locator)
+	: m_locator(locator)
+{
+}
+
+Game ResourcesLoader::loadGame() const
+{
+	json::Value value = json::fromString(m_locator.read("game.json"));
+
+	if (!value.isObject())
+		throw std::runtime_error("game.json: not a JSON object");
+
+	requires("game.json", value, {
+		{ "name", json::Type::String },
+		{ "version", json::Type::String },
+		{ "requires", json::Type::String }
+	});
+
+	return Game(value["name"].toString(),
+		    value["version"].toString(),
+		    value["requires"].toString(),
+		    value.valueOr("license", json::Type::String, "").toString(),
+		    value.valueOr("author", json::Type::String, "").toString());
+}
+
+} // !malikania
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libcommon/malikania/resources-loader.h	Wed Mar 23 17:11:39 2016 +0100
@@ -0,0 +1,110 @@
+/*
+ * resources-loader.h -- load shared resources files
+ *
+ * Copyright (c) 2013-2016 Malikania Authors
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef MALIKANIA_RESOURCES_LOADER_H
+#define MALIKANIA_RESOURCES_LOADER_H
+
+#include <string>
+#include <unordered_map>
+
+#include "json.h"
+#include "resources-locator.h"
+
+namespace malikania {
+
+class Game;
+
+/**
+ * @class ResourcesLoader
+ * @brief Open resources files using a ResourcesLocator.
+ *
+ * This class is used to load resources files that are common to the server and the client.
+ *
+ * @see ResourcesLoaderClient
+ * @see ResourcesLoaderServer
+ */
+class ResourcesLoader {
+private:
+	ResourcesLocator &m_locator;
+
+protected:
+	/**
+	 * Check that an object has the specified properties of the given type.
+	 *
+	 * Throws an error when any of the property is missing or not the correct type.
+	 *
+	 * You can use this function when you have lot of properties to extract, otherwise, you can use one of the
+	 * require* or get* functions to avoid performances overhead.
+	 *
+	 * @pre object.isObject()
+	 * @param id the resource id
+	 * @param object the object
+	 * @param props the properties
+	 * @throw std::runtime_error when a property is missing / invalid
+	 */
+	void requires(const std::string &id,
+		      const json::Value &object,
+		      const std::unordered_map<std::string, json::Type> props) const;
+
+	/**
+	 * Require a string.
+	 *
+	 * @pre object.isObject()
+	 * @param id the resource id
+	 * @param object the object
+	 * @param property the property
+	 * @return the string
+	 * @throw std::runtime_error if the property is not a string or missing
+	 */
+	std::string requireString(const std::string &id, const json::Value &object, const std::string &property) const;
+
+public:
+	/**
+	 * Construct the ResourcesLoader.
+	 *
+	 * @param locator the locator
+	 */
+	ResourcesLoader(ResourcesLocator &locator);
+
+	/**
+	 * Virtual destructor defaulted.
+	 */
+	virtual ~ResourcesLoader() = default;
+
+	/**
+	 * Get the underlying locator.
+	 *
+	 * @return the locator
+	 */
+	inline ResourcesLocator &locator() noexcept
+	{
+		return m_locator;
+	}
+
+	/**
+	 * Load a game.
+	 *
+	 * @return the game
+	 * @throw std::runtime_error on errors
+	 */
+	virtual Game loadGame() const;
+};
+
+} // !malikania
+
+#endif // !MALIKANIA_RESOURCES_LOADER_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libcommon/malikania/resources-locator.cpp	Wed Mar 23 17:11:39 2016 +0100
@@ -0,0 +1,56 @@
+/*
+ * resources-locator.cpp -- file and stream loader
+ *
+ * Copyright (c) 2013-2016 Malikania Authors
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <cerrno>
+#include <cstring>
+#include <fstream>
+#include <iterator>
+#include <stdexcept>
+
+#include "resources-locator.h"
+
+namespace malikania {
+
+ResourcesLocatorDirectory::ResourcesLocatorDirectory(std::string path) noexcept
+	: m_path(std::move(path))
+{
+}
+
+std::string ResourcesLocatorDirectory::read(const std::string &id)
+{
+	std::ifstream in(m_path + "/" + id, std::ifstream::in | std::ifstream::binary);
+
+	if (!in) {
+		throw std::runtime_error(std::strerror(errno));
+	}
+
+	return std::string(std::istreambuf_iterator<char>(in.rdbuf()), std::istreambuf_iterator<char>());
+}
+
+std::unique_ptr<std::istream> ResourcesLocatorDirectory::open(const std::string &id)
+{
+	std::unique_ptr<std::istream> ptr = std::make_unique<std::ifstream>(m_path + "/" + id);
+
+	if (!(*ptr)) {
+		throw std::runtime_error(std::strerror(errno));
+	}
+
+	return ptr;
+}
+
+} // !malikania
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libcommon/malikania/resources-locator.h	Wed Mar 23 17:11:39 2016 +0100
@@ -0,0 +1,82 @@
+/*
+ * resources-locator.h -- file and stream loader
+ *
+ * Copyright (c) 2013-2016 Malikania Authors
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef MALIKANIA_RESOURCES_LOCATOR_H
+#define MALIKANIA_RESOURCES_LOCATOR_H
+
+#include <string>
+#include <memory>
+#include <istream>
+
+namespace malikania {
+
+/**
+ * @class ResourcesLocator
+ * @brief Load files from directories and zip.
+ */
+class ResourcesLocator {
+public:
+	/**
+	 * Read a whole resource as a string.
+	 *
+	 * @param id the resource id
+	 * @return the string
+	 * @throw std::runtime_error on any errors
+	 */
+	virtual std::string read(const std::string &id) = 0;
+
+	/**
+	 * Open a resource as a stream.
+	 *
+	 * @param id the resource id
+	 * @return the stream
+	 * @throw std::runtime_error on any errors
+	 */
+	virtual std::unique_ptr<std::istream> open(const std::string &id) = 0;
+};
+
+/**
+ * @class ResourcesLocatorDirectory
+ * @brief Load a game from a directory.
+ */
+class ResourcesLocatorDirectory : public ResourcesLocator {
+private:
+	std::string m_path;
+
+public:
+	/**
+	 * Load the game from the directory.
+	 *
+	 * @param path the base directory
+	 */
+	ResourcesLocatorDirectory(std::string path) noexcept;
+
+	/**
+	 * @copydoc ResourcesLocator::read
+	 */
+	std::string read(const std::string &id) override;
+
+	/**
+	 * @copydoc ResourcesLocator::open
+	 */
+	std::unique_ptr<std::istream> open(const std::string &id) override;
+};
+
+} // !malikania
+
+#endif // !MALIKANIA_RESOURCES_LOCATOR_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libcommon/malikania/util.cpp	Wed Mar 23 17:11:39 2016 +0100
@@ -0,0 +1,40 @@
+/*
+ * util.cpp -- malikania utilities
+ *
+ * Copyright (c) 2013-2016 Malikania Authors
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "util.h"
+
+namespace malikania {
+
+namespace util {
+
+std::vector<std::string> netsplit(std::string &input)
+{
+	std::vector<std::string> ret;
+	std::string::size_type pos;
+
+	while ((pos = input.find("\r\n\r\n")) != std::string::npos) {
+		ret.push_back(input.substr(0U, pos));
+		input.erase(0U, pos + 4);
+	}
+
+	return ret;
+}
+
+} // !util
+
+} // !malikania
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libcommon/malikania/util.h	Wed Mar 23 17:11:39 2016 +0100
@@ -0,0 +1,47 @@
+/*
+ * util.h -- malikania utilities
+ *
+ * Copyright (c) 2013-2016 Malikania Authors
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef MALIKANIA_UTIL_H
+#define MALIKANIA_UTIL_H
+
+/**
+ * @file util.h
+ * @brief Some utilities
+ */
+
+#include <string>
+#include <vector>
+
+namespace malikania {
+
+namespace util {
+
+/**
+ * Split the network message buffer by \r\n\r\n and update the
+ * buffer in-place.
+ *
+ * @param input the buffer to split and update
+ * @return the list of received message or empty if not ready
+ */
+std::vector<std::string> netsplit(std::string &input);
+
+} // !util
+
+} // !malikania
+
+#endif // !MALIKANIA_UTIL_H
--- a/tests/libclient/animation/main.cpp	Wed Mar 23 09:49:51 2016 +0100
+++ b/tests/libclient/animation/main.cpp	Wed Mar 23 17:11:39 2016 +0100
@@ -22,11 +22,11 @@
 
 #include <gtest/gtest.h>
 
-#include <malikania/Animation.h>
-#include <malikania/Animator.h>
-#include <malikania/ClientResourcesLoader.h>
-#include <malikania/ResourcesLocator.h>
-#include <malikania/Window.h>
+#include <malikania/animation.h>
+#include <malikania/animator.h>
+#include <malikania/client-resources-loader.h>
+#include <malikania/resources-locator.h>
+#include <malikania/window.h>
 
 using namespace malikania;
 
--- a/tests/libclient/color/main.cpp	Wed Mar 23 09:49:51 2016 +0100
+++ b/tests/libclient/color/main.cpp	Wed Mar 23 17:11:39 2016 +0100
@@ -18,7 +18,7 @@
 
 #include <gtest/gtest.h>
 
-#include <malikania/Color.h>
+#include <malikania/color.h>
 
 using namespace malikania;
 
@@ -348,4 +348,4 @@
 	testing::InitGoogleTest(&argc, argv);
 
 	return RUN_ALL_TESTS();
-}
\ No newline at end of file
+}
--- a/tests/libclient/font/main.cpp	Wed Mar 23 09:49:51 2016 +0100
+++ b/tests/libclient/font/main.cpp	Wed Mar 23 17:11:39 2016 +0100
@@ -21,10 +21,10 @@
 
 #include <gtest/gtest.h>
 
-#include <malikania/Color.h>
-#include <malikania/Font.h>
-#include <malikania/ResourcesLocator.h>
-#include <malikania/Window.h>
+#include <malikania/color.h>
+#include <malikania/font.h>
+#include <malikania/resources-locator.h>
+#include <malikania/window.h>
 
 using namespace malikania;
 
--- a/tests/libclient/image/main.cpp	Wed Mar 23 09:49:51 2016 +0100
+++ b/tests/libclient/image/main.cpp	Wed Mar 23 17:11:39 2016 +0100
@@ -21,10 +21,10 @@
 
 #include <gtest/gtest.h>
 
-#include <malikania/ClientResourcesLoader.h>
-#include <malikania/Image.h>
-#include <malikania/ResourcesLocator.h>
-#include <malikania/Window.h>
+#include <malikania/client-resources-loader.h>
+#include <malikania/image.h>
+#include <malikania/resources-locator.h>
+#include <malikania/window.h>
 
 using namespace malikania;
 
--- a/tests/libclient/line/main.cpp	Wed Mar 23 09:49:51 2016 +0100
+++ b/tests/libclient/line/main.cpp	Wed Mar 23 17:11:39 2016 +0100
@@ -18,7 +18,7 @@
 
 #include <gtest/gtest.h>
 
-#include <malikania/Line.h>
+#include <malikania/line.h>
 
 using namespace malikania;
 
--- a/tests/libclient/point/main.cpp	Wed Mar 23 09:49:51 2016 +0100
+++ b/tests/libclient/point/main.cpp	Wed Mar 23 17:11:39 2016 +0100
@@ -18,7 +18,7 @@
 
 #include <gtest/gtest.h>
 
-#include <malikania/Point.h>
+#include <malikania/point.h>
 
 using namespace malikania;
 
--- a/tests/libclient/rectangle/main.cpp	Wed Mar 23 09:49:51 2016 +0100
+++ b/tests/libclient/rectangle/main.cpp	Wed Mar 23 17:11:39 2016 +0100
@@ -18,7 +18,7 @@
 
 #include <gtest/gtest.h>
 
-#include <malikania/Rectangle.h>
+#include <malikania/rectangle.h>
 
 using namespace malikania;
 
--- a/tests/libclient/size/main.cpp	Wed Mar 23 09:49:51 2016 +0100
+++ b/tests/libclient/size/main.cpp	Wed Mar 23 17:11:39 2016 +0100
@@ -18,7 +18,7 @@
 
 #include <gtest/gtest.h>
 
-#include <malikania/Size.h>
+#include <malikania/size.h>
 
 using namespace malikania;
 
--- a/tests/libclient/sprite/main.cpp	Wed Mar 23 09:49:51 2016 +0100
+++ b/tests/libclient/sprite/main.cpp	Wed Mar 23 17:11:39 2016 +0100
@@ -22,10 +22,10 @@
 
 #include <gtest/gtest.h>
 
-#include <malikania/ClientResourcesLoader.h>
-#include <malikania/ResourcesLocator.h>
-#include <malikania/Sprite.h>
-#include <malikania/Window.h>
+#include <malikania/client-resources-loader.h>
+#include <malikania/resources-locator.h>
+#include <malikania/sprite.h>
+#include <malikania/window.h>
 
 using namespace malikania;
 
--- a/tests/libcommon/elapsed-timer/main.cpp	Wed Mar 23 09:49:51 2016 +0100
+++ b/tests/libcommon/elapsed-timer/main.cpp	Wed Mar 23 17:11:39 2016 +0100
@@ -20,7 +20,7 @@
 
 #include <gtest/gtest.h>
 
-#include <malikania/ElapsedTimer.h>
+#include <malikania/elapsed-timer.h>
 
 using namespace malikania;
 using namespace std::chrono_literals;
--- a/tests/libserver/id/main.cpp	Wed Mar 23 09:49:51 2016 +0100
+++ b/tests/libserver/id/main.cpp	Wed Mar 23 17:11:39 2016 +0100
@@ -21,7 +21,7 @@
 
 #include <gtest/gtest.h>
 
-#include <malikania/Id.h>
+#include <malikania/id.h>
 
 using namespace malikania;