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

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

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

@ -1,5 +1,6 @@
#![feature(iter_array_chunks)]
//#![warn(clippy::all, clippy::pedantic, clippy::nursery)]
#![warn(clippy::all, clippy::pedantic, clippy::nursery)]
#![allow(dead_code)]
mod gd;
mod music;
@ -11,13 +12,17 @@ use std::collections::VecDeque;
use std::fs::File;
use std::io::Write;
use thiserror::Error;
use std::error::Error;
use std::mem;
struct PipeDash {
msg_queue: VecDeque<Message>,
selected_level: Option<usize>,
level_list: Vec<gd::OuterLevel>,
loaded_song: Option<Song>,
loaded_level_checksum: Option<(gd::OuterLevel, md5::Digest)>,
editor: Editor,
error: Option<Box<dyn Error>>
}
#[derive(Debug, PartialEq, Eq)]
@ -30,6 +35,8 @@ enum Color {
#[derive(Debug)]
enum Message {
LevelSelected(usize),
CloseError,
LoadLevel,
}
struct Editor {
@ -252,6 +259,8 @@ impl PipeDash {
msg_queue: VecDeque::new(),
level_list: gd::OuterLevel::load_all(),
loaded_song: None,
loaded_level_checksum: None,
error: None,
editor: Editor {
state: EditorState {
scroll_pos: 0f32,
@ -274,7 +283,9 @@ impl PipeDash {
.default_width(100f32)
.show(ctx, |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| {
ui.with_layout(egui::Layout::top_down_justified(egui::Align::Min), |ui| {
for (idx, level) in self.level_list.iter().enumerate() {
@ -324,14 +335,27 @@ impl PipeDash {
});
}
fn handle_message(&mut self, message: Message) {
match message {
Message::LevelSelected(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 self.msg_queue.drain(..) {
for message in mem::take(&mut self.msg_queue) {
println!("{message:?}");
match message {
Message::LevelSelected(idx) => {
self.selected_level = Some(idx);
}
}
self.handle_message(message);
}
}
}
@ -340,8 +364,17 @@ impl eframe::App for PipeDash {
fn update(&mut self, ctx: &egui::Context, frame: &mut eframe::Frame) {
ctx.set_pixels_per_point(2f32);
self.side_panel(ctx, frame);
self.center_panel(ctx, frame);
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.center_panel(ctx, frame);
}
self.handle_messages();
}

Loading…
Cancel
Save