From 8f7d00307829fdd8d6943c084891d4e5f9b41f49 Mon Sep 17 00:00:00 2001 From: Commander-lol <ljcapitanio@gmail.com> Date: Thu, 17 Dec 2015 18:29:48 +0000 Subject: [PATCH] Initial 1.0 working version --- .gitignore | 5 +- app.js | 67 +++++++++++++++ local_modules/reroute.js | 13 +++ local_modules/xbridge.js | 62 ++++++++++++++ package.json | 22 +++++ public/chat.html | 46 +++++++++++ public/index.html | 173 +++++++++++++++++++++++++++++++++++++++ scripts/kill_redis.sh | 1 + scripts/setup.sh | 21 +++++ scripts/xscrp.sh | 19 +++++ 10 files changed, 428 insertions(+), 1 deletion(-) create mode 100644 app.js create mode 100644 local_modules/reroute.js create mode 100644 local_modules/xbridge.js create mode 100644 package.json create mode 100644 public/chat.html create mode 100644 public/index.html create mode 100644 scripts/kill_redis.sh create mode 100644 scripts/setup.sh create mode 100755 scripts/xscrp.sh diff --git a/.gitignore b/.gitignore index d3f11de..0833166 100644 --- a/.gitignore +++ b/.gitignore @@ -2,4 +2,7 @@ # https://help.github.com/articles/ignoring-files # Example .gitignore files: https://github.com/github/gitignore /bower_components/ -/node_modules/ \ No newline at end of file +/node_modules/ +*.log +*.rdb +/db \ No newline at end of file diff --git a/app.js b/app.js new file mode 100644 index 0000000..a0bf1da --- /dev/null +++ b/app.js @@ -0,0 +1,67 @@ +var exec = require("child_process").exec, + level = require("levelup"), + http = require("combi-server")({ + port: 8080, + appname: "Pompey Plays", + useAnsi: true, + websocket: { + enabled: true, + lib: true + } + }), + q = require("q"), + reroute = require("./local_modules/reroute"), + path = require("path"), + x = require("./local_modules/xbridge"), + + ni = require("os").networkInterfaces()["eth0"].reduce(function(p, c){if(c.family == "IPv4"){return c;}else{return p;}}, null); + +console.dir(ni); + +reroute.add("/", "/index.html"); +reroute.add("/log", "/chat.html"); + +http.preListen(function() { + var def = q.defer(); + setTimeout(function() { + console.log("WAITED 1500MS"); + def.resolve(101); + }, 1500); + return def.promise; +}) + +http.postListen(function() { + var def = q.defer(); + setTimeout(function() { + console.log("WAITED 1500MS"); + def.resolve(101); + }, 1500); + return def.promise; +}) + +http.use(reroute.middleware); + +http.static(path.join(__dirname, "public")); + +http.ws.do("input:json", function(conn, data) { + x.do(data.key) + .then(function(e) { + conn.sendPayload("input-response", x.errs[e]); + http.ws.broadcast(JSON.stringify({ + type: "chat", + payload: { + client: conn._id, + message: "pressed " + data.key, + mode: "self" + } + })) + }) + .catch(function(err) { + conn.sendPayload("input-response", { + code: 400, + message: err.message + }) + }); +}) + +http.listen(); diff --git a/local_modules/reroute.js b/local_modules/reroute.js new file mode 100644 index 0000000..717b9fe --- /dev/null +++ b/local_modules/reroute.js @@ -0,0 +1,13 @@ +var reroutes = {}; + +module.exports = { + add: function (from, to) { + reroutes[from] = to; + }, + middleware: function(req, res, next) { + if (reroutes.hasOwnProperty(req.url)) { + req.url = reroutes[req.url]; + } + return next(); + } +} diff --git a/local_modules/xbridge.js b/local_modules/xbridge.js new file mode 100644 index 0000000..067fbed --- /dev/null +++ b/local_modules/xbridge.js @@ -0,0 +1,62 @@ +var errmap = { + "0": { + code: 200, + message: "Ok" + }, + "1": { + code: 404, + message: "Retro Arch Not Found" + }, + "2": { + code: 400, + message: "Invalid Input Given" + } + }, + controlmap = { + gba: { + left: "Left", + right: "Right", + up: "Up", + down: "Down", + a: "x", + b: "z", + r: "w", + l: "q", + select: "Shift_R", + start: "Return" + } + }, + curControl = "gba"; + exec = require("child_process").exec, + q = require("q"); + +module.exports = { + do: function(virtualKey) { + var def = q.defer(); + if (!controlmap[curControl].hasOwnProperty(virtualKey)) { + def.reject(new Error("Invalid Virtual Keypress")); + } else { + exec("bash scripts/xscrp.sh " + controlmap[curControl][virtualKey], function(err, stdout, stderr) { + if (err) { + def.reject(err); + } else { + def.resolve(stdout.toString()); + } + }); + } + return def.promise; + }, + set controls (e) { + if (controlmap.hasOwnProperty(e)) { + curControl = e; + } else { + throw new Error("Invalid Control Scheme"); + } + }, + get controls () { + return curControl; + }, + get errs () { + return errmap; + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..fabfada --- /dev/null +++ b/package.json @@ -0,0 +1,22 @@ +{ + "name": "pompey-plays", + "version": "1.0.0", + "private": true, + "description": "Pompey plays video game multiplexing unicron badassery", + "main": "app.js", + "dependencies": { + "combi-server": "^1.3.1", + "leveldown": "^1.4.3", + "levelup": "^1.3.1", + "node-ip": "^0.1.2", + "q": "^1.4.1" + }, + "scripts": { + "start": "NODE_ENV=production node app", + "kill-redis": "bash scripts/kill_redis.sh", + "inst-ubi": "bash scripts/setup.sh" + }, + "devDependencies": {}, + "author": "Louis Capitanchik", + "license": "ISC" +} diff --git a/public/chat.html b/public/chat.html new file mode 100644 index 0000000..cd34a8f --- /dev/null +++ b/public/chat.html @@ -0,0 +1,46 @@ +<!DOCTYPE html> +<html> + <head> + <meta charset="utf-8"/> + <title>PP :: LOG</title> + <style> + .message { + padding: 0.5em; + } + .message:not(:last-child) { + border-bottom: 1px solid grey; + } + .message strong { + padding-left: 0.2em; + padding-right: 0.3em; + } + </style> + </head> + <body> + <div id="log"> + + </div> + <script src="/ws.lib" type="application/javascript"></script> + <script type="application/javascript"> + var socket = new CombiSocket(), + logBox = document.getElementById("log"); + socket.on("chat", function(data) { + console.log(data); + var message = document.createElement("div"), + user = document.createElement("strong"), + content = data.mode === "self" ? document.createElement("em") : document.createElement("span"); + + message.classList.add("message"); + + user.textContent = data.client; + content.textContent = data.message; + + message.appendChild(user); + message.appendChild(content); + + logBox.appendChild(message); + logBox.scrollIntoView(false); + }); + </script> + </body> +</html> diff --git a/public/index.html b/public/index.html new file mode 100644 index 0000000..cddecab --- /dev/null +++ b/public/index.html @@ -0,0 +1,173 @@ +<!DOCTYPE html> +<html> + <head> + <meta charset="utf-8"/> + <meta content='width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0' name='viewport' /> + <title>Pompey Plays...</title> + <style> + .button .box { + fill: #c3c5c4; + stroke: #555a5d; + } + .button .arrow { + fill: #555a5d; + } + .button text { + font-family: sans-serif; + font-size: 150%; + fill: #555a5d; + text-anchor: middle; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + } + .commands .button text { + font-size: 125%; + } + .group { + position: absolute; + width: 50%; + height: 50%; + display: block; + float: left; + clear: both; + } + .group.letters { + left: 50%; + top: 15%; + } + .group.commands { + left: 25%; + top: 50%; + } + #a .box { + fill: #c92313; + } + #b .box { + fill: #f0ba24; + } + + .hitbox { + fill: black; + opacity: 0; + transition: opacity 0.1s linear; + } + .hitbox:hover { + opacity: 0.3; + } + + .content, html, body { + margin: 0; + padding: 0; + width: 100%; + max-width: 500px; + height: 100%; + max-height: 500px; + } + + </style> + </head> + <body> + <div class="content"> + <div class="group arrows"> + <!-- LEFT ARROW --> + <div id="cont-left" style="position:absolute;left:0px;top:125px;height:200px;width:200px;"> + <svg viewbox="0, 0, 100, 100" class="button" id="left"> + <path class="box" d="M 50,0 L 0,50 L 50,100 L 100,50 Z" /> + <path class="arrow" d="M 50,10 L 60,20 L 30,50 L 60,80 L 50,90 L 10,50 Z" /> + <path class="hitbox" d="M 50,0 L 0,50 L 50,100 L 100,50 Z" /> + </svg> + </div> + + <!-- RIGHT ARROW --> + <div id="cont-right" style="position:absolute;left:250px;top:125px;height:200px;width:200px;"> + <svg viewbox="0, 0, 100, 100" class="button" id="right"> + <path class="box" d="M 50,0 L 0,50 L 50,100 L 100,50 Z" /> + <path class="arrow" d="M 50,10 L 40,20 L 70,50 L 40,80 L 50,90 L 90,50 Z" /> + <path class="hitbox" d="M 50,0 L 0,50 L 50,100 L 100,50 Z" /> + </svg> + </div> + + <!-- UP ARROW --> + <div id="cont-up" style="position:absolute;left:125px;top:0px;height:200px;width:200px;"> + <svg viewbox="0, 0, 100, 100" class="button" id="up"> + <path class="box" d="M 50,0 L 0,50 L 50,100 L 100,50 Z" /> + <path class="arrow" d="M 10,50 L 20,60 L 50,30 L 80,60 L 90,50 L 50,10 Z" /> + <path class="hitbox" d="M 50,0 L 0,50 L 50,100 L 100,50 Z" /> + </svg> + </div> + + <!-- DOWN ARROW --> + <div id="cont-down" style="position:absolute;left:125px;top:250px;height:200px;width:200px;"> + <svg viewbox="0, 0, 100, 100" class="button" id="down"> + <path class="box" d="M 50,0 L 0,50 L 50,100 L 100,50 Z" /> + <path class="arrow" d="M 10,50 L 20,40 L 50,70 L 80,40 L 90,50 L 50,90 Z" /> + <path class="hitbox" d="M 50,0 L 0,50 L 50,100 L 100,50 Z" /> + </svg> + </div> + </div> + + <div class="group letters"> + <div style="position:absolute;left:125px;top:0px;width:200px;height:200px;"> + <svg viewbox="0, 0, 100, 100" class="button" id="a"> + <circle class="box" r="35" cx="50" cy="50"/> + <text x="50" y="50" dy="7">A</text> + <circle class="hitbox" r="35" cx="50" cy="50"/> + </svg> + </div> + <div style="position:absolute;left:0px;top:125px;width:200px;height:200px;"> + <svg viewbox="0, 0, 100, 100" class="button" id="b"> + <circle class="box" r="35" cx="50" cy="50"/> + <text x="50" y="50" dy="7">B</text> + <circle class="hitbox" r="35" cx="50" cy="50"/> + </svg> + </div> + </div> + + <div class="group commands"> + <div style="position:absolute;left:0px;top:0px;width:200px;height:200px;"> + <svg viewbox="0, 0, 100, 100" class="button" id="select"> + <rect class="box" x="1" y="30" width="98" height="40" rx="25" ry="25"/> + <text x="50" y="50" dy="7">SELECT</text> + <rect class="hitbox" x="0" y="30" width="100" height="40" rx="25" ry="25"/> + </svg> + </div> + + <div style="position:absolute;left:225px;top:0px;width:200px;height:200px;"> + <svg viewbox="0, 0, 100, 100" class="button" id="start"> + <rect class="box" x="1" y="30" width="98" height="40" rx="25" ry="25"/> + <text x="50" y="50" dy="7">START</text> + <rect class="hitbox" x="0" y="30" width="100" height="40" rx="25" ry="25"/> + </svg> + </div> + </div> + </div> + + <script src="/ws.lib" type="application/javascript"></script> + <script> + var socket = new CombiSocket(), + keys = [ + "a", + "b", + "left", + "right", + "up", + "down", + "select", + "start" + ], + sendKey = function(key) { + socket.message("input", {key: key}); + }; + socket.on("input-response", function(data) { + console.log(data); + }); + + keys.map(function(e) { + document.querySelector("#" + e + " .hitbox").addEventListener("click", sendKey.bind(null, e)); + }) + + </script> + </body> +</html> diff --git a/scripts/kill_redis.sh b/scripts/kill_redis.sh new file mode 100644 index 0000000..9f9a13f --- /dev/null +++ b/scripts/kill_redis.sh @@ -0,0 +1 @@ +ps -aux | grep redis | head -1 | tr -s ' ' | cut -d ' ' -f 2 | xargs kill $1 diff --git a/scripts/setup.sh b/scripts/setup.sh new file mode 100644 index 0000000..b1a34f9 --- /dev/null +++ b/scripts/setup.sh @@ -0,0 +1,21 @@ +#!/bin/bash +PDIR=`pwd` + +if ! [ -x "$(command -v xdotool)" ]; then # RetroArch doesn't do command lines nicely, has to be bundled with xdotool check + sudo add-apt-repository ppa:libretro/stable + sudo apt-get update + sudo apt-get install xdotool retroarch retroarch-* libretro-* +fi + +# Enable if switching levelDB to Redis +#if ! [ -x ~/Programs/$REDISVER/src/redis-server ]; then +# REDISVER="redis-3.0.5" +# mkdir -p ~/Programs/tmp +# mkdir -p ~/Programs/$REDISVER +# cd ~/Programs/tmp +# wget http://download.redis.io/releases/$REDISVER.tar.gz +# tar xzf $REDISVER.tar.gz -C ../ +# cd ../$REDISVER +# make +# cd $PDIR +#fi diff --git a/scripts/xscrp.sh b/scripts/xscrp.sh new file mode 100755 index 0000000..0c2db0b --- /dev/null +++ b/scripts/xscrp.sh @@ -0,0 +1,19 @@ +#!/bin/bash + +WID=`xdotool search --name RetroArch` +VALID="_z__x__q__w__Left__Right__Up__Down__Shift_R__Return_" +if [[ $WID == "" ]] +then + echo 1 +else + if [[ $VALID == *"_$1_"* ]] + then + xdotool windowactivate $WID + xdotool windowfocus $WID + xdotool keydown $1 + xdotool keyup $1 + echo 0 + else + echo 2 + fi +fi -- GitLab