testmodules/minigame

This commit is contained in:
Perttu Ahola 2014-09-20 01:37:37 +03:00
parent e6ee6600f6
commit 301887c179
6 changed files with 320 additions and 4 deletions

View File

@ -59,7 +59,7 @@ Modify something and see stuff happen
Edit something and then restart the client (CTRL+C in terminal 2):
$ cd $wherever_buildat_is
$ vim test/testmodules/test1/client_lua/init.lua
$ vim test/testmodules/test1/test1.cppp
$ vim test/testmodules/minigame/client_lua/init.lua
$ vim test/testmodules/minigame/minigame.cppp
$ vim builtin/network/network.cpp

View File

@ -47,8 +47,9 @@ struct Module: public interface::Module
m_server->load_module("client_data", builtin+"/client_data");
sv_<ss_> load_list = {
"test1",
"test2",
//"test1",
//"test2",
"minigame",
};
for(const ss_ &name : load_list){
m_server->load_module(name, m_server->get_modules_path()+"/"+name);

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

View File

@ -0,0 +1,134 @@
-- Buildat: minigame/client_lua/init.lua
local log = buildat.Logger("minigame")
local dump = buildat.dump
log:info("minigame/init.lua loaded")
local cereal = require("buildat/extension/cereal")
local g3d = require("buildat/extension/graphics3d")
scene = g3d.Scene(g3d.Scene.SCENE_3D)
ground = g3d.ScenePrimitive(g3d.ScenePrimitive.TYPE_PLANE, 10,10)
ground:loadTexture("minigame/green_texture.png")
scene:addEntity(ground)
scene:getDefaultCamera():setPosition(7,7,7)
scene:getDefaultCamera():lookAt(g3d.Vector3(0,0,0), g3d.Vector3(0,1,0))
local field = {}
local players = {}
local player_boxes = {}
local field_boxes = {}
buildat.sub_packet("minigame:update", function(data)
values = cereal.binary_input(data, {
"int32", "int32", "int32", "int32"
})
local peer = values[1]
local num_players = values[2]
local field_w = values[3]
local field_h = values[4]
values = cereal.binary_input(data, {
"int32", "int32", "int32", "int32",
{"int32", field_w*field_h}, {"int32", num_players*3}
})
--log:info("values="..dump(values))
local new_field = {}
for i=1,field_w*field_h do
table.insert(new_field, values[4+i])
end
field = new_field
log:info("field="..dump(field))
for _, box in ipairs(field_boxes) do
scene:removeEntity(box)
end
field_boxes = {}
for y=1,field_h do
for x=1,field_w do
local v = field[(y-1)*field_w + (x-1) + 1]
if v ~= 0 then
box = g3d.ScenePrimitive(g3d.ScenePrimitive.TYPE_BOX, 1,0.5*v,1)
box:loadTexture("minigame/green_texture.png")
box:setPosition(x-6, 0.25*v, y-6)
scene:addEntity(box)
table.insert(field_boxes, box)
end
end
end
local new_players = {}
local players_start = 5+field_w*field_h
for i=1,num_players do
local player = {
peer = values[players_start+(i-1)*3+0],
x = values[players_start+(i-1)*3+1],
y = values[players_start+(i-1)*3+2],
}
table.insert(new_players, player)
end
local old_players = players
players = new_players
log:info("players="..dump(players))
for _, player in ipairs(players) do
local is_new = true
for _, old_player in ipairs(old_players) do
if old_player.peer == player.peer then
is_new = false
break
end
end
if is_new then
box = g3d.ScenePrimitive(g3d.ScenePrimitive.TYPE_BOX, 0.9,0.9,0.9)
box:loadTexture("minigame/pink_texture.png")
box:setPosition(player.x-5, 0.5, player.y-5)
scene:addEntity(box)
player_boxes[player.peer] = box
end
local v = field[(player.y)*field_w + (player.x) + 1] or 0
player_boxes[player.peer]:setPosition(player.x-5, 0.5+v*0.5, player.y-5)
end
for _, old_player in ipairs(old_players) do
local was_removed = true
for _, player in ipairs(players) do
if player.peer == old_player.peer then
was_removed = false
break
end
end
if was_removed then
scene:removeEntity(player_boxes[old_player.peer])
end
end
end)
local keyinput = require("buildat/extension/keyinput")
keyinput.sub(function(key, state)
if key == keyinput.KEY_LEFT then
if state == "down" then
buildat.send_packet("minigame:move", "left")
end
end
if key == keyinput.KEY_RIGHT then
if state == "down" then
buildat.send_packet("minigame:move", "right")
end
end
if key == keyinput.KEY_UP then
if state == "down" then
buildat.send_packet("minigame:move", "up")
end
end
if key == keyinput.KEY_DOWN then
if state == "down" then
buildat.send_packet("minigame:move", "down")
end
end
if key == keyinput.KEY_SPACE then
if state == "down" then
buildat.send_packet("minigame:move", "place")
end
end
end)

View File

@ -0,0 +1,181 @@
#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>
#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){
tiles.resize(w*h);
}
int get(int x, int y){
size_t i = y*w + x;
if(i > tiles.size())
return 0;
return tiles[i];
}
void set(int x, int y, int v){
size_t i = y*w + x;
if(i > tiles.size())
return;
tiles[i] = v;
}
};
struct Player
{
int peer = 0;
int x = 0;
int y = 0;
Player(int peer=0, int x=0, int y=0): peer(peer), x(x), y(y){}
};
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"));
}
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)
}
void on_start()
{
}
void send_update(int peer)
{
std::ostringstream os(std::ios::binary);
{
cereal::PortableBinaryOutputArchive ar(os);
ar((int32_t)peer);
ar((int32_t)m_players.size());
ar((int32_t)m_playfield.w, (int32_t)m_playfield.h);
// TODO: A way for Lua to read vectors directly
for(int t : m_playfield.tiles)
ar(t);
for(auto &pair : m_players){
auto &player = pair.second;
ar((int32_t)player.peer);
ar((int32_t)player.x);
ar((int32_t)player.y);
}
}
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;
m_players[peer] = Player(peer, rand()%10, rand()%10);
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",
"buildat:run_script_file(\"minigame/init.lua\")");
});
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;
if(packet.data == "left")
player.x -= 1;
if(packet.data == "right")
player.x += 1;
if(packet.data == "up")
player.y -= 1;
if(packet.data == "down")
player.y += 1;
if(packet.data == "place"){
m_playfield.set(player.x, player.y,
m_playfield.get(player.x, player.y) + 1);
}
for(auto &pair : m_players)
send_update(pair.second.peer);
}
};
extern "C" {
EXPORT void* createModule_minigame(interface::Server *server){
return (void*)(new Module(server));
}
}
}