~starkingdoms/starkingdoms

4c612ac480fa5c6a4ea8ef3cecd0f71e7d9424f9 — ghostly_zsh 8 months ago 76a4e41
mining is back
M crates/server/src/crafting/components.rs => crates/server/src/crafting/components.rs +41 -9
@@ 1,21 1,53 @@
use std::collections::HashMap;

use bevy::prelude::Component;
use starkingdoms_common::PlanetType;

#[derive(Debug, Clone, Copy, PartialEq)]
#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)]
pub enum MaterialType {
    Silicon,   // Mercury
    Sulfur,    // Venus
    Iron,      // Mars
    Hydrogen,  // Jupiter
    Helium,    // Saturn
    Rubber,    // Uranus
    Composite, // Neptune
    Ice,       // Pluto
    Plasma, // Sun
    Composite, // Mercury
    Sulfur, // Venus
    Silicon, // Moon
    Iron, // Mars
    Hydrogen, // Jupiter
    Helium, // Saturn
    Rubber, // Uranus
    Methane, // Neptune
    Ice, // Pluto
}
impl TryFrom<PlanetType> for MaterialType {
    type Error = ();
    fn try_from(value: PlanetType) -> Result<Self, ()> {
        match value {
            PlanetType::Sun => Ok(Self::Plasma),
            PlanetType::Mercury => Ok(Self::Composite),
            PlanetType::Venus => Ok(Self::Sulfur),
            PlanetType::Moon => Ok(Self::Silicon),
            PlanetType::Mars => Ok(Self::Iron),
            PlanetType::Jupiter => Ok(Self::Hydrogen),
            PlanetType::Saturn => Ok(Self::Helium),
            PlanetType::Uranus => Ok(Self::Rubber),
            PlanetType::Neptune => Ok(Self::Methane),
            PlanetType::Pluto => Ok(Self::Ice),
            _ => Err(()),
        }
    }
}

#[derive(Component, Debug, Clone)]
pub struct MaterialStorage {
    pub material_type: MaterialType,
    pub stored: u32,
    pub capacity: u32,
}

#[derive(Component, Debug, Clone, Default)]
pub struct VarietyMaterialStorage {
    pub materials: HashMap<MaterialType, u32>,
    pub capacity: u32,
}

#[derive(Component, Debug, Clone, Default)]
pub struct IsMining(pub bool);


A crates/server/src/crafting/mining.rs => crates/server/src/crafting/mining.rs +71 -0
@@ 0,0 1,71 @@
use bevy::prelude::{Children, Entity, Query, Res, With};
use bevy_rapier2d::plugin::RapierContext;
use crate::{module::component::Attach, planet::PlanetType};

use super::components::{IsMining, MaterialType, VarietyMaterialStorage};
pub fn mine_materials(
    rapier_context: Res<RapierContext>,
    planet_query: Query<(&PlanetType, &Children)>,
    mut mineable_query: Query<(Entity, &mut Attach, Option<&IsMining>, Option<&mut VarietyMaterialStorage>)>,
) {
    for (planet_type, children) in &planet_query {
        for (entity1, entity2, intersecting) in rapier_context.intersection_pairs_with(*children.first().unwrap()) {
            if !intersecting { continue }
            let other = if *children.first().unwrap() == entity1 {
                entity2
            } else {
                entity1
            };
            let (entity, attach, mineable, _) = match mineable_query.get(other) {
                Ok(m) => m,
                Err(_) => continue,
            };
            let associated_player = match attach.associated_player {
                Some(e) => e,
                None => entity
            };
            // is the module mining
            if let Some(mineable) = mineable {
                if mineable.0 {
                    if let Some(storage_entity) = find_storage(associated_player, &mineable_query) {
                        let (_, _, _, storage) = mineable_query.get_mut(storage_entity).unwrap();
                        if let Some(mut storage) = storage {
                            if let Ok(material) = planet_type.0.try_into() {
                                match storage.materials.get_mut(&material) {
                                    Some(v) => *v += 1,
                                    None => { storage.materials.insert(material, 1); }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
pub fn find_storage(
    player: Entity,
    mineable_query: &Query<(Entity, &mut Attach, Option<&IsMining>, Option<&mut VarietyMaterialStorage>)>,
) -> Option<Entity> {
    for (entity, attach, _, storage) in mineable_query.iter() {
        if let Some(storage) = storage {
            if attach.associated_player == Some(player) {
                // found a valid storage
                if storage.materials.values().sum::<u32>() > storage.capacity {
                    // cannot store more materials in a filled storage
                    continue;
                }
                return Some(entity);
            } else if attach.associated_player == None {
                // this is a player
                if storage.materials.values().sum::<u32>() > storage.capacity {
                    // cannot store more materials in a filled storage
                    continue;
                }
                return Some(entity);
            }
        }

    }
    return None;
}

M crates/server/src/crafting/mod.rs => crates/server/src/crafting/mod.rs +1 -0
@@ 1,1 1,2 @@
pub mod components;
pub mod mining;

M crates/server/src/main.rs => crates/server/src/main.rs +1 -0
@@ 164,6 164,7 @@ fn main() {
                player::packet::on_position_change,
                module::save::save_eligibility,
                module::convert_modules,
                crafting::mining::mine_materials,
            ),
        )
        .add_systems(

M crates/server/src/player/client_login.rs => crates/server/src/player/client_login.rs +8 -7
@@ 1,4 1,4 @@
use std::net::SocketAddr;
use std::{collections::HashMap, net::SocketAddr};

use bevy::{math::vec2, prelude::*};
use bevy_rapier2d::prelude::*;


@@ 9,14 9,10 @@ use sha2::Sha256;
use starkingdoms_common::{packet::{MessageType, Packet, Part, Planet, ProtoPartFlags}, proto_part_flags, proto_transform, unpack_savefile, PartType as c_PartType, PlanetType as c_PlanetType};

use crate::{
    config::StkConfig,
    module::{
    config::StkConfig, crafting::components::{IsMining, VarietyMaterialStorage}, module::{
        component::{Attach, CanAttach, LooseAttach, PartBundle, PartFlags, PartType},
        save::load_savefile,
    },
    planet::PlanetType,
    ws::{PacketMessageConvert, WsEvent},
    AppKeys, UserToken, CLIENT_SCALE,
    }, planet::PlanetType, ws::{PacketMessageConvert, WsEvent}, AppKeys, UserToken, CLIENT_SCALE
};

use super::component::{Input, Player};


@@ 96,6 92,11 @@ pub fn spawn_player(
        ..default()
    });
    entity_id
        .insert(VarietyMaterialStorage {
            materials: HashMap::new(),
            capacity: 200,
        })
        .insert(IsMining(false))
        .insert(Collider::cuboid(0.5, 0.5))
        .insert(AdditionalMassProperties::MassProperties(MassProperties {
            local_center_of_mass: vec2(0.0, 0.0),

M crates/server/src/player/mod.rs => crates/server/src/player/mod.rs +8 -11
@@ 8,17 8,10 @@ use send_message::send_message;
use starkingdoms_common::{packet::Packet, PartType as c_PartType};

use crate::{
    config::StkConfig,
    err_or_cont,
    mathutil::rot2d,
    module::{
    config::StkConfig, crafting::components::IsMining, err_or_cont, mathutil::rot2d, module::{
        component::{Attach, CanAttach, LooseAttach, PartFlags, PartType},
        PART_HALF_SIZE,
    },
    part,
    planet::PlanetType,
    ws::{PacketMessageConvert, WsEvent},
    AppKeys, CLIENT_SCALE,
    }, part, planet::PlanetType, ws::{PacketMessageConvert, WsEvent}, AppKeys, CLIENT_SCALE
};

pub mod client_login;


@@ 66,6 59,7 @@ pub fn on_message(
        ),
        Without<PlanetType>,
    >,
    mut mining_query: Query<&mut IsMining>,
    mut packet_recv: Local<ManualEventReader<WsEvent>>,
    mut packet_event_send: ResMut<Events<WsEvent>>,
    app_keys: Res<AppKeys>,


@@ 160,11 154,11 @@ pub fn on_message(
                    x,
                    y,
                    released,
                    button: _,
                    button,
                } => {
                    let x = x / CLIENT_SCALE;
                    let y = y / CLIENT_SCALE;
                    for (entity, mut q_player, _transform, _velocity, _attach, _) in
                    for (entity, mut q_player, transform, _velocity, _attach, _) in
                        &mut player_query
                    {
                        if q_player.addr == *from {


@@ 192,9 186,12 @@ pub fn on_message(
                            mouse_picking(
                                &attached_query,
                                &part_query,
                                (entity, transform),
                                &mut mining_query,
                                &mut q_player,
                                x,
                                y,
                                &button,
                                entity,
                            );
                        }

M crates/server/src/player/player_mouse_input.rs => crates/server/src/player/player_mouse_input.rs +24 -3
@@ 2,10 2,9 @@ use bevy::{math::vec3, prelude::*};
use bevy_rapier2d::prelude::*;

use crate::{
    module::component::{Attach, CanAttach, LooseAttach, PartFlags, PartType},
    planet::PlanetType,
    crafting::components::IsMining, module::component::{Attach, CanAttach, LooseAttach, PartFlags, PartType}, planet::PlanetType
};
use starkingdoms_common::PartType as c_PartType;
use starkingdoms_common::{packet::ButtonType, PartType as c_PartType};

use super::component::Player;



@@ 120,9 119,12 @@ pub fn mouse_picking(
        ),
        (Without<PlanetType>, Without<Player>, Without<Attach>),
    >,
    player: (Entity, &Transform),
    mining_query: &mut Query<&mut IsMining>,
    q_player: &mut Player,
    x: f32,
    y: f32,
    button: &ButtonType,
    entity: Entity,
) {
    for (m_entity, part_type, transform, m_attach, _velocity, _, _, _) in attached_query.iter() {


@@ 170,4 172,23 @@ pub fn mouse_picking(
            break;
        }
    }
    {
        let transform = player.1;
        let pos = transform.translation;
        let rel_x = pos.x - x;
        let rel_y = pos.y - y;
        let angle = -transform.rotation.z;
        let x = rel_x * angle.cos() - rel_y * angle.sin();
        let y = rel_x * angle.sin() + rel_y * angle.cos();
        let bound = [-0.5, 0.5, -0.5, 0.5]; // left, right, top, bottom

        if bound[0] < x && x < bound[1] && bound[2] < y && y < bound[3] {
            if *button == ButtonType::Right {
                // toggle mining
                if let Ok(mut is_mining) = mining_query.get_mut(entity) {
                    is_mining.0 = !is_mining.0;
                }
            }
        }
    }
}