~comcloudway/little_town

aae8a16ecb88ef95039f2d1a503ff9793ae7edc3 — Jakob Meier 1 year, 4 months ago 5e2bb4f v0.2.3-r3
cargo clippy --fix -- -W clippy::pedantic -W clippy::nursery -W clippy::unwrap_used
M src/game/blocks.rs => src/game/blocks.rs +27 -27
@@ 35,23 35,23 @@ impl Face {
        // test A face
        {
            let ox = (TEXTURE_WIDTH * scale / 2.0 - x).abs();
            let oy = (TEXTURE_DEPTH * scale / 2.0 + TEXTURE_Y_WHITESPACE * scale - y).abs();
            let oy = (TEXTURE_Y_WHITESPACE.mul_add(scale, TEXTURE_DEPTH * scale / 2.0) - y).abs();

            let y_max = TEXTURE_DEPTH * scale / 2.0;
            let x_max = TEXTURE_WIDTH * scale / 2.0;

            let grow = (0.0 - y_max)/(x_max - 0.0);
            let cy = grow * ox + y_max;
            let cy = grow.mul_add(ox, y_max);

            if cy >= oy {
                return Some(Face::Top);
                return Some(Self::Top);
            }
        }

        // test B and C faces
        {
            let ox = TEXTURE_WIDTH * scale / 2.0 - x;
            let oy = y - (TEXTURE_DEPTH * scale / 2.0 + TEXTURE_Y_WHITESPACE * scale);
            let oy = y - TEXTURE_Y_WHITESPACE.mul_add(scale, TEXTURE_DEPTH * scale / 2.0);

            let ox_abs = ox.abs();



@@ 60,16 60,16 @@ impl Face {

            let grow = (0.0 - y_max)/(x_max - 0.0);

            let y_top = grow * ox_abs + y_max;
            let y_bottom = grow * ox_abs + y_max + TEXTURE_INNER_HEIGHT * scale;
            let y_top = grow.mul_add(ox_abs, y_max);
            let y_bottom = TEXTURE_INNER_HEIGHT.mul_add(scale, grow.mul_add(ox_abs, y_max));

            if oy >= y_top && oy <= y_bottom {
                if x > TEXTURE_WIDTH * scale / 2.0 {
                    // C face
                    return Some(Face::Right);
                    return Some(Self::Right);
                } else {
                    // B face
                    return Some(Face::Left);
                    return Some(Self::Left);
                }
            }
        }


@@ 390,40 390,40 @@ auto_gen_blocks!(
);
impl Default for Block {
    fn default() -> Self {
        Block::StructureHigh
        Self::StructureHigh
    }
}

impl Category {
    /// get a list of all categories
    pub fn all() -> Vec<Category> {
    pub fn all() -> Vec<Self> {
        vec![
            Category::All,
            Category::Building,
            Category::Block,
            Category::Desert,
            Category::Roof,
            Category::Plant,
            Category::Water,
            Category::Wood,
            Self::All,
            Self::Building,
            Self::Block,
            Self::Desert,
            Self::Roof,
            Self::Plant,
            Self::Water,
            Self::Wood,
        ]
    }
    /// get name of category
    pub fn get_name(&self) -> &str {
        match self {
            Category::Building => "Buildings",
            Category::Block => "Blocks",
            Category::Roof => "Roofs",
            Category::Plant => "Plants",
            Category::Water => "Water & River",
            Category::Wood => "Wood",
            Category::All => "All",
            Category::Desert => "Desert"
            Self::Building => "Buildings",
            Self::Block => "Blocks",
            Self::Roof => "Roofs",
            Self::Plant => "Plants",
            Self::Water => "Water & River",
            Self::Wood => "Wood",
            Self::All => "All",
            Self::Desert => "Desert"
        }
    }
}
impl Default for Category {
    fn default() -> Self {
        Category::All
        Self::All
    }
}

M src/game/inventory.rs => src/game/inventory.rs +1 -1
@@ 34,7 34,7 @@ impl Inventory {
    }
    /// adds an item to the inventory
    pub fn add_item(&mut self, block: &Block) {
        if let Some(slot) = self.contents.get_mut(&block) {
        if let Some(slot) = self.contents.get_mut(block) {
            *slot += 1;
        } else {
            self.contents.insert(block.clone(), 1);

M src/game/mod.rs => src/game/mod.rs +1 -1
@@ 10,7 10,7 @@ use crate::screens::Screen;
/// A basic Game component
/// which can be drawn
/// and has a handler for the event loop
/// NOTE: draw and ev_loop are tehcnically the same,
/// NOTE: draw and `ev_loop` are tehcnically the same,
/// but the serve different purposes
pub trait GameComponent {
    /// Callback used to redraw the component

M src/game/types.rs => src/game/types.rs +2 -2
@@ 23,7 23,7 @@ impl Pos3 {
            z
        }
    }
    pub fn cmp(&self, pos: &Pos3) -> Ordering {
    pub fn cmp(&self, pos: &Self) -> Ordering {
        if self == pos {
           return Ordering::Equal;
        }


@@ 32,7 32,7 @@ impl Pos3 {
            return self.z.cmp(&pos.z);
        }

        return (self.x+self.y).cmp(&(pos.x+pos.y));
        (self.x+self.y).cmp(&(pos.x+pos.y))
    }
}


M src/game/world.rs => src/game/world.rs +5 -5
@@ 50,7 50,7 @@ impl World {
        let mut inv = Inventory::new();

        if sandbox {
            for block in Block::all().iter() {
            for block in &Block::all() {
                inv.add_item(block);
            }
        }


@@ 113,7 113,7 @@ impl World {
            if let Ok(rd) = &mut read_dir(dir) {
                let mut builder = Vec::new();

                while let Some(entry) = rd.next() {
                for entry in rd.by_ref() {
                    if let Ok(entry) = entry {
                        if let Ok(ftype) = entry.file_type() && ftype.is_file() {
                            if let Some(name) = entry.file_name().to_str() {


@@ 137,9 137,9 @@ impl World {
                let mut buf_reader = BufReader::new(file);
                let mut contents = String::new();
                if buf_reader.read_to_string(&mut contents).is_ok() {
                    match World::deserialize_json(&contents) {
                    match Self::deserialize_json(&contents) {
                        Ok(bscr) => return Some(bscr),
                        Err(e) => println!("{:?}", e)
                        Err(e) => println!("{e:?}")
                    }
                } else {
                    println!("Faield to read file");


@@ 158,7 158,7 @@ impl World {
    /// tries saving the map to disk
    pub fn to_disk(&self, name: &str) {
        if let Some(dir) = get_data_dir() {
            let json = World::serialize_json(self);
            let json = Self::serialize_json(self);

            DirBuilder::new()
                .recursive(true)

M src/p2p.rs => src/p2p.rs +6 -5
@@ 42,10 42,10 @@ use crate::game::types::{
    Direction
};

/// A custom network behaviour that combines floodsub, ping and mDNS.
/// A custom network behaviour that combines floodsub, ping and `mDNS`.
/// floodsub is used to broadcast messages and events
/// ping is used to keep the connection alive
/// mDNS is used for peer discovery
/// `mDNS` is used for peer discovery
#[derive(NetworkBehaviour)]
struct PeerBehaviour {
    /// for message broadcasting


@@ 59,7 59,7 @@ struct PeerBehaviour {
/// the topic using which data is broadcasted
const TOPIC: &str = "little-town";

/// a GameEvent worth while broadcasting to peers
/// a `GameEvent` worth while broadcasting to peers
#[derive(DeJson, SerJson)]
pub enum GameAction {
    /// event send when a block has been placed


@@ 181,7 181,7 @@ impl Peer {

        let port = self.port;
        let inbox = self.incoming.clone();
        let is_host = self.is_host.clone();
        let is_host = self.is_host;

        thread::spawn(move ||async_std::task::block_on(async {
            let local_key = identity::Keypair::generate_ed25519();


@@ 299,7 299,8 @@ impl Peer {
                            if !is_host {
                                // request data
                                // in case host lost the request
                                for act in [ GameAction::RequestWorld ] {
                                {
                                    let act = GameAction::RequestWorld;
                                    let json = act.serialize_json();
                                    swarm
                                        .behaviour_mut()

M src/screens/build.rs => src/screens/build.rs +19 -27
@@ 53,13 53,11 @@ fn get_screen_coords(pos: &Pos3, scale: f32, center: (f32, f32)) -> (f32, f32) {
        + dx as f32 * w_i / 2.0
        + center.0
        - width / 2.0;
    let y = screen_height() / 2.0
        + dy as f32 * h_i / 2.0
        - pos.z as f32 * h_i
    let y = (pos.z as f32).mul_add(-h_i, screen_height() / 2.0 + dy as f32 * h_i / 2.0)
        + center.1
        - height / 2.0;

    return (x,y);
    (x,y)
}

struct InventoryWidgets {


@@ 119,7 117,7 @@ impl InventoryWidgets {
        let list = inv.category.get_blocks();
        let page_count = list.len().div_ceil(9);
        self.widget_page_indicator.set_text(&format!("{}/{}", self.page+1, page_count));
        self.widget_categories.set_text(&format!("{}", title));
        self.widget_categories.set_text(&format!("{title}"));

        self.load_page(page, inv);
    }


@@ 130,7 128,7 @@ impl InventoryWidgets {
        let max_page = list.len().div_ceil(9);
        for (i, slot) in self.widgets_slots.iter_mut().enumerate() {
            if let Some(block) = list.get(i + page * 9) {
                let amount = if let Some(a) = inv.contents.get(block) { Some(*a) } else { None };
                let amount = inv.contents.get(block).copied();
                slot.update(&Some(block.clone()), &inv.direction, &amount);
            } else {
                slot.empty();


@@ 182,15 180,11 @@ pub struct BuildScreen {
impl BuildScreen {
    /// attempts to load a world from disk
    pub fn from_disk(file_name: &str) -> Option<Self> {
        if let Some(world) = World::from_disk(file_name) {
            Some(Self {
        World::from_disk(file_name).map(|world| Self {
                world: Some(world),
                file_name: Some(file_name.to_string()),
                ..Self::empty()
            })
        } else {
            None
        }
    }
    /// create a new empty world
    pub fn new(file_name: &str, sandbox: bool) -> Self {


@@ 245,14 239,14 @@ impl GameComponent for BuildScreen {
        if let Some(world) = &self.world {
            if self.inventory_widgets.shown {
                // draw inventory
                self.inventory_widgets.widget_back.draw(&assets).await;
                self.inventory_widgets.widget_categories.draw(&assets).await;
                self.inventory_widgets.widget_back.draw(assets).await;
                self.inventory_widgets.widget_categories.draw(assets).await;

                for slot in self.inventory_widgets.widgets_slots.iter() {
                    slot.draw(&assets).await;
                for slot in &self.inventory_widgets.widgets_slots {
                    slot.draw(assets).await;
                }

                self.inventory_widgets.widget_page_indicator.draw(&assets).await;
                self.inventory_widgets.widget_page_indicator.draw(assets).await;

                return;
            }


@@ 261,7 255,7 @@ impl GameComponent for BuildScreen {
            let mut render_order: Vec<(&Pos3, &(Block, Direction))> = world.grid.iter().collect();
            render_order.sort_by(|(p1, _), (p2, _)| p1.cmp(p2));

            for (pos, (block, dir)) in render_order.iter() {
            for (pos, (block, dir)) in &render_order {
                let texture = block.get_texture().await.get_dir(dir);
                let width = TEXTURE_WIDTH * world.cam.scale;
                let height = TEXTURE_HEIGHT * world.cam.scale;


@@ 288,7 282,7 @@ impl GameComponent for BuildScreen {
            }

            // Draw selected item (top right)
            self.item_indicator_widget.draw(&assets).await;
            self.item_indicator_widget.draw(assets).await;
        }
    }
    fn ev_loop(&mut self) -> GameEvent {


@@ 369,9 363,7 @@ impl GameComponent for BuildScreen {
                // update the top-right item indicator
                {
                    let amount = if let Some(block) = &world.inventory.selected {
                        if let Some(a) = world.inventory.contents.get(block) {
                            Some(*a)
                        } else { None }
                        world.inventory.contents.get(block).copied()
                    } else { None };
                    self.item_indicator_widget.update(&world.inventory.selected, &world.inventory.direction, &amount);
                }


@@ 389,13 381,13 @@ impl GameComponent for BuildScreen {
                        // (mx, my)
                        let mut in_path:Vec<&Pos3> = Vec::new();

                        for (pos, _) in render_order.iter() {
                        for (pos, _) in &render_order {
                            let (x,y) = get_screen_coords(pos, world.cam.scale, world.cam.center);

                            if mx >= x
                                && mx <= x + TEXTURE_WIDTH * world.cam.scale
                                && my >= y + TEXTURE_Y_WHITESPACE * world.cam.scale
                                && my <= y + TEXTURE_HEIGHT * world.cam.scale {
                                && mx <= TEXTURE_WIDTH.mul_add(world.cam.scale, x)
                                && my >= TEXTURE_Y_WHITESPACE.mul_add(world.cam.scale, y)
                                && my <= TEXTURE_HEIGHT.mul_add(world.cam.scale, y) {

                                    // check if mouse is above transparent area
                                    // and skip block if necessary


@@ 492,7 484,7 @@ impl GameComponent for BuildScreen {
                    let mut scale = world.cam.scale;
                    let (_, wy) = mouse_wheel();

                    scale += wy as f32 * 1.0/10.0;
                    scale += wy * 1.0/10.0;

                    if scale > 0.05 && scale < 6.0 {
                        world.cam.scale = scale;


@@ 543,7 535,7 @@ impl GameComponent for BuildScreen {
                        // save game

                        if let Some(file_name) = &self.file_name {
                            world.to_disk(&file_name);
                            world.to_disk(file_name);
                        }

                        if is_key_pressed(KeyCode::Q) || is_key_pressed(KeyCode::Escape) {

M src/screens/map_creator.rs => src/screens/map_creator.rs +83 -135
@@ 64,9 64,9 @@ impl GameComponent for MapCreatorScreen {
            draw_rectangle(0.0, 0.0, screen_width(), screen_height(), Color::from_rgba(0, 0, 0, 100));
        }

        self.widget_back.draw(&assets).await;
        self.widget_create.draw(&assets).await;
        self.widget_container.draw(&assets).await;
        self.widget_back.draw(assets).await;
        self.widget_create.draw(assets).await;
        self.widget_container.draw(assets).await;
    }
    fn ev_loop(&mut self) -> GameEvent {



@@ 75,7 75,7 @@ impl GameComponent for MapCreatorScreen {
            if is_key_pressed(KeyCode::Backspace) {
                self.name.pop();

                if self.name.len() == 0 {
                if self.name.is_empty() {
                    self.widget_container.set_text("type here");
                } else {
                    self.widget_container.set_text(&self.name);


@@ 83,167 83,115 @@ impl GameComponent for MapCreatorScreen {
            }


            if self.name.len() < 10 {
                if is_key_pressed(KeyCode::A) {
                    self.name.push('a');
                    self.widget_container.set_text(&self.name);
                }
            if self.name.len() < 10 && is_key_pressed(KeyCode::A) {
                self.name.push('a');
                self.widget_container.set_text(&self.name);
            }
            if self.name.len() < 10 {
                if is_key_pressed(KeyCode::B) {
                    self.name.push('b');
                    self.widget_container.set_text(&self.name);
                }
            if self.name.len() < 10 && is_key_pressed(KeyCode::B) {
                self.name.push('b');
                self.widget_container.set_text(&self.name);
            }
            if self.name.len() < 10 {
                if is_key_pressed(KeyCode::C) {
                    self.name.push('c');
                    self.widget_container.set_text(&self.name);
                }
            if self.name.len() < 10 && is_key_pressed(KeyCode::C) {
                self.name.push('c');
                self.widget_container.set_text(&self.name);
            }
            if self.name.len() < 10 {
                if is_key_pressed(KeyCode::D) {
                    self.name.push('d');
                    self.widget_container.set_text(&self.name);
                }
            if self.name.len() < 10 && is_key_pressed(KeyCode::D) {
                self.name.push('d');
                self.widget_container.set_text(&self.name);
            }
            if self.name.len() < 10 {
                if is_key_pressed(KeyCode::E) {
                    self.name.push('e');
                    self.widget_container.set_text(&self.name);
                }
            if self.name.len() < 10 && is_key_pressed(KeyCode::E) {
                self.name.push('e');
                self.widget_container.set_text(&self.name);
            }
            if self.name.len() < 10 {
                if is_key_pressed(KeyCode::F) {
                    self.name.push('f');
                    self.widget_container.set_text(&self.name);
                }
            if self.name.len() < 10 && is_key_pressed(KeyCode::F) {
                self.name.push('f');
                self.widget_container.set_text(&self.name);
            }
            if self.name.len() < 10 {
                if is_key_pressed(KeyCode::G) {
                    self.name.push('g');
                    self.widget_container.set_text(&self.name);
                }
            if self.name.len() < 10 && is_key_pressed(KeyCode::G) {
                self.name.push('g');
                self.widget_container.set_text(&self.name);
            }
            if self.name.len() < 10 {
                if is_key_pressed(KeyCode::H) {
                    self.name.push('h');
                    self.widget_container.set_text(&self.name);
                }
            if self.name.len() < 10 && is_key_pressed(KeyCode::H) {
                self.name.push('h');
                self.widget_container.set_text(&self.name);
            }
            if self.name.len() < 10 {
                if is_key_pressed(KeyCode::I) {
                    self.name.push('i');
                    self.widget_container.set_text(&self.name);
                }
            if self.name.len() < 10 && is_key_pressed(KeyCode::I) {
                self.name.push('i');
                self.widget_container.set_text(&self.name);
            }
            if self.name.len() < 10 {
                if is_key_pressed(KeyCode::J) {
                    self.name.push('j');
                    self.widget_container.set_text(&self.name);
                }
            if self.name.len() < 10 && is_key_pressed(KeyCode::J) {
                self.name.push('j');
                self.widget_container.set_text(&self.name);
            }
            if self.name.len() < 10 {
                if is_key_pressed(KeyCode::K) {
                    self.name.push('k');
                    self.widget_container.set_text(&self.name);
                }
            if self.name.len() < 10 && is_key_pressed(KeyCode::K) {
                self.name.push('k');
                self.widget_container.set_text(&self.name);
            }
            if self.name.len() < 10 {
                if is_key_pressed(KeyCode::L) {
                    self.name.push('l');
                    self.widget_container.set_text(&self.name);
                }
            if self.name.len() < 10 && is_key_pressed(KeyCode::L) {
                self.name.push('l');
                self.widget_container.set_text(&self.name);
            }
            if self.name.len() < 10 {
                if is_key_pressed(KeyCode::M) {
                    self.name.push('m');
                    self.widget_container.set_text(&self.name);
                }
            if self.name.len() < 10 && is_key_pressed(KeyCode::M) {
                self.name.push('m');
                self.widget_container.set_text(&self.name);
            }
            if self.name.len() < 10 {
                if is_key_pressed(KeyCode::N) {
                    self.name.push('n');
                    self.widget_container.set_text(&self.name);
                }
            if self.name.len() < 10 && is_key_pressed(KeyCode::N) {
                self.name.push('n');
                self.widget_container.set_text(&self.name);
            }
            if self.name.len() < 10 {
                if is_key_pressed(KeyCode::O) {
                    self.name.push('o');
                    self.widget_container.set_text(&self.name);
                }
            if self.name.len() < 10 && is_key_pressed(KeyCode::O) {
                self.name.push('o');
                self.widget_container.set_text(&self.name);
            }
            if self.name.len() < 10 {
                if is_key_pressed(KeyCode::P) {
                    self.name.push('p');
                    self.widget_container.set_text(&self.name);
                }
            if self.name.len() < 10 && is_key_pressed(KeyCode::P) {
                self.name.push('p');
                self.widget_container.set_text(&self.name);
            }
            if self.name.len() < 10 {
                if is_key_pressed(KeyCode::Q) {
                    self.name.push('q');
                    self.widget_container.set_text(&self.name);
                }
            if self.name.len() < 10 && is_key_pressed(KeyCode::Q) {
                self.name.push('q');
                self.widget_container.set_text(&self.name);
            }
            if self.name.len() < 10 {
                if is_key_pressed(KeyCode::R) {
                    self.name.push('r');
                    self.widget_container.set_text(&self.name);
                }
            if self.name.len() < 10 && is_key_pressed(KeyCode::R) {
                self.name.push('r');
                self.widget_container.set_text(&self.name);
            }
            if self.name.len() < 10 {
                if is_key_pressed(KeyCode::S) {
                    self.name.push('s');
                    self.widget_container.set_text(&self.name);
                }
            if self.name.len() < 10 && is_key_pressed(KeyCode::S) {
                self.name.push('s');
                self.widget_container.set_text(&self.name);
            }
            if self.name.len() < 10 {
                if is_key_pressed(KeyCode::T) {
                    self.name.push('t');
                    self.widget_container.set_text(&self.name);
                }
            if self.name.len() < 10 && is_key_pressed(KeyCode::T) {
                self.name.push('t');
                self.widget_container.set_text(&self.name);
            }
            if self.name.len() < 10 {
                if is_key_pressed(KeyCode::U) {
                    self.name.push('u');
                    self.widget_container.set_text(&self.name);
                }
            if self.name.len() < 10 && is_key_pressed(KeyCode::U) {
                self.name.push('u');
                self.widget_container.set_text(&self.name);
            }
            if self.name.len() < 10 {
                if is_key_pressed(KeyCode::V) {
                    self.name.push('v');
                    self.widget_container.set_text(&self.name);
                }
            if self.name.len() < 10 && is_key_pressed(KeyCode::V) {
                self.name.push('v');
                self.widget_container.set_text(&self.name);
            }
            if self.name.len() < 10 {
                if is_key_pressed(KeyCode::W) {
                    self.name.push('w');
                    self.widget_container.set_text(&self.name);
                }
            if self.name.len() < 10 && is_key_pressed(KeyCode::W) {
                self.name.push('w');
                self.widget_container.set_text(&self.name);
            }
            if self.name.len() < 10 {
                if is_key_pressed(KeyCode::X) {
                    self.name.push('x');
                    self.widget_container.set_text(&self.name);
                }
            if self.name.len() < 10 && is_key_pressed(KeyCode::X) {
                self.name.push('x');
                self.widget_container.set_text(&self.name);
            }
            if self.name.len() < 10 {
                if is_key_pressed(KeyCode::Y) {
                    self.name.push('y');
                    self.widget_container.set_text(&self.name);
                }
            if self.name.len() < 10 && is_key_pressed(KeyCode::Y) {
                self.name.push('y');
                self.widget_container.set_text(&self.name);
            }
            if self.name.len() < 10 {
                if is_key_pressed(KeyCode::Z) {
                    self.name.push('z');
                    self.widget_container.set_text(&self.name);
                }
            if self.name.len() < 10 && is_key_pressed(KeyCode::Z) {
                self.name.push('z');
                self.widget_container.set_text(&self.name);
            }
        }

        match self.widget_create.ev_loop() {
            ButtonEvent::LeftClick => {
                if self.name.len() > 0 && self.name.len() <= 10 {
                if !self.name.is_empty() && self.name.len() <= 10 {
                    let name = format!("{}.world", self.name);
                    if !World::get_list().contains(&name) {
                        let bscr = BuildScreen::new(&name, true);

M src/screens/map_select.rs => src/screens/map_select.rs +30 -34
@@ 43,7 43,7 @@ pub struct SelectScreen {
    page: usize
}
impl SelectScreen {
    /// create a new MapSelectorScreen instance
    /// create a new `MapSelectorScreen` instance
    pub fn new() -> Self {
        let levels = World::get_list();
        Self {


@@ 60,7 60,7 @@ impl SelectScreen {
                .with_font_size(30),
            level_select_widgets: vec![
                SelectableText::new(levels.get(0).unwrap_or(&"???".to_string()), 0.5, 0.4)
                    .with_visibility(levels.len() >= 1),
                    .with_visibility(!levels.is_empty()),
                SelectableText::new(levels.get(1).unwrap_or(&"???".to_string()), 0.5, 0.5)
                    .with_visibility(levels.len() >= 2),
                SelectableText::new(levels.get(2).unwrap_or(&"???".to_string()), 0.5, 0.6)


@@ 91,16 91,16 @@ impl GameComponent for SelectScreen {
            draw_rectangle(0.0, 0.0, screen_width(), screen_height(), Color::from_rgba(0, 0, 0, 100));
        }

        self.widget_back.draw(&assets).await;
        self.widget_back.draw(assets).await;

        for slot in self.level_select_widgets.iter() {
            slot.draw(&assets).await;
        for slot in &self.level_select_widgets {
            slot.draw(assets).await;
        }

        #[cfg(feature = "multiplayer")]
        self.widget_host.draw(&assets).await;
        self.widget_new.draw(&assets).await;
        self.widget_play.draw(&assets).await;
        self.widget_host.draw(assets).await;
        self.widget_new.draw(assets).await;
        self.widget_play.draw(assets).await;
    }
    fn ev_loop(&mut self) -> GameEvent {
        match self.widget_back.ev_loop() {


@@ 116,7 116,7 @@ impl GameComponent for SelectScreen {
            match self.widget_host.ev_loop() {
                ButtonEvent::LeftClick => {
                    if let Some(file_name) = &self.selected {
                        if let Some(scr) = BuildScreen::from_disk(&file_name) {
                        if let Some(scr) = BuildScreen::from_disk(file_name) {
                            return GameEvent::ChangeScreen(Screen::Build(scr.as_host()));
                        }
                    }


@@ 133,7 133,7 @@ impl GameComponent for SelectScreen {
        match self.widget_play.ev_loop() {
            ButtonEvent::LeftClick => {
                if let Some(file_name) = &self.selected {
                    if let Some(scr) = BuildScreen::from_disk(&file_name) {
                    if let Some(scr) = BuildScreen::from_disk(file_name) {
                        return GameEvent::ChangeScreen(Screen::Build(scr));
                    }
                }


@@ 141,7 141,7 @@ impl GameComponent for SelectScreen {
            _ => ()
        }

        for slot in self.level_select_widgets.iter_mut() {
        for slot in &mut self.level_select_widgets {
            slot.set_selected(false);
            match slot.ev_loop() {
                ButtonEvent::LeftClick => {


@@ 158,7 158,7 @@ impl GameComponent for SelectScreen {
            }
        }
        if let Some(selection) = &self.selected {
            for slot in self.level_select_widgets.iter_mut() {
            for slot in &mut self.level_select_widgets {
                if &slot.get_text() == selection {
                    slot.set_selected(true);
                }


@@ 170,34 170,30 @@ impl GameComponent for SelectScreen {
            return GameEvent::ChangeScreen(Screen::default())
        }

        if is_key_pressed(KeyCode::Down) {
            if self.list.len() >= self.level_select_widgets.len() && self.page < self.list.len() - self.level_select_widgets.len() {
                self.page += 1;
        if is_key_pressed(KeyCode::Down) && self.list.len() >= self.level_select_widgets.len() && self.page < self.list.len() - self.level_select_widgets.len() {
            self.page += 1;

                // update widget text
                for (i, slot) in self.level_select_widgets.iter_mut().enumerate() {
                    if let Some(text) = self.list.get(i+self.page) {
                        slot.set_visibility(true);
                        slot.set_text(text);
                    } else {
                        slot.set_visibility(false);
                    }
            // update widget text
            for (i, slot) in self.level_select_widgets.iter_mut().enumerate() {
                if let Some(text) = self.list.get(i+self.page) {
                    slot.set_visibility(true);
                    slot.set_text(text);
                } else {
                    slot.set_visibility(false);
                }
            }
        }
        if is_key_pressed(KeyCode::Up) {
            if self.page > 0 {
                self.page -= 1;
        if is_key_pressed(KeyCode::Up) && self.page > 0 {
            self.page -= 1;


                // update widget text
                for (i, slot) in self.level_select_widgets.iter_mut().enumerate() {
                    if let Some(text) = self.list.get(i+self.page) {
                        slot.set_visibility(true);
                        slot.set_text(text);
                    } else {
                        slot.set_visibility(false);
                    }
            // update widget text
            for (i, slot) in self.level_select_widgets.iter_mut().enumerate() {
                if let Some(text) = self.list.get(i+self.page) {
                    slot.set_visibility(true);
                    slot.set_text(text);
                } else {
                    slot.set_visibility(false);
                }
            }
        }

M src/screens/mod.rs => src/screens/mod.rs +8 -8
@@ 28,18 28,18 @@ pub enum Screen {
impl GameComponent for Screen {
    async fn draw(&self, assets: &AssetStore) {
        match self {
            Screen::Welcome(w) => w.draw(&assets).await,
            Screen::Build(b) => b.draw(&assets).await,
            Screen::Select(s) => s.draw(&assets).await,
            Screen::Create(c) => c.draw(&assets).await,
            Self::Welcome(w) => w.draw(assets).await,
            Self::Build(b) => b.draw(assets).await,
            Self::Select(s) => s.draw(assets).await,
            Self::Create(c) => c.draw(assets).await,
        }
    }
    fn ev_loop(&mut self) -> GameEvent {
        match self {
            Screen::Welcome(w) => w.ev_loop(),
            Screen::Build(b) => b.ev_loop(),
            Screen::Select(s) => s.ev_loop(),
            Screen::Create(c) => c.ev_loop(),
            Self::Welcome(w) => w.ev_loop(),
            Self::Build(b) => b.ev_loop(),
            Self::Select(s) => s.ev_loop(),
            Self::Create(c) => c.ev_loop(),
        }
    }
}

M src/screens/welcome.rs => src/screens/welcome.rs +5 -5
@@ 29,7 29,7 @@ pub struct WelcomeScreen {
    widget_quit: TextButton,
}
impl WelcomeScreen {
    /// create a new WelcomeScreen instance
    /// create a new `WelcomeScreen` instance
    pub fn new() -> Self {
        Self {
            widget_title: CenteredText::new("LittleTown", 0.5,0.45)


@@ 66,12 66,12 @@ impl GameComponent for WelcomeScreen {
        }


        self.widget_title.draw(&assets).await;
        self.widget_title.draw(assets).await;

        self.widget_select.draw(&assets).await;
        self.widget_select.draw(assets).await;
        #[cfg(feature = "multiplayer")]
        self.widget_join.draw(&assets).await;
        self.widget_quit.draw(&assets).await;
        self.widget_join.draw(assets).await;
        self.widget_quit.draw(assets).await;
    }
    fn ev_loop(&mut self) -> GameEvent {
        self.widget_title.ev_loop();

M src/ui/item_frame.rs => src/ui/item_frame.rs +3 -3
@@ 51,7 51,7 @@ impl ItemFrame {
            ..self
        };
        if let Some(amount) = amount {
            this.widget_amount.set_text(&format!("{}", amount));
            this.widget_amount.set_text(&format!("{amount}"));
        } else {
            this.widget_amount.set_text("inf");
        }


@@ 65,7 65,7 @@ impl ItemFrame {
        self.amount = amount;

        if let Some(amount) = amount {
            self.widget_amount.set_text(&format!("{}", amount));
            self.widget_amount.set_text(&format!("{amount}"));
        } else {
            self.widget_amount.set_text("inf");
        }


@@ 162,7 162,7 @@ impl Widget for ItemFrame {
                }
            );
            // draw amount
            self.widget_amount.draw(&assets).await;
            self.widget_amount.draw(assets).await;
        }
    }
    fn ev_loop(&mut self) -> Self::Event {

M src/ui/mod.rs => src/ui/mod.rs +1 -1
@@ 12,7 12,7 @@ pub use selectable_text::SelectableText;
pub use text_button::TextButton;

/// A button event send from the Button widget ev-loop
/// i.e WideButton
/// i.e `WideButton`
pub enum ButtonEvent {
    /// nothing happened
    None,