Fuse
Multiplayer Online Standard
Install / Use
/learn @tinspin/FuseREADME
<img width="170" src="https://rawgit.com/tinspin/fuse/master/res/svg/mos.svg"><br>
<pre> +-----------------------------+ | <i>multiplayer online standard</i> | +-----------------------------+ about: <a href="http://fuse.rupy.se/about.html">technical sales pitch</a> protocol: - uses |;, separation: - '|' protocol - ';' objects - ',' attributes - client/server triplex http comet upstream, 'data: \n\n' encapsulated platform: - low internal latency: <a href="http://fuse.rupy.se/data">stat</a> - multithreaded nio with queue, linear perf.: - 1.000 mess./sec. on raspberry pi 1 - 6.500 mess./sec. on raspberry pi 2 - 100.000 mess./sec. on t2.micro - 200.000 mess./sec. on m4.large - 300.000 mess./sec. on t2.medium - 7.200.000 mess./sec. on c5.18xlarge - 9.600.000 mess./sec. on m5d.24xlarge - 100% uptime on hosting and routing with round-robin dns - 100% read uptime on persistence with custom async distributed json file system database with region select - peak garbage collect: - 70 ms (raspberry pi 1) - 14 ms (raspberry pi 2) - 7 ms (aws micro instance) license: - Source available, you have to show the logo on startup, sponsor the fuse tier on <a href="http://tinspin.gumroad.com">gumroad</a> while you are using this, or any derivation, commercially. The .html and graphics are proprietary examples except the javascript in play.html! The protocol is public domain. +------------------+ | <i>work in progress</i> | +------------------+ o-> = async. broadcast to read() (c#) or read(data) (javascript) including self x-> = async. broadcast to read() (c#) or read(data) (javascript) excluding self i-> = async. send to one user for unique feedback -> = sync. return on push(data) <…> = mandatory […] = optional {…} = json * = not implemented yet <spot> = <x>,<y>,<z> <tree> for <b><i>here</i></b>/<b><i>gone</i></b>/<b><i>chat</i></b>: hierarchy: host is a <b><i>root</i></b> game is a <b><i>stem</i></b> and also a room. room is a <b><i>leaf</i></b> in sort of chronological order: +-----------------------------------+ | <i>rule</i> -> <i>echo</i> | +-----------------------------------+ // to get latency <b><i>ping</i></b> -> ping|done // simple crash report <b><i>snap</i></b>|[data] -> snap|done // to get server time in millisec from 1970 <b><i>time</i></b> -> time|done|<time> // register // [name] if you can't store the <id> otherwise set // to empty string (||) // [pass] if you can't store the <key> otherwise set // to empty string (||) // preferably [pass] is a hash with salt // we simply use <i>hash</i>(pass + name.toLowerCase()) <b><i>user</i></b>|[name]|[pass] -> user|done|<salt>|<key>|<id> -> user|fail|name too short // min 2 -> user|fail|name too long // max 6 -> user|fail|name already registered -> user|fail|name invalid // [a-wyA-WY2-9]+ -> user|fail|name alpha missing // [0-9]+ reserved for <id> -> user|fail|pass too short // min 3 -> user|fail|pass too long // max 9 // get salt for <name> or <id> <b><i>salt</i></b>|<name>/<id> -> salt|done|<salt> -> salt|fail|name not found -> salt|fail|id not found -> salt|fail|unknown problem <b><i>\/</i></b> anything below -> main|fail|salt not found // login // <hash> is either <i>hash</i>(<key> + <salt>) // or <i>hash</i>(<i>hash</i>(pass + name.toLowerCase()) + <salt>) <b><i>sign</i></b>|<salt>|<hash> -> sign|done|<name>/<id> -> sign|fail|wrong pass -> sign|fail|unknown problem <b><i>\/</i></b> anything below -> main|fail|not authorized +------------------------------+ | <i>here you have to call pull()</i> | +------------------------------+ <i>you have to wait until pull completes and you receive the first <b>noop</b> before you continue</i> +-----------------------------------------------------+ | <i>below this line <name>/<id> is replaced with <user></i> | +-----------------------------------------------------+ // join a game <b><i>game</i></b>|<salt>|<name> -> game|done x-> <b><i>here</i></b>|<tree>|<user>[|ip] x-> <b><i>ally</i></b>|<user> x-> <b><i>away</b></i>|<user> // away from keyboard o-> <b><i>name</b></i>|<user>|<name> // if <id> used and name set o-> <b><i>nick</b></i>|<user>|<nick> // if <id> used and nick set -> game|fail|name invalid // [a-zA-Z]+ <b><i>\/</i></b> anything below -> main|fail|no game // set nick for user <b><i>nick</i></b>|<salt>|<nick> -> nick|done -> nick|fail|nick invalid // [a-zA-Z0-9.\\-]+ // get nick for any id <b><i>nick</i></b>|<salt>|<id> -> nick|done|<nick> -> nick|fail|not found // set name for user <b><i>name</i></b>|<salt>|<name> -> name|done -> name|fail|name invalid // [a-zA-Z0-9.\\-]+ -> name|fail|name alpha missing // [0-9]+ reserved for <id> -> name|fail|taken // get name for any id <b><i>name</i></b>|<salt>|<id> -> name|done|<name> -> name|fail|not found // set pass <b><i>pass</i></b>|<salt>|<pass> -> pass|done // set mail <b><i>mail</i></b>|<salt>|<mail> -> mail|done -> mail|fail|mail invalid // [a-zA-Z0-9.@\\-\\+]+ // away from keyboard <b><i>away</i></b>|<salt> -> away|done x-> <b><i>away</b></i>|<user> o-> <b><i>hold</b></i> // pause // back <b><i>back</i></b>|<salt> -> back|done x-> <b><i>back</b></i>|<user> o-> <b><i>free</b></i> // unpause // add/remove friend <b><i>ally</i></b>|<salt>|<user>[|info] -> ally|done[|poll] -> ally|fail|user not online -> ally|fail|user busy i-> <b><i>poll</i></b>|ally|<user>[|info] // get user persistent data <b><i>hard</i></b>|<salt>|<user>|<name> -> hard|done|{…} -> hard|fail|not found // get user inventory item <b><i>item</i></b>|<salt>|<user>|<name> -> item|done|{…} -> item|fail|not found // get user transient data <b><i>soft</i></b>|<salt>|<user>|<name> -> soft|done|{…} -> soft|fail|salt not found -> soft|fail|user not found -> soft|fail|not found // drop item, how many and which <b><i>drop</i></b>|<salt>|<name>|<many> -> drop|done|<salt> -> drop|fail|not found -> drop|fail|not enough o-> item|<salt>,<spot>,<name>,<many> // pick item <b><i>pick</i></b>|<salt>|<salt> -> pick|done -> pick|fail|not found o-> pick|<user>|<item> // salt // get user country (ISO 3166) *<b><i>flag</i></b>|<salt>|<user> -> flag|done|<code> // enable peer-to-peer // before you send this it is important to // inform the user that privacy is lost! <b><i>peer</i></b>|<salt>|<ip> -> peer|done // send the internal IP // host room <b><i>room</i></b>|<salt>|<type>|<size> -> room|done x-> <b><i>room</i></b>|<user>,<type>,<size> -> room|fail|not in lobby -> room|fail|type invalid // [a-zA-Z]+ // list files, rooms, room items or user data (hard, soft and inventory items) *<b><i>list</i></b>|<salt>|file|<date> -> list|done|file|<date>,<