Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: respawn #702

Merged
merged 15 commits into from
Dec 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

58 changes: 31 additions & 27 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,33 +15,34 @@ panic = 'abort'

[workspace]
members = [
'crates/bvh-region',
'crates/geometry',
'crates/hyperion',
'crates/hyperion-clap',
'crates/hyperion-command',
'crates/hyperion-crafting',
'crates/hyperion-event-macros',
'crates/hyperion-genmap',
'crates/hyperion-gui',
'crates/hyperion-inventory',
'crates/hyperion-item',
'crates/hyperion-minecraft-proto',
'crates/hyperion-nerd-font',
'crates/hyperion-palette',
'crates/hyperion-permission',
'crates/hyperion-proto',
'crates/hyperion-proxy',
'crates/hyperion-rank-tree',
'crates/hyperion-scheduled',
'crates/hyperion-stats',
'crates/hyperion-text',
'crates/hyperion-utils',
'crates/simd-utils',
'crates/spatial',
'crates/system-order',
'events/tag',
'tools/packet-inspector',
'crates/bvh-region',
'crates/geometry',
'crates/hyperion',
'crates/hyperion-clap',
'crates/hyperion-command',
'crates/hyperion-crafting',
'crates/hyperion-event-macros',
'crates/hyperion-genmap',
'crates/hyperion-gui',
'crates/hyperion-inventory',
'crates/hyperion-item',
'crates/hyperion-minecraft-proto',
'crates/hyperion-nerd-font',
'crates/hyperion-palette',
'crates/hyperion-permission',
'crates/hyperion-proto',
'crates/hyperion-proxy',
'crates/hyperion-rank-tree',
'crates/hyperion-scheduled',
'crates/hyperion-stats',
'crates/hyperion-text',
'crates/hyperion-utils',
'crates/simd-utils',
'crates/spatial',
'crates/system-order',
'events/tag',
'tools/packet-inspector',
'crates/hyperion-respawn',
]
resolver = '2'

Expand Down Expand Up @@ -210,6 +211,9 @@ version = '0.3.6'
features = ['rustls-tls', 'stream']
version = '0.12.9'

[workspace.dependencies.hyperion-respawn]
path = 'crates/hyperion-respawn'

[workspace.dependencies.roaring]
features = ['simd']
version = '0.10.9'
Expand Down
1 change: 1 addition & 0 deletions crates/hyperion-respawn/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/target
14 changes: 14 additions & 0 deletions crates/hyperion-respawn/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
[package]
name = "hyperion-respawn"
version = "0.1.0"
edition = "2021"
authors = ["Andrew Gazelka <andrew.gazelka@gmail.com>"]
readme = "README.md"
publish = false

[dependencies]
hyperion = {workspace = true}
hyperion-utils = {workspace = true}

[lints]
workspace = true
1 change: 1 addition & 0 deletions crates/hyperion-respawn/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# respawn
86 changes: 86 additions & 0 deletions crates/hyperion-respawn/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
use hyperion::{
flecs_ecs::{
self,
core::{EntityViewGet, QueryBuilderImpl, SystemAPI, TermBuilderImpl, World},
macros::{system, Component},
prelude::Module,
},
net::{Compose, ConnectionId},
protocol::{game_mode::OptGameMode, packets::play, ByteAngle, VarInt},
server::{ident, GameMode},
simulation::{
event::{ClientStatusCommand, ClientStatusEvent},
metadata::{entity::Pose, living_entity::Health},
Pitch, Position, Uuid, Yaw,
},
storage::EventQueue,
};
use hyperion_utils::EntityExt;

#[derive(Component)]
pub struct RespawnModule;

impl Module for RespawnModule {
fn module(world: &World) {
system!("handle_respawn", world, &mut EventQueue<ClientStatusEvent>($), &Compose($))
.multi_threaded()
.each_iter(|it, _, (event_queue, compose)| {
let world = it.world();
let system = it.system();
for event in event_queue.drain() {
if event.status == ClientStatusCommand::RequestStats {
continue;
}

let client = event.client.entity_view(world);
client.get::<(
&ConnectionId,
&mut Health,
&mut Pose,
&Uuid,
&Position,
&Yaw,
&Pitch,
)>(
|(connection, health, pose, uuid, position, yaw, pitch)| {
health.heal(20.);

*pose = Pose::Standing;
client.modified::<Pose>(); // this is so observers detect the change

let pkt_health = play::HealthUpdateS2c {
health: health.abs(),
food: VarInt(20),
food_saturation: 5.0,
};

let pkt_respawn = play::PlayerRespawnS2c {
dimension_type_name: ident!("minecraft:overworld").into(),
dimension_name: ident!("minecraft:overworld").into(),
hashed_seed: 0,
game_mode: GameMode::Survival,
previous_game_mode: OptGameMode::default(),
is_debug: false,
is_flat: false,
copy_metadata: false,
last_death_location: None,
portal_cooldown: VarInt::default(),
};

let pkt_add_player = play::PlayerSpawnS2c {
entity_id: VarInt(client.minecraft_id()),
player_uuid: uuid.0,
position: position.as_dvec3(),
yaw: ByteAngle::from_degrees(**yaw),
pitch: ByteAngle::from_degrees(**pitch),
};

compose.unicast(&pkt_health, *connection, system).unwrap();
compose.unicast(&pkt_respawn, *connection, system).unwrap();
compose.broadcast(&pkt_add_player, system).send().unwrap();
},
);
}
});
}
}
3 changes: 3 additions & 0 deletions crates/hyperion/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ use std::{
use anyhow::Context;
use derive_more::{Constructor, Deref, DerefMut};
use egress::EgressModule;
pub use flecs_ecs;
use flecs_ecs::prelude::*;
pub use glam;
use glam::{I16Vec2, IVec2};
Expand All @@ -51,6 +52,7 @@ use storage::{Events, GlobalEventHandlers, LocalDb, SkinHandler, ThreadLocal};
use tracing::{info, info_span, warn};
use util::mojang::MojangClient;
pub use uuid;
pub use valence_protocol as protocol;
// todo: slowly move more and more things to arbitrary module
// and then eventually do not re-export valence_protocol
pub use valence_protocol;
Expand All @@ -59,6 +61,7 @@ pub use valence_protocol::{
ItemKind, ItemStack, Particle,
block::{BlockKind, BlockState},
};
pub use valence_server as server;

use crate::{
net::{Compose, Compressors, IoBuf, MAX_PACKET_SIZE, proxy::init_proxy_comms},
Expand Down
12 changes: 12 additions & 0 deletions crates/hyperion/src/simulation/event.rs
Original file line number Diff line number Diff line change
Expand Up @@ -134,3 +134,15 @@ pub struct Command<'a> {
}

pub struct BlockInteract {}

#[derive(Clone, Debug, PartialEq, Eq)]
pub enum ClientStatusCommand {
PerformRespawn,
RequestStats,
}

#[derive(Clone, Debug)]
pub struct ClientStatusEvent {
pub client: Entity,
pub status: ClientStatusCommand,
}
18 changes: 18 additions & 0 deletions crates/hyperion/src/simulation/handlers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ use super::{
block_bounds,
blocks::Blocks,
bow::BowCharging,
event::ClientStatusEvent,
};
use crate::{
net::{Compose, ConnectionId, decoder::BorrowedPacketFrame},
Expand Down Expand Up @@ -613,6 +614,22 @@ pub fn request_command_completions(
Ok(())
}

pub fn client_status(mut data: &'static [u8], query: &PacketSwitchQuery<'_>) -> anyhow::Result<()> {
let pkt = play::ClientStatusC2s::decode(&mut data)?;

let command = ClientStatusEvent {
client: query.id,
status: match pkt {
play::ClientStatusC2s::PerformRespawn => event::ClientStatusCommand::PerformRespawn,
play::ClientStatusC2s::RequestStats => event::ClientStatusCommand::RequestStats,
},
};

query.events.push(command, query.world);

Ok(())
}

pub fn packet_switch(
raw: BorrowedPacketFrame<'_>,
query: &mut PacketSwitchQuery<'_>,
Expand All @@ -628,6 +645,7 @@ pub fn packet_switch(
play::ChatMessageC2s::ID => chat_message(data, query)?,
play::ClickSlotC2s::ID => click_slot(data, query)?,
play::ClientCommandC2s::ID => client_command(data, query)?,
play::ClientStatusC2s::ID => client_status(data, query)?,
play::CommandExecutionC2s::ID => chat_command(data, query)?,
play::CreativeInventoryActionC2s::ID => creative_inventory_action(data, query)?,
play::CustomPayloadC2s::ID => custom_payload(data, query)?,
Expand Down
14 changes: 7 additions & 7 deletions crates/hyperion/src/simulation/metadata/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ pub struct MetadataPrefabs {
pub player_base: Entity,
}

fn component_and_prev<T>(world: &World) -> fn(&mut EntityView<'_>)
fn component_and_track<T>(world: &World) -> fn(&mut EntityView<'_>)
where
T: ComponentId + Copy + PartialEq + Metadata + Default + flecs_ecs::core::DataComponent + Debug,
<T as ComponentId>::UnderlyingType: Meta<<T as ComponentId>::UnderlyingType>,
Expand Down Expand Up @@ -86,7 +86,7 @@ where
}

trait EntityViewExt {
fn component_and_prev<T>(self) -> Self
fn component_and_track<T>(self) -> Self
where
T: ComponentId
+ Copy
Expand All @@ -99,7 +99,7 @@ trait EntityViewExt {
}

impl EntityViewExt for EntityView<'_> {
fn component_and_prev<T>(mut self) -> Self
fn component_and_track<T>(mut self) -> Self
where
T: ComponentId
+ Copy
Expand All @@ -112,7 +112,7 @@ impl EntityViewExt for EntityView<'_> {
{
let world = self.world();
// todo: how this possible exclusive mut
component_and_prev::<T>(&world)(&mut self);
component_and_track::<T>(&world)(&mut self);
self
}
}
Expand All @@ -123,8 +123,8 @@ pub fn register_prefabs(world: &World) -> MetadataPrefabs {

let entity_base = entity::register_prefab(world, None)
.add::<MetadataChanges>()
.component_and_prev::<EntityFlags>()
.component_and_prev::<Pose>()
.component_and_track::<EntityFlags>()
.component_and_track::<Pose>()
.id();

let display_base = display::register_prefab(world, Some(entity_base)).id();
Expand Down Expand Up @@ -216,7 +216,7 @@ macro_rules! register_component_ids {
($world:expr, $entity:ident, $($name:ident),* $(,)?) => {
{
$(
let reg = $crate::simulation::metadata::component_and_prev::<$name>($world);
let reg = $crate::simulation::metadata::component_and_track::<$name>($world);
reg(&mut $entity);
)*

Expand Down
1 change: 1 addition & 0 deletions crates/hyperion/src/storage/event/queue/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ define_events! {
event::SwingArm,
event::ToggleDoor,
event::ReleaseUseItem,
event::ClientStatusEvent
}

pub trait ReducedLifetime {
Expand Down
3 changes: 2 additions & 1 deletion events/tag/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,12 @@ tracing = { workspace = true }
tracing-subscriber = { workspace = true }
tracing-tracy = { workspace = true }
uuid = { workspace = true }
hyperion-respawn = { workspace = true }
valence_protocol = { workspace = true }
valence_server = { workspace = true }

[dev-dependencies]
tracing = {workspace = true, features = ["release_max_level_info"]}
tracing = { workspace = true, features = ["release_max_level_info"] }

[lints]
workspace = true
Expand Down
1 change: 1 addition & 0 deletions events/tag/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ impl Module for TagModule {
world.import::<SkinModule>();
world.import::<VanishModule>();
world.import::<hyperion_genmap::GenMapModule>();
world.import::<hyperion_respawn::RespawnModule>();

world.get::<&mut CommandRegistry>(|registry| {
command::register(registry, world);
Expand Down
Loading
Loading