testmodules/minigame
This commit is contained in:
parent
e6ee6600f6
commit
301887c179
@ -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
|
||||
|
||||
|
@ -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);
|
||||
|
BIN
test/testmodules/minigame/client_data/green_texture.png
Normal file
BIN
test/testmodules/minigame/client_data/green_texture.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 3.1 KiB |
BIN
test/testmodules/minigame/client_data/pink_texture.png
Normal file
BIN
test/testmodules/minigame/client_data/pink_texture.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 3.1 KiB |
134
test/testmodules/minigame/client_lua/init.lua
Normal file
134
test/testmodules/minigame/client_lua/init.lua
Normal 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)
|
||||
|
181
test/testmodules/minigame/minigame.cpp
Normal file
181
test/testmodules/minigame/minigame.cpp
Normal 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));
|
||||
}
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user