Commit 701a02ca authored by louiz’'s avatar louiz’

Introduce the Mod module. #56

Parse a yaml file containing various informations about the game and use
them in the world and gui modules.
parent da05b050
......@@ -58,6 +58,7 @@ find_package(Cryptopp REQUIRED)
include_directories(${Boost_INCLUDE_DIR})
include_directories(${CRYPTO++_INCLUDE_DIR})
include_directories("src/")
include_directories("src/yaml-cpp/include/")
link_directories(${Boost_LIBRARY_DIRS})
link_directories(${CRYPTO++_LIBRARIES})
......@@ -183,6 +184,42 @@ target_link_libraries(
${CMAKE_THREAD_LIBS_INIT}
)
file(
GLOB
source_yaml
src/yaml-cpp/src/*.cpp
)
add_library(yaml STATIC ${source_yaml})
target_link_libraries(
yaml
)
file(
GLOB
source_clientmod
src/mod/mod.cpp
src/mod/client_mod.cpp
)
add_library(clientmod STATIC ${source_clientmod})
target_link_libraries(
clientmod
yaml
world
gui
)
file(
GLOB
source_mod
src/mod/mod.cpp
)
add_library(mod STATIC ${source_mod})
target_link_libraries(
mod
yaml
world
)
if(BUILD_CLIENT)
file(
......@@ -203,6 +240,7 @@ target_Link_libraries(
config
world
utils
clientmod
${SFML_LIBRARIES}
${SFGUI_LIBRARY}
${Boost_LIBRARIES}
......@@ -225,6 +263,7 @@ target_Link_libraries(
serialization
pathfinding
mpreal
mod
utils
${Boost_LIBRARIES}
${CMAKE_THREAD_LIBS_INIT}
......
......@@ -35,13 +35,15 @@
#include <gui/hud/action_panel_table.hpp>
#include <world/selection.hpp>
#include <vector>
#include <mod/client_mod.hpp>
class Screen;
class ActionPanel
{
friend class Mod;
public:
ActionPanel(sf::RenderWindow*, Screen*, const Selection*);
ActionPanel(sf::RenderWindow*, Screen*, const Selection*, ClientMod&);
~ActionPanel();
void draw();
bool handle_event(const sf::Event&);
......@@ -51,6 +53,7 @@ public:
* sucessfully executed, etc.
*/
void reset_all_tables();
private:
ActionPanel(const ActionPanel&);
ActionPanel& operator=(const ActionPanel&);
......
......@@ -21,13 +21,14 @@
#include <gui/hud/minimap.hpp>
#include <gui/hud/selection_panel.hpp>
#include <gui/hud/action_panel.hpp>
#include <mod/client_mod.hpp>
class Screen;
class Hud
{
public:
Hud(GraphMap*, ClientWorld*, sf::RenderWindow*, Camera*, Screen*);
Hud(GraphMap*, ClientWorld*, sf::RenderWindow*, Camera*, Screen*, ClientMod&);
~Hud();
void draw(Camera*);
bool handle_event(const sf::Event&);
......
#include <gui/screen/screen.hpp>
#include <gui/common.hpp>
Screen::Screen(ClientWorld* world, GraphMap* map, sf::RenderWindow* win):
Screen::Screen(ClientWorld* world, GraphMap* map, sf::RenderWindow* win, ClientMod& mod):
win(win),
camera(world, map, win, this),
world(world),
......
......@@ -22,11 +22,12 @@
#include <world/client_world.hpp>
#include <logging/logging.hpp>
#include <gui/cursor.hpp>
#include <mod/client_mod.hpp>
class Screen
{
public:
Screen(ClientWorld*, GraphMap*, sf::RenderWindow*);
Screen(ClientWorld*, GraphMap*, sf::RenderWindow*, ClientMod&);
~Screen();
/**
* Draw all elements of the screen.
......
......@@ -6,6 +6,7 @@
#include <gui/screen/screen.hpp>
#include <network/command.hpp>
#include <gui/camera/map.hpp>
#include <mod/client_mod.hpp>
int main()
{
......@@ -15,7 +16,8 @@ int main()
GameClient* c = new GameClient();
GraphMap* map = new GraphMap;
map->load_from_file("test4.tmx");
ClientWorld* world = new ClientWorld(map);
ClientMod mod("monsters.yaml");
ClientWorld* world = new ClientWorld(map, mod);
world->set_next_turn_callback(boost::bind(&ClientWorld::on_next_turn, world, _1));
......@@ -45,7 +47,7 @@ int main()
c->poll(10);
}
Screen screen(world, map, window);
Screen screen(world, map, window, mod);
sf::Clock fps_clock;
......
......@@ -13,7 +13,8 @@ int main()
log_debug("Starting server");
srand(getpid());
GameServer s(7879);
Mod mod("monsters.yaml");
GameServer s(7879, mod);
s.start();
Time time1 = boost::posix_time::microsec_clock::universal_time();
......
#include <boost/bind.hpp>
#include <gui/screen/screen.hpp>
#include <mod/client_mod.hpp>
#include <world/client_world.hpp>
#include <gui/sprites/archive_sprite.hpp>
ClientMod::ClientMod(const std::string& filename):
Mod(filename)
{
this->building_sprites["building_archive"] = new ArchiveSprite;
}
std::vector<ActionPanelTable*> ClientMod::get_action_tables(Screen* screen)
{
ModActionInfos action_infos;
std::vector<ActionPanelTable*> tables;
log_warning("heu, coucou: " << this->units_doc->size());
for (unsigned int i=0; i < this->units_doc->size(); i++)
{
const YAML::Node& unit = (*this->units_doc)[i];
ActionPanelTable* table = new ActionPanelTable;
tables.push_back(table);
log_warning("Adding a new table, for a unit");
// A table always contains at least ONE page
this->fill_default_unit_actions(screen, table);
const YAML::Node& actions = unit["actions"];
for (unsigned int i=0; i < actions.size(); i++)
{
const YAML::Node& action = actions[i];
action >> action_infos;
this->add_action_to_table(table, action_infos, screen);
}
}
// YAML::Node buildings;
// parser.GetNextDocument(units);
return tables;
}
std::vector<BuildingSprite*> ClientMod::get_building_sprites()
{
std::vector<BuildingSprite*> sprites;
std::map<const std::string, BuildingSprite*>::iterator it;
std::string sprite_name;
for (unsigned int i=0; i < this->buildings_doc->size(); i++)
{
(*this->buildings_doc)[i]["sprite"] >> sprite_name;
it = this->building_sprites.find(sprite_name);
if (it == this->building_sprites.end())
{
log_error("Can not find the sprite for building: " << sprite_name << ". Will probably segfault later on because of that.");
continue ;
}
sprites.push_back(it->second);
}
return sprites;
}
void ClientMod::add_empty_pages(ActionPanelTable* table, const std::size_t size)
{
while (table->pages.size() < size)
table->pages.push_back(new ActionPanelPage);
}
void ClientMod::fill_default_unit_actions(Screen* screen, ActionPanelTable* table)
{
this->add_empty_pages(table, 1);
ActionPanelPage* page = table->pages[0];
const t_left_click null_left = {0, 0, 0};
t_left_click left_click = null_left;
// Move button
left_click.callback = boost::bind(&ClientWorld::action_move, screen->get_world(), _1, _2, _3);
left_click.cursor_callback = boost::bind(&Screen::draw_move_cursor, screen, _1, _2, _3);
page->add_button(new ActionPanelButton("move.png",
boost::bind(&Screen::set_left_click_callback, screen, _1), 0, left_click), 0);
// Empty buttons, yet
page->add_button(new ActionPanelButton("stop.png",
0, 1, null_left), 1);
page->add_button(new ActionPanelButton("keep_position.png",
0, 2, null_left), 2);
page->add_button(new ActionPanelButton("patrol.png",
0, 3, null_left), 3);
page->add_button(new ActionPanelButton("attack.png",
0, 4, null_left), 4);
}
void ClientMod::add_action_to_table(ActionPanelTable* table, const ModActionInfos& infos, Screen* screen)
{
t_left_click left_click = {0, 0, 0};
ActionPanelButton* button;
this->add_empty_pages(table, infos.page + 1); // To can add the button into its page.
ActionPanelPage* page = table->pages[infos.page];
if (infos.type == "page")
{
this->add_empty_pages(table, infos.value + 1); // To be able to switch to the page.
// Indicate what page we switch to when clicking the button.
left_click.id = infos.value;
button = new ActionPanelButton(infos.image_filename, boost::bind(&ActionPanelTable::action_change_current_page, table, _1), infos.position, left_click);
}
else if (infos.type == "build")
{
left_click.id = infos.value;
left_click.callback = boost::bind(&ClientWorld::action_build, screen->get_world(), _1, _2, _3);
left_click.cursor_callback = boost::bind(&Screen::draw_build_cursor, screen, _1, _2, _3);
button = new ActionPanelButton(infos.image_filename, boost::bind(&Screen::set_left_click_callback, screen, _1), infos.position, left_click);
}
else
{
log_error("Unknown type of action: " << infos.type);
return ;
}
page->add_button(button, infos.position);
}
void operator >>(const YAML::Node& node, ModActionInfos& v)
{
node["type"] >> v.type;
node["page"] >> v.page;
node["position"] >> v.position;
node["value"] >> v.value;
node["image"] >> v.image_filename;
}
#ifndef __CLIENT_MOD_HPP__
# define __CLIENT_MOD_HPP__
#include <mod/mod.hpp>
#include <gui/sprites/building_sprite.hpp>
class Screen;
/**
* Just a structure containing some numbers or string, describing an action,
* it is filled with a YAML node.
*/
struct ModActionInfos
{
std::string type;
unsigned int page;
unsigned int position;
std::string image_filename;
unsigned int value;
};
class ClientMod: public Mod
{
public:
std::vector<ActionPanelTable*> get_action_tables(Screen*);
std::vector<BuildingSprite*> get_building_sprites();
ClientMod(const std::string& filename);
private:
ClientMod(const ClientMod&);
ClientMod& operator=(const ClientMod&);
void fill_default_unit_actions(Screen*, ActionPanelTable*);
/**
* Add empty pages until the table contains the given number of pages.
* It may not add any pages if there are already enough of them.
*/
void add_empty_pages(ActionPanelTable*, const std::size_t);
void add_action_to_table(ActionPanelTable*, const ModActionInfos&, Screen*);
std::map<const std::string, BuildingSprite*> building_sprites;
};
void operator >>(const YAML::Node& node, ModActionInfos& v);
#endif // __CLIENT_MOD_HPP__
#include <mod/mod.hpp>
#include <gui/hud/action_panel_page.hpp>
#include <gui/hud/action_panel_button.hpp>
#include <gui/screen/screen.hpp>
Mod::Mod(const std::string& filename):
fin(filename.c_str()),
units_doc(new YAML::Node),
buildings_doc(new YAML::Node)
{
YAML::Parser parser(this->fin);
parser.GetNextDocument(*this->units_doc);
parser.GetNextDocument(*this->buildings_doc);
}
Mod::~Mod()
{
delete this->units_doc;
delete this->buildings_doc;
}
std::vector<const Unit*> Mod::get_unit_models()
{
std::vector<const Unit*> models;
Unit* unit;
for (unsigned int i=0; i < this->units_doc->size(); i++)
{
unit = new Unit;
(*this->units_doc)[i] >> *unit;
models.push_back(unit);
}
return models;
}
std::vector<const Building*> Mod::get_building_models()
{
std::vector<const Building*> buildings;
Building* building;
for (unsigned int i=0; i < this->buildings_doc->size(); i++)
{
building = new Building;
(*this->buildings_doc)[i] >> *building;
buildings.push_back(building);
}
return buildings;
}
void operator >>(const YAML::Node& node, mpreal& v)
{
float f;
node >> f;
v = f;
}
void operator >>(const YAML::Node& node, Unit& v)
{
node["name"] >> v.name;
node["speed"] >> v.speed;
node["width"] >> v.width;
}
void operator >>(const YAML::Node& node, Building& v)
{
node["name"] >> v.name;
node["build_time"] >> v.build_time;
node["cells"] >> v.cells;
}
/** @addtogroup Mod Defines a class that can provide a serie of various
* objects or list of objects, defined in a mod file. A mod file is a yaml
* file describing various aspects and "rules" of the game (for example a
* list of units and spells, their attributes, what unit can cast which
* spell, etc). This class only creates the object, the various class using
* them are responsible for destroying them later (for example, the list of
* Entity* that the World class requires has to be freed be the World
* class). One single mod object must be created each game and passed to
* every class that needs it.
*
* A mod file is structured like this:
* Two documents, in that order: the first contains a list of units
* @class Mod
*/
#ifndef __MOD_HPP__
# define __MOD_HPP__
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <yaml-cpp/yaml.h>
#include <gui/hud/action_panel_table.hpp>
#include <world/unit.hpp>
#include <world/building.hpp>
#define NUMBER_OF_DOCUMENTS 1
class Mod
{
public:
Mod(const std::string& filename);
~Mod();
/**
* Returns the list of all the entity models defined in the mod file.
* These Entitys are then copied by World to create the real entities that
* actually "live".
*/
std::vector<const Unit*> get_unit_models();
std::vector<const Building*> get_building_models();
private:
Mod(const Mod&);
Mod& operator=(const Mod&);
protected:
std::ifstream fin;
/**
* Pointers to the various yaml documents in the mod file.
*/
YAML::Node* units_doc;
YAML::Node* buildings_doc;
};
void operator >>(const YAML::Node& node, mpreal& v);
void operator >>(const YAML::Node& node, Unit& v);
void operator >>(const YAML::Node& node, Building& v);
#endif // __MOD_HPP__
#include <network/game_server.hpp>
GameServer::GameServer(short port):
GameServer::GameServer(short port, Mod& mod):
Server<RemoteGameClient>(port)
{
this->world = new ServerWorld;
this->world = new ServerWorld(mod);
}
GameServer::~GameServer()
......
......@@ -14,13 +14,14 @@
# define __GAME_SERVER_HPP__
#include <world/server_world.hpp>
#include <mod/mod.hpp>
#include <network/server.hpp>
#include <network/remote_game_client.hpp>
class GameServer: public Server<RemoteGameClient>
{
public:
GameServer(short port);
GameServer(short port, Mod& mod);
~GameServer();
ServerWorld* get_world() const;
......
#include <world/client_world.hpp>
ClientWorld::ClientWorld():
World()
{
this->init();
}
ClientWorld::ClientWorld(Map* map):
World(map)
ClientWorld::ClientWorld(Map* map, Mod& mod):
World(map, mod)
{
}
......@@ -15,11 +9,6 @@ ClientWorld::~ClientWorld()
{
}
void ClientWorld::init()
{
}
void ClientWorld::new_occupant_callback(Command* command)
{
log_debug("new_occupant_callback");
......
......@@ -7,8 +7,7 @@
class ClientWorld: public World
{
public:
ClientWorld();
ClientWorld(Map*);
ClientWorld(Map*, Mod&);
~ClientWorld();
void init();
/**
......
......@@ -23,7 +23,7 @@ public:
* on a model.
*/
Entity(const Entity&);
virtual ~Entity() {};
virtual ~Entity() {};
unsigned short get_id() const { return this->id; }
/**
......
#include <world/server_world.hpp>
ServerWorld::ServerWorld():
World()
ServerWorld::ServerWorld(Mod& mod):
World(mod)
{
this->init();
}
......
......@@ -2,11 +2,12 @@
# define __SERVER_WORLD_HPP__
#include <world/world.hpp>
#include <mod/mod.hpp>
class ServerWorld: public World
{
public:
ServerWorld();
ServerWorld(Mod&);
~ServerWorld();
/**
* In addition to call World::init(), this will create the initial game
......
#include <world/world.hpp>
#include <world/path.hpp>
World::World():
World::World(Mod& mod):
started(false),
map(0)
{
this->replay = new Replay;
this->turn_handler = new TurnHandler(this->replay);
this->init();
this->init(mod);
}
World::World(Map* map):
World::World(Map* map, Mod& mod):
started(false),
map(map)
{
this->replay = new Replay;
this->turn_handler = new TurnHandler(this->replay);
this->init();
this->init(mod);
}
World::~World()
......
......@@ -36,6 +36,7 @@
#include <mpreal/mpreal.h>
#include <world/position.hpp>
#include <world/path.hpp>
#include <mod/mod.hpp>
/**
* From left to right, and from top to bottom, a cell has this size, in the
......@@ -48,15 +49,15 @@
class World
{
public:
World();
World(Map*);
World(Mod&);
World(Map*, Mod&);
~World();
/**
* Init the world by reading the Mod files.
* The initial state of the world (the map, the unit that are available
* and their stats, etc).
*/
void init();
void init(Mod&);
/**
* Start the world and it's turn_handler.
* Before this method is called, tick() will do nothing.
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment