+-----------------------------+ | multiplayer online standard | +-----------------------------+ about: technical sales pitch protocol: - uses |;, separation: - '|' protocol - ';' objects - ',' attributes - client/server triplex http comet upstream, 'data: \n\n' encapsulated platform: - low internal latency: stat - 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 gumroad 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. +------------------+ | work in progress | +------------------+ 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 here/gone/chat: hierarchy: host is a root game is a stem and also a room. room is a leaf in sort of chronological order: +-----------------------------------+ | rule -> echo | +-----------------------------------+ // to get latency ping -> ping|done // simple crash report snap|[data] -> snap|done // to get server time in millisec from 1970 time -> 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 hash(pass + name.toLowerCase()) user|[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> salt|<name>/<id> -> salt|done|<salt> -> salt|fail|name not found -> salt|fail|id not found -> salt|fail|unknown problem \/ anything below -> main|fail|salt not found // login // <hash> is either hash(<key> + <salt>) // or hash(hash(pass + name.toLowerCase()) + <salt>) sign|<salt>|<hash> -> sign|done|<name>/<id> -> sign|fail|wrong pass -> sign|fail|unknown problem \/ anything below -> main|fail|not authorized +------------------------------+ | here you have to call pull() | +------------------------------+ you have to wait until pull completes and you receive the first noop before you continue +-----------------------------------------------------+ | below this line <name>/<id> is replaced with <user> | +-----------------------------------------------------+ // join a game game|<salt>|<name> -> game|done x-> here|<tree>|<user>[|ip] x-> ally|<user> x-> away|<user> // away from keyboard o-> name|<user>|<name> // if <id> used and name set o-> nick|<user>|<nick> // if <id> used and nick set -> game|fail|name invalid // [a-zA-Z]+ \/ anything below -> main|fail|no game // set nick for user nick|<salt>|<nick> -> nick|done -> nick|fail|nick invalid // [a-zA-Z0-9.\\-]+ // get nick for any id nick|<salt>|<id> -> nick|done|<nick> -> nick|fail|not found // set name for user name|<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 name|<salt>|<id> -> name|done|<name> -> name|fail|not found // set pass pass|<salt>|<pass> -> pass|done // set mail mail|<salt>|<mail> -> mail|done -> mail|fail|mail invalid // [a-zA-Z0-9.@\\-\\+]+ // away from keyboard away|<salt> -> away|done x-> away|<user> o-> hold // pause // back back|<salt> -> back|done x-> back|<user> o-> free // unpause // add/remove friend ally|<salt>|<user>[|info] -> ally|done[|poll] -> ally|fail|user not online -> ally|fail|user busy i-> poll|ally|<user>[|info] // get user persistent data hard|<salt>|<user>|<name> -> hard|done|{…} -> hard|fail|not found // get user inventory item item|<salt>|<user>|<name> -> item|done|{…} -> item|fail|not found // get user transient data soft|<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 drop|<salt>|<name>|<many> -> drop|done|<salt> -> drop|fail|not found -> drop|fail|not enough o-> item|<salt>,<spot>,<name>,<many> // pick item pick|<salt>|<salt> -> pick|done -> pick|fail|not found o-> pick|<user>|<item> // salt // get user country (ISO 3166) *flag|<salt>|<user> -> flag|done|<code> // enable peer-to-peer // before you send this it is important to // inform the user that privacy is lost! peer|<salt>|<ip> -> peer|done // send the internal IP // host room room|<salt>|<type>|<size> -> room|done x-> room|<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) *list|<salt>|file|<date> -> list|done|file|<date>,<size>,[hash];… list|<salt>|room -> list|done|room|<user>,<type>,<here>,<size>;… list|<salt>|room|item -> list|done|room|item|<salt>,<spot>,<name>,<many>;… list|<salt>|user|hard -> list|done|user|hard|<name>,<size>;… list|<salt>|user|soft -> list|done|user|soft|<name>,<size>;… list|<salt>|user|item -> list|done|user|item|<name>,<many>;… -> list|fail|not found -> list|fail|type missing -> list|fail|wrong type // pull & push resource file // data is base64 which sucks // so I might implement this // later... poke/peek? *push|<salt>|<name>|<data> -> file|done *pull|<salt>|<name> -> file|done|<data> // join room // between lock and view nobody can join // this sends a poll to the user if he has no room join|<salt>|<user>[|info] -> join|done|poll/room i-> poll|join|<user>[|info] x-> here|<tree>|<user>[|ip] // leaf, in new room x-> ally|<user> x-> gone|<tree>|<user>|<room> // stem, in lobby x-> lock|<room> // in lobby if room is full -> join|fail|not found -> join|fail|already here -> join|fail|is full -> join|fail|user busy // accept poll, you can only have one poll per user at the same time. // <user> is the user name received in the poll request // type = join; player joins the room of the host // type = ally; both players stored as friends poll|<salt>|<user>|<bool> -> poll|done|<type> -> poll|fail|user not online -> poll|fail|wrong user -> poll|fail|type not found // permanently ban user from room *kick|<salt>|<user> -> kick|done -> kick|fail|not creator -> kick|fail|not here // exit room exit|<salt> -> exit|done x-> here|<tree>|<user>[|ip] // stem, in lobby x-> ally|<user> x-> away|<user> // away from keyboard, if creator exit x-> gone|<tree>|<user>|<room> // leaf, in old room x-> drop|<user> // in lobby if creator leaves x-> stop|<user> // in old room if creator leaves x-> open|<room> // in lobby if room is not full -> exit|fail|in lobby // quit platform quit|<salt> -> quit|done x-> quit|<user> /* data handling save/load/tear: * the default disk stored [type] is "hard" * to save inventory items to disk use [type] = "item" (needs "count" number) * to save transient data in memory use [type] = "soft" (disappears on relogin) */ // save data save|<salt>|<name>|{…}[|type] -> save|done -> save|fail|name too short // min 3 -> save|fail|name too long // max 64 -> save|fail|unknown problem // load data load|<salt>|<name>[|type] -> load|done|{…} -> load|fail|not found // delete data tear|<salt>|<name>[|type] -> tear|done -> tear|fail|not found // play game play|<salt>[|seed] -> play|done o-> play[|seed] // to start the game x-> view|<room> // in lobby if room has started -> play|fail|in lobby -> play|fail|not creator -> play|fail|only one player -> play|fail|already playing -> play|fail|someone is away // game over over|<salt>[|data] -> over|done // insecure, only for development o-> over|<user>[|data] // the game is over -> over|fail|not playing +-----------------------------------------------------------+ | these have to be sent in a separate thread from rendering | +-----------------------------------------------------------+ // chat in any room // <tree> are root, stem or leaf chat|<salt>|<tree>|<text> -> chat|done // @[user] of private destination o-> chat|<tree>|<user>|<text> -> chat|fail|not online // send any gameplay data to room send|<salt>|<data> -> send|done x-> send|<user>|<data> // send any gameplay data to room show|<salt>|<data> -> show|done o-> show|<user>|<data> // motion for 3D MMO games with dynamic here/gone move|<salt>|<data> -> move|done x-> move|<user>|<x>,<y>,<z>;<x>,<y>,<z>,<w>;<action>(;<speed>;…) // position |rotation |key/button-down/up // destination to interpolate to *path|<salt>|<spot> -> path|done x-> path|<user>|<spot> // object to follow *hunt|<salt>|<salt> -> hunt|done x-> hunt|<user>|<salt> // object to attack *kill|<salt>|<salt> -> kill|done x-> kill|<user>|<salt> /\ type not found -> main|fail|type not found +-----------------+ | broadcast rules | +-----------------+ o-> noop // no operation; to keep socket alive o-> item|<salt>,<name>,<many>,<spot>,<rota>,<velo> // dynamic with orientation o-> item|<salt>,<name>,<many>,<spot>,<rota> // static with orientation o-> item|<salt>,<name>,<many>,<spot>,<velo> // dynamic o-> item|<salt>,<name>,<many>,<spot> // static o-> warn|boot/info/none|<text> // to broadcast global messages +----------------+ | sketched rules | +----------------+ // peer protocol *talk // send voice *look // send eye movement *head // send head movement *body // send body movement *hand // send hand movement // name pool lead date head tail push pull show hide gain lose item info data tape task step time host prey solo slow slot skip skin size site fill full make seal seek sell slay ruin rise poll said rank rate star drop made halt vote read rest peek body text sent loss plan page need find idle keep mark mask mate look wake like have home undo tool turn grab grip grow file face edit echo drop copy busy base paid rent cash sold coin earn bill sale tone tune mute walk zero none // todo - Hm, done?! // attribution res/mp3/pop.mp3 - Mark DiAngelo res/mp3/snap.mp3 - Mark DiAngelo res/svg/animal/* - Freepik res/console.svg - Freepik res/advance.svg - David Pérez res/fuse.svg - Freepik // credits pilot developer: Jonas Oien feedback: Søren Tramm Nicolai Farver
-
Notifications
You must be signed in to change notification settings - Fork 9
Multiplayer Online Standard
License
tinspin/fuse
Folders and files
Name | Name | Last commit message | Last commit date | |
---|---|---|---|---|
Repository files navigation
About
Multiplayer Online Standard
Topics
Resources
License
Stars
Watchers
Forks
Releases
No releases published
Packages 0
No packages published