Update
- Moved the web-api to the master branch
- Rewrote parts of the web-api to support ES6
- Added local webserver to the web-api
- Added command to start the local webserver ("npm run api")
|
|
@ -58,7 +58,7 @@ The required database tables get generated automatically.
|
|||
|
||||
You need at minimum [Node.js](https://nodejs.org/en/) version 6.x.
|
||||
|
||||
Open up a terminal and enter ``npm run boot`` to start the server.
|
||||
Open up a terminal and enter ``npm run boot`` to start the server or ``npm run api`` to start the web-api.
|
||||
|
||||
## Docker setup
|
||||
|
||||
|
|
|
|||
262
api/css/main.css
Normal file
|
|
@ -0,0 +1,262 @@
|
|||
html {
|
||||
-webkit-animation: fadein 1s;
|
||||
-moz-animation: fadein 1s;
|
||||
-ms-animation: fadein 1s;
|
||||
-o-animation: fadein 1s;
|
||||
animation: fadein 1s;
|
||||
}
|
||||
|
||||
body {
|
||||
overflow-x: hidden;
|
||||
overflow-y: scroll !important;
|
||||
}
|
||||
|
||||
#map {
|
||||
position: absolute;
|
||||
left: calc(50% - 400px);
|
||||
width: 800px !important;
|
||||
height: 400px !important;
|
||||
}
|
||||
|
||||
#map_manager {
|
||||
padding-bottom: 500px;
|
||||
margin-top: -100px;
|
||||
display: none;
|
||||
}
|
||||
|
||||
.view {
|
||||
letter-spacing: 0px;
|
||||
padding: 5px 25px !important;
|
||||
margin-top: -35px;
|
||||
}
|
||||
|
||||
.area {
|
||||
font-family: "Andale Mono", AndaleMono, monospace;
|
||||
text-align: center;
|
||||
font-style: normal;
|
||||
font-variant: normal;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
font-size: 75px;
|
||||
letter-spacing: -5px;
|
||||
color: #fff;
|
||||
position: relative;
|
||||
margin-top: 5px;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.Codemirror {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.ping {
|
||||
position: absolute;
|
||||
top: 0px;
|
||||
left: 10px;
|
||||
font-size: 18px;
|
||||
letter-spacing: 0px;
|
||||
}
|
||||
|
||||
.version {
|
||||
font-size: 15px;
|
||||
letter-spacing: 0px;
|
||||
margin-top: -75px;
|
||||
margin-bottom: -25px;
|
||||
text-transform: none;
|
||||
}
|
||||
|
||||
.btn {
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.centered {
|
||||
text-align: center;
|
||||
position: relative;
|
||||
top: 40%;
|
||||
transform: translateY(-40%);
|
||||
margin-top: -175px;
|
||||
-webkit-transform: translateY(-40%);
|
||||
-moz-transform: translateY(0%);
|
||||
}
|
||||
|
||||
@-moz-document url-prefix() {
|
||||
.centered {
|
||||
margin-top: 0px;
|
||||
}
|
||||
}
|
||||
|
||||
.body {
|
||||
background: #2d2d2d;
|
||||
background-color: #2d2d2d;
|
||||
}
|
||||
|
||||
.star {
|
||||
position: absolute;
|
||||
width: 2px;
|
||||
height: 2px;
|
||||
background: rgba(255, 255, 255, 0.45);
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.btn {
|
||||
font-family: "Andale Mono", AndaleMono, monospace;
|
||||
display: inline-block;
|
||||
padding: 5px;
|
||||
border: 1px solid rgba(255, 255, 255, .35);
|
||||
border-radius: 4px;
|
||||
color: rgba(255, 255, 255, .75);
|
||||
text-decoration: none;
|
||||
transition: border .35s, background .35s;
|
||||
min-width: 100px;
|
||||
text-align: center;
|
||||
font-size: 15px;
|
||||
font-style: normal;
|
||||
font-variant: normal;
|
||||
font-weight: 500;
|
||||
line-height: 25px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.input {
|
||||
background: rgba(0,0,0,0);
|
||||
cursor: auto;
|
||||
}
|
||||
|
||||
input:focus {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
button:focus {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.label {
|
||||
background: rgba(255, 255, 255, .05);
|
||||
border: 1px solid rgba(255, 255, 255, .5);
|
||||
color: #79a2b7;
|
||||
}
|
||||
|
||||
.info {
|
||||
padding-bottom: 45px;
|
||||
margin-top: -45px;
|
||||
font-size: 18px;
|
||||
letter-spacing: 0px;
|
||||
}
|
||||
|
||||
.cmd_label {
|
||||
border: none;
|
||||
background: rgba(255,255,255,0.05);
|
||||
color: white;
|
||||
cursor: auto;
|
||||
text-transform: none;
|
||||
}
|
||||
|
||||
.submit {
|
||||
background: rgba(165, 165, 165, 0.15);
|
||||
}
|
||||
|
||||
.with_label {
|
||||
margin-left: 25px;
|
||||
width: 120px;
|
||||
}
|
||||
|
||||
#connection_status {
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.login_area {
|
||||
font-size: 25px;
|
||||
letter-spacing: 0px;
|
||||
text-transform: none;
|
||||
margin: -25px;
|
||||
padding: 0px;
|
||||
}
|
||||
|
||||
.login_input {
|
||||
text-transform: none;
|
||||
background: rgba(0,0,0,0);
|
||||
}
|
||||
|
||||
.noselect {
|
||||
-webkit-touch-callout: none;
|
||||
-webkit-user-select: none;
|
||||
-khtml-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.btn:hover {
|
||||
background: rgba(255, 255, 255, .05);
|
||||
border: 1px solid rgba(255, 255, 255, .5);
|
||||
}
|
||||
|
||||
.txt {
|
||||
margin-left: calc(20%);
|
||||
margin-right: calc(20%);
|
||||
left: auto;
|
||||
width: auto;
|
||||
min-height: 300px;
|
||||
background: rgba(255, 255, 255, 0.0) !important;
|
||||
border: 1px solid rgba(255, 255, 255, 0.0) !important;
|
||||
border-radius: 4px !important;
|
||||
padding: 10px 15px !important;
|
||||
color: rgba(255, 255, 255, .75) !important;
|
||||
resize: none;
|
||||
transition: color .35s !important;
|
||||
}
|
||||
|
||||
.txt:focus {
|
||||
outline: none;
|
||||
color: rgba(255, 255, 255, .85);
|
||||
}
|
||||
|
||||
::-moz-selection {
|
||||
color: rgba(255, 255, 255, .85);
|
||||
background: rgba(255, 255, 255, .075);
|
||||
}
|
||||
::selection {
|
||||
color: rgba(255, 255, 255, .85);
|
||||
background: rgba(255, 255, 255, .075);
|
||||
}
|
||||
|
||||
::-webkit-scrollbar{
|
||||
width: 10px;
|
||||
height: 0px;
|
||||
background: transparent;
|
||||
}
|
||||
::-webkit-scrollbar-thumb{
|
||||
background: rgba(255, 255, 255, .15);
|
||||
border-radius: 5px;
|
||||
}
|
||||
::-webkit-scrollbar-corner{
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
@keyframes fadein {
|
||||
from { opacity: 0; }
|
||||
to { opacity: 1; }
|
||||
}
|
||||
@-webkit-keyframes fadein {
|
||||
from { opacity: 0; }
|
||||
to { opacity: 1; }
|
||||
}
|
||||
@-moz-keyframes fadein {
|
||||
from { opacity: 0; }
|
||||
to { opacity: 1; }
|
||||
}
|
||||
|
||||
@keyframes pulsate {
|
||||
0% {transform: scale(0.1, 0.1); opacity: 0.0;}
|
||||
50% {opacity: 1.0;}
|
||||
100% {transform: scale(1.2, 1.2); opacity: 0.0;}
|
||||
}
|
||||
@-webkit-keyframes pulsate {
|
||||
0% {-webkit-transform: scale(0.1, 0.1); opacity: 0.0;}
|
||||
50% {opacity: 1.0;}
|
||||
100% {-webkit-transform: scale(1.2, 1.2); opacity: 0.0;}
|
||||
}
|
||||
@-moz-keyframes pulsate {
|
||||
0% {transform: scale(0.1, 0.1); opacity: 0.0;}
|
||||
50% {opacity: 1.0;}
|
||||
100% {transform: scale(1.2, 1.2); opacity: 0.0;}
|
||||
}
|
||||
23
api/css/pure.min.css
vendored
Normal file
208
api/css/vex.css
Normal file
|
|
@ -0,0 +1,208 @@
|
|||
@keyframes vex-fadein {
|
||||
0% {
|
||||
opacity: 0; }
|
||||
100% {
|
||||
opacity: 1; } }
|
||||
|
||||
@-webkit-keyframes vex-fadein {
|
||||
0% {
|
||||
opacity: 0; }
|
||||
100% {
|
||||
opacity: 1; } }
|
||||
|
||||
@-moz-keyframes vex-fadein {
|
||||
0% {
|
||||
opacity: 0; }
|
||||
100% {
|
||||
opacity: 1; } }
|
||||
|
||||
@-ms-keyframes vex-fadein {
|
||||
0% {
|
||||
opacity: 0; }
|
||||
100% {
|
||||
opacity: 1; } }
|
||||
|
||||
@-o-keyframes vex-fadein {
|
||||
0% {
|
||||
opacity: 0; }
|
||||
100% {
|
||||
opacity: 1; } }
|
||||
|
||||
@keyframes vex-fadeout {
|
||||
0% {
|
||||
opacity: 1; }
|
||||
100% {
|
||||
opacity: 0; } }
|
||||
|
||||
@-webkit-keyframes vex-fadeout {
|
||||
0% {
|
||||
opacity: 1; }
|
||||
100% {
|
||||
opacity: 0; } }
|
||||
|
||||
@-moz-keyframes vex-fadeout {
|
||||
0% {
|
||||
opacity: 1; }
|
||||
100% {
|
||||
opacity: 0; } }
|
||||
|
||||
@-ms-keyframes vex-fadeout {
|
||||
0% {
|
||||
opacity: 1; }
|
||||
100% {
|
||||
opacity: 0; } }
|
||||
|
||||
@-o-keyframes vex-fadeout {
|
||||
0% {
|
||||
opacity: 1; }
|
||||
100% {
|
||||
opacity: 0; } }
|
||||
|
||||
@keyframes vex-rotation {
|
||||
0% {
|
||||
transform: rotate(0deg);
|
||||
-webkit-transform: rotate(0deg);
|
||||
-moz-transform: rotate(0deg);
|
||||
-ms-transform: rotate(0deg);
|
||||
-o-transform: rotate(0deg); }
|
||||
100% {
|
||||
transform: rotate(359deg);
|
||||
-webkit-transform: rotate(359deg);
|
||||
-moz-transform: rotate(359deg);
|
||||
-ms-transform: rotate(359deg);
|
||||
-o-transform: rotate(359deg); } }
|
||||
|
||||
@-webkit-keyframes vex-rotation {
|
||||
0% {
|
||||
transform: rotate(0deg);
|
||||
-webkit-transform: rotate(0deg);
|
||||
-moz-transform: rotate(0deg);
|
||||
-ms-transform: rotate(0deg);
|
||||
-o-transform: rotate(0deg); }
|
||||
100% {
|
||||
transform: rotate(359deg);
|
||||
-webkit-transform: rotate(359deg);
|
||||
-moz-transform: rotate(359deg);
|
||||
-ms-transform: rotate(359deg);
|
||||
-o-transform: rotate(359deg); } }
|
||||
|
||||
@-moz-keyframes vex-rotation {
|
||||
0% {
|
||||
transform: rotate(0deg);
|
||||
-webkit-transform: rotate(0deg);
|
||||
-moz-transform: rotate(0deg);
|
||||
-ms-transform: rotate(0deg);
|
||||
-o-transform: rotate(0deg); }
|
||||
100% {
|
||||
transform: rotate(359deg);
|
||||
-webkit-transform: rotate(359deg);
|
||||
-moz-transform: rotate(359deg);
|
||||
-ms-transform: rotate(359deg);
|
||||
-o-transform: rotate(359deg); } }
|
||||
|
||||
@-ms-keyframes vex-rotation {
|
||||
0% {
|
||||
transform: rotate(0deg);
|
||||
-webkit-transform: rotate(0deg);
|
||||
-moz-transform: rotate(0deg);
|
||||
-ms-transform: rotate(0deg);
|
||||
-o-transform: rotate(0deg); }
|
||||
100% {
|
||||
transform: rotate(359deg);
|
||||
-webkit-transform: rotate(359deg);
|
||||
-moz-transform: rotate(359deg);
|
||||
-ms-transform: rotate(359deg);
|
||||
-o-transform: rotate(359deg); } }
|
||||
|
||||
@-o-keyframes vex-rotation {
|
||||
0% {
|
||||
transform: rotate(0deg);
|
||||
-webkit-transform: rotate(0deg);
|
||||
-moz-transform: rotate(0deg);
|
||||
-ms-transform: rotate(0deg);
|
||||
-o-transform: rotate(0deg); }
|
||||
100% {
|
||||
transform: rotate(359deg);
|
||||
-webkit-transform: rotate(359deg);
|
||||
-moz-transform: rotate(359deg);
|
||||
-ms-transform: rotate(359deg);
|
||||
-o-transform: rotate(359deg); } }
|
||||
|
||||
.vex, .vex *, .vex *:before, .vex *:after {
|
||||
-moz-box-sizing: border-box;
|
||||
-webkit-box-sizing: border-box;
|
||||
box-sizing: border-box; }
|
||||
|
||||
.vex {
|
||||
position: fixed;
|
||||
overflow: auto;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
z-index: 1111;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0; }
|
||||
|
||||
.vex-scrollbar-measure {
|
||||
position: absolute;
|
||||
top: -9999px;
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
overflow: scroll; }
|
||||
|
||||
.vex-overlay {
|
||||
background: #000;
|
||||
filter: alpha(opacity=40);
|
||||
-ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=40)"; }
|
||||
|
||||
.vex-overlay {
|
||||
animation: vex-fadein 0.5s;
|
||||
-webkit-animation: vex-fadein 0.5s;
|
||||
-moz-animation: vex-fadein 0.5s;
|
||||
-ms-animation: vex-fadein 0.5s;
|
||||
-o-animation: vex-fadein 0.5s;
|
||||
-webkit-backface-visibility: hidden;
|
||||
position: fixed;
|
||||
background: rgba(0, 0, 0, 0.4);
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0; }
|
||||
|
||||
.vex-close:before {
|
||||
font-family: Arial, sans-serif;
|
||||
content: "\00D7"; }
|
||||
|
||||
.vex-dialog-form {
|
||||
margin: 0; }
|
||||
|
||||
.vex-dialog-button {
|
||||
text-rendering: optimizeLegibility;
|
||||
-moz-appearance: none;
|
||||
-webkit-appearance: none;
|
||||
cursor: pointer;
|
||||
-webkit-tap-highlight-color: transparent; }
|
||||
|
||||
.vex-loading-spinner {
|
||||
animation: vex-rotation 0.7s linear infinite;
|
||||
-webkit-animation: vex-rotation 0.7s linear infinite;
|
||||
-moz-animation: vex-rotation 0.7s linear infinite;
|
||||
-ms-animation: vex-rotation 0.7s linear infinite;
|
||||
-o-animation: vex-rotation 0.7s linear infinite;
|
||||
-webkit-backface-visibility: hidden;
|
||||
-moz-box-shadow: 0 0 1em rgba(0, 0, 0, 0.1);
|
||||
-webkit-box-shadow: 0 0 1em rgba(0, 0, 0, 0.1);
|
||||
box-shadow: 0 0 1em rgba(0, 0, 0, 0.1);
|
||||
position: fixed;
|
||||
z-index: 1112;
|
||||
margin: auto;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
height: 2em;
|
||||
width: 2em;
|
||||
background: #fff; }
|
||||
|
||||
body.vex-open {
|
||||
overflow: hidden; }
|
||||
BIN
api/img/gym_NEUTRAL.png
Normal file
|
After Width: | Height: | Size: 3.6 KiB |
BIN
api/img/gym_blue.png
Normal file
|
After Width: | Height: | Size: 3.7 KiB |
BIN
api/img/gym_red.png
Normal file
|
After Width: | Height: | Size: 3.7 KiB |
BIN
api/img/gym_yellow.png
Normal file
|
After Width: | Height: | Size: 3.9 KiB |
1
api/img/license.txt
Normal file
|
|
@ -0,0 +1 @@
|
|||
https://shareicon.net/license/cc-3-0-by
|
||||
BIN
api/img/pokestop_blue.png
Normal file
|
After Width: | Height: | Size: 2.5 KiB |
BIN
api/img/pokestop_lure.png
Normal file
|
After Width: | Height: | Size: 3.8 KiB |
BIN
api/img/pokestop_puple.png
Normal file
|
After Width: | Height: | Size: 2.7 KiB |
BIN
api/img/spawn_point.png
Normal file
|
After Width: | Height: | Size: 4.8 KiB |
51
api/index.html
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
<html>
|
||||
<head>
|
||||
<meta charset='utf-8'>
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta http-equiv="Content-Language" content="en">
|
||||
<meta name="viewport" content="width=device-width">
|
||||
<meta content="origin-when-cross-origin" name="referrer" />
|
||||
<title>POGOserver api</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link rel="stylesheet" type="text/css" href="/api//css/main.css">
|
||||
<link rel="stylesheet" type="text/css" href="/api/css/pure.min.css">
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/vex-js/2.3.4/js/vex.combined.min.js"></script>
|
||||
<script>vex.defaultOptions.className = "vex-theme-plain";</script>
|
||||
<link rel="stylesheet" type="text/css" href="/api/css/vex.css">
|
||||
<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/vex-js/2.3.4/css/vex-theme-plain.css">
|
||||
</head>
|
||||
<body class="body">
|
||||
|
||||
<p class="ping area" id="server_ping" style="position: absolute;top: 0px;left: 10px; display:none;">Ping: 0ms</p>
|
||||
|
||||
<div class="area">
|
||||
<p>POGOserver</p>
|
||||
<p id="version" class="version"> </p>
|
||||
<p><button class="btn color-1 view login_input" id="connection_status" href="#" style="color:yellow;">Connecting..</button></p>
|
||||
</div>
|
||||
|
||||
<div id="login_area" class="area">
|
||||
<p class="login_area">Login</p>
|
||||
<p><input class="btn color-1 view input login_input" id="login_username" style="margin:-20px;" autocomplete="new-password" value="root"></input></p>
|
||||
<p><input class="btn color-1 view input login_input" id="login_password" type="password" autocomplete="new-password"></input></p>
|
||||
<p><button class="btn color-1 view login_input" id="login_attempt">Login</button></p>
|
||||
</div>
|
||||
|
||||
<div id="world_manager" class="area" style="display:none;">
|
||||
<p class="info" id="server_version">Server version: v0.1.0</p>
|
||||
<p class="info" id="connected_players">Connected players: 0</p>
|
||||
<p class="login_area" style="padding-bottom: 15px;">World Manager</p>
|
||||
<p><button class="btn color-1 view cmd_label label">Spawn</button><input class="btn color-1 view input login_input with_label" id="spawn_user" placeholder="Username" autocomplete="new-password"></input><input class="btn color-1 view input login_input with_label" autocomplete="new-password" id="spawn_pkmn" placeholder="Pokemon"></input><button id="submit_spawn" class="btn color-1 view login_input with_label submit">Submit</button></p>
|
||||
<br/>
|
||||
</div>
|
||||
|
||||
<div class="area" id="map_manager">
|
||||
<div id="map"></div>
|
||||
</div>
|
||||
|
||||
<script src="/api/cfg.js"></script>
|
||||
<script src="/api/js/init.js"></script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
36
api/index.js
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
import http from "http";
|
||||
import url from "url";
|
||||
import path from "path";
|
||||
import fs from "fs";
|
||||
const port = process.argv[2] || 9000;
|
||||
|
||||
http.createServer((request, response) => {
|
||||
const uri = url.parse(request.url).pathname;
|
||||
let filename = path.join(process.cwd(), uri);
|
||||
|
||||
fs.exists(filename, exists => {
|
||||
if(!exists) {
|
||||
response.writeHead(404, {"Content-Type": "text/plain"});
|
||||
response.write("404 Not Found\n");
|
||||
response.end();
|
||||
return;
|
||||
}
|
||||
|
||||
if (fs.statSync(filename).isDirectory()) filename += '/api/index.html';
|
||||
|
||||
fs.readFile(filename, "binary", (err, file) => {
|
||||
if(err) {
|
||||
response.writeHead(500, {"Content-Type": "text/plain"});
|
||||
response.write(`${err}\n`);
|
||||
response.end();
|
||||
return;
|
||||
}
|
||||
|
||||
response.writeHead(200);
|
||||
response.write(file, "binary");
|
||||
response.end();
|
||||
});
|
||||
});
|
||||
}).listen(parseInt(port, 10));
|
||||
|
||||
console.log(`Web-API for POGOserver running at => http://localhost:${port}/\nCTRL + C to shutdown`);
|
||||
22
api/js/ajax.js
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
function send(data, resolve) {
|
||||
const xhr = new XMLHttpRequest();
|
||||
const protocol = window.location.protocol;
|
||||
xhr.open("POST", `${protocol}//${CFG.API.HOST}:${CFG.API.PORT}${CFG.API.ROUTE}`, true);
|
||||
xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
|
||||
xhr.onreadystatechange = () => {
|
||||
if (xhr.readyState === 4) {
|
||||
if (xhr.status === 200) {
|
||||
if (typeof resolve === "function") {
|
||||
try {
|
||||
resolve(JSON.parse(xhr.responseText));
|
||||
} catch (e) {
|
||||
resolve(void 0);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
resolve(xhr.statusText);
|
||||
}
|
||||
}
|
||||
};
|
||||
xhr.send(JSON.stringify(data));
|
||||
}
|
||||
2
api/js/gmaps.js
Normal file
17
api/js/init.js
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
((() => {
|
||||
|
||||
function loadScriptDefered(src) {
|
||||
let js = null;
|
||||
js = document.createElement("script");
|
||||
js.type = "text/javascript";
|
||||
js.src = src;
|
||||
js.async = false;
|
||||
document.body.appendChild(js);
|
||||
};
|
||||
|
||||
loadScriptDefered(`http://maps.google.com/maps/api/js?key=${CFG.GMAPS.API_KEY}`);
|
||||
loadScriptDefered("/api/js/gmaps.js");
|
||||
loadScriptDefered("/api/js/ajax.js");
|
||||
loadScriptDefered("/api/js/main.js");
|
||||
|
||||
}))();
|
||||
299
api/js/main.js
Normal file
|
|
@ -0,0 +1,299 @@
|
|||
((() => {
|
||||
|
||||
let loggedIn = false;
|
||||
let loginTimeout = null;
|
||||
|
||||
let heartInterval = null;
|
||||
let heartTimeout = null;
|
||||
let heartTimedOut = true;
|
||||
|
||||
const header = `
|
||||
<div class="pure-form pure-g">
|
||||
<div class="pure-u-1-3">
|
||||
<center>
|
||||
<img src='/api/img/spawn_point.png'/><br/>
|
||||
<input id="option_one" type="radio" name="type" style="margin: 18px;" value="SPAWN">
|
||||
</center>
|
||||
</div>
|
||||
<div class="pure-u-1-3">
|
||||
<center>
|
||||
<img src='/api/img/pokestop_blue.png'/><br/>
|
||||
<input id="option_two" type="radio" name="type" style="margin: 18px;" value="CHECKPOINT" >
|
||||
</center>
|
||||
</div>
|
||||
<div class="pure-u-1-3">
|
||||
<center>
|
||||
<img src='/api/img/gym_NEUTRAL.png'/><br/>
|
||||
<input id="option_three" type="radio" name="type" style="margin: 18px;" value="GYM">
|
||||
</center>
|
||||
</div>
|
||||
</div>
|
||||
<div id="form_checkpoint" style="display:none;">
|
||||
<input name="name" placeholder="Name" type="text" />
|
||||
<input name="description" placeholder="Description" type="text" />
|
||||
<input name="image_url" placeholder="Image" type="text" />
|
||||
<input name="experience" placeholder="Experience" type="text" />
|
||||
</div>
|
||||
<div id="form_spawn" style="display:none;">
|
||||
<input name="interval" placeholder="Interval" type="text" />
|
||||
<input name="encounters" placeholder="Encounters" type="text" />
|
||||
</div>
|
||||
<div id="form_gym" style="display:none;">
|
||||
<input name="team" placeholder="Team" type="text" />
|
||||
</div>
|
||||
<script>
|
||||
function hideAllForms() {
|
||||
form_checkpoint.style.display = "none";
|
||||
form_spawn.style.display = "none";
|
||||
form_gym.style.display = "none";
|
||||
}
|
||||
function showForm(e) {
|
||||
var target = e.target || e;
|
||||
hideAllForms();
|
||||
var key = "#form_" + target.value.toLowerCase();
|
||||
var el = document.querySelector(key);
|
||||
el.style.display = "block";
|
||||
}
|
||||
option_one.onclick = showForm;
|
||||
option_two.onclick = showForm;
|
||||
option_three.onclick = showForm;
|
||||
option_one.checked = true;
|
||||
showForm(option_one);
|
||||
</script>
|
||||
`;
|
||||
|
||||
const gmap = new GMaps({
|
||||
el: "#map",
|
||||
disableDoubleClickZoom: true,
|
||||
lat: 0,
|
||||
lng: 0,
|
||||
disableDefaultUI: true,
|
||||
dblclick(e) {
|
||||
vex.dialog.open({
|
||||
message: "",
|
||||
input: header,
|
||||
buttons: [
|
||||
$.extend({}, vex.dialog.buttons.YES, {
|
||||
text: "Submit"
|
||||
}),
|
||||
$.extend({}, vex.dialog.buttons.NO, {
|
||||
text: "Abort"
|
||||
})
|
||||
],
|
||||
callback(data) {
|
||||
if (data !== false && Object.keys(data).length) {
|
||||
const ed = e.data = {};
|
||||
if (data.type === "SPAWN") {
|
||||
ed.interval = data.interval;
|
||||
ed.encounters = data.encounters;
|
||||
}
|
||||
else if (data.type === "CHECKPOINT") {
|
||||
ed.name = data.name;
|
||||
ed.description = data.description;
|
||||
ed.imageUrl = data.image_url;
|
||||
ed.experience = data.experience;
|
||||
}
|
||||
else if (data.type === "GYM") {
|
||||
ed.team = data.team;
|
||||
}
|
||||
e.type = data.type;
|
||||
addFort(e, ed);
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
});
|
||||
|
||||
function addFort(e, data) {
|
||||
let lat = e.latLng.lat();
|
||||
let lng = e.latLng.lng();
|
||||
let obj = {
|
||||
action: "addFortToPosition",
|
||||
latitude: lat,
|
||||
longitude: lng,
|
||||
zoom: gmap.zoom,
|
||||
type: e.type
|
||||
};
|
||||
Object.assign(obj, data);
|
||||
send(obj, res => {
|
||||
console.log(res);
|
||||
refreshMapForts();
|
||||
});
|
||||
}
|
||||
|
||||
function setStatus(txt, color) {
|
||||
connection_status.innerHTML = txt;
|
||||
connection_status.style.color = color;
|
||||
}
|
||||
|
||||
setStatus("Connecting", "yellow");
|
||||
|
||||
send({
|
||||
action: "init"
|
||||
}, res => {
|
||||
if (res.success) {
|
||||
setStatus("Connected!", "green");
|
||||
}
|
||||
else {
|
||||
if (res.reason !== void 0) {
|
||||
setStatus(res.reason);
|
||||
} else {
|
||||
setStatus("Connection failed!", "red");
|
||||
}
|
||||
return void 0;
|
||||
}
|
||||
});
|
||||
|
||||
login_attempt.addEventListener("click", login);
|
||||
|
||||
submit_spawn.addEventListener("click", () => {
|
||||
send({
|
||||
action: "spawnPkmnToPlayer",
|
||||
player: spawn_user.value,
|
||||
pkmn: spawn_pkmn.value
|
||||
}, res => {
|
||||
console.log(res);
|
||||
});
|
||||
});
|
||||
|
||||
function login() {
|
||||
|
||||
const username = login_username.value;
|
||||
const password = login_password.value;
|
||||
|
||||
send({
|
||||
action: "login",
|
||||
username,
|
||||
password
|
||||
}, res => {
|
||||
if (res.success) {
|
||||
afterLogin();
|
||||
}
|
||||
else {
|
||||
setStatus("Login failed!", "red");
|
||||
clearTimeout(loginTimeout);
|
||||
loginTimeout = setTimeout(() => {
|
||||
if (loggedIn) {
|
||||
setStatus("Connected!", "green");
|
||||
}
|
||||
}, 3e3);
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
function afterLogin() {
|
||||
loggedIn = true;
|
||||
login_area.style.display = "none";
|
||||
setStatus("Logged in!", "green");
|
||||
world_manager.style.display = "block";
|
||||
server_ping.style.display = "block";
|
||||
map_manager.style.display = "block";
|
||||
gmap.refresh();
|
||||
gmap.setCenter({
|
||||
lat: CFG.GMAPS.BASE_LAT,
|
||||
lng: CFG.GMAPS.BASE_LNG
|
||||
});
|
||||
gmap.setZoom(CFG.GMAPS.BASE_ZOOM);
|
||||
initHeartBeat();
|
||||
refreshMapForts();
|
||||
refreshConnectedPlayers();
|
||||
getServerVersion();
|
||||
}
|
||||
|
||||
function refreshConnectedPlayers() {
|
||||
send({
|
||||
action: "getConnectedPlayers"
|
||||
}, res => {
|
||||
connected_players.innerHTML = `Connected players: ${res.connected_players}`;
|
||||
});
|
||||
}
|
||||
|
||||
function getServerVersion() {
|
||||
send({
|
||||
action: "getServerVersion"
|
||||
}, res => {
|
||||
server_version.innerHTML = `Server version: v${res.version}`;
|
||||
});
|
||||
}
|
||||
|
||||
function getFortIcon(fort) {
|
||||
if (fort.type === "CHECKPOINT") return ("/api/img/pokestop_blue.png");
|
||||
else if (fort.uid[fort.uid.length - 1] === "S") return ("/api/img/spawn_point.png");
|
||||
else return (`/api/img/gym_${fort.owned_by_team}.png`);
|
||||
}
|
||||
|
||||
function refreshMapForts() {
|
||||
let center = gmap.getCenter();
|
||||
let lat = center.lat();
|
||||
let lng = center.lng();
|
||||
send({
|
||||
action: "getFortsByPosition",
|
||||
latitude: lat,
|
||||
longitude: lng,
|
||||
zoom: gmap.zoom
|
||||
}, result => {
|
||||
gmap.removeMarkers();
|
||||
result.forts.map((fort) => {
|
||||
let icon = getFortIcon(fort);
|
||||
gmap.addMarker({
|
||||
lat: fort.latitude,
|
||||
lng: fort.longitude,
|
||||
title: fort.name,
|
||||
icon,
|
||||
rightclick: function(e) {
|
||||
vex.dialog.confirm({
|
||||
message: `<center><img src='${getFortIcon(this)}' /><br/>Delete this fort?</center>`,
|
||||
callback: function(value) {
|
||||
if (value) removeFort(this);
|
||||
}.bind(fort)
|
||||
})
|
||||
}.bind(fort)
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function removeFort(fort) {
|
||||
send({
|
||||
action: "deleteFortById",
|
||||
uid: fort.uid,
|
||||
latitude: fort.latitude,
|
||||
longitude: fort.longitude,
|
||||
zoom: gmap.zoom
|
||||
}, res => {
|
||||
console.log(res);
|
||||
refreshMapForts();
|
||||
});
|
||||
}
|
||||
|
||||
function initHeartBeat() {
|
||||
clearInterval(heartInterval);
|
||||
heartInterval = setInterval(() => {
|
||||
heartTimedOut = true;
|
||||
const now = +new Date();
|
||||
heartTimeout = setTimeout(() => {
|
||||
if (heartTimedOut) {
|
||||
console.error("Heartbeat timeout!");
|
||||
loggedIn = false;
|
||||
setStatus("Reconnecting..", "yellow");
|
||||
login();
|
||||
}
|
||||
}, 5e3);
|
||||
send({
|
||||
action: "heartBeat",
|
||||
timestamp: now
|
||||
}, res => {
|
||||
if (res.timestamp) {
|
||||
heartTimedOut = false;
|
||||
clearTimeout(heartTimeout);
|
||||
const ping = res.timestamp - now;
|
||||
server_ping.innerHTML = `Ping: ${ping}ms`;
|
||||
refreshConnectedPlayers();
|
||||
refreshMapForts();
|
||||
}
|
||||
});
|
||||
}, 3e3);
|
||||
}
|
||||
|
||||
}))();
|
||||
|
|
@ -9,7 +9,8 @@
|
|||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\"",
|
||||
"babel-node": "babel-node --presets=es2015",
|
||||
"boot": "npm run babel-node -- ./src/index.js"
|
||||
"boot": "npm run babel-node -- ./src/index.js",
|
||||
"api": "npm run babel-node -- ./api/index.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 6.x",
|
||||
|
|
|
|||