Moved some data around, added some initial types for configs and way of generating the models for it during the build. Added fuzzr (similar to fuzzy_matcher rust crate I've used before). Using custom-built version of fuzzr npm package, git in package.json instead of through npm's packages.

merge-notes
isark 2 years ago
parent 0ffb195618
commit 9fb81ca554

@ -17,7 +17,15 @@
"main": "src/main.ts",
"polyfills": ["zone.js"],
"tsConfig": "tsconfig.app.json",
"assets": ["src/favicon.ico", "src/assets"],
"assets": [
"src/favicon.ico",
"src/assets",
{
"glob": "**/*.wasm",
"input": "./node_modules/fuzzr",
"output": "/fuzzr"
}
],
"styles": ["src/styles.scss"],
"scripts": []
},

@ -19,6 +19,8 @@
"@angular/platform-browser": "^16.1.4",
"@angular/platform-browser-dynamic": "^16.1.4",
"@tauri-apps/api": "^1.2.0",
"copy-webpack-plugin": "^11.0.0",
"fuzzr": "github:isark2/fuzzr#v0.3.1",
"ngx-moveable": "^0.48.1",
"rxjs": "~7.8.1",
"tslib": "^2.6.0",

46
src-tauri/Cargo.lock generated

@ -2,6 +2,12 @@
# It is not intended for manual editing.
version = 3
[[package]]
name = "Inflector"
version = "0.11.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fe438c63458706e03479442743baae6c88256498e6431708f6dfc520a26515d3"
[[package]]
name = "Underlayer"
version = "0.2.2"
@ -1954,12 +1960,6 @@ dependencies = [
"windows-sys 0.48.0",
]
[[package]]
name = "multi-map"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bba551d6d795f74a01767577ea8339560bf0a65354e0417b7e915ed608443d46"
[[package]]
name = "native-tls"
version = "0.2.11"
@ -2046,6 +2046,7 @@ dependencies = [
"statig",
"tauri",
"tauri-build",
"ts-rs",
"x11rb",
]
@ -2501,7 +2502,6 @@ name = "poe_data"
version = "0.1.0"
dependencies = [
"fuzzy-matcher",
"multi-map",
"serde",
"serde_derive",
"serde_json",
@ -3673,6 +3673,15 @@ dependencies = [
"utf-8",
]
[[package]]
name = "termcolor"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "be55cf8942feac5c765c2c993422806843c9a9a45d4d5c407ad6dd2ea95eb9b6"
dependencies = [
"winapi-util",
]
[[package]]
name = "thin-slice"
version = "0.1.1"
@ -3920,6 +3929,29 @@ version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed"
[[package]]
name = "ts-rs"
version = "6.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4added4070a4fdf9df03457206cd2e4b12417c8560a2954d91ffcbe60177a56a"
dependencies = [
"thiserror",
"ts-rs-macros",
]
[[package]]
name = "ts-rs-macros"
version = "6.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9f807fdb3151fee75df7485b901a89624358cd07a67a8fb1a5831bf5a07681ff"
dependencies = [
"Inflector",
"proc-macro2",
"quote",
"syn 1.0.109",
"termcolor",
]
[[package]]
name = "typenum"
version = "1.16.0"

@ -6,12 +6,17 @@ authors = ["you"]
license = ""
repository = ""
edition = "2021"
build = "src/build.rs"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[build-dependencies]
poe_data = { path = "poe_data" }
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
tauri-build = { version = "1.2", features = [] }
ts-rs = "6.2.1"
[dependencies]
tauri = { version = "1.2", features = [ "api-all"] }

@ -1,8 +0,0 @@
fn main() {
tauri_build::build();
const OUT_PROCESSED: &'static str = "data/processed_world_areas.json";
println!("cargo:rerun-if-changed=data/WorldAreas.json");
poe_data::world_area::repack(&include_str!("data/WorldAreas.json"), OUT_PROCESSED);
}

@ -23,12 +23,6 @@ version = "1.0.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38"
[[package]]
name = "multi-map"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bba551d6d795f74a01767577ea8339560bf0a65354e0417b7e915ed608443d46"
[[package]]
name = "once_cell"
version = "1.18.0"
@ -40,7 +34,6 @@ name = "poe_data"
version = "0.1.0"
dependencies = [
"fuzzy-matcher",
"multi-map",
"serde",
"serde_derive",
"serde_json",

@ -7,7 +7,6 @@ edition = "2021"
[dependencies]
serde_derive = "1.0.175"
multi-map = "1.3.0"
fuzzy-matcher = "0.3.7"
serde_json = "1.0.103"
serde = "1.0.175"
serde = "1.0.175"

@ -2,9 +2,8 @@ use std::collections::BinaryHeap;
use std::collections::HashMap;
use std::ops::Deref;
use fuzzy_matcher::FuzzyMatcher;
use fuzzy_matcher::skim::SkimMatcherV2;
use multi_map::MultiMap;
use fuzzy_matcher::FuzzyMatcher;
use serde_derive::Deserialize;
use serde_derive::Serialize;
@ -16,9 +15,9 @@ type UnprocessedAreas = Vec<UnprocessedArea>;
struct UnprocessedArea {
#[serde(rename = "Id")]
pub named_id: String,
#[serde(rename = "_rid")]
pub key_id: usize,
pub key_id: usize,
#[serde(rename = "Name")]
pub name: String,
@ -39,10 +38,10 @@ struct UnprocessedArea {
pub is_vaal_area: bool,
#[serde(rename = "Unknown64")]
pub unknown64: bool,
pub unknown64: bool,
#[serde(rename = "Unknown9")]
pub unknown9: i64,
pub unknown9: i64,
}
pub type AreaName = String;
@ -52,11 +51,14 @@ pub struct WorldArea {
#[serde(rename = "Name")]
pub name: String,
#[serde(rename = "NamedId")]
pub named_id: String,
#[serde(rename = "Act")]
pub act: i64,
#[serde(rename = "_rid")]
pub key_id: usize,
pub key_id: usize,
#[serde(rename = "IsTown")]
pub is_town: bool,
@ -69,94 +71,79 @@ pub struct WorldArea {
}
pub type AreaId = usize;
pub type WorldAreasMap = MultiMap<AreaName, AreaId, WorldArea>;
pub type WorldAreasMap = HashMap<String, WorldArea>;
#[allow(dead_code)]
pub fn load_world_areas_map(content: &'static str) -> WorldAreasMap {
let mut world_area_map = WorldAreasMap::new();
serde_json::from_str::<HashMap<AreaName, WorldArea>>(content)
.expect("Could not load world areas json")
.into_iter()
.for_each(|(area_name, world_area)|
{
world_area_map.insert(area_name, world_area.key_id, world_area);
});
world_area_map
serde_json::from_str::<WorldAreasMap>(content)
.expect("Could not load world areas json")
}
#[macro_export]
macro_rules! load_world_areas {
($e:expr) => {
crate::world_area::load_world_areas_map(&include_str!($e))
};
($e:expr) => {
crate::world_area::load_world_areas_map(&include_str!($e))
};
}
#[allow(dead_code)]
pub struct WorldAreas {
pub areas_map: WorldAreasMap,
matcher: Matcher,
pub areas_map: WorldAreasMap,
matcher: Matcher,
}
impl WorldAreas {
#[allow(dead_code)]
pub fn new(areas: WorldAreasMap, matcher: Matcher) -> Self {
Self {
areas_map: areas,
matcher,
}
}
#[allow(dead_code)]
pub fn fuzzy_area(&self, count: usize, area: &str) -> Vec<WorldArea> {
let mut matches = Vec::new();
for (_k, (_key_id, v)) in &self.areas_map {
if let Some(mut score) = self.matcher.fuzzy_match(&v.name, area) {
if v.name.contains(area) {
score = i64::MAX;
}
let f_entry = FEntry{area: v.clone(), score};
matches.push(f_entry);
}
}
matches.sort_by(|entry1, entry2| {
entry1.score.cmp(&entry2.score).reverse()
.then(entry1.area.key_id.cmp(&entry2.area.key_id))
});
let matches_areas = matches
.into_iter()
.map(|entry| entry.area)
.take(count)
.collect::<Vec<WorldArea>>();
matches_areas
}
#[allow(dead_code)]
pub fn by_area_id(&self, key: AreaId) -> Option<&WorldArea> {
self.areas_map.get_alt(&key)
}
#[allow(dead_code)]
pub fn by_area_name(&self, key: AreaName) -> Option<&WorldArea> {
self.areas_map.get(&key)
}
}
#[allow(dead_code)]
pub fn new(areas: WorldAreasMap, matcher: Matcher) -> Self {
Self {
areas_map: areas,
matcher,
}
}
#[allow(dead_code)]
pub fn fuzzy_area(&self, count: usize, area: &str) -> Vec<WorldArea> {
let mut matches = Vec::new();
for (_key_id, v) in &self.areas_map {
if let Some(mut score) = self.matcher.fuzzy_match(&v.name, area) {
if v.name.contains(area) {
score = i64::MAX;
}
let f_entry = FEntry {
area: v.clone(),
score,
};
matches.push(f_entry);
}
}
matches.sort_by(|entry1, entry2| {
entry1
.score
.cmp(&entry2.score)
.reverse()
.then(entry1.area.key_id.cmp(&entry2.area.key_id))
});
let matches_areas = matches
.into_iter()
.map(|entry| entry.area)
.take(count)
.collect::<Vec<WorldArea>>();
matches_areas
}
#[allow(dead_code)]
pub fn by_area_id(&self, key: String) -> Option<&WorldArea> {
self.areas_map.get(&key)
}
}
#[derive(PartialEq, Eq, Clone, Debug)]
struct FEntry {
area: WorldArea,
score: i64,
area: WorldArea,
score: i64,
}
impl Ord for FEntry {
@ -167,25 +154,23 @@ impl Ord for FEntry {
impl PartialOrd for FEntry {
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
Some(self.score.cmp(&other.score))
Some(self.score.cmp(&other.score))
}
}
pub struct Matcher(SkimMatcherV2);
impl Matcher {
#[allow(dead_code)]
pub fn new() -> Self {
let matcher = SkimMatcherV2::default()
.ignore_case()
.use_cache(true);
Matcher(matcher)
}
#[allow(dead_code)]
pub fn new() -> Self {
let matcher = SkimMatcherV2::default().ignore_case().use_cache(true);
Matcher(matcher)
}
}
impl Deref for Matcher {
type Target = SkimMatcherV2;
type Target = SkimMatcherV2;
fn deref(&self) -> &Self::Target {
&self.0
@ -193,69 +178,73 @@ impl Deref for Matcher {
}
impl Matcher {
#[allow(dead_code)]
pub fn fuzzy_area(&self, areas: &WorldAreasMap, area: &str) -> Vec<WorldArea> {
let mut matches: BinaryHeap<FEntry> = BinaryHeap::new();
for (_k, (_key_id, v)) in areas {
//println!("k: {:?}\nv: {:?}\n\n", k, v);
if let Some(score) = self.fuzzy_match(&v.name, area) {
let f_entry = FEntry{area: v.clone(), score};
matches.push(f_entry);
}
}
let mut values = matches.into_iter();
let mut return_vec = Vec::new();
for _i in 0..30 {
if let Some(value) = values.next() {
return_vec.push(value.area.clone());
} else {
break;
}
}
return_vec
}
#[allow(dead_code)]
pub fn fuzzy_area(&self, areas: &WorldAreasMap, area: &str) -> Vec<WorldArea> {
let mut matches: BinaryHeap<FEntry> = BinaryHeap::new();
for (_key_id, v) in areas {
if let Some(score) = self.fuzzy_match(&v.name, area) {
let f_entry = FEntry {
area: v.clone(),
score,
};
matches.push(f_entry);
}
}
let mut values = matches.into_iter();
let mut return_vec = Vec::new();
for _i in 0..30 {
if let Some(value) = values.next() {
return_vec.push(value.area.clone());
} else {
break;
}
}
return_vec
}
}
//TODO: Multimap
#[allow(dead_code)]
pub fn repack(content: &str, out_path: &str) {
let areas_json = serde_json::from_str::<UnprocessedAreas>(content);
let area_map = areas_json.expect("Could not read world areas").into_iter().filter_map(|w_a| {
if
w_a.act < 11 &&
!w_a.is_vaal_area &&
!w_a.connections_world_areas_keys.is_empty() &&
!w_a.unknown64 &&
!w_a.named_id.starts_with("Map") &&
!w_a.named_id.starts_with("Descent") &&
!w_a.named_id.starts_with("EndlessLedge") &&
w_a.unknown9 != 20
{
Some((
w_a.named_id,
WorldArea{
name: w_a.name,
act: w_a.act,
is_town: w_a.is_town,
has_waypoint: w_a.has_waypoint,
connections_world_areas_keys: w_a.connections_world_areas_keys,
key_id: w_a.key_id,
}
))
} else {
None
}
}).collect::<HashMap<AreaName, WorldArea>>();
let new_json = serde_json::to_string(&area_map).unwrap();
std::fs::write(out_path, &new_json).expect("Could not write to file");
}
let areas_json = serde_json::from_str::<UnprocessedAreas>(content);
let area_map = areas_json
.expect("Could not read world areas")
.into_iter()
.filter_map(|w_a| {
if w_a.act < 11
&& !w_a.is_vaal_area
&& !w_a.connections_world_areas_keys.is_empty()
&& !w_a.unknown64
&& !w_a.named_id.starts_with("Map")
&& !w_a.named_id.starts_with("Descent")
&& !w_a.named_id.starts_with("EndlessLedge")
&& w_a.unknown9 != 20
{
Some((
w_a.named_id.clone(),
WorldArea {
name: w_a.name,
named_id: w_a.named_id,
act: w_a.act,
is_town: w_a.is_town,
has_waypoint: w_a.has_waypoint,
connections_world_areas_keys: w_a.connections_world_areas_keys,
key_id: w_a.key_id,
},
))
} else {
None
}
})
.collect::<WorldAreasMap>();
let new_json = serde_json::to_string(&area_map).unwrap();
std::fs::write(out_path, &new_json).expect("Could not write to file");
}

@ -0,0 +1,21 @@
use ts_rs::TS;
mod config;
fn main() {
tauri_build::build();
const OUT_PROCESSED: &'static str = "../data/processed_world_areas.json";
println!("cargo:rerun-if-changed=../data/WorldAreas.json");
poe_data::world_area::repack(&include_str!("../../data/WorldAreas.json"), OUT_PROCESSED);
//Let's go with uppercase names, allows automatic import to work...
config::Rect::export_to("../src/app/models/generated/Rect.ts").expect("Could not generate config struct");
config::Config::export_to("../src/app/models/generated/Config.ts").expect("Could not generate config struct");
println!("cargo:rerun-if-changed=src/config.rs");
println!("cargo:rerun-if-changed=../src/app/models/generated/Rect.ts");
println!("cargo:rerun-if-changed=../src/app/models/generated/Config.ts");
println!("cargo:rustc-cfg=build_only");
}

@ -0,0 +1,31 @@
use serde::{Deserialize, Serialize};
#[cfg(not(build_only))]
use ts_rs::TS;
#[cfg_attr(not(build_only), derive(TS))]
#[cfg_attr(not(build_only), ts(rename_all = "camelCase"))]
#[derive(Serialize, Deserialize, Debug, Default)]
pub struct Rect {
x: i32,
y: i32,
width: u32,
height: u32,
}
#[cfg_attr(not(build_only), derive(TS))]
#[cfg_attr(not(build_only), ts(rename_all = "camelCase"))]
#[derive(Serialize, Deserialize, Debug)]
pub struct Config {
initial_plan_window_position: Rect,
}
impl Default for Config {
fn default() -> Self {
Self {
initial_plan_window_position: Default::default(),
}
}
}

@ -1,23 +1,25 @@
// Prevents additional console window on Windows in release, DO NOT REMOVE!!
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
use std::collections::HashMap;
use crossbeam::channel::Sender;
use overlay::{Event, LockedOverlayData, Overlay};
use poe_data::world_area::WorldArea;
use simple_logger::SimpleLogger;
// use overlay::{Overlay, Manager};
use tauri::Manager;
mod overlay;
mod plan;
mod config;
#[tauri::command]
fn set_interactable(interactable: bool, state: tauri::State<Sender<Event>>) {
log::info!("set_interactable: {interactable:?}");
if interactable {
state
.send(overlay::State::Interactable{}.into())
.ok();
state.send(overlay::State::Interactable {}.into()).ok();
} else {
state.send(overlay::Event::Return).ok();
}
@ -31,6 +33,12 @@ fn set_auto_hide(auto_hide: bool, state: tauri::State<LockedOverlayData>) {
}
}
#[tauri::command]
fn load_world_areas() -> HashMap<String, WorldArea> {
log::info!("Loading world areas");
poe_data::world_area::load_world_areas_map(include_str!("../../data/processed_world_areas.json"))
}
fn main() {
SimpleLogger::new()
.with_module_level("underlayer", log::LevelFilter::Info)
@ -47,9 +55,16 @@ fn main() {
);
app.manage(tx);
// app.get_window("Overlay")
// .expect("Could not get main overlay window").open_devtools();
Ok(())
})
.invoke_handler(tauri::generate_handler![set_interactable, set_auto_hide])
.invoke_handler(tauri::generate_handler![
set_interactable,
set_auto_hide,
load_world_areas
])
.run(tauri::generate_context!())
.expect("error while running tauri application");
}
}

@ -4,14 +4,10 @@ use crossbeam::{
};
use serde::Serialize;
use statig::prelude::*;
use std::{
sync::{mpsc::Receiver as MpscReceiver, Mutex},
time::Duration,
};
use std::sync::{mpsc::Receiver as MpscReceiver, Mutex};
use tauri::{Manager, PhysicalPosition, PhysicalSize, Window};
use underlayer::{Bounds, UnderlayEvent};
impl From<State> for Event {
fn from(value: State) -> Self {
Self::State(value)
@ -61,9 +57,7 @@ impl Overlay {
previous: State::hidden(),
};
window.manage(Mutex::new(OverlayData {
auto_hide: true
}));
window.manage(Mutex::new(OverlayData { auto_hide: true }));
let mut fsm = Overlay::uninitialized_state_machine(overlay).init();
@ -132,7 +126,7 @@ impl Overlay {
UnderlayEvent::Detach => fsm.handle(&State::hidden().into()),
UnderlayEvent::Focus => {
if let State::Hidden {} = fsm.state() {
fsm.handle(&State::Visible { }.into());
fsm.handle(&State::Visible {}.into());
}
}
UnderlayEvent::Blur => {

@ -1 +1,9 @@
<plan-display></plan-display>
<plan-display></plan-display>
<!-- <div *ngIf="areas && areas.matcher && areas.world_areas">
<ul>
<li *ngFor="let item of areas.fuzz()">{{item}}</li>
</ul>
</div> -->
<span *ngIf="worldAreas.matcher">matched init</span>

@ -0,0 +1,9 @@
plan-display {
position: absolute;
z-index: 1000;
}
:host {
width: 100%;
height: 100%;
}

@ -3,6 +3,7 @@ import { invoke } from "@tauri-apps/api/tauri";
import { ShortcutService } from "./services/shortcut.service";
import { EventsService } from "./services/events.service";
import { Event } from "@tauri-apps/api/event";
import { WorldAreaService } from "./services/world-area.service";
class StateEvent {
Visible?: any;
@ -20,7 +21,7 @@ export class AppComponent implements OnInit, OnDestroy {
interactable: boolean = false;
isBinding: boolean = false;
constructor(private shortcuts: ShortcutService, private events: EventsService) { }
constructor(public worldAreas: WorldAreaService, private shortcuts: ShortcutService, private events: EventsService) { }
ngOnDestroy(): void {
this.shortcuts.unregister(this.onToggleOverlay);
@ -28,10 +29,11 @@ export class AppComponent implements OnInit, OnDestroy {
ngOnInit(): void {
invoke("set_auto_hide", { auto_hide: this.auto_hide }).then();
console.log("Loading world areas");
this.shortcuts.register('F6', this.onToggleOverlay);
this.events.listen<StateEvent>("OverlayStateChange").subscribe(this.onOverlayStateChange)
}
onOverlayStateChange(event: Event<StateEvent>) {
this.interactable = event.payload.Interactable != null;
}
@ -48,7 +50,6 @@ export class AppComponent implements OnInit, OnDestroy {
}
toggleAutoHide() {
console.log("toggle auto hide!!");
invoke("set_auto_hide", { autoHide: this.auto_hide }).then();
}
@ -62,6 +63,6 @@ export class AppComponent implements OnInit, OnDestroy {
console.log(chord);
this.shortcuts.rebind(chord, this.onToggleOverlay);
}
}

@ -0,0 +1 @@
generated

@ -0,0 +1,6 @@
interface Rect {
x: number,
y: number,
width: number,
height: number,
}

@ -0,0 +1,9 @@
export interface WorldArea {
name: string
namedId: string
act: number
_rid: number
isTown: boolean
hasWaypoint: boolean
connections_WorldAreasKeys: number[]
}

@ -1,3 +1,3 @@
<div class="target" #targetRef>Hello!</div>
<ngx-moveable [target]="targetRef" [draggable]="draggable" [resizable]="true" (drag)="onDrag($event)"
(resize)="onResize($event)"></ngx-moveable>
(resize)="onResize($event)" #moveableRef></ngx-moveable>

@ -0,0 +1,9 @@
:host {
height: 0;
width: 0;
}
.target {
min-width: 50px;
min-height: 50px;
}

@ -1,27 +1,44 @@
import { Component } from '@angular/core';
import { OnResize } from 'ngx-moveable';
import { AfterViewInit, Component, ElementRef, OnInit, ViewChild } from '@angular/core';
import { NgxMoveableComponent, OnResize } from 'ngx-moveable';
import { OnDrag } from 'ngx-moveable';
import { DefaultOptions } from 'ngx-moveable';
import { MoveableEvents } from 'ngx-moveable';
import { ConfigService } from '../services/config.service';
@Component({
selector: 'plan-display',
templateUrl: './plan-display.component.html',
styleUrls: ['./plan-display.component.scss']
})
export class PlanDisplayComponent {
export class PlanDisplayComponent implements OnInit {
draggable: boolean = true;
x: number = 0;
y: number = 0;
width: number = 0;
height: number = 0;
@ViewChild("moveableRef")
moveableRef!: NgxMoveableComponent;
constructor(private configService: ConfigService) {}
ngOnInit(): void {
}
setPosition(x: number, y: number) {
this.moveableRef.request("draggable", {
x,
y,
}, true);
}
setArea(width: number, height: number) {
this.moveableRef.request("resizable", {
offsetWidth: 500,
offsetHeight: 500,
}, true);
}
onDrag(e: OnDrag) {
e.target.style.transform = e.transform;
this.x = e.left;
this.y = e.top;
console.log(this.x);
// this.x = e.left;
// this.y = e.top;
// console.log(this.x);
}
onResize(e: OnResize) {

@ -0,0 +1,12 @@
import { Injectable } from '@angular/core';
@Injectable({
providedIn: 'root'
})
export class ConfigService {
constructor() {}
public get lastPlanWindowPosition() {
return 0;
}
}

@ -3,7 +3,7 @@ import { Injectable } from '@angular/core';
@Injectable({
providedIn: 'root'
})
export class PlanServiceService {
export class PlanService {
constructor() { }
}

@ -0,0 +1,25 @@
import { Injectable } from '@angular/core';
import init, { Fuzzr } from 'fuzzr/pkg';
import { WorldArea } from '../models/world-area';
import { invoke } from '@tauri-apps/api';
import { from } from 'rxjs';
@Injectable({
providedIn: 'root'
})
export class WorldAreaService {
world_areas?: Map<string, WorldArea>;
matcher?: Fuzzr;
constructor() {
from(invoke<Map<string, WorldArea>>('load_world_areas')).subscribe((data) => {
this.world_areas = new Map(Object.entries(data));
from(init("/fuzzr/pkg/fuzzr_bg.wasm")).subscribe(() => {
this.matcher = new Fuzzr(this.world_areas);
});
});
}
}

@ -3405,7 +3405,7 @@ copy-anything@^2.0.1:
dependencies:
is-what "^3.14.1"
copy-webpack-plugin@11.0.0:
copy-webpack-plugin@11.0.0, copy-webpack-plugin@^11.0.0:
version "11.0.0"
resolved "https://registry.yarnpkg.com/copy-webpack-plugin/-/copy-webpack-plugin-11.0.0.tgz#96d4dbdb5f73d02dd72d0528d1958721ab72e04a"
integrity sha512-fX2MWpamkW0hZxMEg0+mYnA40LTosOSa5TqZ9GYIBzyJa9C3QUaMPSE2xAi/buNr8u89SfD9wHSQVBzrRa/SOQ==
@ -4163,6 +4163,10 @@ function-bind@^1.1.1:
resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d"
integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==
"fuzzr@github:isark2/fuzzr#v0.3.1":
version "0.0.0"
resolved "git+ssh://git@github.com/isark2/fuzzr.git#8709d405ae8cc012dc681b46809878d0e793c412"
gauge@^4.0.3:
version "4.0.4"
resolved "https://registry.yarnpkg.com/gauge/-/gauge-4.0.4.tgz#52ff0652f2bbf607a989793d53b751bef2328dce"

Loading…
Cancel
Save