-
Notifications
You must be signed in to change notification settings - Fork 0
Home
HyroVitalyProtago edited this page Apr 1, 2022
·
8 revisions
- Peers are discovered through a signalling server and connected through WebRTC.
- A contract is established between them as a list of slots. This way, only listened messages are sent between them.
- The contract evolves during the connection when listeners are added/removed through on/off calls.
- Messages are initially serialized in JSON, but I recommend using flatbuffers or at least flexbuffers.
- A default signalling server
metahack-meet.glitch.me
enables everyone to meet as a meta-multiplayer layer, but you can just remix it to create a meeting space for your app. For now, rooms (isolate groups inside a meeting space) aren't supported.
By default, there is nothing to do, but you can configure the library by calling the init function before anything else from the lib
// signalling server address
mh.init('metahack-meet.glitch.me');
// TODO full config
mh.init({
server: 'metahack-meet.glitch.me',
network: 'webrtc', // websocket, ...
serializer: 'json', // flatbuffers, ...
options: {
'iceServers': [
{"urls":"stun:stun.l.google.com:19302"},
{"urls":"stun:stun1.l.google.com:19302"},
{"urls":"stun:stun2.l.google.com:19302"},
{"urls":"stun:stun3.l.google.com:19302"},
]
}
});
// default way to use the lib is by sending json signals
// object.evt define the signal name connected to a slot with the same name
// userId is optional, broadcast when not used
// mh.send(object, userId?:int);
mh.jsend('avatar', { position: {x:0, y:0, z:0} }); // elegant way
mh.jsend({ evt:'avatar', position: {x:0, y:0, z:0} }); // raw way
// you can also send raw values
mh.send('image', rawData, userId);
// how to receive data
// define slot to receive signal
mh.on('avatar', (data, userId) => {
// data.position ...
});
[Serializable]
class Avatar {
public Vector3 position;
}
Avatar avatar = new Avatar();
MH.JSend('avatar', avatar); // MH equivalent of MetaHack.Singleton
MH.On('avatar', (json, userId) => {
Avatar avatar = JsonConvert.DeserializeObject<Avatar>(json);
// avatar.position
});
public class MetaCube : MetaBehaviour {
protected override void OnReady(int userId) {
Debug.Log($"OnReady {userId}");
JSend("{\"evt\":\"test\", \"str\":\"hello\"}", userId);
}
protected override void OnQuit(int userId) {
Debug.Log($"OnQuit {userId}");
gameObject.GetComponent<Renderer>().material.color = Color.white;
}
[On("test")]
void OnTest(JObject obj, int userId) {
Debug.Log($"receive hello from {userId}");
gameObject.GetComponent<Renderer>().material.color = Color.red;
}
}
TODO
TODO: Federated signalling servers
Here is the default node signalling server hosted on phone-tracker.glitch.me
.
You can create your own just by remixing the glitch app (equivalent to a fork in git).
const http = require("http");
const express = require("express");
const ws = require('ws')
//const cors = require('cors');
const port = process.env.PORT || 8080;
const app = express();
// force http because of websocket for the leap motion, but need to try some little things...
function forceHttp(req, res, next) {
if (req.get('X-Forwarded-Proto').indexOf("https")!=-1) {
res.redirect('http://' + req.hostname + req.url);
} else {
return next()
}
}
app.all('*', forceHttp);
//app.use(cors({origin: '*'}));
app.use(express.static('public'));
const webServer = http.createServer(app).listen(port);
let ID = 0;
const clients = [];
// WebRTC signalling server
// mesh configuration (*<->*)
const wrtc = new ws.Server({server: webServer, path: "/wrtc"});
wrtc.on('connection', ws => {
const userID = ID++;
clients[userID] = ws;
console.log('connected: ' + userID + ' in ' + Object.getOwnPropertyNames(clients));
//ws.send(JSON.stringify({userID:userID}));
// by default, send a message to all already existing users
clients.forEach((c,id) => { // broadcast message over clients
if (id !== userID) c.send(JSON.stringify({ newConnection:userID }));
});
ws.on('message', message => {
const msg = JSON.parse(message);
msg.from = userID;
if (msg.to && clients[msg.to])
clients[msg.to].send(JSON.stringify(msg));
})
ws.on('close', function () {
delete clients[userID];
console.log('deleted: ' + userID);
})
})
// TODO add a TURN server to support WebRTC over more distant networks
// https://github.com/Atlantis-Software/node-turn
// note: https://www.html5rocks.com/en/tutorials/webrtc/infrastructure/
// note on security: https://tools.ietf.org/html/draft-uberti-rtcweb-turn-rest-00