2014-09-20 01:37:37 +03:00
|
|
|
#include "interface/module.h"
|
|
|
|
#include "interface/server.h"
|
|
|
|
#include "interface/event.h"
|
|
|
|
#include "client_file/api.h"
|
|
|
|
#include "network/api.h"
|
|
|
|
#include "core/log.h"
|
|
|
|
#include <cereal/archives/portable_binary.hpp>
|
2014-09-20 14:38:49 +03:00
|
|
|
#include <cereal/types/unordered_map.hpp>
|
|
|
|
#include <cereal/types/vector.hpp>
|
2014-09-20 01:37:37 +03:00
|
|
|
#include <cstdlib>
|
|
|
|
|
|
|
|
using interface::Event;
|
|
|
|
|
|
|
|
namespace minigame {
|
|
|
|
|
|
|
|
struct Playfield
|
|
|
|
{
|
|
|
|
size_t w = 0;
|
|
|
|
size_t h = 0;
|
|
|
|
sv_<int> tiles;
|
|
|
|
Playfield(size_t w, size_t h): w(w), h(h){
|
2014-09-20 11:23:49 +03:00
|
|
|
tiles.resize(w * h);
|
2014-09-20 01:37:37 +03:00
|
|
|
}
|
|
|
|
int get(int x, int y){
|
2014-09-20 11:23:49 +03:00
|
|
|
size_t i = y * w + x;
|
2014-09-20 01:37:37 +03:00
|
|
|
if(i > tiles.size())
|
|
|
|
return 0;
|
|
|
|
return tiles[i];
|
|
|
|
}
|
|
|
|
void set(int x, int y, int v){
|
2014-09-20 11:23:49 +03:00
|
|
|
size_t i = y * w + x;
|
2014-09-20 01:37:37 +03:00
|
|
|
if(i > tiles.size())
|
|
|
|
return;
|
2014-09-30 12:31:37 +03:00
|
|
|
if(!inside_field(x, y))
|
2014-09-29 19:02:12 +02:00
|
|
|
return;
|
2014-09-20 01:37:37 +03:00
|
|
|
tiles[i] = v;
|
|
|
|
}
|
2014-09-20 14:38:49 +03:00
|
|
|
|
2014-09-29 19:02:12 +02:00
|
|
|
bool inside_field(int x, int y){
|
2014-09-30 12:31:37 +03:00
|
|
|
if(x >= w || x < 0)
|
2014-09-29 19:02:12 +02:00
|
|
|
return false;
|
2014-09-30 12:31:37 +03:00
|
|
|
if(y >= h || y < 0)
|
2014-09-29 19:02:12 +02:00
|
|
|
return false;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2014-09-20 14:38:49 +03:00
|
|
|
template<class Archive>
|
|
|
|
void serialize(Archive &archive){
|
|
|
|
archive((int32_t)w, (int32_t)h);
|
|
|
|
archive(tiles);
|
|
|
|
}
|
2014-09-20 01:37:37 +03:00
|
|
|
};
|
|
|
|
|
|
|
|
struct Player
|
|
|
|
{
|
|
|
|
int peer = 0;
|
|
|
|
int x = 0;
|
|
|
|
int y = 0;
|
2014-09-20 14:38:49 +03:00
|
|
|
|
2014-09-20 11:23:49 +03:00
|
|
|
Player(int peer = 0, int x = 0, int y = 0): peer(peer), x(x), y(y){}
|
2014-09-20 14:38:49 +03:00
|
|
|
|
|
|
|
template<class Archive>
|
|
|
|
void serialize(Archive &archive){
|
|
|
|
archive((int32_t)peer, (int32_t)x, (int32_t)y);
|
|
|
|
}
|
2014-09-20 01:37:37 +03:00
|
|
|
};
|
|
|
|
|
|
|
|
struct Module: public interface::Module
|
|
|
|
{
|
|
|
|
interface::Server *m_server;
|
|
|
|
Playfield m_playfield;
|
|
|
|
sm_<int, Player> m_players;
|
|
|
|
|
|
|
|
Module(interface::Server *server):
|
|
|
|
interface::Module("minigame"),
|
|
|
|
m_server(server),
|
|
|
|
m_playfield(10, 10)
|
|
|
|
{
|
|
|
|
log_v(MODULE, "minigame construct");
|
|
|
|
}
|
|
|
|
|
|
|
|
~Module()
|
|
|
|
{
|
|
|
|
log_v(MODULE, "minigame destruct");
|
|
|
|
}
|
|
|
|
|
|
|
|
void init()
|
|
|
|
{
|
|
|
|
log_v(MODULE, "minigame init");
|
|
|
|
m_server->sub_event(this, Event::t("core:start"));
|
|
|
|
m_server->sub_event(this, Event::t("network:new_client"));
|
|
|
|
m_server->sub_event(this, Event::t("network:client_disconnected"));
|
|
|
|
m_server->sub_event(this, Event::t("client_file:files_transmitted"));
|
|
|
|
m_server->sub_event(this, Event::t("network:packet_received/minigame:move"));
|
2014-09-22 18:57:34 +03:00
|
|
|
m_server->sub_event(this,
|
|
|
|
Event::t("network:packet_received/minigame:clear_field"));
|
2014-09-20 01:37:37 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
void event(const Event::Type &type, const Event::Private *p)
|
|
|
|
{
|
|
|
|
EVENT_VOIDN("core:start", on_start)
|
|
|
|
EVENT_TYPEN("network:new_client", on_new_client, network::NewClient)
|
|
|
|
EVENT_TYPEN("network:client_disconnected", on_client_disconnected,
|
|
|
|
network::OldClient)
|
|
|
|
EVENT_TYPEN("client_file:files_transmitted", on_files_transmitted,
|
|
|
|
client_file::FilesTransmitted)
|
|
|
|
EVENT_TYPEN("network:packet_received/minigame:move", on_packet_move,
|
|
|
|
network::Packet)
|
2014-09-22 02:16:21 +03:00
|
|
|
EVENT_TYPEN("network:packet_received/minigame:clear_field",
|
|
|
|
on_packet_clear_field, network::Packet)
|
2014-09-20 01:37:37 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
void on_start()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
void send_update(int peer)
|
|
|
|
{
|
|
|
|
std::ostringstream os(std::ios::binary);
|
|
|
|
{
|
|
|
|
cereal::PortableBinaryOutputArchive ar(os);
|
|
|
|
ar((int32_t)peer);
|
2014-09-20 14:38:49 +03:00
|
|
|
ar(m_players);
|
|
|
|
ar(m_playfield);
|
2014-09-20 01:37:37 +03:00
|
|
|
}
|
|
|
|
network::access(m_server, [&](network::Interface * inetwork){
|
|
|
|
inetwork->send(peer, "minigame:update", os.str());
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
void on_new_client(const network::NewClient &new_client)
|
|
|
|
{
|
|
|
|
log_i(MODULE, "minigame::on_new_client: id=%zu", new_client.info.id);
|
|
|
|
|
|
|
|
int peer = new_client.info.id;
|
|
|
|
|
2014-09-20 11:23:49 +03:00
|
|
|
m_players[peer] = Player(peer, rand() % 10, rand() % 10);
|
2014-09-20 01:37:37 +03:00
|
|
|
|
|
|
|
for(auto &pair : m_players)
|
|
|
|
send_update(pair.second.peer);
|
|
|
|
}
|
|
|
|
|
|
|
|
void on_client_disconnected(const network::OldClient &old_client)
|
|
|
|
{
|
|
|
|
log_i(MODULE, "minigame::on_client_disconnected: id=%zu", old_client.info.id);
|
|
|
|
|
|
|
|
int peer = old_client.info.id;
|
|
|
|
|
|
|
|
m_players.erase(peer);
|
|
|
|
|
|
|
|
for(auto &pair : m_players)
|
|
|
|
send_update(pair.second.peer);
|
|
|
|
}
|
|
|
|
|
|
|
|
void on_files_transmitted(const client_file::FilesTransmitted &event)
|
|
|
|
{
|
|
|
|
log_v(MODULE, "on_files_transmitted(): recipient=%zu", event.recipient);
|
|
|
|
|
|
|
|
network::access(m_server, [&](network::Interface * inetwork){
|
|
|
|
inetwork->send(event.recipient, "core:run_script",
|
2014-09-29 23:50:37 +03:00
|
|
|
"buildat.run_script_file(\"main/init.lua\")");
|
2014-09-20 01:37:37 +03:00
|
|
|
});
|
|
|
|
|
|
|
|
send_update(event.recipient);
|
|
|
|
}
|
|
|
|
|
|
|
|
void on_packet_move(const network::Packet &packet)
|
|
|
|
{
|
|
|
|
log_i(MODULE, "minigame::on_packet_move: name=%zu, size=%zu",
|
|
|
|
cs(packet.name), packet.data.size());
|
|
|
|
auto it = m_players.find(packet.sender);
|
|
|
|
if(it == m_players.end()){
|
|
|
|
log_w(MODULE, "Player not found: %i", packet.sender);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
Player &player = it->second;
|
2014-09-29 19:02:12 +02:00
|
|
|
if(packet.data == "up")
|
2014-09-20 01:37:37 +03:00
|
|
|
player.x -= 1;
|
2014-09-29 19:02:12 +02:00
|
|
|
if(packet.data == "down")
|
2014-09-20 01:37:37 +03:00
|
|
|
player.x += 1;
|
2014-09-29 19:02:12 +02:00
|
|
|
if(packet.data == "left")
|
2014-09-20 01:37:37 +03:00
|
|
|
player.y -= 1;
|
2014-09-29 19:02:12 +02:00
|
|
|
if(packet.data == "right")
|
2014-09-20 01:37:37 +03:00
|
|
|
player.y += 1;
|
|
|
|
if(packet.data == "place"){
|
2014-09-20 11:23:49 +03:00
|
|
|
m_playfield.set(player.x, player.y,
|
2014-09-20 01:37:37 +03:00
|
|
|
m_playfield.get(player.x, player.y) + 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
for(auto &pair : m_players)
|
|
|
|
send_update(pair.second.peer);
|
|
|
|
}
|
2014-09-22 02:16:21 +03:00
|
|
|
|
|
|
|
void on_packet_clear_field(const network::Packet &packet)
|
|
|
|
{
|
|
|
|
log_i(MODULE, "minigame::on_packet_clear_field: name=%zu, size=%zu",
|
|
|
|
cs(packet.name), packet.data.size());
|
|
|
|
|
2014-09-22 18:57:34 +03:00
|
|
|
for(size_t y = 0; y < m_playfield.h; y++)
|
|
|
|
for(size_t x = 0; x < m_playfield.w; x++)
|
|
|
|
m_playfield.set(x, y, 0);
|
2014-09-22 02:16:21 +03:00
|
|
|
|
|
|
|
for(auto &pair : m_players)
|
|
|
|
send_update(pair.second.peer);
|
|
|
|
}
|
2014-09-20 01:37:37 +03:00
|
|
|
};
|
|
|
|
|
|
|
|
extern "C" {
|
2014-09-29 23:50:37 +03:00
|
|
|
EXPORT void* createModule_main(interface::Server *server){
|
2014-09-20 01:37:37 +03:00
|
|
|
return (void*)(new Module(server));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2014-09-24 14:53:57 +03:00
|
|
|
// vim: set noet ts=4 sw=4:
|