Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added basic chest opening and closing #421

Merged
merged 4 commits into from
Dec 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions pumpkin-inventory/src/open_container.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,10 @@ impl OpenContainer {
self.players.clone()
}

pub fn get_number_of_players(&self) -> usize {
self.players.len()
}

pub fn get_location(&self) -> Option<WorldPosition> {
self.location
}
Expand Down
31 changes: 31 additions & 0 deletions pumpkin-protocol/src/client/play/c_block_event.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
use pumpkin_core::math::position::WorldPosition;

use pumpkin_macros::client_packet;
use serde::Serialize;

use crate::VarInt;

#[derive(Serialize)]
#[client_packet("play:block_event")]
pub struct CBlockAction<'a> {
location: &'a WorldPosition,
action_id: u8,
action_parameter: u8,
block_type: VarInt,
}

impl<'a> CBlockAction<'a> {
pub fn new(
location: &'a WorldPosition,
action_id: u8,
action_parameter: u8,
block_type: VarInt,
) -> Self {
Self {
location,
action_id,
action_parameter,
block_type,
}
}
}
2 changes: 2 additions & 0 deletions pumpkin-protocol/src/client/play/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ mod bossevent_action;
mod c_acknowledge_block;
mod c_actionbar;
mod c_block_destroy_stage;
mod c_block_event;
mod c_block_update;
mod c_boss_event;
mod c_center_chunk;
Expand Down Expand Up @@ -72,6 +73,7 @@ pub use bossevent_action::*;
pub use c_acknowledge_block::*;
pub use c_actionbar::*;
pub use c_block_destroy_stage::*;
pub use c_block_event::*;
pub use c_block_update::*;
pub use c_boss_event::*;
pub use c_center_chunk::*;
Expand Down
71 changes: 58 additions & 13 deletions pumpkin/src/block/blocks/chest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,24 @@ use async_trait::async_trait;
use pumpkin_core::math::position::WorldPosition;
use pumpkin_inventory::{Chest, OpenContainer, WindowType};
use pumpkin_macros::{pumpkin_block, sound};
use pumpkin_world::{block::block_registry::Block, item::item_registry::Item};
use pumpkin_protocol::{client::play::CBlockAction, codec::var_int::VarInt};
use pumpkin_world::{
block::block_registry::{get_block, Block},
item::item_registry::Item,
};

use crate::{
block::{block_manager::BlockActionResult, pumpkin_block::PumpkinBlock},
entity::player::Player,
server::Server,
};

#[derive(PartialEq)]
pub enum ChestState {
IsOpened,
IsClosed,
}

#[pumpkin_block("minecraft:chest")]
pub struct ChestBlock;

Expand All @@ -24,10 +34,6 @@ impl PumpkinBlock for ChestBlock {
) {
self.open_chest_block(block, player, _location, server)
.await;
player
.world()
.play_block_sound(sound!("block.chest.open"), _location)
.await;
}

async fn on_use_with_item<'a>(
Expand Down Expand Up @@ -57,15 +63,14 @@ impl PumpkinBlock for ChestBlock {
&self,
_block: &Block,
player: &Player,
_location: WorldPosition,
_server: &Server,
_container: &OpenContainer,
location: WorldPosition,
server: &Server,
container: &mut OpenContainer,
) {
player
.world()
.play_block_sound(sound!("block.chest.close"), _location)
container.remove_player(player.entity_id());

self.play_chest_action(container, player, location, server, ChestState::IsClosed)
.await;
// TODO: send entity updates close
}
}

Expand All @@ -86,6 +91,46 @@ impl ChestBlock {
WindowType::Generic9x3,
)
.await;
// TODO: send entity updates open

if let Some(container_id) = server.get_container_id(location, block.clone()).await {
let open_containers = server.open_containers.read().await;
if let Some(container) = open_containers.get(&u64::from(container_id)) {
self.play_chest_action(container, player, location, server, ChestState::IsOpened)
.await;
}
}
}

pub async fn play_chest_action(
&self,
container: &OpenContainer,
player: &Player,
location: WorldPosition,
server: &Server,
state: ChestState,
) {
let num_players = container.get_number_of_players() as u8;
if state == ChestState::IsClosed && num_players == 0 {
player
.world()
.play_block_sound(sound!("block.chest.close"), location)
.await;
} else if state == ChestState::IsOpened && num_players == 1 {
player
.world()
.play_block_sound(sound!("block.chest.open"), location)
.await;
}

if let Some(e) = get_block("minecraft:chest").cloned() {
server
.broadcast_packet_all(&CBlockAction::new(
&location,
1,
num_players,
VarInt(e.id.into()),
))
.await;
}
}
}
4 changes: 3 additions & 1 deletion pumpkin/src/block/blocks/crafting_table.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ impl PumpkinBlock for CraftingTableBlock {
player: &Player,
_location: WorldPosition,
_server: &Server,
container: &OpenContainer,
container: &mut OpenContainer,
) {
let entity_id = player.entity_id();
for player_id in container.all_player_ids() {
Expand All @@ -62,6 +62,8 @@ impl PumpkinBlock for CraftingTableBlock {
}
}

container.remove_player(entity_id);

// TODO: items should be re-added to player inventory or dropped dependending on if they are in movement.
// TODO: unique containers should be implemented as a separate stack internally (optimizes large player servers for example)
// TODO: ephemeral containers (crafting tables) might need to be separate data structure than stored (ender chest)
Expand Down
2 changes: 1 addition & 1 deletion pumpkin/src/block/pumpkin_block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ pub trait PumpkinBlock: Send + Sync {
_player: &Player,
_location: WorldPosition,
_server: &Server,
_container: &OpenContainer,
_container: &mut OpenContainer,
) {
}
}
Loading