Skip to content

Commit

Permalink
Allow pasting chat code (closes #13)
Browse files Browse the repository at this point in the history
  • Loading branch information
Zerthox committed Jul 7, 2024
1 parent 5cb218c commit 38d077c
Show file tree
Hide file tree
Showing 6 changed files with 68 additions and 9 deletions.
7 changes: 7 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ rust-version = "1.76.0"

[dependencies]
arc_util = { git = "https://github.com/zerthox/arcdps-utils", features = ["update"] } # TODO: isolate updater
base64 = "0.22.1"
enumflags2 = "0.7.9"
log = "0.4.18"
nexus = { git = "https://github.com/zerthox/nexus-rs", features = ["log", "mumble_json"] }
Expand Down
1 change: 1 addition & 0 deletions src/elements/icon_source.rs
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ impl IconSource {
Self::Url(url) => {
ui.input_text("##url", url)
.hint("https://wiki.guildwars2.com/...")
.auto_select_all(true)
.build();
ui.same_line();
if ui.button("Load") {
Expand Down
22 changes: 22 additions & 0 deletions src/render_util/input.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use crate::util::decode_skill;
use nexus::imgui::{sys, InputTextFlags, Ui};
use std::ffi::CString;

Expand Down Expand Up @@ -51,3 +52,24 @@ pub fn input_size(x: &mut f32, y: &mut f32) {
input_float_with_format("Size x", x, 1.0, 10.0, "%.2f", InputTextFlags::empty());
input_float_with_format("Size y", y, 1.0, 10.0, "%.2f", InputTextFlags::empty());
}

pub fn input_buff_id(ui: &Ui, label: impl AsRef<str>, id: &mut u32, flags: InputTextFlags) -> bool {
let mut text = id.to_string(); // TODO: switch to faster int/float to string conversion libraries
if ui
.input_text(label, &mut text)
.flags(flags | InputTextFlags::CALLBACK_RESIZE)
.build()
{
if let Ok(new) = text.parse() {
*id = new;
} else if let Some(new) = decode_skill(text.trim()) {
*id = new;
}
true
} else {
false
}
}

#[cfg(test)]
mod tests {}
13 changes: 8 additions & 5 deletions src/trigger/buff_id.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
use crate::{
action::Action,
context::Context,
render_util::{enum_combo, helper, impl_static_variants, input_u32},
render_util::{enum_combo, helper, impl_static_variants, input_buff_id},
traits::RenderOptions,
};
use nexus::imgui::{ComboBoxFlags, Ui};
use nexus::imgui::{ComboBoxFlags, InputTextFlags, Ui};
use serde::{Deserialize, Serialize};
use strum::{AsRefStr, EnumIter, IntoStaticStr};

Expand Down Expand Up @@ -48,6 +48,7 @@ impl BuffTriggerId {
.iter()
.find_map(|id| ctx.time_range(*id))
.unwrap_or((0, 0)), // times of first match
// TODO: max of apply and max of runout
}
}

Expand All @@ -63,7 +64,7 @@ impl BuffTriggerId {
ui.same_line();
helper(ui, || {
ui.text("Can be found on the wiki");
ui.text("Hover over the chatcode");
ui.text("Type the id or paste the chat link");
});
}
}
Expand All @@ -86,14 +87,16 @@ impl RenderOptions for BuffTriggerId {
match self {
Self::None => {}
Self::Single(id) => {
input_u32(ui, "Effect Id", id, 0, 0);
input_buff_id(ui, "Effect Id", id, InputTextFlags::empty());
Self::helper(ui);
}
Self::Any(ids) => {
let mut action = Action::new();
for (i, id) in ids.iter_mut().enumerate() {
let _id = ui.push_id(i as i32);
action.input_with_buttons(ui, i, || input_u32(ui, "##id", id, 0, 0));
action.input_with_buttons(ui, i, || {
input_buff_id(ui, "##id", id, InputTextFlags::empty())
});

ui.same_line();
ui.text(format!("Effect Id {}", i + 1));
Expand Down
33 changes: 29 additions & 4 deletions src/util.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use base64::{prelude::BASE64_STANDARD, Engine};
use std::{borrow::Cow, path::Path};

pub fn file_name(path: &Path) -> Cow<str> {
Expand All @@ -6,8 +7,32 @@ pub fn file_name(path: &Path) -> Cow<str> {
.unwrap_or_default()
}

pub fn as_secs_hundreds(millis: u32) -> (u32, u32) {
let secs = millis / 1000;
let millis = millis % 1000;
(secs, millis / 100)
/// Decodes a skill id from a skill
pub fn decode_skill(chatcode: &str) -> Option<u32> {
if let Some(code) = chatcode
.strip_prefix("[&")
.and_then(|text| text.strip_suffix(']'))
{
let bytes = BASE64_STANDARD.decode(code).ok()?;
if let [0x06, b1, b2, b3, b4] = *bytes.as_slice() {
return Some(u32::from_le_bytes([b1, b2, b3, b4]));
}
}
None
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn chatcode() {
assert_eq!(decode_skill("[&BuQCAAA=]"), Some(740)); // might
assert_eq!(decode_skill("[&BgAZAQA=]"), Some(71936)); // fire bullet
assert_eq!(decode_skill("[&BgAZAQA="), None); // broken
assert_eq!(decode_skill("[&AQEAAAA=]"), None); // coin
assert_eq!(decode_skill("[&AgH1WQAA]"), None); // item
assert_eq!(decode_skill("[&BDgAAAA=]"), None); // poi
assert_eq!(decode_skill("[&B/IDAAA=]"), None); // trait
}
}

0 comments on commit 38d077c

Please sign in to comment.