mirror of
https://codeberg.org/demostf/inspector.git
synced 2026-06-03 10:04:09 +02:00
rework wip
This commit is contained in:
parent
a653d1c0e3
commit
93130dd16b
7 changed files with 261 additions and 175 deletions
|
|
@ -12,8 +12,11 @@ default = ["console_error_panic_hook"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
bitbuffer = { version = "0.10" }
|
bitbuffer = { version = "0.10" }
|
||||||
tf-demo-parser = { version = "0.4", path = "../tf-demo-parser" }
|
#tf-demo-parser = { version = "0.4", path = "../tf-demo-parser" }
|
||||||
|
tf-demo-parser = { version = "0.4", git = "https://github.com/demostf/parser" }
|
||||||
|
serde = { version = "1.0.144", features = ["derive"] }
|
||||||
serde_json = "1"
|
serde_json = "1"
|
||||||
|
js-sys = "0.3.59"
|
||||||
wasm-bindgen = { version = "0.2", features = ["serde-serialize"] }
|
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
|
||||||
|
|
|
||||||
70
README.md
70
README.md
|
|
@ -1,69 +1 @@
|
||||||
<div align="center">
|
tf2 demo inspector
|
||||||
|
|
||||||
<h1><code>wasm-pack-template</code></h1>
|
|
||||||
|
|
||||||
<strong>A template for kick starting a Rust and WebAssembly project using <a href="https://github.com/rustwasm/wasm-pack">wasm-pack</a>.</strong>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
<a href="https://travis-ci.org/rustwasm/wasm-pack-template"><img src="https://img.shields.io/travis/rustwasm/wasm-pack-template.svg?style=flat-square" alt="Build Status" /></a>
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<h3>
|
|
||||||
<a href="https://rustwasm.github.io/docs/wasm-pack/tutorials/npm-browser-packages/index.html">Tutorial</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
|
|
||||||
|
|
||||||
[**📚 Read this template tutorial! 📚**][template-docs]
|
|
||||||
|
|
||||||
This template is designed for compiling Rust libraries into WebAssembly and
|
|
||||||
publishing the resulting package to NPM.
|
|
||||||
|
|
||||||
Be sure to check out [other `wasm-pack` tutorials online][tutorials] for other
|
|
||||||
templates and usages of `wasm-pack`.
|
|
||||||
|
|
||||||
[tutorials]: https://rustwasm.github.io/docs/wasm-pack/tutorials/index.html
|
|
||||||
[template-docs]: https://rustwasm.github.io/docs/wasm-pack/tutorials/npm-browser-packages/index.html
|
|
||||||
|
|
||||||
## 🚴 Usage
|
|
||||||
|
|
||||||
### 🐑 Use `cargo generate` to Clone this Template
|
|
||||||
|
|
||||||
[Learn more about `cargo generate` here.](https://github.com/ashleygwilliams/cargo-generate)
|
|
||||||
|
|
||||||
```
|
|
||||||
cargo generate --git https://github.com/rustwasm/wasm-pack-template.git --name my-project
|
|
||||||
cd my-project
|
|
||||||
```
|
|
||||||
|
|
||||||
### 🛠️ Build with `wasm-pack build`
|
|
||||||
|
|
||||||
```
|
|
||||||
wasm-pack build
|
|
||||||
```
|
|
||||||
|
|
||||||
### 🔬 Test in Headless Browsers with `wasm-pack test`
|
|
||||||
|
|
||||||
```
|
|
||||||
wasm-pack test --headless --firefox
|
|
||||||
```
|
|
||||||
|
|
||||||
### 🎁 Publish to NPM with `wasm-pack publish`
|
|
||||||
|
|
||||||
```
|
|
||||||
wasm-pack publish
|
|
||||||
```
|
|
||||||
|
|
||||||
## 🔋 Batteries Included
|
|
||||||
|
|
||||||
* [`wasm-bindgen`](https://github.com/rustwasm/wasm-bindgen) for communicating
|
|
||||||
between WebAssembly and JavaScript.
|
|
||||||
* [`console_error_panic_hook`](https://github.com/rustwasm/console_error_panic_hook)
|
|
||||||
for logging panic messages to the developer console.
|
|
||||||
* [`wee_alloc`](https://github.com/rustwasm/wee_alloc), an allocator optimized
|
|
||||||
for small code size.
|
|
||||||
|
|
|
||||||
140
src/lib.rs
140
src/lib.rs
|
|
@ -1,40 +1,99 @@
|
||||||
mod utils;
|
mod utils;
|
||||||
|
|
||||||
use wasm_bindgen::prelude::*;
|
|
||||||
use crate::utils::set_panic_hook;
|
use crate::utils::set_panic_hook;
|
||||||
use tf_demo_parser::demo::parser::{DemoHandler, NullHandler};
|
use bitbuffer::{BitRead, BitReadBuffer, BitReadStream, LittleEndian};
|
||||||
|
use js_sys::Function;
|
||||||
|
use serde::Serialize;
|
||||||
use tf_demo_parser::demo::header::Header;
|
use tf_demo_parser::demo::header::Header;
|
||||||
|
use tf_demo_parser::demo::packet::datatable::{DataTablePacket, SendTableName, ServerClassName};
|
||||||
|
use tf_demo_parser::demo::packet::Packet;
|
||||||
use tf_demo_parser::demo::parser::RawPacketStream;
|
use tf_demo_parser::demo::parser::RawPacketStream;
|
||||||
use bitbuffer::{BitRead, LittleEndian, BitReadBuffer, BitReadStream};
|
use tf_demo_parser::demo::parser::{DemoHandler, NullHandler};
|
||||||
|
use tf_demo_parser::demo::sendprop::SendPropName;
|
||||||
|
use wasm_bindgen::prelude::*;
|
||||||
|
|
||||||
#[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;
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize)]
|
||||||
|
pub struct PacketMeta {
|
||||||
|
index: usize,
|
||||||
|
tick: u32,
|
||||||
|
ty: u8,
|
||||||
|
}
|
||||||
|
|
||||||
#[wasm_bindgen]
|
#[wasm_bindgen]
|
||||||
pub struct Parser {
|
pub struct Parser {
|
||||||
handler: DemoHandler<'static, NullHandler>,
|
|
||||||
header: Header,
|
header: Header,
|
||||||
packets: RawPacketStream<'static>,
|
packets: Vec<Packet<'static>>,
|
||||||
|
prop_names: Vec<(u64, SendTableName, SendPropName)>,
|
||||||
|
class_names: Vec<(u16, ServerClassName)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[wasm_bindgen]
|
#[wasm_bindgen]
|
||||||
impl Parser {
|
impl Parser {
|
||||||
#[wasm_bindgen(constructor)]
|
#[wasm_bindgen(constructor)]
|
||||||
pub fn new(input: Vec<u8>) -> Self {
|
pub fn new(input: Vec<u8>, progress: Function) -> Self {
|
||||||
set_panic_hook();
|
|
||||||
let buffer = BitReadBuffer::new_owned(input, LittleEndian);
|
let buffer = BitReadBuffer::new_owned(input, LittleEndian);
|
||||||
let mut stream = BitReadStream::new(buffer);
|
let mut stream = BitReadStream::new(buffer);
|
||||||
let header = Header::read(&mut stream).unwrap();
|
let header = Header::read(&mut stream).unwrap();
|
||||||
|
|
||||||
let packets = RawPacketStream::new(stream);
|
let mut packet_stream = RawPacketStream::new(stream);
|
||||||
let mut handler = DemoHandler::default();
|
let mut handler = DemoHandler::default();
|
||||||
handler.handle_header(&header);
|
handler.handle_header(&header);
|
||||||
|
|
||||||
|
let mut packets = Vec::new();
|
||||||
|
|
||||||
|
let mut last_progress = 0.0;
|
||||||
|
|
||||||
|
let mut prop_names = Vec::new();
|
||||||
|
let mut class_names = Vec::new();
|
||||||
|
|
||||||
|
while let Some(packet) = packet_stream.next(handler.get_parser_state()).unwrap() {
|
||||||
|
let tick = packet.tick();
|
||||||
|
packets.push(packet.clone());
|
||||||
|
|
||||||
|
if let Packet::DataTables(DataTablePacket {
|
||||||
|
tables,
|
||||||
|
server_classes,
|
||||||
|
..
|
||||||
|
}) = &packet
|
||||||
|
{
|
||||||
|
for table in tables {
|
||||||
|
for prop in &table.props {
|
||||||
|
prop_names.push((
|
||||||
|
prop.identifier.into(),
|
||||||
|
prop.identifier
|
||||||
|
.table_name()
|
||||||
|
.unwrap_or_else(|| table.name.clone()),
|
||||||
|
prop.identifier
|
||||||
|
.prop_name()
|
||||||
|
.unwrap_or_else(|| prop.name.clone()),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for class in server_classes {
|
||||||
|
class_names.push((class.id.into(), class.name.clone()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
handler.handle_packet(packet).unwrap();
|
||||||
|
|
||||||
|
let new_progress = ((tick as f32 / header.ticks as f32) * 100.0).floor();
|
||||||
|
if new_progress > last_progress {
|
||||||
|
last_progress = new_progress;
|
||||||
|
progress
|
||||||
|
.call1(&JsValue::NULL, &JsValue::from(new_progress))
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Parser {
|
Parser {
|
||||||
handler,
|
|
||||||
header,
|
header,
|
||||||
packets
|
packets,
|
||||||
|
prop_names,
|
||||||
|
class_names,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -42,11 +101,60 @@ impl Parser {
|
||||||
JsValue::from_serde(&self.header).unwrap()
|
JsValue::from_serde(&self.header).unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn next(&mut self) -> JsValue {
|
pub fn packets(&self) -> Vec<JsValue> {
|
||||||
self.packets.next(&self.handler.state_handler).unwrap().map(|packet| {
|
self.packets
|
||||||
let out = JsValue::from_serde(&packet).unwrap();
|
.iter()
|
||||||
self.handler.handle_packet(packet).unwrap();
|
.enumerate()
|
||||||
out
|
.map(|(index, packet)| PacketMeta {
|
||||||
}).unwrap_or(JsValue::NULL)
|
index,
|
||||||
|
tick: packet.tick(),
|
||||||
|
ty: packet.packet_type() as u8,
|
||||||
|
})
|
||||||
|
.map(|meta| JsValue::from_serde(&meta).unwrap())
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn packet(&self, index: usize) -> JsValue {
|
||||||
|
JsValue::from_serde(&self.packets[index]).unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn prop_names(&self) -> Vec<JsValue> {
|
||||||
|
self.prop_names
|
||||||
|
.iter()
|
||||||
|
.map(|(identifier, table, prop)| {
|
||||||
|
JsValue::from_serde(&PropName {
|
||||||
|
identifier: *identifier,
|
||||||
|
table: table.to_string(),
|
||||||
|
prop: prop.to_string(),
|
||||||
|
})
|
||||||
|
.unwrap()
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn class_names(&self) -> Vec<JsValue> {
|
||||||
|
self.class_names
|
||||||
|
.iter()
|
||||||
|
.map(|(identifier, name)| {
|
||||||
|
JsValue::from_serde(&ClassName {
|
||||||
|
identifier: *identifier,
|
||||||
|
name: name.to_string(),
|
||||||
|
})
|
||||||
|
.unwrap()
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize)]
|
||||||
|
pub struct PropName {
|
||||||
|
pub identifier: u64,
|
||||||
|
pub table: String,
|
||||||
|
pub prop: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize)]
|
||||||
|
pub struct ClassName {
|
||||||
|
pub identifier: u16,
|
||||||
|
pub name: String,
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,21 +8,46 @@ import {filterPacket, Search, SearchBar} from "./search";
|
||||||
|
|
||||||
let _style = require('../styles/style.css');
|
let _style = require('../styles/style.css');
|
||||||
|
|
||||||
|
export interface PacketMeta {
|
||||||
|
index: number,
|
||||||
|
tick: number,
|
||||||
|
ty: PacketType,
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum PacketType {
|
||||||
|
Signon = 1,
|
||||||
|
Message = 2,
|
||||||
|
SyncTick = 3,
|
||||||
|
ConsoleCmd = 4,
|
||||||
|
UserCmd = 5,
|
||||||
|
DataTables = 6,
|
||||||
|
Stop = 7,
|
||||||
|
StringTables = 8,
|
||||||
|
}
|
||||||
|
|
||||||
interface AppState {
|
interface AppState {
|
||||||
loading: boolean,
|
loading: boolean,
|
||||||
header: Header | null,
|
header: Header | null,
|
||||||
packets: Packet[],
|
progress: number,
|
||||||
|
packets: PacketMeta[],
|
||||||
prop_names: Map<number, { table: string, prop: string }>,
|
prop_names: Map<number, { table: string, prop: string }>,
|
||||||
class_names: Map<number, string>,
|
class_names: Map<number, string>,
|
||||||
active: Packet | null,
|
active: Packet | null,
|
||||||
activeIndex: number | null,
|
activeIndex: number | null,
|
||||||
search: Search,
|
search: Search,
|
||||||
|
worker: Worker
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type MessageData = { type: "progress", progress: number }
|
||||||
|
| { type: "packet", packet: Packet }
|
||||||
|
| { type: "done", packets: PacketMeta[], header: Header, prop_names: {identifier: number, table: string, prop: string}[], class_names: {identifier: number, name: string}[] }
|
||||||
|
| { type: "packet_names", packet: {} };
|
||||||
|
|
||||||
class App extends Component<{}, AppState> {
|
class App extends Component<{}, AppState> {
|
||||||
state: AppState = {
|
state: AppState = {
|
||||||
loading: false,
|
loading: false,
|
||||||
header: null,
|
header: null,
|
||||||
|
progress: 0,
|
||||||
packets: [],
|
packets: [],
|
||||||
prop_names: new Map(),
|
prop_names: new Map(),
|
||||||
class_names: new Map(),
|
class_names: new Map(),
|
||||||
|
|
@ -33,7 +58,8 @@ class App extends Component<{}, AppState> {
|
||||||
filter: "",
|
filter: "",
|
||||||
classIds: [],
|
classIds: [],
|
||||||
propIds: [],
|
propIds: [],
|
||||||
}
|
},
|
||||||
|
worker: null
|
||||||
}
|
}
|
||||||
|
|
||||||
onSearch = debounce((search: Search) => this.setState({search}), 500)
|
onSearch = debounce((search: Search) => this.setState({search}), 500)
|
||||||
|
|
@ -41,54 +67,53 @@ class App extends Component<{}, AppState> {
|
||||||
load(data: ArrayBuffer) {
|
load(data: ArrayBuffer) {
|
||||||
this.setState({loading: true});
|
this.setState({loading: true});
|
||||||
const worker = new Worker('./worker.js');
|
const worker = new Worker('./worker.js');
|
||||||
worker.addEventListener("message", (event: MessageEvent<{ type: "header", header: Header } | { type: "packet", packet: Packet } | { type: "done" }>) => {
|
this.setState({worker});
|
||||||
switch (event.data.type) {
|
worker.addEventListener("message", (event: MessageEvent<MessageData>) => {
|
||||||
case "header":
|
const data = event.data;
|
||||||
let header = event.data.header;
|
if (data.type !== "progress") {
|
||||||
this.setState({header});
|
console.log(data);
|
||||||
break;
|
}
|
||||||
case "packet":
|
switch (data.type) {
|
||||||
let packet = event.data.packet;
|
case "progress":
|
||||||
let packets = this.state.packets;
|
let progress = data.progress;
|
||||||
packets.push(packet);
|
this.setState({progress});
|
||||||
this.setState({packets});
|
|
||||||
if (packet.type == "DataTables") {
|
|
||||||
let prop_names = this.state.prop_names;
|
|
||||||
let class_names = this.state.class_names;
|
|
||||||
for (let table of packet.tables) {
|
|
||||||
for (let prop of table.props) {
|
|
||||||
prop_names.set(prop.identifier, {table: table.name, prop: prop.name});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (let server_class of packet.server_classes) {
|
|
||||||
class_names.set(server_class.id, server_class.name);
|
|
||||||
}
|
|
||||||
this.setState({class_names, prop_names});
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case "done":
|
case "done":
|
||||||
this.setState({loading: false});
|
const prop_names = new Map();
|
||||||
|
for (let prop of data.prop_names) {
|
||||||
|
prop_names.set(prop.identifier, prop);
|
||||||
|
}
|
||||||
|
const class_names = new Map();
|
||||||
|
for (let c of data.class_names) {
|
||||||
|
class_names.set(c.identifier, c.name);
|
||||||
|
}
|
||||||
|
this.setState({loading: false, packets: data.packets, header: data.header, prop_names, class_names});
|
||||||
break;
|
break;
|
||||||
|
case "packet":
|
||||||
|
this.setState({active: data.packet})
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
worker.postMessage(data, [data]);
|
worker.postMessage({
|
||||||
|
type: "data",
|
||||||
|
data
|
||||||
|
}, [data]);
|
||||||
}
|
}
|
||||||
|
|
||||||
filteredPackets(): Packet[] {
|
filteredPackets(): PacketMeta[] {
|
||||||
if (this.state.search.filter || this.state.search.entity) {
|
return this.state.packets;
|
||||||
return this.state.packets.filter(packet => filterPacket(packet, this.state.search));
|
// if (this.state.search.filter || this.state.search.entity) {
|
||||||
} else {
|
// return this.state.packets.filter(packet => filterPacket(packet, this.state.search));
|
||||||
return this.state.packets;
|
// } else {
|
||||||
}
|
// return this.state.packets;
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
if (this.state.loading && this.state.header && this.state.packets.length) {
|
if (this.state.loading && this.state.progress > 0) {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<h1>Loading</h1>
|
<h1>Loading</h1>
|
||||||
<p>{this.state.packets.slice(-1)[0].tick}/{this.state.header.ticks}</p>
|
<progress value={this.state.progress} max={100}/>
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
} else if (this.state.loading) {
|
} else if (this.state.loading) {
|
||||||
|
|
@ -107,12 +132,15 @@ class App extends Component<{}, AppState> {
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<SearchBar onSearch={this.onSearch} class_names={this.state.class_names} prop_names={this.state.prop_names}/>
|
<SearchBar onSearch={this.onSearch} class_names={this.state.class_names}
|
||||||
|
prop_names={this.state.prop_names}/>
|
||||||
<div className="packets">
|
<div className="packets">
|
||||||
<PacketTable packets={this.filteredPackets()} class_names={this.state.class_names}
|
<PacketTable packets={this.filteredPackets()} class_names={this.state.class_names}
|
||||||
activeIndex={this.state.activeIndex}
|
activeIndex={this.state.activeIndex}
|
||||||
prop_names={this.state.prop_names}
|
prop_names={this.state.prop_names}
|
||||||
onClick={(activeIndex, active) => this.setState({activeIndex, active})}/>
|
onClick={(index) => {
|
||||||
|
this.state.worker.postMessage({type: "get", packet: index})
|
||||||
|
}}/>
|
||||||
{active}
|
{active}
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
|
|
@ -166,10 +194,12 @@ function DemoDropzone(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
function debounce(func: Function, timeout = 300){
|
function debounce(func: Function, timeout = 300) {
|
||||||
let timer: any;
|
let timer: any;
|
||||||
return (...args:any[]) => {
|
return (...args: any[]) => {
|
||||||
clearTimeout(timer);
|
clearTimeout(timer);
|
||||||
timer = setTimeout(() => { func.apply(this, args); }, timeout);
|
timer = setTimeout(() => {
|
||||||
|
func.apply(this, args);
|
||||||
|
}, timeout);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
@ -80,14 +80,15 @@ function formatPropValue(value: SendPropValue): string {
|
||||||
|
|
||||||
function formatEntity(entity: PacketEntity, prop_names: Map<number, { table: String, prop: String }>, class_names: Map<number, String>,): string {
|
function formatEntity(entity: PacketEntity, prop_names: Map<number, { table: String, prop: String }>, class_names: Map<number, String>,): string {
|
||||||
let class_name = class_names.get(entity.server_class);
|
let class_name = class_names.get(entity.server_class);
|
||||||
let baseline = entity.baseline_props.map(prop => {
|
// let baseline = entity.baseline_props.map(prop => {
|
||||||
let names = prop_names.get(prop.identifier);
|
// let names = prop_names.get(prop.identifier);
|
||||||
if (names) {
|
// if (names) {
|
||||||
return `(${names.table}.${names.prop})=${formatPropValue(prop.value)}`;
|
// return `(${names.table}.${names.prop})=${formatPropValue(prop.value)}`;
|
||||||
} else {
|
// } else {
|
||||||
return `([unknown prop])=${prop.value}`;
|
// return `([unknown prop])=${prop.value}`;
|
||||||
}
|
// }
|
||||||
})
|
// })
|
||||||
|
|
||||||
let props = entity.props.map(prop => {
|
let props = entity.props.map(prop => {
|
||||||
let names = prop_names.get(prop.identifier);
|
let names = prop_names.get(prop.identifier);
|
||||||
if (names) {
|
if (names) {
|
||||||
|
|
@ -96,7 +97,7 @@ function formatEntity(entity: PacketEntity, prop_names: Map<number, { table: Str
|
||||||
return `[unknown prop]=${prop.value}`;
|
return `[unknown prop]=${prop.value}`;
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
return `entity ${entity.entity_index}(${class_name}) ${entity.update_type}: ` + baseline.concat(props).join(', ');
|
return `entity ${entity.entity_index}(${class_name}) ${entity.update_type}: ` + props.join(', ');
|
||||||
}
|
}
|
||||||
|
|
||||||
function formatEventDefinition(event: GameEventDefinition): string {
|
function formatEventDefinition(event: GameEventDefinition): string {
|
||||||
|
|
|
||||||
|
|
@ -4,20 +4,21 @@ import {FixedSizeList as List} from 'react-window';
|
||||||
import {MessageInfo} from "./packets/message";
|
import {MessageInfo} from "./packets/message";
|
||||||
import {UserCmdDetails} from "./packets/usercmd";
|
import {UserCmdDetails} from "./packets/usercmd";
|
||||||
import {filterMessage, filterPacket, Search} from "./search";
|
import {filterMessage, filterPacket, Search} from "./search";
|
||||||
|
import {PacketMeta, PacketType} from "./index"
|
||||||
|
|
||||||
interface TableProps {
|
interface TableProps {
|
||||||
packets: Packet[],
|
packets: PacketMeta[],
|
||||||
prop_names: Map<number, { table: string, prop: string }>,
|
prop_names: Map<number, { table: string, prop: string }>,
|
||||||
class_names: Map<number, string>,
|
class_names: Map<number, string>,
|
||||||
onClick: (i: number, packet: Packet) => void,
|
onClick: (i: number) => void,
|
||||||
activeIndex: number | null,
|
activeIndex: number | null,
|
||||||
}
|
}
|
||||||
|
|
||||||
export function PacketTable({packets, prop_names, class_names, onClick, activeIndex}: TableProps) {
|
export function PacketTable({packets, prop_names, class_names, onClick, activeIndex}: TableProps) {
|
||||||
const Row: (props: { index: number, style: CSSProperties }) => any = ({index, style}) => (
|
const Row: (props: { index: number, style: CSSProperties }) => any = ({index, style}) => (
|
||||||
<p key={index} onClick={() => {
|
<p key={packets[index].index} onClick={() => {
|
||||||
onClick(index, packets[index])
|
onClick(packets[index].index)
|
||||||
}} style={style} className={(activeIndex == index ? 'active ' : '') + 'prop_row'}>
|
}} style={style} className={(activeIndex == packets[index].index ? 'active ' : '') + 'prop_row'}>
|
||||||
<PacketRow packet={packets[index]}/>
|
<PacketRow packet={packets[index]}/>
|
||||||
</p>
|
</p>
|
||||||
);
|
);
|
||||||
|
|
@ -32,46 +33,46 @@ export function PacketTable({packets, prop_names, class_names, onClick, activeIn
|
||||||
}
|
}
|
||||||
|
|
||||||
interface RowProps {
|
interface RowProps {
|
||||||
packet: Packet,
|
packet: PacketMeta,
|
||||||
}
|
}
|
||||||
|
|
||||||
export function PacketRow({packet}: RowProps) {
|
export function PacketRow({packet}: RowProps) {
|
||||||
switch (packet.type) {
|
switch (packet.ty) {
|
||||||
case "Signon":
|
case PacketType.Signon:
|
||||||
case "Message":
|
case PacketType.Message:
|
||||||
return <>
|
return <>
|
||||||
<span className="tick">{packet.tick}</span>
|
<span className="tick">{packet.tick}</span>
|
||||||
<span className="type">{packet.type}</span>
|
<span className="type">{PacketType[packet.ty]}</span>
|
||||||
</>
|
</>
|
||||||
case "SyncTick":
|
case PacketType.SyncTick:
|
||||||
return <>
|
return <>
|
||||||
<span className="tick">{packet.tick}</span>
|
<span className="tick">{packet.tick}</span>
|
||||||
<span className="type">{packet.type}</span>
|
<span className="type">{PacketType[packet.ty]}</span>
|
||||||
</>;
|
</>;
|
||||||
case "ConsoleCmd":
|
case PacketType.ConsoleCmd:
|
||||||
return <>
|
return <>
|
||||||
<span className="tick">{packet.tick}</span>
|
<span className="tick">{packet.tick}</span>
|
||||||
<span className="type">{packet.type}</span>
|
<span className="type">{PacketType[packet.ty]}</span>
|
||||||
</>;
|
</>;
|
||||||
case "UserCmd":
|
case PacketType.UserCmd:
|
||||||
return <>
|
return <>
|
||||||
<span className="tick">{packet.tick}</span>
|
<span className="tick">{packet.tick}</span>
|
||||||
<span className="type">{packet.type}</span>
|
<span className="type">{PacketType[packet.ty]}</span>
|
||||||
</>;
|
</>;
|
||||||
case "DataTables":
|
case PacketType.DataTables:
|
||||||
return <>
|
return <>
|
||||||
<span className="tick">{packet.tick}</span>
|
<span className="tick">{packet.tick}</span>
|
||||||
<span className="type">{packet.type}</span>
|
<span className="type">{PacketType[packet.ty]}</span>
|
||||||
</>;
|
</>;
|
||||||
case "Stop":
|
case PacketType.Stop:
|
||||||
return <>
|
return <>
|
||||||
<span className="tick">{packet.tick}</span>
|
<span className="tick">{packet.tick}</span>
|
||||||
<span className="type">{packet.type}</span>
|
<span className="type">{PacketType[packet.ty]}</span>
|
||||||
</>;
|
</>;
|
||||||
case "StringTables":
|
case PacketType.StringTables:
|
||||||
return <>
|
return <>
|
||||||
<span className="tick">{packet.tick}</span>
|
<span className="tick">{packet.tick}</span>
|
||||||
<span className="type">{packet.type}</span>
|
<span className="type">{PacketType[packet.ty]}</span>
|
||||||
</>;
|
</>;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,22 +2,33 @@ import {Parser} from "demo-inspector";
|
||||||
|
|
||||||
declare function postMessage(message: any): void;
|
declare function postMessage(message: any): void;
|
||||||
|
|
||||||
onmessage = function (event) {
|
let parser: Parser | null = null;
|
||||||
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()})
|
type MessageData = {type: "data", data: ArrayBuffer} | {type: "get", packet: number}
|
||||||
|
|
||||||
let packet;
|
onmessage = function (event: MessageEvent<MessageData>) {
|
||||||
do {
|
const data = event.data;
|
||||||
packet = parser.next();
|
switch (data.type) {
|
||||||
if (packet) {
|
case "data":
|
||||||
postMessage({type: "packet", packet})
|
import("demo-inspector")
|
||||||
}
|
.then(({Parser}) => {
|
||||||
} while (packet);
|
parser = new Parser(new Uint8Array(data.data), (progress: number) => {
|
||||||
postMessage({type: "done"})
|
postMessage({type: "progress", progress})
|
||||||
})
|
});
|
||||||
|
postMessage({
|
||||||
|
type: "done",
|
||||||
|
packets: parser.packets(),
|
||||||
|
header: parser.header(),
|
||||||
|
prop_names: parser.prop_names(),
|
||||||
|
class_names: parser.class_names()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
break;
|
||||||
|
case "get":
|
||||||
|
if (parser) {
|
||||||
|
const packet = parser.packet(data.packet);
|
||||||
|
postMessage({type: "packet", packet})
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
Loading…
Add table
Add a link
Reference in a new issue