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