#include "game.h" #include "video.h" #include "messages.h" #include #include #include Game* Game::game = NULL; Game::Game() : socket(io_service) { scene = new Scene(); scene->lua->set_say_func(boost::bind(&Game::say, this, _1)); } Game::~Game() { delete scene; } void Game::say(const std::string msg) { message::Message m(msg); m.send(socket); } void Game::run(const std::string host, const unsigned int port) { run(host, boost::lexical_cast(port)); } void Game::run(const std::string host, const std::string port) { SDL_WarpMouse(video::width/2, video::height/2); scene->last_time = SDL_GetTicks(); scene->update(); { boost::asio::ip::tcp::resolver resolver(io_service); boost::asio::ip::tcp::resolver::query query(host, port); boost::asio::ip::tcp::resolver::iterator iterator = resolver.resolve(query); socket.connect(boost::asio::ip::tcp::endpoint(*iterator)); message::Hello h(1); h.send(socket); } async_read(); unsigned int last = SDL_GetTicks(); Vector3 last_pos = scene->pos; while(scene->running) { if(SDL_GetTicks() - last >= 100 && scene->pos != last_pos) { message::Pos pos(scene->pos); pos.send(socket); last = SDL_GetTicks(); } io_service.poll_one(); scene->events(); scene->render(); SDL_Delay(1); } } void Game::async_read() { uint8_t *t = new uint8_t; boost::asio::async_read(socket, boost::asio::buffer(t, sizeof(uint8_t)), boost::asio::transfer_all(), boost::bind(&Game::handle_type, this, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred, t)); } void Game::handle_type(const boost::system::error_code& error, std::size_t bytes_transferred, uint8_t *type) { if(error) { std::cerr << error << std::endl; delete type; scene->running = false; return; } switch(*type) { case message::MSG_TYPE_POS: handle_pos(); break; case message::MSG_TYPE_CHUNK: handle_chunk(); break; case message::MSG_TYPE_MSG: handle_message(); break; case message::MSG_TYPE_PLAYER: handle_player(); break; case message::MSG_TYPE_OBJECT: handle_object(); break; default: std::cout << "unknown type: " << (int)*type << std::endl; } delete type; async_read(); } void Game::handle_pos() { message::Pos m; m.recv(socket); uint32_t id = m.get_id(); Vector3 pos = m.get_pos(); if(id == 0) { // my pos scene->pos = pos; } else { // other player's pos for(PlayerList::iterator it = scene->players.begin(); it != scene->players.end(); it++) { if((*it)->get_id() == id) { (*it)->set_pos(pos); break; } } } } void Game::handle_chunk() { message::Chunk m; m.recv(socket); int64_t x, y; m.get_coords(x, y); float *data = m.get_data(); scene->terrain->tc->add_chunk(data, x, y, Terrain::chunk_size_total, Terrain::chunk_size_total); Terrain::Chunk *chunk = NULL; try { chunk = new Terrain::Chunk(scene->terrain, x, y); } catch(...) { } if(chunk) scene->terrain->chunks.push_back(chunk); } void Game::handle_message() { message::Message m; m.recv(socket); std::string s = m.get_str(); scene->chat->add_line(s); } void Game::handle_player() { message::Player m; m.recv(socket); uint32_t id = m.get_id(); Vector3 pos(m.get_pos()); std::string name = m.get_name(); scene->players.push_back(Player::p(new Player(id, pos, name))); } void Game::handle_object() { message::Object m; m.recv(socket); // type is ignored for now uint32_t type = m.get_type(); Vector3 pos(m.get_pos()); Terrain::Chunk *chunk = scene->terrain->find_chunk(pos.x, pos.z); if(!chunk) { std::cerr << "got object for non-existing chunk, discarding" << std::endl; return; } pos.y = chunk->find(pos.x, pos.z)->get_height(pos.x, pos.z); int64_t x = pos.x; x -= x % Terrain::chunk_size; int64_t z = pos.z; z -= z % Terrain::chunk_size; TerrainCacheObject::p ob = scene->terrain->tc->get_chunk(x, z, Terrain::chunk_size_total, Terrain::chunk_size_total); ob->objects.push_back(pos); models::ModelManager& model_mgr = models::ModelManager::get_instance(); chunk->objects.push_back(Terrain::Chunk::ObjectPair(model_mgr.get_model("tree"), pos)); } Game& Game::get_instance() { if(!game) game = new Game(); return *game; } void Game::free() { if(game) { delete game; game = NULL; } }