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;
+ }
+ }
+ }
+ }
}