Browse Source

Fixed some includes, made a basic implementation for forwarding an uberclient

master
Joshua Moerman 12 years ago
parent
commit
85af1c09a2
  1. 8
      src/adaptions.h
  2. 75
      src/app.h
  3. 10
      src/app_common.h
  4. 64
      src/main.cpp
  5. 7
      src/websockets.h

8
src/adaptions.h

@ -4,9 +4,9 @@
#include <boost/fusion/include/define_struct.hpp>
#include <boost/fusion/include/adapt_struct.hpp>
#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)
)
)

75
src/app.h

@ -7,33 +7,54 @@
#include <vector>
#include <algorithm>
#include <lib/libwebsockets.h>
#include "websockets.h"
#include "app_common.h"
struct libwebsocket;
using namespace websockets;
struct App{
std::vector<User*> people_online;
libwebsocket * uberclient{nullptr};
std::vector<AbstractLine> 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<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(){
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();
}
};

10
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<float>(v.x), static_cast<float>(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)

64
src/main.cpp

@ -31,24 +31,35 @@ websockets::TestProtocol<User> 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<AbstractLine>(object["data"]));
app->add_line(from_json<cheap_line_type>(object["data"]));
std::cout << "Line from: " << &user << ": " << user.name << std::endl;
request_write(binfo);
} else if (command == "update user") {
user = from_json<IncomingPacket>(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<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{
// 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<Empty> 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<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){
@ -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
};

7
src/websockets.h

@ -1,3 +1,5 @@
#pragma once
#include <iostream>
#include <string>
#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)
// 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;