Fixed some includes, made a basic implementation for forwarding an uberclient
This commit is contained in:
parent
d3dcc616f8
commit
85af1c09a2
5 changed files with 114 additions and 50 deletions
|
@ -4,9 +4,9 @@
|
||||||
#include <boost/fusion/include/define_struct.hpp>
|
#include <boost/fusion/include/define_struct.hpp>
|
||||||
#include <boost/fusion/include/adapt_struct.hpp>
|
#include <boost/fusion/include/adapt_struct.hpp>
|
||||||
|
|
||||||
#include "simulation/Simulation.h"
|
#include "../simulation/Simulation.h"
|
||||||
#include "simulation/Beat.h"
|
#include "../simulation/Beat.h"
|
||||||
#include "simulation/Math.h"
|
#include "../simulation/Math.h"
|
||||||
|
|
||||||
BOOST_FUSION_ADAPT_STRUCT(
|
BOOST_FUSION_ADAPT_STRUCT(
|
||||||
::math::Vec2,
|
::math::Vec2,
|
||||||
|
|
73
src/app.h
73
src/app.h
|
@ -7,33 +7,54 @@
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
|
#include <lib/libwebsockets.h>
|
||||||
|
#include "websockets.h"
|
||||||
|
|
||||||
#include "app_common.h"
|
#include "app_common.h"
|
||||||
|
|
||||||
struct libwebsocket;
|
using namespace websockets;
|
||||||
|
|
||||||
struct App{
|
struct App{
|
||||||
std::vector<User*> people_online;
|
std::vector<User*> people_online;
|
||||||
libwebsocket * uberclient{nullptr};
|
libwebsocket * uberclient{nullptr};
|
||||||
|
|
||||||
std::vector<AbstractLine> lines;
|
|
||||||
|
|
||||||
simu_type sim;
|
|
||||||
beat_type beat;
|
|
||||||
|
|
||||||
const float iframerate = 1.0/60.0;
|
|
||||||
int peopleuid{0};
|
int peopleuid{0};
|
||||||
int balluid{0};
|
int balluid{0};
|
||||||
|
int lineuid{0};
|
||||||
|
|
||||||
|
struct OfflineSim {
|
||||||
|
std::vector<cheap_line_type> lines;
|
||||||
|
std::vector<cheap_ball_type> balls;
|
||||||
|
} offline_sim;
|
||||||
|
|
||||||
|
struct OnlineSim {
|
||||||
|
const float iframerate = 1.0/60.0;
|
||||||
|
std::vector<AbstractLine> lines;
|
||||||
|
simu_type sim;
|
||||||
|
beat_type beat;
|
||||||
|
} online_sim;
|
||||||
|
|
||||||
App(){
|
App(){
|
||||||
beat.notes.emplace_back(note_type::kQuarterNote, note_info{100.0f, 100.0f});
|
online_sim.beat.notes.emplace_back(note_type::kQuarterNote, note_info{100.0f, 100.0f});
|
||||||
|
|
||||||
AbstractLine line(Vec2{50.0f, 100.0f}, Vec2{150.0f, 200.0f}, simulation::kOneWay);
|
AbstractLine line(Vec2{50.0f, 100.0f}, Vec2{150.0f, 200.0f}, simulation::kOneWay);
|
||||||
add_line(line);
|
add_line(line);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void add_line(cheap_line_type const & line){
|
||||||
|
if(uberclient){
|
||||||
|
// write
|
||||||
|
} else {
|
||||||
|
add_line(AbstractLine{
|
||||||
|
to_FloatVec2(line.starting_point),
|
||||||
|
to_FloatVec2(line.end_point),
|
||||||
|
line.line_kind});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void add_line(AbstractLine const & line){
|
void add_line(AbstractLine const & line){
|
||||||
lines.push_back(line);
|
online_sim.lines.push_back(line);
|
||||||
for(auto & l : line.calculate_lines()){
|
for(auto & l : line.calculate_lines()){
|
||||||
sim.lines.push_back(l);
|
online_sim.sim.lines.push_back(l);
|
||||||
}
|
}
|
||||||
for(auto & u : people_online){
|
for(auto & u : people_online){
|
||||||
u->update_lines = true;
|
u->update_lines = true;
|
||||||
|
@ -50,11 +71,33 @@ struct App{
|
||||||
}
|
}
|
||||||
|
|
||||||
void update(){
|
void update(){
|
||||||
float dt = iframerate;
|
if(!uberclient){
|
||||||
sim.update(dt);
|
float dt = online_sim.iframerate;
|
||||||
|
online_sim.sim.update(dt);
|
||||||
|
|
||||||
for(auto n : beat.update(dt)){
|
for(auto n : online_sim.beat.update(dt)){
|
||||||
sim.balls.emplace_back(n.x, n.y, 0, 0, balluid++);
|
online_sim.sim.balls.emplace_back(n.x, n.y, 0, 0, balluid++);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void uberclient_connected(basic_websocket_info binfo){
|
||||||
|
if(uberclient) throw websockets::runtime_error("Warning: another uberclient connection\n");
|
||||||
|
uberclient = binfo.wsi;
|
||||||
|
|
||||||
|
online_sim.lines.clear();
|
||||||
|
online_sim.sim.lines.clear();
|
||||||
|
online_sim.sim.balls.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void uberclient_disconnected(basic_websocket_info binfo){
|
||||||
|
if(uberclient != binfo.wsi) throw websockets::runtime_error("Warning: non-uberclient disconnected");
|
||||||
|
uberclient = nullptr;
|
||||||
|
|
||||||
|
for(auto l : offline_sim.lines){
|
||||||
|
add_line(l);
|
||||||
|
}
|
||||||
|
offline_sim.lines.clear();
|
||||||
|
offline_sim.balls.clear();
|
||||||
|
}
|
||||||
};
|
};
|
|
@ -3,8 +3,8 @@
|
||||||
#include "basics.h"
|
#include "basics.h"
|
||||||
#include "adaptions.h"
|
#include "adaptions.h"
|
||||||
|
|
||||||
#include "simulation/Simulation.h"
|
#include "../simulation/Simulation.h"
|
||||||
#include "simulation/Beat.h"
|
#include "../simulation/Beat.h"
|
||||||
|
|
||||||
using Vec2 = math::Vec2;
|
using Vec2 = math::Vec2;
|
||||||
using LineKind = simulation::LineKind;
|
using LineKind = simulation::LineKind;
|
||||||
|
@ -70,10 +70,15 @@ BOOST_FUSION_DEFINE_STRUCT(
|
||||||
(int, y)
|
(int, y)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
inline math::Vec2 to_FloatVec2(IntVec2 v){
|
||||||
|
return {static_cast<float>(v.x), static_cast<float>(v.y)};
|
||||||
|
}
|
||||||
|
|
||||||
struct cheap_ball_type {
|
struct cheap_ball_type {
|
||||||
IntVec2 position;
|
IntVec2 position;
|
||||||
ball_info information;
|
ball_info information;
|
||||||
|
|
||||||
|
cheap_ball_type() = default;
|
||||||
cheap_ball_type(ball_type const & b)
|
cheap_ball_type(ball_type const & b)
|
||||||
: position(b.position)
|
: position(b.position)
|
||||||
, information(b.information)
|
, information(b.information)
|
||||||
|
@ -91,6 +96,7 @@ struct cheap_line_type {
|
||||||
IntVec2 end_point;
|
IntVec2 end_point;
|
||||||
int line_kind;
|
int line_kind;
|
||||||
|
|
||||||
|
cheap_line_type() = default;
|
||||||
cheap_line_type(AbstractLine const & l)
|
cheap_line_type(AbstractLine const & l)
|
||||||
: starting_point(l.starting_point)
|
: starting_point(l.starting_point)
|
||||||
, end_point(l.end_point)
|
, end_point(l.end_point)
|
||||||
|
|
64
src/main.cpp
64
src/main.cpp
|
@ -31,24 +31,35 @@ websockets::TestProtocol<User> default_protocol{
|
||||||
[](User& user, basic_websocket_info) -> std::string{
|
[](User& user, basic_websocket_info) -> std::string{
|
||||||
js::Object ret;
|
js::Object ret;
|
||||||
if(user.update_lines){
|
if(user.update_lines){
|
||||||
ret["lines"] = vector_to_json(app->lines, [](AbstractLine const & l){return cheap_line_type(l);});
|
if(app->uberclient){
|
||||||
|
ret["lines"] = vector_to_json(app->offline_sim.lines);
|
||||||
|
} else {
|
||||||
|
ret["lines"] = vector_to_json(app->online_sim.lines, [](AbstractLine const & l){return cheap_line_type(l);});
|
||||||
|
}
|
||||||
user.update_lines = false;
|
user.update_lines = false;
|
||||||
} else {
|
} else {
|
||||||
ret["balls"] = vector_to_json(app->sim.balls, [](ball_type const & b){return cheap_ball_type(b);});
|
if(app->uberclient){
|
||||||
|
ret["balls"] = vector_to_json(app->offline_sim.balls);
|
||||||
|
} else {
|
||||||
|
ret["balls"] = vector_to_json(app->online_sim.sim.balls, [](ball_type const & b){return cheap_ball_type(b);});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return write_json(ret);
|
return write_json(ret);
|
||||||
},
|
},
|
||||||
// receive
|
// receive
|
||||||
[](User& user, std::string in, basic_websocket_info){
|
[](User& user, std::string in, basic_websocket_info binfo){
|
||||||
try{
|
try{
|
||||||
auto object = parse_json(in).getObject();
|
auto object = parse_json(in).getObject();
|
||||||
auto command = object["command"];
|
auto command = object["command"];
|
||||||
if(command == "add line"){
|
if(command == "add line"){
|
||||||
app->add_line(from_json<AbstractLine>(object["data"]));
|
app->add_line(from_json<cheap_line_type>(object["data"]));
|
||||||
std::cout << "Line from: " << &user << ": " << user.name << std::endl;
|
std::cout << "Line from: " << &user << ": " << user.name << std::endl;
|
||||||
|
request_write(binfo);
|
||||||
} else if (command == "update user") {
|
} else if (command == "update user") {
|
||||||
user = from_json<IncomingPacket>(object["data"]);
|
user = from_json<IncomingPacket>(object["data"]);
|
||||||
std::cout << "Updated user: " << &user << ": " << user.name << std::endl;
|
std::cout << "Updated user: " << &user << ": " << user.name << std::endl;
|
||||||
|
} else if (command == "poll") {
|
||||||
|
request_write(binfo);
|
||||||
}
|
}
|
||||||
} catch(std::exception& e) {
|
} catch(std::exception& e) {
|
||||||
throw websockets::runtime_error(e.what());
|
throw websockets::runtime_error(e.what());
|
||||||
|
@ -56,32 +67,16 @@ websockets::TestProtocol<User> default_protocol{
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
websockets::TestProtocol<Empty> observer_protocol{
|
|
||||||
// connection established
|
|
||||||
[](Empty& user, basic_websocket_info){},
|
|
||||||
// connection closed
|
|
||||||
[](Empty& user, basic_websocket_info){},
|
|
||||||
// write (will always come after receive)
|
|
||||||
[](Empty& user, basic_websocket_info) -> std::string{
|
|
||||||
js::Object ret;
|
|
||||||
ret["people"] = vector_to_json(app->people_online, [](User* u){return *u;});
|
|
||||||
ret["balls"] = vector_to_json(app->sim.balls);
|
|
||||||
ret["lines"] = vector_to_json(app->sim.lines);
|
|
||||||
return write_json(ret);
|
|
||||||
},
|
|
||||||
// receive
|
|
||||||
[](Empty& user, std::string in, basic_websocket_info){}
|
|
||||||
};
|
|
||||||
|
|
||||||
websockets::TestProtocol<Empty> uberclient_protocol{
|
websockets::TestProtocol<Empty> uberclient_protocol{
|
||||||
// connection established
|
// connection established
|
||||||
[](Empty& user, basic_websocket_info binfo){
|
[](Empty& user, basic_websocket_info binfo){
|
||||||
if(app->uberclient) throw websockets::runtime_error("Warning: another uberclient connection\n");
|
std::cout << "uberclient connected!\n";
|
||||||
app->uberclient = binfo.wsi;
|
app->uberclient_connected(binfo);
|
||||||
},
|
},
|
||||||
// connection closed
|
// connection closed
|
||||||
[](Empty& user, basic_websocket_info){
|
[](Empty& user, basic_websocket_info binfo){
|
||||||
app->uberclient = nullptr;
|
std::cout << "uberclient left!\n";
|
||||||
|
app->uberclient_disconnected(binfo);
|
||||||
},
|
},
|
||||||
// write (will always come after receive)
|
// write (will always come after receive)
|
||||||
[](Empty& user, basic_websocket_info) -> std::string{
|
[](Empty& user, basic_websocket_info) -> std::string{
|
||||||
|
@ -89,7 +84,23 @@ websockets::TestProtocol<Empty> uberclient_protocol{
|
||||||
return std::to_string(i++);
|
return std::to_string(i++);
|
||||||
},
|
},
|
||||||
// receive
|
// receive
|
||||||
[](Empty& user, std::string in, basic_websocket_info){}
|
[](Empty& user, std::string in, basic_websocket_info){
|
||||||
|
auto object = parse_json(in).getObject();
|
||||||
|
if(object.count("lines")){
|
||||||
|
app->offline_sim.lines.clear();
|
||||||
|
auto lines = object["lines"];
|
||||||
|
for(auto&& js : lines.getArray()){
|
||||||
|
app->offline_sim.lines.push_back(from_json<cheap_line_type>(js));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(object.count("balls")){
|
||||||
|
app->offline_sim.balls.clear();
|
||||||
|
auto balls = object["balls"];
|
||||||
|
for(auto&& js : balls.getArray()){
|
||||||
|
app->offline_sim.balls.push_back(from_json<cheap_ball_type>(js));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
int main(int argc, char **argv){
|
int main(int argc, char **argv){
|
||||||
|
@ -97,7 +108,6 @@ int main(int argc, char **argv){
|
||||||
|
|
||||||
libwebsocket_protocols protocols[] = {
|
libwebsocket_protocols protocols[] = {
|
||||||
WSstandard_protocol("default", default_protocol),
|
WSstandard_protocol("default", default_protocol),
|
||||||
WSstandard_protocol("observer", observer_protocol),
|
|
||||||
WSstandard_protocol("uberclient", uberclient_protocol),
|
WSstandard_protocol("uberclient", uberclient_protocol),
|
||||||
{ NULL, NULL, 0 } // end of list
|
{ NULL, NULL, 0 } // end of list
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
@ -97,6 +99,10 @@ namespace websockets {
|
||||||
{}
|
{}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
inline void request_write(basic_websocket_info const & binfo){
|
||||||
|
libwebsocket_callback_on_writable(binfo.context, binfo.wsi);
|
||||||
|
}
|
||||||
|
|
||||||
// 4-function Protocol, provide functions to handle establishment, closing, receiving and writing (follows receiving)
|
// 4-function Protocol, provide functions to handle establishment, closing, receiving and writing (follows receiving)
|
||||||
// To let the callback return something non-zero (in case of error), use websockets::runtime_error
|
// To let the callback return something non-zero (in case of error), use websockets::runtime_error
|
||||||
// Only types with no-arg ctor are allowed (uses placement new, because libwebsockets allocates for us)
|
// Only types with no-arg ctor are allowed (uses placement new, because libwebsockets allocates for us)
|
||||||
|
@ -146,7 +152,6 @@ namespace websockets {
|
||||||
}
|
}
|
||||||
case LWS_CALLBACK_RECEIVE:
|
case LWS_CALLBACK_RECEIVE:
|
||||||
receive_func(user, std::string((char*)in, len), binfo);
|
receive_func(user, std::string((char*)in, len), binfo);
|
||||||
libwebsocket_callback_on_writable(context, wsi);
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
|
Reference in a new issue