feat: add name tag logic
This commit is contained in:
parent
736f073b3c
commit
c5c3ffc005
File diff suppressed because it is too large
Load Diff
@ -18,6 +18,7 @@ pub struct EntityType {
|
|||||||
pub loot_table: Option<LootTableStruct>,
|
pub loot_table: Option<LootTableStruct>,
|
||||||
pub summonable: bool,
|
pub summonable: bool,
|
||||||
pub fire_immune: bool,
|
pub fire_immune: bool,
|
||||||
|
pub saveable: bool,
|
||||||
pub category: MobCategory,
|
pub category: MobCategory,
|
||||||
pub can_spawn_far_from_player: bool,
|
pub can_spawn_far_from_player: bool,
|
||||||
pub dimension: [f32; 2],
|
pub dimension: [f32; 2],
|
||||||
@ -106,6 +107,7 @@ impl ToTokens for NamedEntityType<'_> {
|
|||||||
MobCategory::MISC => quote! { MobCategory::MISC },
|
MobCategory::MISC => quote! { MobCategory::MISC },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let saveable = entity.saveable;
|
||||||
let summonable = entity.summonable;
|
let summonable = entity.summonable;
|
||||||
let fire_immune = entity.fire_immune;
|
let fire_immune = entity.fire_immune;
|
||||||
let eye_height = entity.eye_height;
|
let eye_height = entity.eye_height;
|
||||||
@ -136,6 +138,7 @@ impl ToTokens for NamedEntityType<'_> {
|
|||||||
max_health: #max_health,
|
max_health: #max_health,
|
||||||
attackable: #attackable,
|
attackable: #attackable,
|
||||||
mob: #mob,
|
mob: #mob,
|
||||||
|
saveable: #saveable,
|
||||||
limit_per_chunk: #limit_per_chunk,
|
limit_per_chunk: #limit_per_chunk,
|
||||||
summonable: #summonable,
|
summonable: #summonable,
|
||||||
fire_immune: #fire_immune,
|
fire_immune: #fire_immune,
|
||||||
@ -192,6 +195,7 @@ pub(crate) fn build() -> TokenStream {
|
|||||||
pub max_health: Option<f32>,
|
pub max_health: Option<f32>,
|
||||||
pub attackable: Option<bool>,
|
pub attackable: Option<bool>,
|
||||||
pub mob: bool,
|
pub mob: bool,
|
||||||
|
pub saveable: bool,
|
||||||
pub limit_per_chunk: i32,
|
pub limit_per_chunk: i32,
|
||||||
pub summonable: bool,
|
pub summonable: bool,
|
||||||
pub fire_immune: bool,
|
pub fire_immune: bool,
|
||||||
|
|||||||
@ -151,7 +151,13 @@ impl DataComponentImpl for DamageImpl {
|
|||||||
#[derive(Clone, Debug, Hash, PartialEq)]
|
#[derive(Clone, Debug, Hash, PartialEq)]
|
||||||
pub struct UnbreakableImpl;
|
pub struct UnbreakableImpl;
|
||||||
#[derive(Clone, Debug, Hash, PartialEq)]
|
#[derive(Clone, Debug, Hash, PartialEq)]
|
||||||
pub struct CustomNameImpl;
|
pub struct CustomNameImpl {
|
||||||
|
// TODO make TextComponent const
|
||||||
|
pub name: &'static str,
|
||||||
|
}
|
||||||
|
impl DataComponentImpl for CustomNameImpl {
|
||||||
|
default_impl!(CustomName);
|
||||||
|
}
|
||||||
#[derive(Clone, Debug, Hash, PartialEq)]
|
#[derive(Clone, Debug, Hash, PartialEq)]
|
||||||
pub struct ItemNameImpl {
|
pub struct ItemNameImpl {
|
||||||
// TODO make TextComponent const
|
// TODO make TextComponent const
|
||||||
|
|||||||
@ -405,6 +405,16 @@ impl Entity {
|
|||||||
self.send_velocity().await;
|
self.send_velocity().await;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Sets a custom name for the entity, typically used with nametags
|
||||||
|
pub async fn set_custon_name(&self, name: TextComponent) {
|
||||||
|
self.send_meta_data(&[Metadata::new(
|
||||||
|
2,
|
||||||
|
MetaDataType::OptionalTextComponent,
|
||||||
|
Some(name),
|
||||||
|
)])
|
||||||
|
.await;
|
||||||
|
}
|
||||||
|
|
||||||
pub async fn send_velocity(&self) {
|
pub async fn send_velocity(&self) {
|
||||||
let velocity = self.velocity.load();
|
let velocity = self.velocity.load();
|
||||||
self.world
|
self.world
|
||||||
|
|||||||
@ -91,4 +91,8 @@ impl EntityBase for ThrownItemEntity {
|
|||||||
fn as_nbt_storage(&self) -> &dyn NBTStorage {
|
fn as_nbt_storage(&self) -> &dyn NBTStorage {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_gravity(&self) -> f64 {
|
||||||
|
0.03
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -85,7 +85,7 @@ impl ItemBehaviour for HoeItem {
|
|||||||
Uuid::new_v4(),
|
Uuid::new_v4(),
|
||||||
world.clone(),
|
world.clone(),
|
||||||
location,
|
location,
|
||||||
&EntityType::SNOWBALL,
|
&EntityType::ITEM,
|
||||||
false,
|
false,
|
||||||
);
|
);
|
||||||
// TODO: Merge stacks together
|
// TODO: Merge stacks together
|
||||||
|
|||||||
@ -11,6 +11,7 @@ pub mod ignite;
|
|||||||
pub mod ink_sac;
|
pub mod ink_sac;
|
||||||
pub mod mace;
|
pub mod mace;
|
||||||
pub mod minecart;
|
pub mod minecart;
|
||||||
|
pub mod name_tag;
|
||||||
pub mod shovel;
|
pub mod shovel;
|
||||||
pub mod snowball;
|
pub mod snowball;
|
||||||
pub mod swords;
|
pub mod swords;
|
||||||
@ -18,6 +19,7 @@ pub mod trident;
|
|||||||
|
|
||||||
use crate::item::items::end_crystal::EndCrystalItem;
|
use crate::item::items::end_crystal::EndCrystalItem;
|
||||||
use crate::item::items::minecart::MinecartItem;
|
use crate::item::items::minecart::MinecartItem;
|
||||||
|
use crate::item::items::name_tag::NameTagItem;
|
||||||
|
|
||||||
use super::registry::ItemRegistry;
|
use super::registry::ItemRegistry;
|
||||||
use axe::AxeItem;
|
use axe::AxeItem;
|
||||||
@ -56,6 +58,7 @@ pub fn default_registry() -> Arc<ItemRegistry> {
|
|||||||
manager.register(EndCrystalItem);
|
manager.register(EndCrystalItem);
|
||||||
manager.register(MinecartItem);
|
manager.register(MinecartItem);
|
||||||
manager.register(HoneyCombItem);
|
manager.register(HoneyCombItem);
|
||||||
|
manager.register(NameTagItem);
|
||||||
manager.register(EnderEyeItem);
|
manager.register(EnderEyeItem);
|
||||||
manager.register(FireChargeItem);
|
manager.register(FireChargeItem);
|
||||||
manager.register(DyeItem);
|
manager.register(DyeItem);
|
||||||
|
|||||||
40
pumpkin/src/item/items/name_tag.rs
Normal file
40
pumpkin/src/item/items/name_tag.rs
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
use crate::entity::EntityBase;
|
||||||
|
use crate::entity::player::Player;
|
||||||
|
use crate::item::{ItemBehaviour, ItemMetadata};
|
||||||
|
use async_trait::async_trait;
|
||||||
|
use pumpkin_data::data_component_impl::CustomNameImpl;
|
||||||
|
use pumpkin_data::item::Item;
|
||||||
|
use pumpkin_util::text::TextComponent;
|
||||||
|
use pumpkin_world::item::ItemStack;
|
||||||
|
|
||||||
|
pub struct NameTagItem;
|
||||||
|
|
||||||
|
impl ItemMetadata for NameTagItem {
|
||||||
|
fn ids() -> Box<[u16]> {
|
||||||
|
[Item::NAME_TAG.id].into()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[async_trait]
|
||||||
|
impl ItemBehaviour for NameTagItem {
|
||||||
|
async fn use_on_entity(
|
||||||
|
&self,
|
||||||
|
item: &mut ItemStack,
|
||||||
|
player: &Player,
|
||||||
|
entity: Arc<dyn EntityBase>,
|
||||||
|
) {
|
||||||
|
let entity = entity.get_entity();
|
||||||
|
if entity.entity_type.saveable
|
||||||
|
&& let Some(name) = item.get_data_component::<CustomNameImpl>()
|
||||||
|
{
|
||||||
|
// TODO
|
||||||
|
entity.set_custon_name(TextComponent::text(name.name)).await;
|
||||||
|
item.decrement_unless_creative(player.gamemode.load(), 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn as_any(&self) -> &dyn std::any::Any {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -2,7 +2,9 @@ pub mod items;
|
|||||||
pub mod registry;
|
pub mod registry;
|
||||||
|
|
||||||
use std::any::Any;
|
use std::any::Any;
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
use crate::entity::EntityBase;
|
||||||
use crate::entity::player::Player;
|
use crate::entity::player::Player;
|
||||||
use crate::server::Server;
|
use crate::server::Server;
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
@ -32,6 +34,14 @@ pub trait ItemBehaviour: Send + Sync {
|
|||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn use_on_entity(
|
||||||
|
&self,
|
||||||
|
_item: &mut ItemStack,
|
||||||
|
_player: &Player,
|
||||||
|
_entity: Arc<dyn EntityBase>,
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
|
||||||
fn can_mine(&self, _player: &Player) -> bool {
|
fn can_mine(&self, _player: &Player) -> bool {
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
use crate::entity::EntityBase;
|
||||||
use crate::entity::player::Player;
|
use crate::entity::player::Player;
|
||||||
use crate::server::Server;
|
use crate::server::Server;
|
||||||
use pumpkin_data::Block;
|
use pumpkin_data::Block;
|
||||||
@ -48,6 +49,18 @@ impl ItemRegistry {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn use_on_entity(
|
||||||
|
&self,
|
||||||
|
stack: &mut ItemStack,
|
||||||
|
player: &Player,
|
||||||
|
entity: Arc<dyn EntityBase>,
|
||||||
|
) {
|
||||||
|
let pumpkin_item = self.get_pumpkin_item(stack.item);
|
||||||
|
if let Some(pumpkin_item) = pumpkin_item {
|
||||||
|
pumpkin_item.use_on_entity(stack, player, entity).await;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn can_mine(&self, item: &Item, player: &Player) -> bool {
|
pub fn can_mine(&self, item: &Item, player: &Player) -> bool {
|
||||||
let pumpkin_block = self.get_pumpkin_item(item);
|
let pumpkin_block = self.get_pumpkin_item(item);
|
||||||
if let Some(pumpkin_block) = pumpkin_block {
|
if let Some(pumpkin_block) = pumpkin_block {
|
||||||
|
|||||||
@ -571,7 +571,7 @@ impl JavaClient {
|
|||||||
.await;
|
.await;
|
||||||
}
|
}
|
||||||
SInteract::PACKET_ID => {
|
SInteract::PACKET_ID => {
|
||||||
self.handle_interact(player, SInteract::read(payload)?)
|
self.handle_interact(player, SInteract::read(payload)?, server)
|
||||||
.await;
|
.await;
|
||||||
}
|
}
|
||||||
SKeepAlive::PACKET_ID => {
|
SKeepAlive::PACKET_ID => {
|
||||||
|
|||||||
@ -1065,15 +1065,21 @@ impl JavaClient {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn handle_interact(&self, player: &Player, interact: SInteract) {
|
pub async fn handle_interact(
|
||||||
|
&self,
|
||||||
|
player: &Player,
|
||||||
|
interact: SInteract,
|
||||||
|
server: &Arc<Server>,
|
||||||
|
) {
|
||||||
if !player.has_client_loaded() {
|
if !player.has_client_loaded() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
let entity_id = interact.entity_id;
|
||||||
|
|
||||||
let sneaking = interact.sneaking;
|
let sneaking = interact.sneaking;
|
||||||
let entity = &player.living_entity.entity;
|
let player_entity = &player.living_entity.entity;
|
||||||
if entity.sneaking.load(Ordering::Relaxed) != sneaking {
|
if player_entity.sneaking.load(Ordering::Relaxed) != sneaking {
|
||||||
entity.set_sneaking(sneaking).await;
|
player_entity.set_sneaking(sneaking).await;
|
||||||
}
|
}
|
||||||
let Ok(action) = ActionType::try_from(interact.r#type.0) else {
|
let Ok(action) = ActionType::try_from(interact.r#type.0) else {
|
||||||
self.kick(TextComponent::text("Invalid action type")).await;
|
self.kick(TextComponent::text("Invalid action type")).await;
|
||||||
@ -1082,7 +1088,6 @@ impl JavaClient {
|
|||||||
|
|
||||||
match action {
|
match action {
|
||||||
ActionType::Attack => {
|
ActionType::Attack => {
|
||||||
let entity_id = interact.entity_id;
|
|
||||||
let config = &advanced_config().pvp;
|
let config = &advanced_config().pvp;
|
||||||
// TODO: do validation and stuff
|
// TODO: do validation and stuff
|
||||||
if !config.enabled {
|
if !config.enabled {
|
||||||
@ -1091,7 +1096,7 @@ impl JavaClient {
|
|||||||
|
|
||||||
// TODO: set as camera entity when spectator
|
// TODO: set as camera entity when spectator
|
||||||
|
|
||||||
let world = &entity.world;
|
let world = &player_entity.world;
|
||||||
let player_victim = world.get_player_by_id(entity_id.0).await;
|
let player_victim = world.get_player_by_id(entity_id.0).await;
|
||||||
if entity_id.0 == player.entity_id() {
|
if entity_id.0 == player.entity_id() {
|
||||||
// This can't be triggered from a non-modded client.
|
// This can't be triggered from a non-modded client.
|
||||||
@ -1137,7 +1142,16 @@ impl JavaClient {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
ActionType::Interact | ActionType::InteractAt => {
|
ActionType::Interact | ActionType::InteractAt => {
|
||||||
log::debug!("todo");
|
// TODO: split this up
|
||||||
|
let entity = player.world().get_player_by_id(entity_id.0).await;
|
||||||
|
if let Some(entity) = entity {
|
||||||
|
let held = player.inventory.held_item();
|
||||||
|
let mut stack = held.lock().await;
|
||||||
|
server
|
||||||
|
.item_registry
|
||||||
|
.use_on_entity(&mut stack, player, entity)
|
||||||
|
.await;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1425,14 +1439,14 @@ impl JavaClient {
|
|||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
let mut stack = item.lock().await;
|
||||||
|
|
||||||
if item.lock().await.is_empty() {
|
if stack.is_empty() {
|
||||||
// TODO item cool down
|
// TODO item cool down
|
||||||
// If the hand is empty we stop here
|
// If the hand is empty we stop here
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut stack = item.lock().await;
|
|
||||||
server
|
server
|
||||||
.item_registry
|
.item_registry
|
||||||
.use_on_block(&mut stack, player, position, face, block, server)
|
.use_on_block(&mut stack, player, position, face, block, server)
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user