error handling, working on loading lines (have yet to decode ILS)

main
aprzn 2 years ago
parent f8691ec6b9
commit 1593cbc2ef

7
Cargo.lock generated

@ -1517,6 +1517,12 @@ dependencies = [
"libc", "libc",
] ]
[[package]]
name = "md5"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "490cc448043f947bae3cbee9c203358d62dbee0db12107a74be5c30ccfd09771"
[[package]] [[package]]
name = "memchr" name = "memchr"
version = "2.5.0" version = "2.5.0"
@ -2026,6 +2032,7 @@ dependencies = [
"flate2", "flate2",
"gd_plist", "gd_plist",
"home", "home",
"md5",
"ordered-float", "ordered-float",
"reqwest", "reqwest",
"rodio", "rodio",

@ -17,3 +17,4 @@ ordered-float = "3.4.0"
thiserror = "1.0.38" thiserror = "1.0.38"
reqwest = {version = "0.11.14", features = [ "blocking" ]} reqwest = {version = "0.11.14", features = [ "blocking" ]}
urlencoding = "2.1.2" urlencoding = "2.1.2"
md5 = "0.7.0"

@ -29,25 +29,27 @@ struct Level {
song: Song, song: Song,
} }
#[derive(Debug)] #[derive(Debug, Clone)]
pub struct OuterLevel { pub struct OuterLevel {
name: String, // k2 name: String, // k2
revision: Option<i64>, // k46 revision: Option<i64>, // k46
} }
#[derive(Debug, Error, Clone)] pub struct InnerLevel(String);
#[derive(Debug, Error)]
pub enum SongRequestError { pub enum SongRequestError {
#[error("Request failed")] #[error("Request failed")]
ConnectionFailure, ConnectionFailure(#[from] reqwest::Error),
#[error("Index is not an int?????")] #[error("Index is not an int?????")]
ParseFailure(#[from] ParseIntError), ParseFailure(#[from] ParseIntError),
#[error("Not a Newgrounds song")] #[error("Not a Newgrounds song")]
NotNewgrounds, NotNewgrounds,
} }
impl From<reqwest::Error> for SongRequestError { impl InnerLevel {
fn from(_: reqwest::Error) -> Self { pub fn try_from_encoded_ils(ils: &str) -> Option<Self> {
Self::ConnectionFailure todo!()
} }
} }
@ -108,8 +110,7 @@ impl SongResponse {
impl OuterLevel { impl OuterLevel {
pub fn load_all() -> Vec<Self> { pub fn load_all() -> Vec<Self> {
let plist = get_local_level_plist(); get_local_level_plist()
let levels: Vec<Self> = plist
.as_dictionary() .as_dictionary()
.and_then(|dict| dict.get("LLM_01")) .and_then(|dict| dict.get("LLM_01"))
.unwrap() .unwrap()
@ -128,8 +129,31 @@ impl OuterLevel {
} }
builder.build_outer_level().unwrap() builder.build_outer_level().unwrap()
}) })
.collect(); .collect()
levels }
pub fn load_inner(&self) -> InnerLevel {
get_local_level_plist()
.as_dictionary()
.and_then(|dict| dict.get("LLM_01"))
.unwrap()
.as_dictionary()
.unwrap()
.iter()
.find(|(key, val)| key.as_str() != "_isArr" && {
let props = val.as_dictionary().unwrap();
props.get("k2").unwrap().as_string().unwrap() == self.name
&& props.get("k46").and_then(|rev| rev.as_signed_integer()) == self.revision
})
.unwrap()
.1
.as_dictionary()
.unwrap()
.get("k4")
.unwrap()
.as_string()
.and_then(|str| InnerLevel::try_from_encoded_ils(str))
.unwrap()
} }
pub fn display_name(&self) -> LayoutJob { pub fn display_name(&self) -> LayoutJob {

@ -1,5 +1,6 @@
#![feature(iter_array_chunks)] #![feature(iter_array_chunks)]
//#![warn(clippy::all, clippy::pedantic, clippy::nursery)] #![warn(clippy::all, clippy::pedantic, clippy::nursery)]
#![allow(dead_code)]
mod gd; mod gd;
mod music; mod music;
@ -11,13 +12,17 @@ use std::collections::VecDeque;
use std::fs::File; use std::fs::File;
use std::io::Write; use std::io::Write;
use thiserror::Error; use thiserror::Error;
use std::error::Error;
use std::mem;
struct PipeDash { struct PipeDash {
msg_queue: VecDeque<Message>, msg_queue: VecDeque<Message>,
selected_level: Option<usize>, selected_level: Option<usize>,
level_list: Vec<gd::OuterLevel>, level_list: Vec<gd::OuterLevel>,
loaded_song: Option<Song>, loaded_song: Option<Song>,
loaded_level_checksum: Option<(gd::OuterLevel, md5::Digest)>,
editor: Editor, editor: Editor,
error: Option<Box<dyn Error>>
} }
#[derive(Debug, PartialEq, Eq)] #[derive(Debug, PartialEq, Eq)]
@ -30,6 +35,8 @@ enum Color {
#[derive(Debug)] #[derive(Debug)]
enum Message { enum Message {
LevelSelected(usize), LevelSelected(usize),
CloseError,
LoadLevel,
} }
struct Editor { struct Editor {
@ -252,6 +259,8 @@ impl PipeDash {
msg_queue: VecDeque::new(), msg_queue: VecDeque::new(),
level_list: gd::OuterLevel::load_all(), level_list: gd::OuterLevel::load_all(),
loaded_song: None, loaded_song: None,
loaded_level_checksum: None,
error: None,
editor: Editor { editor: Editor {
state: EditorState { state: EditorState {
scroll_pos: 0f32, scroll_pos: 0f32,
@ -274,7 +283,9 @@ impl PipeDash {
.default_width(100f32) .default_width(100f32)
.show(ctx, |ui| { .show(ctx, |ui| {
ui.with_layout(egui::Layout::top_down(egui::Align::LEFT), |ui| { ui.with_layout(egui::Layout::top_down(egui::Align::LEFT), |ui| {
ui.button("Load Level"); if ui.add_enabled(self.selected_level.is_some(), egui::Button::new("Load Level")).clicked() {
self.msg_queue.push_back(Message::LoadLevel);
}
egui::ScrollArea::vertical().show(ui, |ui| { egui::ScrollArea::vertical().show(ui, |ui| {
ui.with_layout(egui::Layout::top_down_justified(egui::Align::Min), |ui| { ui.with_layout(egui::Layout::top_down_justified(egui::Align::Min), |ui| {
for (idx, level) in self.level_list.iter().enumerate() { for (idx, level) in self.level_list.iter().enumerate() {
@ -324,14 +335,27 @@ impl PipeDash {
}); });
} }
fn handle_messages(&mut self) { fn handle_message(&mut self, message: Message) {
for message in self.msg_queue.drain(..) {
println!("{message:?}");
match message { match message {
Message::LevelSelected(idx) => { Message::LevelSelected(idx) => self.selected_level = Some(idx),
self.selected_level = Some(idx); Message::CloseError => self.error = None,
Message::LoadLevel => {
// Load song & GdlData
let level = self.selected_level
.and_then(|idx| self.level_list.get(idx))
.unwrap() // will not panic. selected_level range is same as level_list...
.clone(); // ...length - 1; message will not be sent if selected_level is none
todo!();
},
} }
} }
fn handle_messages(&mut self) {
for message in mem::take(&mut self.msg_queue) {
println!("{message:?}");
self.handle_message(message);
} }
} }
} }
@ -340,8 +364,17 @@ impl eframe::App for PipeDash {
fn update(&mut self, ctx: &egui::Context, frame: &mut eframe::Frame) { fn update(&mut self, ctx: &egui::Context, frame: &mut eframe::Frame) {
ctx.set_pixels_per_point(2f32); ctx.set_pixels_per_point(2f32);
if let Some(boxed_err) = &self.error {
egui::CentralPanel::default().show(ctx, |ui| {
ui.label(boxed_err.to_string());
if ui.button("Close").clicked() {
self.msg_queue.push_back(Message::CloseError);
}
});
} else {
self.side_panel(ctx, frame); self.side_panel(ctx, frame);
self.center_panel(ctx, frame); self.center_panel(ctx, frame);
}
self.handle_messages(); self.handle_messages();
} }

Loading…
Cancel
Save