From 85af1c09a2aff22d5d71b2be01cead12c6db88fe Mon Sep 17 00:00:00 2001 From: Joshua Moerman Date: Tue, 16 Apr 2013 21:26:08 +0200 Subject: [PATCH] Fixed some includes, made a basic implementation for forwarding an uberclient --- src/adaptions.h | 8 +++--- src/app.h | 75 +++++++++++++++++++++++++++++++++++++----------- src/app_common.h | 10 +++++-- src/main.cpp | 64 ++++++++++++++++++++++++----------------- src/websockets.h | 7 ++++- 5 files changed, 114 insertions(+), 50 deletions(-) diff --git a/src/adaptions.h b/src/adaptions.h index eebcf88..2e37f9a 100644 --- a/src/adaptions.h +++ b/src/adaptions.h @@ -4,9 +4,9 @@ #include #include -#include "simulation/Simulation.h" -#include "simulation/Beat.h" -#include "simulation/Math.h" +#include "../simulation/Simulation.h" +#include "../simulation/Beat.h" +#include "../simulation/Math.h" BOOST_FUSION_ADAPT_STRUCT( ::math::Vec2, @@ -28,4 +28,4 @@ BOOST_FUSION_ADAPT_TPL_STRUCT( (::math::Vec2, starting_point) (::math::Vec2, end_point) (simulation::LineKind, line_kind) -) \ No newline at end of file +) diff --git a/src/app.h b/src/app.h index d7f2ca4..ea52b14 100644 --- a/src/app.h +++ b/src/app.h @@ -7,33 +7,54 @@ #include #include +#include +#include "websockets.h" + #include "app_common.h" -struct libwebsocket; +using namespace websockets; + struct App{ std::vector people_online; libwebsocket * uberclient{nullptr}; - - std::vector lines; - - simu_type sim; - beat_type beat; - - const float iframerate = 1.0/60.0; int peopleuid{0}; int balluid{0}; + int lineuid{0}; + + struct OfflineSim { + std::vector lines; + std::vector balls; + } offline_sim; + + struct OnlineSim { + const float iframerate = 1.0/60.0; + std::vector lines; + simu_type sim; + beat_type beat; + } online_sim; 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); 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){ - lines.push_back(line); + online_sim.lines.push_back(line); for(auto & l : line.calculate_lines()){ - sim.lines.push_back(l); + online_sim.sim.lines.push_back(l); } for(auto & u : people_online){ u->update_lines = true; @@ -50,11 +71,33 @@ struct App{ } void update(){ - float dt = iframerate; - sim.update(dt); - - for(auto n : beat.update(dt)){ - sim.balls.emplace_back(n.x, n.y, 0, 0, balluid++); + if(!uberclient){ + float dt = online_sim.iframerate; + online_sim.sim.update(dt); + + for(auto n : online_sim.beat.update(dt)){ + 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(); } }; \ No newline at end of file diff --git a/src/app_common.h b/src/app_common.h index a5024a4..2ee9c73 100644 --- a/src/app_common.h +++ b/src/app_common.h @@ -3,8 +3,8 @@ #include "basics.h" #include "adaptions.h" -#include "simulation/Simulation.h" -#include "simulation/Beat.h" +#include "../simulation/Simulation.h" +#include "../simulation/Beat.h" using Vec2 = math::Vec2; using LineKind = simulation::LineKind; @@ -70,10 +70,15 @@ BOOST_FUSION_DEFINE_STRUCT( (int, y) ) +inline math::Vec2 to_FloatVec2(IntVec2 v){ + return {static_cast(v.x), static_cast(v.y)}; +} + struct cheap_ball_type { IntVec2 position; ball_info information; + cheap_ball_type() = default; cheap_ball_type(ball_type const & b) : position(b.position) , information(b.information) @@ -91,6 +96,7 @@ struct cheap_line_type { IntVec2 end_point; int line_kind; + cheap_line_type() = default; cheap_line_type(AbstractLine const & l) : starting_point(l.starting_point) , end_point(l.end_point) diff --git a/src/main.cpp b/src/main.cpp index 72bc143..8c73c51 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -31,24 +31,35 @@ websockets::TestProtocol default_protocol{ [](User& user, basic_websocket_info) -> std::string{ js::Object ret; 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; } 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); }, // receive - [](User& user, std::string in, basic_websocket_info){ + [](User& user, std::string in, basic_websocket_info binfo){ try{ auto object = parse_json(in).getObject(); auto command = object["command"]; if(command == "add line"){ - app->add_line(from_json(object["data"])); + app->add_line(from_json(object["data"])); std::cout << "Line from: " << &user << ": " << user.name << std::endl; + request_write(binfo); } else if (command == "update user") { user = from_json(object["data"]); std::cout << "Updated user: " << &user << ": " << user.name << std::endl; + } else if (command == "poll") { + request_write(binfo); } } catch(std::exception& e) { throw websockets::runtime_error(e.what()); @@ -56,32 +67,16 @@ websockets::TestProtocol default_protocol{ } }; -websockets::TestProtocol 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 uberclient_protocol{ // connection established [](Empty& user, basic_websocket_info binfo){ - if(app->uberclient) throw websockets::runtime_error("Warning: another uberclient connection\n"); - app->uberclient = binfo.wsi; + std::cout << "uberclient connected!\n"; + app->uberclient_connected(binfo); }, // connection closed - [](Empty& user, basic_websocket_info){ - app->uberclient = nullptr; + [](Empty& user, basic_websocket_info binfo){ + std::cout << "uberclient left!\n"; + app->uberclient_disconnected(binfo); }, // write (will always come after receive) [](Empty& user, basic_websocket_info) -> std::string{ @@ -89,7 +84,23 @@ websockets::TestProtocol uberclient_protocol{ return std::to_string(i++); }, // 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(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(js)); + } + } + } }; int main(int argc, char **argv){ @@ -97,7 +108,6 @@ int main(int argc, char **argv){ libwebsocket_protocols protocols[] = { WSstandard_protocol("default", default_protocol), - WSstandard_protocol("observer", observer_protocol), WSstandard_protocol("uberclient", uberclient_protocol), { NULL, NULL, 0 } // end of list }; diff --git a/src/websockets.h b/src/websockets.h index a5323f4..3cd81de 100644 --- a/src/websockets.h +++ b/src/websockets.h @@ -1,3 +1,5 @@ +#pragma once + #include #include #include @@ -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) // 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) @@ -146,7 +152,6 @@ namespace websockets { } case LWS_CALLBACK_RECEIVE: receive_func(user, std::string((char*)in, len), binfo); - libwebsocket_callback_on_writable(context, wsi); break; default: break;