Add Flint and Steel
This commit is contained in:
parent
3e2ee98a93
commit
c32b74f584
96
pumpkin/src/block/blocks/fire/fire.rs
Normal file
96
pumpkin/src/block/blocks/fire/fire.rs
Normal file
@ -0,0 +1,96 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use pumpkin_world::chunk::TickPriority;
|
||||
use rand::Rng;
|
||||
|
||||
use crate::block::pumpkin_block::PumpkinBlock;
|
||||
use crate::entity::player::Player;
|
||||
use crate::server::Server;
|
||||
use crate::world::World;
|
||||
use async_trait::async_trait;
|
||||
use pumpkin_data::{Block, BlockState};
|
||||
use pumpkin_macros::pumpkin_block;
|
||||
use pumpkin_util::math::position::BlockPos;
|
||||
use pumpkin_world::BlockStateId;
|
||||
use pumpkin_world::block::BlockDirection;
|
||||
|
||||
use super::FireBlockBase;
|
||||
|
||||
#[pumpkin_block("minecraft:fire")]
|
||||
pub struct FireBlock;
|
||||
|
||||
impl FireBlock {
|
||||
pub fn get_fire_tick_delay() -> i32 {
|
||||
30 + rand::thread_rng().gen_range(0..10)
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl PumpkinBlock for FireBlock {
|
||||
async fn placed(
|
||||
&self,
|
||||
world: &Arc<World>,
|
||||
block: &Block,
|
||||
state_id: BlockStateId,
|
||||
pos: &BlockPos,
|
||||
old_state_id: BlockStateId,
|
||||
notify: bool,
|
||||
) {
|
||||
FireBlockBase::placed(
|
||||
&FireBlockBase,
|
||||
world,
|
||||
block,
|
||||
state_id,
|
||||
pos,
|
||||
old_state_id,
|
||||
notify,
|
||||
)
|
||||
.await;
|
||||
world
|
||||
.schedule_block_tick(
|
||||
block,
|
||||
*pos,
|
||||
Self::get_fire_tick_delay() as u16,
|
||||
TickPriority::Normal,
|
||||
)
|
||||
.await;
|
||||
}
|
||||
|
||||
async fn get_state_for_neighbor_update(
|
||||
&self,
|
||||
world: &World,
|
||||
_block: &Block,
|
||||
state: BlockStateId,
|
||||
block_pos: &BlockPos,
|
||||
direction: BlockDirection,
|
||||
_neighbor_pos: &BlockPos,
|
||||
_neighbor_state: BlockStateId,
|
||||
) -> BlockStateId {
|
||||
// TODO: add can_place_at
|
||||
if self.can_place_at(world, block_pos, direction).await {
|
||||
return state;
|
||||
}
|
||||
Block::AIR.default_state_id
|
||||
}
|
||||
|
||||
async fn broken(
|
||||
&self,
|
||||
block: &Block,
|
||||
player: &Player,
|
||||
position: BlockPos,
|
||||
server: &Server,
|
||||
world: Arc<World>,
|
||||
state: BlockState,
|
||||
) {
|
||||
FireBlockBase::broken(
|
||||
&FireBlockBase,
|
||||
block,
|
||||
player,
|
||||
position,
|
||||
server,
|
||||
world,
|
||||
state,
|
||||
)
|
||||
.await;
|
||||
}
|
||||
}
|
||||
80
pumpkin/src/block/blocks/fire/mod.rs
Normal file
80
pumpkin/src/block/blocks/fire/mod.rs
Normal file
@ -0,0 +1,80 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use crate::block::pumpkin_block::PumpkinBlock;
|
||||
use crate::entity::player::Player;
|
||||
use crate::server::Server;
|
||||
use crate::world::World;
|
||||
use async_trait::async_trait;
|
||||
use pumpkin_data::world::WorldEvent;
|
||||
use pumpkin_data::{Block, BlockState};
|
||||
use pumpkin_util::math::position::BlockPos;
|
||||
use pumpkin_world::BlockStateId;
|
||||
use pumpkin_world::block::BlockDirection;
|
||||
use soul_fire::SoulFireBlock;
|
||||
|
||||
#[expect(clippy::module_inception)]
|
||||
pub mod fire;
|
||||
pub mod soul_fire;
|
||||
|
||||
pub struct FireBlockBase;
|
||||
|
||||
impl FireBlockBase {
|
||||
pub async fn get_state(world: &World, pos: &BlockPos) -> Block {
|
||||
let (block, _block_state) = world.get_block_and_block_state(&pos.down()).await.unwrap();
|
||||
if SoulFireBlock::is_soul_base(&block) {
|
||||
return Block::SOUL_FIRE;
|
||||
}
|
||||
// TODO
|
||||
Block::FIRE
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl PumpkinBlock for FireBlockBase {
|
||||
async fn placed(
|
||||
&self,
|
||||
_world: &Arc<World>,
|
||||
_block: &Block,
|
||||
state_id: BlockStateId,
|
||||
_pos: &BlockPos,
|
||||
old_state_id: BlockStateId,
|
||||
_notify: bool,
|
||||
) {
|
||||
if old_state_id == state_id {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
async fn can_place_at(
|
||||
&self,
|
||||
world: &World,
|
||||
block_pos: &BlockPos,
|
||||
face: BlockDirection,
|
||||
) -> bool {
|
||||
let block_state = world.get_block_state(block_pos).await.unwrap();
|
||||
|
||||
if !block_state.is_air() {
|
||||
return false;
|
||||
}
|
||||
let block = Self::get_state(world, block_pos).await;
|
||||
|
||||
if let Some(block) = world.block_registry.get_pumpkin_block(&block) {
|
||||
return block.can_place_at(world, block_pos, face).await;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
async fn broken(
|
||||
&self,
|
||||
_block: &Block,
|
||||
_player: &Player,
|
||||
position: BlockPos,
|
||||
_server: &Server,
|
||||
world: Arc<World>,
|
||||
_state: BlockState,
|
||||
) {
|
||||
world
|
||||
.sync_world_event(WorldEvent::FireExtinguished, position, 0)
|
||||
.await;
|
||||
}
|
||||
}
|
||||
97
pumpkin/src/block/blocks/fire/soul_fire.rs
Normal file
97
pumpkin/src/block/blocks/fire/soul_fire.rs
Normal file
@ -0,0 +1,97 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use pumpkin_data::tag::Tagable;
|
||||
|
||||
use crate::block::pumpkin_block::PumpkinBlock;
|
||||
use crate::entity::player::Player;
|
||||
use crate::server::Server;
|
||||
use crate::world::World;
|
||||
use async_trait::async_trait;
|
||||
use pumpkin_data::{Block, BlockState};
|
||||
use pumpkin_macros::pumpkin_block;
|
||||
use pumpkin_util::math::position::BlockPos;
|
||||
use pumpkin_world::BlockStateId;
|
||||
use pumpkin_world::block::BlockDirection;
|
||||
|
||||
use super::FireBlockBase;
|
||||
|
||||
#[pumpkin_block("minecraft:soul_fire")]
|
||||
pub struct SoulFireBlock;
|
||||
|
||||
impl SoulFireBlock {
|
||||
pub fn is_soul_base(block: &Block) -> bool {
|
||||
block
|
||||
.is_tagged_with("minecraft:soul_fire_base_blocks")
|
||||
.unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl PumpkinBlock for SoulFireBlock {
|
||||
async fn placed(
|
||||
&self,
|
||||
world: &Arc<World>,
|
||||
block: &Block,
|
||||
state_id: BlockStateId,
|
||||
pos: &BlockPos,
|
||||
old_state_id: BlockStateId,
|
||||
notify: bool,
|
||||
) {
|
||||
FireBlockBase::placed(
|
||||
&FireBlockBase,
|
||||
world,
|
||||
block,
|
||||
state_id,
|
||||
pos,
|
||||
old_state_id,
|
||||
notify,
|
||||
)
|
||||
.await;
|
||||
}
|
||||
|
||||
async fn get_state_for_neighbor_update(
|
||||
&self,
|
||||
world: &World,
|
||||
_block: &Block,
|
||||
state: BlockStateId,
|
||||
block_pos: &BlockPos,
|
||||
direction: BlockDirection,
|
||||
_neighbor_pos: &BlockPos,
|
||||
_neighbor_state: BlockStateId,
|
||||
) -> BlockStateId {
|
||||
if self.can_place_at(world, block_pos, direction).await {
|
||||
return state;
|
||||
}
|
||||
Block::AIR.default_state_id
|
||||
}
|
||||
|
||||
async fn can_place_at(
|
||||
&self,
|
||||
world: &World,
|
||||
block_pos: &BlockPos,
|
||||
_face: BlockDirection,
|
||||
) -> bool {
|
||||
Self::is_soul_base(&world.get_block(&block_pos.down()).await.unwrap())
|
||||
}
|
||||
|
||||
async fn broken(
|
||||
&self,
|
||||
block: &Block,
|
||||
player: &Player,
|
||||
position: BlockPos,
|
||||
server: &Server,
|
||||
world: Arc<World>,
|
||||
state: BlockState,
|
||||
) {
|
||||
FireBlockBase::broken(
|
||||
&FireBlockBase,
|
||||
block,
|
||||
player,
|
||||
position,
|
||||
server,
|
||||
world,
|
||||
state,
|
||||
)
|
||||
.await;
|
||||
}
|
||||
}
|
||||
@ -7,6 +7,7 @@ use crate::server::Server;
|
||||
use crate::world::{BlockFlags, World};
|
||||
use async_trait::async_trait;
|
||||
use pumpkin_data::item::Item;
|
||||
use pumpkin_data::world::WorldEvent;
|
||||
use pumpkin_data::{
|
||||
Block, BlockState,
|
||||
block_properties::{BlockProperties, JukeboxLikeProperties},
|
||||
@ -41,9 +42,11 @@ impl JukeboxBlock {
|
||||
.await;
|
||||
}
|
||||
|
||||
async fn stop_music(&self, block: &Block, location: BlockPos, world: &Arc<World>) {
|
||||
self.set_record(false, block, location, world).await;
|
||||
world.stop_record(location).await;
|
||||
async fn stop_music(&self, block: &Block, position: BlockPos, world: &Arc<World>) {
|
||||
self.set_record(false, block, position, world).await;
|
||||
world
|
||||
.sync_world_event(WorldEvent::JukeboxStopsPlaying, position, 0)
|
||||
.await;
|
||||
}
|
||||
}
|
||||
|
||||
@ -95,7 +98,13 @@ impl PumpkinBlock for JukeboxBlock {
|
||||
//TODO: Update block nbt
|
||||
|
||||
self.set_record(true, block, location, world).await;
|
||||
world.play_record(jukebox_song as i32, location).await;
|
||||
world
|
||||
.sync_world_event(
|
||||
WorldEvent::JukeboxStartsPlaying,
|
||||
location,
|
||||
jukebox_song as i32,
|
||||
)
|
||||
.await;
|
||||
|
||||
BlockActionResult::Consume
|
||||
}
|
||||
@ -104,12 +113,14 @@ impl PumpkinBlock for JukeboxBlock {
|
||||
&self,
|
||||
_block: &Block,
|
||||
_player: &Player,
|
||||
location: BlockPos,
|
||||
position: BlockPos,
|
||||
_server: &Server,
|
||||
world: Arc<World>,
|
||||
_state: BlockState,
|
||||
) {
|
||||
// For now just stop the music at this position
|
||||
world.stop_record(location).await;
|
||||
world
|
||||
.sync_world_event(WorldEvent::JukeboxStopsPlaying, position, 0)
|
||||
.await;
|
||||
}
|
||||
}
|
||||
|
||||
@ -13,6 +13,7 @@ pub mod doors;
|
||||
pub mod farmland;
|
||||
pub mod fence_gates;
|
||||
pub mod fences;
|
||||
pub mod fire;
|
||||
pub mod furnace;
|
||||
pub mod glass_panes;
|
||||
pub mod iron_bars;
|
||||
|
||||
@ -4,6 +4,8 @@ use blocks::doors::DoorBlock;
|
||||
use blocks::farmland::FarmLandBlock;
|
||||
use blocks::fence_gates::FenceGateBlock;
|
||||
use blocks::fences::FenceBlock;
|
||||
use blocks::fire::fire::FireBlock;
|
||||
use blocks::fire::soul_fire::SoulFireBlock;
|
||||
use blocks::glass_panes::GlassPaneBlock;
|
||||
use blocks::iron_bars::IronBarsBlock;
|
||||
use blocks::logs::LogBlock;
|
||||
@ -52,7 +54,7 @@ use crate::{block::blocks::crafting_table::CraftingTableBlock, entity::player::P
|
||||
use crate::{block::blocks::jukebox::JukeboxBlock, entity::experience_orb::ExperienceOrbEntity};
|
||||
use std::sync::Arc;
|
||||
|
||||
mod blocks;
|
||||
pub(crate) mod blocks;
|
||||
mod fluids;
|
||||
pub mod pumpkin_block;
|
||||
pub mod pumpkin_fluid;
|
||||
@ -84,6 +86,10 @@ pub fn default_registry() -> Arc<BlockRegistry> {
|
||||
manager.register(TorchBlock);
|
||||
manager.register(WallBlock);
|
||||
|
||||
// Fire
|
||||
manager.register(SoulFireBlock);
|
||||
manager.register(FireBlock);
|
||||
|
||||
// Redstone
|
||||
manager.register(ButtonBlock);
|
||||
manager.register(LeverBlock);
|
||||
|
||||
54
pumpkin/src/item/items/flint_and_steel.rs
Normal file
54
pumpkin/src/item/items/flint_and_steel.rs
Normal file
@ -0,0 +1,54 @@
|
||||
use crate::block::blocks::fire::FireBlockBase;
|
||||
use crate::block::pumpkin_block::PumpkinBlock;
|
||||
use crate::entity::player::Player;
|
||||
use crate::item::pumpkin_item::{ItemMetadata, PumpkinItem};
|
||||
use crate::server::Server;
|
||||
use crate::world::BlockFlags;
|
||||
use async_trait::async_trait;
|
||||
use pumpkin_data::Block;
|
||||
use pumpkin_data::item::Item;
|
||||
use pumpkin_util::math::position::BlockPos;
|
||||
use pumpkin_world::block::{BlockDirection, HorizontalFacingExt};
|
||||
|
||||
pub struct FlintAndSteelItem;
|
||||
|
||||
impl ItemMetadata for FlintAndSteelItem {
|
||||
fn ids() -> Box<[u16]> {
|
||||
[Item::FLINT_AND_STEEL.id].into()
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl PumpkinItem for FlintAndSteelItem {
|
||||
async fn use_on_block(
|
||||
&self,
|
||||
_item: &Item,
|
||||
player: &Player,
|
||||
location: BlockPos,
|
||||
face: BlockDirection,
|
||||
_block: &Block,
|
||||
_server: &Server,
|
||||
) {
|
||||
// TODO: check CampfireBlock, CandleBlock and CandleCakeBlock
|
||||
let world = player.world().await;
|
||||
let pos = location.offset(face.to_offset());
|
||||
if FireBlockBase::can_place_at(
|
||||
&FireBlockBase,
|
||||
&world,
|
||||
&pos,
|
||||
player
|
||||
.living_entity
|
||||
.entity
|
||||
.get_horizontal_facing()
|
||||
.to_block_direction(),
|
||||
)
|
||||
.await
|
||||
{
|
||||
let state = FireBlockBase::get_state(&world, &pos).await;
|
||||
world
|
||||
.set_block_state(&pos, state.default_state_id, BlockFlags::NOTIFY_ALL)
|
||||
.await;
|
||||
// TODO
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,5 +1,6 @@
|
||||
mod axe;
|
||||
mod egg;
|
||||
mod flint_and_steel;
|
||||
mod hoe;
|
||||
mod honeycomb;
|
||||
mod shovel;
|
||||
@ -9,6 +10,7 @@ mod trident;
|
||||
|
||||
use axe::AxeItem;
|
||||
use egg::EggItem;
|
||||
use flint_and_steel::FlintAndSteelItem;
|
||||
use hoe::HoeItem;
|
||||
use honeycomb::HoneyCombItem;
|
||||
use shovel::ShovelItem;
|
||||
@ -25,6 +27,7 @@ pub fn default_registry() -> Arc<ItemRegistry> {
|
||||
manager.register(SnowBallItem);
|
||||
manager.register(HoeItem);
|
||||
manager.register(EggItem);
|
||||
manager.register(FlintAndSteelItem);
|
||||
manager.register(SwordItem);
|
||||
manager.register(TridentItem);
|
||||
manager.register(ShovelItem);
|
||||
|
||||
@ -44,6 +44,7 @@ use pumpkin_nbt::to_bytes_unnamed;
|
||||
use pumpkin_protocol::client::play::{
|
||||
CRemoveMobEffect, CSetEntityMetadata, MetaDataType, Metadata,
|
||||
};
|
||||
use pumpkin_protocol::codec::identifier::Identifier;
|
||||
use pumpkin_protocol::ser::serializer::Serializer;
|
||||
use pumpkin_protocol::{
|
||||
ClientPacket, IdOr, SoundEvent,
|
||||
@ -54,7 +55,6 @@ use pumpkin_protocol::{
|
||||
},
|
||||
server::play::SChatMessage,
|
||||
};
|
||||
use pumpkin_protocol::{client::play::CLevelEvent, codec::identifier::Identifier};
|
||||
use pumpkin_protocol::{
|
||||
client::play::{
|
||||
CBlockUpdate, CDisguisedChatMessage, CExplosion, CRespawn, CSetBlockDestroyStage,
|
||||
@ -361,26 +361,6 @@ impl World {
|
||||
self.play_sound(sound, category, &new_vec).await;
|
||||
}
|
||||
|
||||
pub async fn play_record(&self, record_id: i32, position: BlockPos) {
|
||||
self.broadcast_packet_all(&CLevelEvent::new(
|
||||
WorldEvent::JukeboxStartsPlaying as i32,
|
||||
position,
|
||||
record_id,
|
||||
false,
|
||||
))
|
||||
.await;
|
||||
}
|
||||
|
||||
pub async fn stop_record(&self, position: BlockPos) {
|
||||
self.broadcast_packet_all(&CLevelEvent::new(
|
||||
WorldEvent::JukeboxStopsPlaying as i32,
|
||||
position,
|
||||
0,
|
||||
false,
|
||||
))
|
||||
.await;
|
||||
}
|
||||
|
||||
pub async fn tick(self: &Arc<Self>, server: &Server) {
|
||||
self.flush_block_updates().await;
|
||||
|
||||
@ -1536,6 +1516,11 @@ impl World {
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn sync_world_event(&self, world_event: WorldEvent, position: BlockPos, data: i32) {
|
||||
self.broadcast_packet_all(&CWorldEvent::new(world_event as i32, position, data, false))
|
||||
.await;
|
||||
}
|
||||
|
||||
pub async fn get_chunk(&self, position: &BlockPos) -> Arc<RwLock<ChunkData>> {
|
||||
let (chunk_coordinate, _) = position.chunk_and_chunk_relative_position();
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user