Added manual server emulation and javascript graph
This commit is contained in:
parent
2abf9fd7f0
commit
dd8f37fe42
|
@ -11,8 +11,8 @@ clients = set()
|
||||||
|
|
||||||
STRUCTS = {
|
STRUCTS = {
|
||||||
"start": b"fHB%ds",
|
"start": b"fHB%ds",
|
||||||
"end": b"",
|
|
||||||
"flight_data": b"BBHhHfff",
|
"flight_data": b"BBHhHfff",
|
||||||
|
"end": b"",
|
||||||
"server_open": b"",
|
"server_open": b"",
|
||||||
"server_close": b""
|
"server_close": b""
|
||||||
}
|
}
|
||||||
|
@ -223,7 +223,7 @@ class DiscoveryProtocol(asyncio.DatagramProtocol):
|
||||||
def connection_made(self, transport):
|
def connection_made(self, transport):
|
||||||
self.transport = transport
|
self.transport = transport
|
||||||
def datagram_received(self, data, addr):
|
def datagram_received(self, data, addr):
|
||||||
logging.info("Received data from %s:%d" % addr)
|
logging.debug("Received data from %s:%d" % addr)
|
||||||
|
|
||||||
if len(data) < 4: # Not even a header... smh
|
if len(data) < 4: # Not even a header... smh
|
||||||
logging.debug("Noise received: %b" % data)
|
logging.debug("Noise received: %b" % data)
|
||||||
|
@ -266,9 +266,9 @@ class DiscoveryProtocol(asyncio.DatagramProtocol):
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def handle_server_open(_):
|
def handle_server_open(_):
|
||||||
pass
|
logging.info("Received server opened message")
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def handle_server_close(_):
|
def handle_server_close(_):
|
||||||
pass
|
logging.info("Received server closed message")
|
||||||
|
|
104
serv_emu.py
Normal file
104
serv_emu.py
Normal file
|
@ -0,0 +1,104 @@
|
||||||
|
import sys
|
||||||
|
import socket
|
||||||
|
import struct
|
||||||
|
import pathlib
|
||||||
|
import logging
|
||||||
|
|
||||||
|
from objects import glob
|
||||||
|
from handlers.mainHandler import STRUCTS
|
||||||
|
|
||||||
|
sock_addr = (glob.config["socket"]["ip"] if glob.config["socket"]["ip"] != "0.0.0.0" else "127.0.0.1", glob.config["socket"]["port"])
|
||||||
|
|
||||||
|
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
|
||||||
|
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
||||||
|
sock.connect(sock_addr)
|
||||||
|
sock.setblocking(0)
|
||||||
|
|
||||||
|
def send_packet(type, data = b""):
|
||||||
|
global sock
|
||||||
|
packet_id = list(STRUCTS.keys()).index(type) + 1
|
||||||
|
data = struct.pack(b"<3sB%ds" % len(data), b"FLY", packet_id, data)
|
||||||
|
logging.info("<< %s" % data)
|
||||||
|
sock.send(data)
|
||||||
|
|
||||||
|
def sinput(p = "> "):
|
||||||
|
s = input(p)
|
||||||
|
if s in ["exit", "close", "stop"]:
|
||||||
|
send_packet("server_close")
|
||||||
|
exit()
|
||||||
|
return s
|
||||||
|
|
||||||
|
def srvr():
|
||||||
|
keys = list(STRUCTS.keys())
|
||||||
|
def choose_packetType():
|
||||||
|
print("Choose packetID to send")
|
||||||
|
for i in range(len(keys)):
|
||||||
|
print(" %d: %s" % (i + 1, keys[i]))
|
||||||
|
id = 0
|
||||||
|
while id > len(keys) or id < 1:
|
||||||
|
try:
|
||||||
|
id = int( sinput() )
|
||||||
|
except SystemExit or KeyboardInterrupt:
|
||||||
|
exit()
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
return id
|
||||||
|
|
||||||
|
def send_data(id):
|
||||||
|
def _start():
|
||||||
|
ret = (
|
||||||
|
int( input(" FlightUUID (I) [DWORD] > ") ),
|
||||||
|
float( input(" VehicleMaxFuel (f) [FLOAT] > ") ),
|
||||||
|
int( input(" VehicleModelID (H) [WORD] > ") ),
|
||||||
|
input(" PlayerName (%ds) [STRING] > ").encode()
|
||||||
|
)
|
||||||
|
send_packet("start",
|
||||||
|
struct.pack(b"<I" + STRUCTS["start"] % 24,
|
||||||
|
ret[0], # flightUUID
|
||||||
|
ret[1], # vehicleMaxFuel
|
||||||
|
ret[2], # vehicleModelID
|
||||||
|
len( ret[3] ), # playerNameLength
|
||||||
|
ret[3] # playerName
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
def _flight_data():
|
||||||
|
ret = (
|
||||||
|
int( input(" FlightUUID (I) [DWORD] > ") ),
|
||||||
|
int( input(" Flags 0-3 (B) [BYTE] > ") ),
|
||||||
|
int( input(" Satisfaction (B) [BYTE] > ") ),
|
||||||
|
int( input(" Speed (H) [WORD] > ") ),
|
||||||
|
int( input(" Altitude (h) [WORD] > ") ),
|
||||||
|
int( input(" Health (H) [WORD] > ") ),
|
||||||
|
float( input(" FuelLevel (f) [FLOAT] > ") ),
|
||||||
|
float( input(" X pos (f) [FLOAT] > ") ),
|
||||||
|
float( input(" Y pos (f) [FLOAT] > ") )
|
||||||
|
)
|
||||||
|
send_packet("flight_data", struct.pack(b"<I" + STRUCTS["flight_data"], *ret) )
|
||||||
|
|
||||||
|
def _end():
|
||||||
|
ret = (
|
||||||
|
int( input(" FlightUUID (I) [DWORD] > ") ),
|
||||||
|
)
|
||||||
|
send_packet("end", struct.pack(b"<I" + STRUCTS["end"], *ret))
|
||||||
|
|
||||||
|
def _server_open():
|
||||||
|
send_packet("server_open")
|
||||||
|
def _server_close():
|
||||||
|
send_packet("server_close")
|
||||||
|
|
||||||
|
switch = {
|
||||||
|
1: _start,
|
||||||
|
2: _flight_data,
|
||||||
|
3: _end,
|
||||||
|
4: _server_open,
|
||||||
|
5: _server_close
|
||||||
|
}
|
||||||
|
switch.get(id)()
|
||||||
|
|
||||||
|
send_packet("server_open")
|
||||||
|
while True:
|
||||||
|
id = choose_packetType()
|
||||||
|
send_data(id)
|
||||||
|
|
||||||
|
srvr()
|
50
www/js/graph.js
Normal file
50
www/js/graph.js
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
class Graph {
|
||||||
|
constructor(canvas, color) {
|
||||||
|
this.canvas = canvas;
|
||||||
|
|
||||||
|
this.ctx = this.canvas.getContext("2d");
|
||||||
|
this.ctx.save();
|
||||||
|
|
||||||
|
this.scale = {x: 1, y: 1};
|
||||||
|
|
||||||
|
this.canvas.onresize = this.onresize();
|
||||||
|
this.setColor(color);
|
||||||
|
|
||||||
|
this.values = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
setColor(color) {
|
||||||
|
this.color = color;
|
||||||
|
this.ctx.fillStyle = this.color;
|
||||||
|
}
|
||||||
|
|
||||||
|
updateScale() {
|
||||||
|
this.onresize();
|
||||||
|
}
|
||||||
|
|
||||||
|
onresize() {
|
||||||
|
this.ctx.restore();
|
||||||
|
this.ctx.save();
|
||||||
|
this.ctx.fillStyle = this.color;
|
||||||
|
this.ctx.translate(0, this.canvas.height);
|
||||||
|
this.ctx.scale(this.scale.x, -this.scale.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
draw() {
|
||||||
|
this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
|
||||||
|
|
||||||
|
this.ctx.beginPath();
|
||||||
|
this.ctx.moveTo(0, 0);
|
||||||
|
|
||||||
|
let step = this.canvas.width / this.values.length;
|
||||||
|
this.ctx.save();
|
||||||
|
for (let i = 0; i < this.values.length; i++) {
|
||||||
|
this.ctx.lineTo(0, this.values[i]);
|
||||||
|
this.ctx.translate(step, 0);
|
||||||
|
}
|
||||||
|
this.ctx.restore();
|
||||||
|
|
||||||
|
this.ctx.lineTo(this.canvas.width, 0);
|
||||||
|
this.ctx.fill();
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,21 +0,0 @@
|
||||||
The MIT License (MIT)
|
|
||||||
|
|
||||||
Copyright (c) 2016 Aksel Jensen (TheRealAksel at github)
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
|
||||||
in the Software without restriction, including without limitation the rights
|
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in all
|
|
||||||
copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
SOFTWARE.
|
|
|
@ -1,60 +0,0 @@
|
||||||
// https://github.com/lyngklip/structjs
|
|
||||||
"use strict"
|
|
||||||
const rechk = /^([<>])?(([1-9]\d*)?([xcbB?hHiIfdsp]))*$/
|
|
||||||
const refmt = /([1-9]\d*)?([xcbB?hHiIfdsp])/g
|
|
||||||
const str = (v,o,c) => String.fromCharCode(
|
|
||||||
...new Uint8Array(v.buffer, v.byteOffset + o, c))
|
|
||||||
const rts = (v,o,c,s) => new Uint8Array(v.buffer, v.byteOffset + o, c)
|
|
||||||
.set(s.split('').map(str => str.charCodeAt(0)))
|
|
||||||
const pst = (v,o,c) => str(v, o + 1, Math.min(v.getUint8(o), c - 1))
|
|
||||||
const tsp = (v,o,c,s) => { v.setUint8(o, s.length); rts(v, o + 1, c - 1, s) }
|
|
||||||
const lut = le => ({
|
|
||||||
x: c=>[1,c,0],
|
|
||||||
c: c=>[c,1,o=>({u:v=>str(v, o, 1) , p:(v,c)=>rts(v, o, 1, c) })],
|
|
||||||
'?': c=>[c,1,o=>({u:v=>Boolean(v.getUint8(o)),p:(v,B)=>v.setUint8(o,B)})],
|
|
||||||
b: c=>[c,1,o=>({u:v=>v.getInt8( o ), p:(v,b)=>v.setInt8( o,b )})],
|
|
||||||
B: c=>[c,1,o=>({u:v=>v.getUint8( o ), p:(v,B)=>v.setUint8( o,B )})],
|
|
||||||
h: c=>[c,2,o=>({u:v=>v.getInt16( o,le), p:(v,h)=>v.setInt16( o,h,le)})],
|
|
||||||
H: c=>[c,2,o=>({u:v=>v.getUint16( o,le), p:(v,H)=>v.setUint16( o,H,le)})],
|
|
||||||
i: c=>[c,4,o=>({u:v=>v.getInt32( o,le), p:(v,i)=>v.setInt32( o,i,le)})],
|
|
||||||
I: c=>[c,4,o=>({u:v=>v.getUint32( o,le), p:(v,I)=>v.setUint32( o,I,le)})],
|
|
||||||
f: c=>[c,4,o=>({u:v=>v.getFloat32(o,le), p:(v,f)=>v.setFloat32(o,f,le)})],
|
|
||||||
d: c=>[c,8,o=>({u:v=>v.getFloat64(o,le), p:(v,d)=>v.setFloat64(o,d,le)})],
|
|
||||||
s: c=>[1,c,o=>({u:v=>str(v,o,c), p:(v,s)=>rts(v,o,c,s.slice(0,c ) )})],
|
|
||||||
p: c=>[1,c,o=>({u:v=>pst(v,o,c), p:(v,s)=>tsp(v,o,c,s.slice(0,c - 1) )})]
|
|
||||||
})
|
|
||||||
const errbuf = new RangeError("Structure larger than remaining buffer")
|
|
||||||
const errval = new RangeError("Not enough values for structure")
|
|
||||||
const struct = format => {
|
|
||||||
let fns = [], size = 0, m = rechk.exec(format)
|
|
||||||
if (!m) { throw new RangeError("Invalid format string") }
|
|
||||||
const t = lut('<' === m[1]), lu = (n, c) => t[c](n ? parseInt(n, 10) : 1)
|
|
||||||
while ((m = refmt.exec(format))) { ((r, s, f) => {
|
|
||||||
for (let i = 0; i < r; ++i, size += s) { if (f) {fns.push(f(size))} }
|
|
||||||
})(...lu(...m.slice(1)))}
|
|
||||||
const unpack_from = (arrb, offs) => {
|
|
||||||
if (arrb.byteLength < (offs|0) + size) { throw errbuf }
|
|
||||||
let v = new DataView(arrb, offs|0)
|
|
||||||
return fns.map(f => f.u(v))
|
|
||||||
}
|
|
||||||
const pack_into = (arrb, offs, ...values) => {
|
|
||||||
if (values.length < fns.length) { throw errval }
|
|
||||||
if (arrb.byteLength < offs + size) { throw errbuf }
|
|
||||||
const v = new DataView(arrb, offs)
|
|
||||||
new Uint8Array(arrb, offs, size).fill(0)
|
|
||||||
fns.forEach((f, i) => f.p(v, values[i]))
|
|
||||||
}
|
|
||||||
const pack = (...values) => {
|
|
||||||
let b = new ArrayBuffer(size)
|
|
||||||
pack_into(b, 0, ...values)
|
|
||||||
return b
|
|
||||||
}
|
|
||||||
const unpack = arrb => unpack_from(arrb, 0)
|
|
||||||
function* iter_unpack(arrb) {
|
|
||||||
for (let offs = 0; offs + size <= arrb.byteLength; offs += size) {
|
|
||||||
yield unpack_from(arrb, offs);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return Object.freeze({
|
|
||||||
unpack, pack, unpack_from, pack_into, iter_unpack, format, size})
|
|
||||||
}
|
|
|
@ -2,8 +2,8 @@
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<title>WebSocket DEMO</title>
|
<title>WebSocket DEMO</title>
|
||||||
<script src="js/struct/struct.js"></script>
|
|
||||||
<script src="js/fly-ws.js"></script>
|
<script src="js/fly-ws.js"></script>
|
||||||
|
<script src="js/graph.js"></script>
|
||||||
<style>
|
<style>
|
||||||
html, body {
|
html, body {
|
||||||
width: 100vw;
|
width: 100vw;
|
||||||
|
@ -90,22 +90,21 @@
|
||||||
.map {
|
.map {
|
||||||
grid-area: map;
|
grid-area: map;
|
||||||
}
|
}
|
||||||
.data-al {
|
#data_al {
|
||||||
grid-area: data-al;
|
grid-area: data-al;
|
||||||
}
|
}
|
||||||
.data-sp {
|
#data_sp {
|
||||||
grid-area: data-sp;
|
grid-area: data-sp;
|
||||||
}
|
}
|
||||||
.data-ps {
|
#data_ps {
|
||||||
grid-area: data-ps;
|
grid-area: data-ps;
|
||||||
}
|
}
|
||||||
.data-hp {
|
#data_hp {
|
||||||
grid-area: data-hp;
|
grid-area: data-hp;
|
||||||
}
|
}
|
||||||
#stdin {
|
#stdin {
|
||||||
grid-area: stdin;
|
grid-area: stdin;
|
||||||
}
|
}
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
@ -120,10 +119,10 @@
|
||||||
<button onclick="connect()">Connect</button>
|
<button onclick="connect()">Connect</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="map border"></div>
|
<div class="map border"></div>
|
||||||
<div class="data-al border"></div>
|
<div class="border" id="data_al"></div>
|
||||||
<div class="data-sp border"></div>
|
<div class="border" id="data_sp"></div>
|
||||||
<div class="data-ps border"></div>
|
<div class="border" id="data_ps"></div>
|
||||||
<div class="data-hp border"></div>
|
<div class="border" id="data_hp"></div>
|
||||||
<div class="console border">
|
<div class="console border">
|
||||||
<pre id="stdout"></pre>
|
<pre id="stdout"></pre>
|
||||||
</div>
|
</div>
|
||||||
|
@ -136,6 +135,12 @@
|
||||||
<script>
|
<script>
|
||||||
var fs;
|
var fs;
|
||||||
|
|
||||||
|
// init graphs
|
||||||
|
let canvas = document.createElement("canvas");
|
||||||
|
canvas.width = canvas.height = 215;
|
||||||
|
data_al.appendChild(canvas);
|
||||||
|
let graph = new Graph(canvas, "#FFBF00");
|
||||||
|
|
||||||
function* buffer2HexArray(buff, start = 0, end = buff.byteLength) {
|
function* buffer2HexArray(buff, start = 0, end = buff.byteLength) {
|
||||||
for (let i = start; i < end; i++) {
|
for (let i = start; i < end; i++) {
|
||||||
let hex = buff.getUint8(i).toString(16);
|
let hex = buff.getUint8(i).toString(16);
|
||||||
|
|
Loading…
Reference in New Issue
Block a user