mirror of
https://codeberg.org/demostf/inspector.git
synced 2026-06-03 10:04:09 +02:00
packet loading
This commit is contained in:
parent
55211ac364
commit
57650faeac
15 changed files with 11726 additions and 1662 deletions
|
|
@ -1,5 +1,5 @@
|
||||||
[package]
|
[package]
|
||||||
name = "inspector"
|
name = "demo-inspector"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
authors = ["Robin Appelman <robin@icewind.nl>"]
|
authors = ["Robin Appelman <robin@icewind.nl>"]
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
|
@ -11,7 +11,10 @@ crate-type = ["cdylib", "rlib"]
|
||||||
default = ["console_error_panic_hook"]
|
default = ["console_error_panic_hook"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
wasm-bindgen = "0.2.63"
|
bitbuffer = { version = "0.10", path = "../../bitbuffer" }
|
||||||
|
tf-demo-parser = { version = "0.3", path = "../tf-demo-parser" }
|
||||||
|
serde_json = "1"
|
||||||
|
wasm-bindgen = { version = "0.2", features = ["serde-serialize"] }
|
||||||
|
|
||||||
# The `console_error_panic_hook` crate provides better debugging of panics by
|
# The `console_error_panic_hook` crate provides better debugging of panics by
|
||||||
# logging them with `console.error`. This is great for development, but requires
|
# logging them with `console.error`. This is great for development, but requires
|
||||||
|
|
|
||||||
45
src/lib.rs
45
src/lib.rs
|
|
@ -1,19 +1,52 @@
|
||||||
mod utils;
|
mod utils;
|
||||||
|
|
||||||
use wasm_bindgen::prelude::*;
|
use wasm_bindgen::prelude::*;
|
||||||
|
use crate::utils::set_panic_hook;
|
||||||
|
use tf_demo_parser::demo::parser::{DemoHandler, NullHandler};
|
||||||
|
use tf_demo_parser::demo::header::Header;
|
||||||
|
use tf_demo_parser::demo::parser::RawPacketStream;
|
||||||
|
use bitbuffer::{BitRead, LittleEndian, BitReadBuffer, BitReadStream};
|
||||||
|
|
||||||
// When the `wee_alloc` feature is enabled, use `wee_alloc` as the global
|
|
||||||
// allocator.
|
|
||||||
#[cfg(feature = "wee_alloc")]
|
#[cfg(feature = "wee_alloc")]
|
||||||
#[global_allocator]
|
#[global_allocator]
|
||||||
static ALLOC: wee_alloc::WeeAlloc = wee_alloc::WeeAlloc::INIT;
|
static ALLOC: wee_alloc::WeeAlloc = wee_alloc::WeeAlloc::INIT;
|
||||||
|
|
||||||
#[wasm_bindgen]
|
#[wasm_bindgen]
|
||||||
extern {
|
pub struct Parser {
|
||||||
fn alert(s: &str);
|
handler: DemoHandler<'static, NullHandler>,
|
||||||
|
header: Header,
|
||||||
|
packets: RawPacketStream<'static>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[wasm_bindgen]
|
#[wasm_bindgen]
|
||||||
pub fn greet() {
|
impl Parser {
|
||||||
alert("Hello, inspector!");
|
#[wasm_bindgen(constructor)]
|
||||||
|
pub fn new(input: Vec<u8>) -> Self {
|
||||||
|
set_panic_hook();
|
||||||
|
let buffer = BitReadBuffer::new_owned(input, LittleEndian);
|
||||||
|
let mut stream = BitReadStream::new(buffer);
|
||||||
|
let header = Header::read(&mut stream).unwrap();
|
||||||
|
|
||||||
|
let packets = RawPacketStream::new(stream);
|
||||||
|
let mut handler = DemoHandler::default();
|
||||||
|
handler.handle_header(&header);
|
||||||
|
|
||||||
|
Parser {
|
||||||
|
handler,
|
||||||
|
header,
|
||||||
|
packets
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn header(&self) -> JsValue {
|
||||||
|
JsValue::from_serde(&self.header).unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn next(&mut self) -> JsValue {
|
||||||
|
self.packets.next(&self.handler.state_handler).unwrap().map(|packet| {
|
||||||
|
let out = JsValue::from_serde(&packet).unwrap();
|
||||||
|
self.handler.handle_packet(packet).unwrap();
|
||||||
|
out
|
||||||
|
}).unwrap_or(JsValue::NULL)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +0,0 @@
|
||||||
language: node_js
|
|
||||||
node_js: "10"
|
|
||||||
|
|
||||||
script:
|
|
||||||
- ./node_modules/.bin/webpack
|
|
||||||
|
|
@ -1,67 +0,0 @@
|
||||||
<div align="center">
|
|
||||||
|
|
||||||
<h1><code>create-wasm-app</code></h1>
|
|
||||||
|
|
||||||
<strong>An <code>npm init</code> template for kick starting a project that uses NPM packages containing Rust-generated WebAssembly and bundles them with Webpack.</strong>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
<a href="https://travis-ci.org/rustwasm/create-wasm-app"><img src="https://img.shields.io/travis/rustwasm/create-wasm-app.svg?style=flat-square" alt="Build Status" /></a>
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<h3>
|
|
||||||
<a href="#usage">Usage</a>
|
|
||||||
<span> | </span>
|
|
||||||
<a href="https://discordapp.com/channels/442252698964721669/443151097398296587">Chat</a>
|
|
||||||
</h3>
|
|
||||||
|
|
||||||
<sub>Built with 🦀🕸 by <a href="https://rustwasm.github.io/">The Rust and WebAssembly Working Group</a></sub>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
## About
|
|
||||||
|
|
||||||
This template is designed for depending on NPM packages that contain
|
|
||||||
Rust-generated WebAssembly and using them to create a Website.
|
|
||||||
|
|
||||||
* Want to create an NPM package with Rust and WebAssembly? [Check out
|
|
||||||
`wasm-pack-template`.](https://github.com/rustwasm/wasm-pack-template)
|
|
||||||
* Want to make a monorepo-style Website without publishing to NPM? Check out
|
|
||||||
[`rust-webpack-template`](https://github.com/rustwasm/rust-webpack-template)
|
|
||||||
and/or
|
|
||||||
[`rust-parcel-template`](https://github.com/rustwasm/rust-parcel-template).
|
|
||||||
|
|
||||||
## 🚴 Usage
|
|
||||||
|
|
||||||
```
|
|
||||||
npm init wasm-app
|
|
||||||
```
|
|
||||||
|
|
||||||
## 🔋 Batteries Included
|
|
||||||
|
|
||||||
- `.gitignore`: ignores `node_modules`
|
|
||||||
- `LICENSE-APACHE` and `LICENSE-MIT`: most Rust projects are licensed this way, so these are included for you
|
|
||||||
- `README.md`: the file you are reading now!
|
|
||||||
- `index.html`: a bare bones html document that includes the webpack bundle
|
|
||||||
- `index.js`: example js file with a comment showing how to import and use a wasm pkg
|
|
||||||
- `package.json` and `package-lock.json`:
|
|
||||||
- pulls in devDependencies for using webpack:
|
|
||||||
- [`webpack`](https://www.npmjs.com/package/webpack)
|
|
||||||
- [`webpack-cli`](https://www.npmjs.com/package/webpack-cli)
|
|
||||||
- [`webpack-dev-server`](https://www.npmjs.com/package/webpack-dev-server)
|
|
||||||
- defines a `start` script to run `webpack-dev-server`
|
|
||||||
- `webpack.config.js`: configuration file for bundling your js with webpack
|
|
||||||
|
|
||||||
## License
|
|
||||||
|
|
||||||
Licensed under either of
|
|
||||||
|
|
||||||
* Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0)
|
|
||||||
* MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT)
|
|
||||||
|
|
||||||
at your option.
|
|
||||||
|
|
||||||
### Contribution
|
|
||||||
|
|
||||||
Unless you explicitly state otherwise, any contribution intentionally
|
|
||||||
submitted for inclusion in the work by you, as defined in the Apache-2.0
|
|
||||||
license, shall be dual licensed as above, without any additional terms or
|
|
||||||
conditions.
|
|
||||||
4
www/bootstrap.js
vendored
4
www/bootstrap.js
vendored
|
|
@ -1,5 +1,5 @@
|
||||||
// A dependency graph that contains any wasm must all be imported
|
// A dependency graph that contains any wasm must all be imported
|
||||||
// asynchronously. This `bootstrap.js` file does the single async import, so
|
// asynchronously. This `bootstrap.js` file does the single async import, so
|
||||||
// that no one else needs to worry about it again.
|
// that no one else needs to worry about it again.
|
||||||
import("./index.js")
|
import("./src")
|
||||||
.catch(e => console.error("Error importing `index.js`:", e));
|
.catch(e => console.error("Error importing `index.tsx`:", e));
|
||||||
|
|
|
||||||
|
|
@ -7,5 +7,6 @@
|
||||||
<body>
|
<body>
|
||||||
<noscript>This page contains webassembly and javascript content, please enable javascript in your browser.</noscript>
|
<noscript>This page contains webassembly and javascript content, please enable javascript in your browser.</noscript>
|
||||||
<script src="./bootstrap.js"></script>
|
<script src="./bootstrap.js"></script>
|
||||||
|
<div id="root"></div>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
||||||
|
|
@ -1,3 +0,0 @@
|
||||||
import * as wasm from "hello-wasm-pack";
|
|
||||||
|
|
||||||
wasm.greet();
|
|
||||||
9630
www/package-lock.json
generated
9630
www/package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
|
@ -2,35 +2,28 @@
|
||||||
"name": "create-wasm-app",
|
"name": "create-wasm-app",
|
||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"description": "create an app to consume rust-generated wasm packages",
|
"description": "create an app to consume rust-generated wasm packages",
|
||||||
"main": "index.js",
|
"main": "src/index.tsx",
|
||||||
"bin": {
|
"bin": {
|
||||||
"create-wasm-app": ".bin/create-wasm-app.js"
|
"create-wasm-app": ".bin/create-wasm-app.js"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "webpack --config webpack.config.js",
|
"build": "webpack --config webpack.config.js",
|
||||||
"start": "webpack-dev-server"
|
"start": "webpack serve"
|
||||||
},
|
},
|
||||||
"repository": {
|
"dependencies": {
|
||||||
"type": "git",
|
"demo-inspector": "file:../pkg",
|
||||||
"url": "git+https://github.com/rustwasm/create-wasm-app.git"
|
"react": "^17.0.2",
|
||||||
|
"react-dom": "^17.0.2",
|
||||||
|
"react-dropzone": "^11.3.4"
|
||||||
},
|
},
|
||||||
"keywords": [
|
|
||||||
"webassembly",
|
|
||||||
"wasm",
|
|
||||||
"rust",
|
|
||||||
"webpack"
|
|
||||||
],
|
|
||||||
"author": "Ashley Williams <ashley666ashley@gmail.com>",
|
|
||||||
"license": "(MIT OR Apache-2.0)",
|
|
||||||
"bugs": {
|
|
||||||
"url": "https://github.com/rustwasm/create-wasm-app/issues"
|
|
||||||
},
|
|
||||||
"homepage": "https://github.com/rustwasm/create-wasm-app#readme",
|
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"hello-wasm-pack": "^0.1.0",
|
"@types/react": "^17.0.15",
|
||||||
"webpack": "^4.29.3",
|
"@types/react-dom": "^17.0.9",
|
||||||
"webpack-cli": "^3.1.0",
|
"copy-webpack-plugin": "^9.0.1",
|
||||||
"webpack-dev-server": "^3.1.5",
|
"ts-loader": "^9.2.4",
|
||||||
"copy-webpack-plugin": "^5.0.0"
|
"typescript": "^4.3.5",
|
||||||
|
"webpack": "^5.46.0",
|
||||||
|
"webpack-cli": "^4.7.2",
|
||||||
|
"webpack-dev-server": "^3.11.2"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
13
www/src/header.d.ts
vendored
Normal file
13
www/src/header.d.ts
vendored
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
export interface Header {
|
||||||
|
demo_type: string,
|
||||||
|
version: number,
|
||||||
|
protocol: number,
|
||||||
|
server: string,
|
||||||
|
nick: string,
|
||||||
|
map: string,
|
||||||
|
game: string,
|
||||||
|
duration: number,
|
||||||
|
ticks: number,
|
||||||
|
frames: number,
|
||||||
|
sigon: number
|
||||||
|
}
|
||||||
103
www/src/index.tsx
Normal file
103
www/src/index.tsx
Normal file
|
|
@ -0,0 +1,103 @@
|
||||||
|
import {Packet} from "./parser";
|
||||||
|
import React, {useCallback, Component} from 'react'
|
||||||
|
import {useDropzone} from 'react-dropzone'
|
||||||
|
import ReactDOM from "react-dom";
|
||||||
|
import {Header} from "./header";
|
||||||
|
|
||||||
|
class App extends Component<{}, {
|
||||||
|
loading: boolean,
|
||||||
|
header: Header | null,
|
||||||
|
packets: Packet[]
|
||||||
|
}> {
|
||||||
|
state: {
|
||||||
|
loading: boolean,
|
||||||
|
header: Header | null,
|
||||||
|
packets: Packet[]
|
||||||
|
} = {
|
||||||
|
loading: false,
|
||||||
|
header: null,
|
||||||
|
packets: []
|
||||||
|
}
|
||||||
|
|
||||||
|
load(data: ArrayBuffer) {
|
||||||
|
this.setState({loading: true});
|
||||||
|
const worker = new Worker('./worker.js');
|
||||||
|
worker.addEventListener("message", (event: MessageEvent<{ type: "header", header: Header } | { type: "packet", packet: Packet } | { type: "done" }>) => {
|
||||||
|
switch (event.data.type) {
|
||||||
|
case "header":
|
||||||
|
let header = event.data.header;
|
||||||
|
this.setState({header});
|
||||||
|
break;
|
||||||
|
case "packet":
|
||||||
|
let packet = event.data.packet;
|
||||||
|
let packets = this.state.packets;
|
||||||
|
packets.push(packet);
|
||||||
|
this.setState({packets});
|
||||||
|
break;
|
||||||
|
case "done":
|
||||||
|
this.setState({loading: false});
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
});
|
||||||
|
worker.postMessage(data, [data]);
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
if (this.state.loading && this.state.header && this.state.packets.length) {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<h1>Loading</h1>
|
||||||
|
<p>{this.state.packets.slice(-1)[0].tick}/{this.state.header.ticks}</p>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
} else if (this.state.loading) {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<h1>Loading</h1>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
} else if (this.state.packets.length) {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<h1>{this.state.packets.length}</h1>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<DemoDropzone onDrop={(data) => this.load(data)}/>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ReactDOM.render(
|
||||||
|
<App/>,
|
||||||
|
document.getElementById("root")
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
function DemoDropzone({onDrop}: { onDrop: (data: ArrayBuffer) => void }) {
|
||||||
|
const onDropCb = useCallback(acceptedFiles => {
|
||||||
|
let reader = new FileReader();
|
||||||
|
reader.readAsArrayBuffer(acceptedFiles[0]);
|
||||||
|
reader.addEventListener('load', () => {
|
||||||
|
let result = reader.result as ArrayBuffer;
|
||||||
|
onDrop(result)
|
||||||
|
});
|
||||||
|
}, [])
|
||||||
|
const {getRootProps, getInputProps, isDragActive} = useDropzone({onDrop: onDropCb})
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div {...getRootProps()}>
|
||||||
|
<input {...getInputProps()} />
|
||||||
|
{
|
||||||
|
isDragActive ?
|
||||||
|
<p>Drop the files here ...</p> :
|
||||||
|
<p>Drag 'n' drop some files here, or click to select files</p>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
3387
www/src/parser.d.ts
vendored
Normal file
3387
www/src/parser.d.ts
vendored
Normal file
File diff suppressed because it is too large
Load diff
23
www/src/worker.ts
Normal file
23
www/src/worker.ts
Normal file
|
|
@ -0,0 +1,23 @@
|
||||||
|
import {Parser} from "demo-inspector";
|
||||||
|
|
||||||
|
declare function postMessage(message: any): void;
|
||||||
|
|
||||||
|
onmessage = function (event) {
|
||||||
|
let data = event.data as ArrayBuffer;
|
||||||
|
import("demo-inspector")
|
||||||
|
.then(({Parser}) => {
|
||||||
|
console.log(data);
|
||||||
|
let parser = new Parser(new Uint8Array(data));
|
||||||
|
|
||||||
|
postMessage({type: "header", header: parser.header()})
|
||||||
|
|
||||||
|
let packet;
|
||||||
|
do {
|
||||||
|
packet = parser.next();
|
||||||
|
if (packet) {
|
||||||
|
postMessage({type: "packet", packet})
|
||||||
|
}
|
||||||
|
} while (packet);
|
||||||
|
postMessage({type: "done"})
|
||||||
|
})
|
||||||
|
};
|
||||||
12
www/tsconfig.json
Normal file
12
www/tsconfig.json
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"outDir": "./dist/",
|
||||||
|
"noImplicitAny": true,
|
||||||
|
"module": "es2020",
|
||||||
|
"target": "es6",
|
||||||
|
"jsx": "react",
|
||||||
|
"allowJs": true,
|
||||||
|
"moduleResolution": "node",
|
||||||
|
"allowSyntheticDefaultImports": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,14 +1,49 @@
|
||||||
const CopyWebpackPlugin = require("copy-webpack-plugin");
|
const CopyWebpackPlugin = require("copy-webpack-plugin");
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
|
|
||||||
module.exports = {
|
module.exports = [{
|
||||||
entry: "./bootstrap.js",
|
entry: "./bootstrap.js",
|
||||||
output: {
|
output: {
|
||||||
path: path.resolve(__dirname, "dist"),
|
path: path.resolve(__dirname, "dist"),
|
||||||
filename: "bootstrap.js",
|
filename: "bootstrap.js",
|
||||||
},
|
},
|
||||||
mode: "development",
|
mode: "development",
|
||||||
plugins: [
|
module: {
|
||||||
new CopyWebpackPlugin(['index.html'])
|
rules: [
|
||||||
],
|
{
|
||||||
};
|
test: /\.tsx?$/,
|
||||||
|
use: 'ts-loader',
|
||||||
|
exclude: /node_modules/,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
resolve: {
|
||||||
|
extensions: ['.tsx', '.ts', '.js'],
|
||||||
|
},
|
||||||
|
plugins: [
|
||||||
|
new CopyWebpackPlugin({patterns: [{from: 'index.html'}]})
|
||||||
|
],
|
||||||
|
}, {
|
||||||
|
entry: "./src/worker.ts",
|
||||||
|
target: 'webworker',
|
||||||
|
output: {
|
||||||
|
path: path.resolve(__dirname, "dist"),
|
||||||
|
filename: "worker.js"
|
||||||
|
},
|
||||||
|
module: {
|
||||||
|
rules: [
|
||||||
|
{
|
||||||
|
test: /\.tsx?$/,
|
||||||
|
use: 'ts-loader',
|
||||||
|
exclude: /node_modules/,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
resolve: {
|
||||||
|
extensions: ['.tsx', '.ts', '.js'],
|
||||||
|
},
|
||||||
|
experiments: {
|
||||||
|
syncWebAssembly: true
|
||||||
|
},
|
||||||
|
mode: "development",
|
||||||
|
}];
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue