Skip to main content

steel_core/player/game_mode/
mod.rs

1//! Game mode specific logic for player interactions.
2//!
3//! This module implements the logic from Java's `ServerPlayerGameMode`, particularly
4//! the `useItemOn` method that handles block placement and block interactions.
5
6use std::mem::swap;
7use std::sync::Arc;
8
9use glam::DVec3;
10use steel_protocol::packets::game::{
11    CBlockChangedAck, CBlockUpdate, CChangeDifficulty, CGameEvent, COpenSignEditor,
12    CPlayerInfoUpdate, CSetCamera, CSetEntityMotion, CSetHeldSlot, GameEventType, PlayerAction,
13    SAttack, SInteract, SPickItemFromBlock, SPlayerAction, SSignUpdate, SSpectatorAction, SUseItem,
14    SUseItemOn,
15};
16use steel_registry::blocks::block_state_ext::BlockStateExt;
17use steel_registry::blocks::properties::Direction;
18use steel_registry::damage_type::DamageType;
19use steel_registry::data_components::components::PiercingWeapon;
20use steel_registry::entity_type::EntityTypeRef;
21use steel_registry::item_stack::ItemStack;
22use steel_registry::sound_event::{SoundEventHolder, SoundEventRef};
23use steel_registry::{REGISTRY, vanilla_attributes, vanilla_damage_types, vanilla_entities};
24use steel_utils::types::{Difficulty, GameType, InteractionHand};
25use steel_utils::{BlockPos, Downcast as _, Identifier, WorldAabb};
26use text_components::TextComponent;
27use text_components::translation::TranslatedMessage;
28
29use crate::behavior::{
30    BLOCK_BEHAVIORS, BlockCollisionContext, BlockHitResult, ITEM_BEHAVIORS, InteractionResult,
31    InventoryAccess, UseOnContext,
32};
33use crate::block_entity::BlockEntity;
34use crate::block_entity::entities::SignBlockEntity;
35use crate::command::player_can_change_difficulty;
36use crate::enchantment_helper::{self, EnchantmentDamageContext, EnchantmentPostAttackContext};
37use crate::entity::attribute::{AttributeModifier, AttributeModifierOperation};
38use crate::entity::damage::DamageSource;
39use crate::entity::{Entity, LivingEntity, SharedEntity};
40use crate::physics::collision::{CollisionWorld, WorldCollisionProvider};
41use crate::physics::shapes;
42use crate::player::Player;
43use crate::player::movement::wrap_degrees;
44use crate::player::player_inventory::PlayerInventory;
45use crate::world::{ClipBlockShape, ClipFluid, World};
46use steel_utils::axis::Axis;
47
48pub mod block_breaking;
49mod block_interaction;
50mod entity_interaction;
51mod item_interaction;
52mod player_methods;
53mod raycast;
54
55pub(super) use block_breaking::BlockBreakingManager;
56pub use item_interaction::{use_item, use_item_on};
57
58/// Current and previous player game mode stored as one coherent state.
59#[derive(Debug, Clone, Copy)]
60pub(super) struct PlayerGameModeState {
61    current: GameType,
62    previous: Option<GameType>,
63}
64
65impl PlayerGameModeState {
66    #[must_use]
67    pub(super) const fn new(initial: GameType) -> Self {
68        Self {
69            current: initial,
70            previous: None,
71        }
72    }
73
74    #[must_use]
75    pub(super) const fn current(self) -> GameType {
76        self.current
77    }
78
79    #[must_use]
80    pub(super) const fn previous(self) -> Option<GameType> {
81        self.previous
82    }
83
84    pub(super) const fn set_pair(&mut self, current: GameType, previous: Option<GameType>) {
85        self.current = current;
86        self.previous = previous;
87    }
88
89    pub(super) fn change_current(&mut self, game_mode: GameType) -> bool {
90        if self.current == game_mode {
91            return false;
92        }
93
94        self.previous = Some(self.current);
95        self.current = game_mode;
96        true
97    }
98}
99
100use raycast::piercing_ray_hit_t;
101
102const CREATIVE_BLOCK_RANGE_MODIFIER_AMOUNT: f64 = 0.5;
103const CREATIVE_ENTITY_RANGE_MODIFIER_AMOUNT: f64 = 2.0;
104const ATTACK_RANGE_BUFFER: f64 = 3.0;
105const ENTITY_INTERACTION_RANGE_BUFFER: f64 = 3.0;
106const FLIGHT_DISABLE_RANGE: f64 = 1.0;
107
108#[cfg(test)]
109mod tests;