Added apple and mushroom collection

This commit is contained in:
Joshua Barretto 2019-09-25 15:56:57 +01:00
parent b0a1619698
commit a961a267f1
7 changed files with 96 additions and 12 deletions

View File

@ -1,3 +1,4 @@
use crate::terrain::{Block, BlockKind};
use specs::{Component, FlaggedStorage};
use specs_idvs::IDVStorage;
@ -70,6 +71,23 @@ impl Armor {
}
}
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum Consumable {
Apple,
Potion,
Mushroom,
}
impl Consumable {
pub fn name(&self) -> &'static str {
match self {
Consumable::Apple => "apple",
Consumable::Potion => "potion",
Consumable::Mushroom => "mushroom",
}
}
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum ConsumptionEffect {
Health(i32),
@ -93,6 +111,7 @@ pub enum Item {
health_bonus: i32,
},
Consumable {
kind: Consumable,
effect: ConsumptionEffect,
},
Ingredient,
@ -123,6 +142,30 @@ impl Item {
pub fn description(&self) -> String {
format!("{} ({})", self.name(), self.category())
}
pub fn try_reclaim_from_block(block: Block) -> Option<Self> {
match block.kind() {
BlockKind::Apple => Some(Self::apple()),
BlockKind::Mushroom => Some(Self::mushroom()),
_ => None,
}
}
// General item constructors
pub fn apple() -> Self {
Item::Consumable {
kind: Consumable::Apple,
effect: ConsumptionEffect::Health(3),
}
}
pub fn mushroom() -> Self {
Item::Consumable {
kind: Consumable::Mushroom,
effect: ConsumptionEffect::Health(1),
}
}
}
impl Default for Item {

View File

@ -5,7 +5,6 @@ pub mod item;
pub use self::item::{Debug, Item, Tool};
use specs::{Component, HashMapStorage, NullStorage};
//use specs_idvs::IDVStorage;
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct Inventory {

View File

@ -55,6 +55,15 @@ impl BlockChange {
self.blocks.insert(pos, block);
}
pub fn try_set(&mut self, pos: Vec3<i32>, block: Block) -> Option<()> {
if !self.blocks.contains_key(&pos) {
self.blocks.insert(pos, block);
Some(())
} else {
None
}
}
pub fn clear(&mut self) {
self.blocks.clear();
}
@ -234,11 +243,16 @@ impl State {
self.ecs.write_resource()
}
/// Get a writable reference to this state's terrain.
/// Set a block in this state's terrain.
pub fn set_block(&mut self, pos: Vec3<i32>, block: Block) {
self.ecs.write_resource::<BlockChange>().set(pos, block);
}
/// Set a block in this state's terrain. Will return `None` if the block has already been modified this tick.
pub fn try_set_block(&mut self, pos: Vec3<i32>, block: Block) -> Option<()> {
self.ecs.write_resource::<BlockChange>().try_set(pos, block)
}
/// Removes every chunk of the terrain.
pub fn clear_terrain(&mut self) {
let keys = self

View File

@ -32,6 +32,13 @@ pub enum BlockKind {
}
impl BlockKind {
pub fn is_tangeable(&self) -> bool {
match self {
BlockKind::Air => false,
kind => !kind.is_fluid(),
}
}
pub fn is_air(&self) -> bool {
match self {
BlockKind::Air => true,

View File

@ -765,7 +765,6 @@ impl Server {
let mut new_chat_msgs = Vec::new();
let mut disconnected_clients = Vec::new();
let mut requested_chunks = Vec::new();
let mut modified_blocks = Vec::new();
let mut dropped_items = Vec::new();
self.clients.remove_if(|entity, client| {
@ -1003,7 +1002,13 @@ impl Server {
.get(entity)
.is_some()
{
modified_blocks.push((pos, Block::empty()));
let block = state.terrain().get(pos).ok().copied();
if state.try_set_block(pos, Block::empty()).is_some() {
block
.and_then(|block| comp::Item::try_reclaim_from_block(block))
.map(|item| state.give_item(entity, item));
}
}
}
ClientMsg::PlaceBlock(pos, block) => {
@ -1013,7 +1018,7 @@ impl Server {
.get(entity)
.is_some()
{
modified_blocks.push((pos, block));
state.try_set_block(pos, block);
}
}
ClientMsg::TerrainChunkRequest { key } => match client.client_state {
@ -1117,10 +1122,6 @@ impl Server {
self.generate_chunk(entity, key);
}
for (pos, block) in modified_blocks {
self.state.set_block(pos, block);
}
for (pos, ori, item) in dropped_items {
let vel = ori.0.normalized() * 5.0
+ Vec3::unit_z() * 10.0
@ -1384,3 +1385,17 @@ impl Drop for Server {
self.clients.notify_registered(ServerMsg::Shutdown);
}
}
trait StateExt {
fn give_item(&mut self, entity: EcsEntity, item: comp::Item);
}
impl StateExt for State {
fn give_item(&mut self, entity: EcsEntity, item: comp::Item) {
self.ecs()
.write_storage::<comp::Inventory>()
.get_mut(entity)
.map(|inv| inv.push(item));
self.write_component(entity, comp::InventoryUpdate);
}
}

View File

@ -144,7 +144,10 @@ impl PlayState for SessionState {
{
let (d, b) = {
let terrain = client.state().terrain();
let ray = terrain.ray(cam_pos, cam_pos + cam_dir * 100.0).cast();
let ray = terrain
.ray(cam_pos, cam_pos + cam_dir * 100.0)
.until(|block| !block.is_air())
.cast();
(ray.0, if let Ok(Some(_)) = ray.1 { true } else { false })
};
@ -169,7 +172,10 @@ impl PlayState for SessionState {
{
let (d, b) = {
let terrain = client.state().terrain();
let ray = terrain.ray(cam_pos, cam_pos + cam_dir * 100.0).cast();
let ray = terrain
.ray(cam_pos, cam_pos + cam_dir * 100.0)
.until(|block| block.is_tangeable())
.cast();
(ray.0, if let Ok(Some(_)) = ray.1 { true } else { false })
};

View File

@ -437,7 +437,7 @@ impl<'a> ZCache<'a> {
}
});
let ground_max = (self.sample.alt + 2.0 + warp + rocks).max(cliff);
let ground_max = (self.sample.alt + 3.0 + warp + rocks).max(cliff);
let min = min + structure_min;
let max = (ground_max + structure_max)