|
|
|
@ -7,12 +7,12 @@ use once_cell::sync::Lazy;
|
|
|
|
|
use valence::{
|
|
|
|
|
entity::{living::Health, player::PlayerEntityBundle, EntityId},
|
|
|
|
|
packet::WritePacket,
|
|
|
|
|
prelude::{*, event::PerformRespawn},
|
|
|
|
|
prelude::{event::PerformRespawn, *},
|
|
|
|
|
};
|
|
|
|
|
use valence_protocol::{
|
|
|
|
|
packet::s2c::play::{
|
|
|
|
|
synchronize_tags::{Tag, TagGroup},
|
|
|
|
|
ChunkRenderDistanceCenterS2c, SynchronizeTagsS2c
|
|
|
|
|
ChunkRenderDistanceCenterS2c, SynchronizeTagsS2c,
|
|
|
|
|
},
|
|
|
|
|
var_int::VarInt,
|
|
|
|
|
Encode,
|
|
|
|
@ -23,64 +23,6 @@ use crate::PLAYER_COUNT;
|
|
|
|
|
static PLAYER_HEIGHT_HISTORY: Lazy<Mutex<HashMap<i32, f64>>> =
|
|
|
|
|
Lazy::new(|| Mutex::new(HashMap::new()));
|
|
|
|
|
|
|
|
|
|
pub fn fall_damage(
|
|
|
|
|
mut clients: Query<
|
|
|
|
|
(
|
|
|
|
|
&mut Client,
|
|
|
|
|
&OnGround,
|
|
|
|
|
&EntityId,
|
|
|
|
|
&mut Health,
|
|
|
|
|
&GameMode,
|
|
|
|
|
&Position,
|
|
|
|
|
),
|
|
|
|
|
Changed<Position>,
|
|
|
|
|
>,
|
|
|
|
|
instances: Query<&Instance>,
|
|
|
|
|
) {
|
|
|
|
|
let instance = instances.single();
|
|
|
|
|
for (_client, on_ground, id, mut health, gamemode, position) in &mut clients {
|
|
|
|
|
let current_block = instance
|
|
|
|
|
.block(BlockPos {
|
|
|
|
|
x: position.0.x.floor() as i32,
|
|
|
|
|
y: position.0.y.floor() as i32 - 1,
|
|
|
|
|
z: position.0.z.floor() as i32,
|
|
|
|
|
})
|
|
|
|
|
.unwrap();
|
|
|
|
|
let mut hashmap = PLAYER_HEIGHT_HISTORY.lock().unwrap();
|
|
|
|
|
if *gamemode == GameMode::Survival {
|
|
|
|
|
// hack that potentially makes water not apply fall damage?
|
|
|
|
|
if current_block.state().to_kind() == BlockKind::Vine
|
|
|
|
|
|| current_block.state().to_kind() == BlockKind::SlimeBlock
|
|
|
|
|
|| current_block.state().is_liquid()
|
|
|
|
|
{
|
|
|
|
|
hashmap.insert(id.get(), position.0.y);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let old_position = hashmap.get(&id.get()).unwrap_or(&-1.0);
|
|
|
|
|
let delta_y = old_position - position.0.y;
|
|
|
|
|
|
|
|
|
|
if on_ground.0 {
|
|
|
|
|
if delta_y > 3.0 {
|
|
|
|
|
health.0 -= (delta_y - 3.0) as f32;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
hashmap.insert(id.get(), position.0.y);
|
|
|
|
|
} else if delta_y < 0.0 {
|
|
|
|
|
hashmap.insert(id.get(), position.0.y);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn death(mut healths: Query<(&mut Client, &Health, &Username), Changed<Health>>) {
|
|
|
|
|
for (mut client, health, username) in &mut healths {
|
|
|
|
|
if health.0 <= 0.0 {
|
|
|
|
|
tracing::debug!("Trying to kill player {}", username);
|
|
|
|
|
client.kill(None, format!("{} fell from a high place.", username));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn init_clients(
|
|
|
|
|
mut new_clients: Query<
|
|
|
|
|
(
|
|
|
|
@ -156,6 +98,63 @@ pub fn init_clients(
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn fall_damage(
|
|
|
|
|
mut clients: Query<
|
|
|
|
|
(
|
|
|
|
|
&mut Client,
|
|
|
|
|
&OnGround,
|
|
|
|
|
&EntityId,
|
|
|
|
|
&mut Health,
|
|
|
|
|
&GameMode,
|
|
|
|
|
&Position,
|
|
|
|
|
),
|
|
|
|
|
Changed<Position>,
|
|
|
|
|
>,
|
|
|
|
|
instances: Query<&Instance>,
|
|
|
|
|
) {
|
|
|
|
|
let instance = instances.single();
|
|
|
|
|
for (_client, on_ground, id, mut health, gamemode, position) in &mut clients {
|
|
|
|
|
let current_block = instance
|
|
|
|
|
.block(BlockPos {
|
|
|
|
|
x: position.0.x.floor() as i32,
|
|
|
|
|
y: position.0.y.floor() as i32 - 1,
|
|
|
|
|
z: position.0.z.floor() as i32,
|
|
|
|
|
})
|
|
|
|
|
.unwrap();
|
|
|
|
|
let mut hashmap = PLAYER_HEIGHT_HISTORY.lock().unwrap();
|
|
|
|
|
if *gamemode == GameMode::Survival {
|
|
|
|
|
// hack that potentially makes water not apply fall damage?
|
|
|
|
|
if current_block.state().to_kind() == BlockKind::Vine
|
|
|
|
|
|| current_block.state().to_kind() == BlockKind::SlimeBlock
|
|
|
|
|
|| current_block.state().is_liquid()
|
|
|
|
|
{
|
|
|
|
|
hashmap.insert(id.get(), position.0.y);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let old_position = hashmap.get(&id.get()).unwrap_or(&-1.0);
|
|
|
|
|
let delta_y = old_position - position.0.y;
|
|
|
|
|
|
|
|
|
|
if on_ground.0 {
|
|
|
|
|
if delta_y > 3.0 {
|
|
|
|
|
health.0 -= (delta_y - 3.0) as f32;
|
|
|
|
|
}
|
|
|
|
|
hashmap.insert(id.get(), position.0.y);
|
|
|
|
|
} else if delta_y < 0.0 {
|
|
|
|
|
hashmap.insert(id.get(), position.0.y);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn death(mut healths: Query<(&mut Client, &Health, &Username), Changed<Health>>) {
|
|
|
|
|
for (mut client, health, username) in &mut healths {
|
|
|
|
|
if health.0 <= 0.0 {
|
|
|
|
|
tracing::debug!("Trying to kill player {}", username);
|
|
|
|
|
client.kill(None, format!("{} fell from a high place.", username));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn despawn_disconnected_clients(
|
|
|
|
|
mut commands: Commands,
|
|
|
|
|
mut disconnected_clients: RemovedComponents<Client>,
|
|
|
|
@ -185,4 +184,4 @@ pub fn respawn(
|
|
|
|
|
loc.0 = instances.single();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|