feat: building wither
This commit is contained in:
parent
59c82aa30e
commit
20a14d730b
10
README.md
10
README.md
@ -13,7 +13,7 @@
|
|||||||
and customizable experience. It prioritizes performance and player enjoyment while adhering to the core mechanics of the game.
|
and customizable experience. It prioritizes performance and player enjoyment while adhering to the core mechanics of the game.
|
||||||
<div align="center">
|
<div align="center">
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -35,12 +35,6 @@ and customizable experience. It prioritizes performance and player enjoyment whi
|
|||||||
- Networking
|
- Networking
|
||||||
- [x] Encryption
|
- [x] Encryption
|
||||||
- [x] Packet Compression
|
- [x] Packet Compression
|
||||||
- Player Configuration
|
|
||||||
- [x] Registries (biome types, paintings, dimensions)
|
|
||||||
- [x] Server Brand
|
|
||||||
- [x] Server Links
|
|
||||||
- [x] Set Resource Pack
|
|
||||||
- [x] Cookies
|
|
||||||
- World
|
- World
|
||||||
- [x] World Joining
|
- [x] World Joining
|
||||||
- [x] Player Tab-list
|
- [x] Player Tab-list
|
||||||
@ -53,7 +47,6 @@ and customizable experience. It prioritizes performance and player enjoyment whi
|
|||||||
- [x] Entity Spawning
|
- [x] Entity Spawning
|
||||||
- [x] Item drops (W.I.P)
|
- [x] Item drops (W.I.P)
|
||||||
- [x] Bossbar
|
- [x] Bossbar
|
||||||
- [x] TNT
|
|
||||||
- [x] Chunk Loading (Vanilla, Linear)
|
- [x] Chunk Loading (Vanilla, Linear)
|
||||||
- [x] Chunk Generation
|
- [x] Chunk Generation
|
||||||
- [x] Chunk Saving (Vanilla, Linear)
|
- [x] Chunk Saving (Vanilla, Linear)
|
||||||
@ -64,7 +57,6 @@ and customizable experience. It prioritizes performance and player enjoyment whi
|
|||||||
- [ ] Structure Generation
|
- [ ] Structure Generation
|
||||||
- Player
|
- Player
|
||||||
- [x] Skins
|
- [x] Skins
|
||||||
- [x] Client brand
|
|
||||||
- [x] Teleport
|
- [x] Teleport
|
||||||
- [x] Movement
|
- [x] Movement
|
||||||
- [x] Animation
|
- [x] Animation
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 25 MiB After Width: | Height: | Size: 23 MiB |
@ -299,9 +299,11 @@ impl ChunkEntityData {
|
|||||||
| (uuid[3] as u128),
|
| (uuid[3] as u128),
|
||||||
),
|
),
|
||||||
None => {
|
None => {
|
||||||
println!(
|
log::debug!(
|
||||||
"Entity in chunk {},{} is missing UUID: {:?}",
|
"Entity in chunk {},{} is missing UUID: {:?}",
|
||||||
position.x, position.y, entity_nbt
|
position.x,
|
||||||
|
position.y,
|
||||||
|
entity_nbt
|
||||||
);
|
);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -8,7 +8,6 @@ pub mod candle_cakes;
|
|||||||
pub mod candles;
|
pub mod candles;
|
||||||
pub mod carpet;
|
pub mod carpet;
|
||||||
pub mod carved_pumpkin;
|
pub mod carved_pumpkin;
|
||||||
pub mod wither_skull;
|
|
||||||
pub mod chain;
|
pub mod chain;
|
||||||
pub mod chests;
|
pub mod chests;
|
||||||
pub mod chiseled_bookshelf;
|
pub mod chiseled_bookshelf;
|
||||||
@ -54,6 +53,7 @@ pub mod torches;
|
|||||||
pub mod trapdoor;
|
pub mod trapdoor;
|
||||||
pub mod vine;
|
pub mod vine;
|
||||||
pub mod walls;
|
pub mod walls;
|
||||||
|
pub mod wither_skull;
|
||||||
|
|
||||||
pub mod banners;
|
pub mod banners;
|
||||||
pub mod shulker_box;
|
pub mod shulker_box;
|
||||||
|
|||||||
@ -17,7 +17,6 @@ impl BlockMetadata for SkullBlock {
|
|||||||
fn ids(&self) -> &'static [&'static str] {
|
fn ids(&self) -> &'static [&'static str] {
|
||||||
&[
|
&[
|
||||||
"skeleton_skull",
|
"skeleton_skull",
|
||||||
"wither_skeleton_skull",
|
|
||||||
"player_head",
|
"player_head",
|
||||||
"zombie_head",
|
"zombie_head",
|
||||||
"creeper_head",
|
"creeper_head",
|
||||||
|
|||||||
@ -0,0 +1,103 @@
|
|||||||
|
use pumpkin_data::{Block, BlockDirection, entity::EntityType, world::WorldEvent};
|
||||||
|
use pumpkin_world::{BlockStateId, world::BlockFlags};
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
block::{
|
||||||
|
BlockBehaviour, BlockFuture, BlockMetadata, OnPlaceArgs, PlacedArgs,
|
||||||
|
blocks::skull_block::SkullBlock,
|
||||||
|
},
|
||||||
|
entity::{Entity, boss::wither::WitherEntity},
|
||||||
|
};
|
||||||
|
|
||||||
|
pub struct WitherSkeletonSkullBlock;
|
||||||
|
|
||||||
|
impl BlockMetadata for WitherSkeletonSkullBlock {
|
||||||
|
fn namespace(&self) -> &'static str {
|
||||||
|
"minecraft"
|
||||||
|
}
|
||||||
|
|
||||||
|
fn ids(&self) -> &'static [&'static str] {
|
||||||
|
&[Block::WITHER_SKELETON_SKULL.name]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl BlockBehaviour for WitherSkeletonSkullBlock {
|
||||||
|
fn on_place<'a>(&'a self, args: OnPlaceArgs<'a>) -> BlockFuture<'a, BlockStateId> {
|
||||||
|
SkullBlock::on_place(&SkullBlock, args)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn placed<'a>(&'a self, args: PlacedArgs<'a>) -> BlockFuture<'a, ()> {
|
||||||
|
Box::pin(async move {
|
||||||
|
let world = args.world;
|
||||||
|
let pos = args.position;
|
||||||
|
|
||||||
|
let is_soul_block =
|
||||||
|
|block: &Block| block == &Block::SOUL_SAND || block == &Block::SOUL_SOIL;
|
||||||
|
let is_skull = |block: &Block| block == &Block::WITHER_SKELETON_SKULL;
|
||||||
|
|
||||||
|
for dir in [BlockDirection::North, BlockDirection::West] {
|
||||||
|
let opposite = dir.opposite();
|
||||||
|
for offset in 0..3 {
|
||||||
|
let center_skull_pos = match offset {
|
||||||
|
0 => *pos,
|
||||||
|
1 => pos.offset(opposite.to_offset()),
|
||||||
|
2 => pos.offset(dir.to_offset()),
|
||||||
|
_ => unreachable!(),
|
||||||
|
};
|
||||||
|
|
||||||
|
let top_middle = center_skull_pos.down();
|
||||||
|
let base = top_middle.down();
|
||||||
|
let arm1 = top_middle.offset(dir.to_offset());
|
||||||
|
let arm2 = top_middle.offset(opposite.to_offset());
|
||||||
|
let skull1_pos = arm1.up();
|
||||||
|
let skull2_pos = arm2.up();
|
||||||
|
|
||||||
|
if is_soul_block(world.get_block(&top_middle).await)
|
||||||
|
&& is_soul_block(world.get_block(&base).await)
|
||||||
|
&& is_soul_block(world.get_block(&arm1).await)
|
||||||
|
&& is_soul_block(world.get_block(&arm2).await)
|
||||||
|
&& is_skull(world.get_block(¢er_skull_pos).await)
|
||||||
|
&& is_skull(world.get_block(&skull1_pos).await)
|
||||||
|
&& is_skull(world.get_block(&skull2_pos).await)
|
||||||
|
{
|
||||||
|
let pattern = [
|
||||||
|
center_skull_pos,
|
||||||
|
skull1_pos,
|
||||||
|
skull2_pos,
|
||||||
|
top_middle,
|
||||||
|
arm1,
|
||||||
|
arm2,
|
||||||
|
base,
|
||||||
|
];
|
||||||
|
|
||||||
|
for p in pattern {
|
||||||
|
world
|
||||||
|
.set_block_state(
|
||||||
|
&p,
|
||||||
|
Block::AIR.default_state.id,
|
||||||
|
BlockFlags::NOTIFY_ALL,
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
world
|
||||||
|
.sync_world_event(
|
||||||
|
WorldEvent::BlockBroken,
|
||||||
|
p,
|
||||||
|
Block::SOUL_SAND.default_state.id.into(),
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
}
|
||||||
|
|
||||||
|
let entity = Entity::new(
|
||||||
|
world.clone(),
|
||||||
|
top_middle.to_centered_f64(),
|
||||||
|
&EntityType::WITHER,
|
||||||
|
);
|
||||||
|
let wither = WitherEntity::make(entity).await;
|
||||||
|
world.spawn_entity(wither).await;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -76,6 +76,7 @@ use crate::block::blocks::torches::TorchBlock;
|
|||||||
use crate::block::blocks::trapdoor::TrapDoorBlock;
|
use crate::block::blocks::trapdoor::TrapDoorBlock;
|
||||||
use crate::block::blocks::vine::VineBlock;
|
use crate::block::blocks::vine::VineBlock;
|
||||||
use crate::block::blocks::walls::WallBlock;
|
use crate::block::blocks::walls::WallBlock;
|
||||||
|
use crate::block::blocks::wither_skull::WitherSkeletonSkullBlock;
|
||||||
use crate::block::fluid::lava::FlowingLava;
|
use crate::block::fluid::lava::FlowingLava;
|
||||||
use crate::block::fluid::water::FlowingWater;
|
use crate::block::fluid::water::FlowingWater;
|
||||||
use crate::block::{
|
use crate::block::{
|
||||||
@ -153,6 +154,7 @@ pub fn default_registry() -> Arc<BlockRegistry> {
|
|||||||
manager.register(CactusBlock);
|
manager.register(CactusBlock);
|
||||||
manager.register(CarpetBlock);
|
manager.register(CarpetBlock);
|
||||||
manager.register(CarvedPumpkinBlock);
|
manager.register(CarvedPumpkinBlock);
|
||||||
|
manager.register(WitherSkeletonSkullBlock);
|
||||||
manager.register(CampfireBlock);
|
manager.register(CampfireBlock);
|
||||||
manager.register(MossCarpetBlock);
|
manager.register(MossCarpetBlock);
|
||||||
manager.register(PaleMossCarpetBlock);
|
manager.register(PaleMossCarpetBlock);
|
||||||
|
|||||||
1
pumpkin/src/entity/boss/mod.rs
Normal file
1
pumpkin/src/entity/boss/mod.rs
Normal file
@ -0,0 +1 @@
|
|||||||
|
pub mod wither;
|
||||||
46
pumpkin/src/entity/boss/wither.rs
Normal file
46
pumpkin/src/entity/boss/wither.rs
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
use std::sync::{Arc, Weak};
|
||||||
|
|
||||||
|
use pumpkin_data::entity::EntityType;
|
||||||
|
|
||||||
|
use crate::entity::{
|
||||||
|
Entity, NBTStorage,
|
||||||
|
ai::goal::{look_around::LookAroundGoal, look_at_entity::LookAtEntityGoal},
|
||||||
|
mob::{Mob, MobEntity},
|
||||||
|
};
|
||||||
|
|
||||||
|
pub struct WitherEntity {
|
||||||
|
pub mob_entity: MobEntity,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl WitherEntity {
|
||||||
|
pub async fn make(entity: Entity) -> Arc<Self> {
|
||||||
|
let mob_entity = MobEntity::new(entity);
|
||||||
|
let wither = Self { mob_entity };
|
||||||
|
let mob_arc = Arc::new(wither);
|
||||||
|
let mob_weak: Weak<dyn Mob> = {
|
||||||
|
let mob_arc: Arc<dyn Mob> = mob_arc.clone();
|
||||||
|
Arc::downgrade(&mob_arc)
|
||||||
|
};
|
||||||
|
|
||||||
|
{
|
||||||
|
let mut goal_selector = mob_arc.mob_entity.goals_selector.lock().await;
|
||||||
|
|
||||||
|
// TODO
|
||||||
|
goal_selector.add_goal(
|
||||||
|
8,
|
||||||
|
LookAtEntityGoal::with_default(mob_weak, &EntityType::PLAYER, 8.0),
|
||||||
|
);
|
||||||
|
goal_selector.add_goal(8, Box::new(LookAroundGoal::default()));
|
||||||
|
};
|
||||||
|
|
||||||
|
mob_arc
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl NBTStorage for WitherEntity {}
|
||||||
|
|
||||||
|
impl Mob for WitherEntity {
|
||||||
|
fn get_mob_entity(&self) -> &MobEntity {
|
||||||
|
&self.mob_entity
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -54,6 +54,7 @@ use tokio::sync::Mutex;
|
|||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
pub mod ai;
|
pub mod ai;
|
||||||
|
pub mod boss;
|
||||||
pub mod decoration;
|
pub mod decoration;
|
||||||
pub mod effect;
|
pub mod effect;
|
||||||
pub mod experience_orb;
|
pub mod experience_orb;
|
||||||
|
|||||||
@ -7,6 +7,7 @@ use uuid::Uuid;
|
|||||||
use crate::{
|
use crate::{
|
||||||
entity::{
|
entity::{
|
||||||
Entity, EntityBase,
|
Entity, EntityBase,
|
||||||
|
boss::wither::WitherEntity,
|
||||||
decoration::{
|
decoration::{
|
||||||
armor_stand::ArmorStandEntity, end_crystal::EndCrystalEntity, painting::PaintingEntity,
|
armor_stand::ArmorStandEntity, end_crystal::EndCrystalEntity, painting::PaintingEntity,
|
||||||
},
|
},
|
||||||
@ -35,6 +36,7 @@ pub async fn from_type(
|
|||||||
id if id == EntityType::CREEPER.id => CreeperEntity::make(entity).await,
|
id if id == EntityType::CREEPER.id => CreeperEntity::make(entity).await,
|
||||||
id if id == EntityType::SNOW_GOLEM.id => SnowGolemEntity::make(entity).await,
|
id if id == EntityType::SNOW_GOLEM.id => SnowGolemEntity::make(entity).await,
|
||||||
id if id == EntityType::WOLF.id => WolfEntity::make(entity).await,
|
id if id == EntityType::WOLF.id => WolfEntity::make(entity).await,
|
||||||
|
id if id == EntityType::WITHER.id => WitherEntity::make(entity).await,
|
||||||
id if id == EntityType::ARMOR_STAND.id => Arc::new(ArmorStandEntity::new(entity)),
|
id if id == EntityType::ARMOR_STAND.id => Arc::new(ArmorStandEntity::new(entity)),
|
||||||
id if id == EntityType::PAINTING.id => Arc::new(PaintingEntity::new(entity)),
|
id if id == EntityType::PAINTING.id => Arc::new(PaintingEntity::new(entity)),
|
||||||
id if id == EntityType::END_CRYSTAL.id => Arc::new(EndCrystalEntity::new(entity)),
|
id if id == EntityType::END_CRYSTAL.id => Arc::new(EndCrystalEntity::new(entity)),
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user