Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 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
14 changes: 13 additions & 1 deletion feather/server/src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ use common::{
use libcraft_items::InventorySlot;
use packets::server::{Particle, SetSlot, SpawnLivingEntity, UpdateLight, WindowConfirmation};
use protocol::packets::server::{
EntityPosition, EntityPositionAndRotation, EntityTeleport, HeldItemChange, PlayerAbilities,
ChangeGameState, EntityPosition, EntityPositionAndRotation, EntityTeleport, HeldItemChange,
PlayerAbilities, StateReason,
};
use protocol::{
packets::{
Expand Down Expand Up @@ -331,6 +332,10 @@ impl Client {
self.send_packet(PlayerInfo::RemovePlayers(vec![uuid]));
}

pub fn change_player_tablist_gamemode(&self, uuid: Uuid, gamemode: Gamemode) {
self.send_packet(PlayerInfo::UpdateGamemodes(vec![(uuid, gamemode)]));
}

pub fn unload_entity(&self, id: NetworkId) {
log::trace!("Unloading {:?} on {}", id, self.username);
self.sent_entities.borrow_mut().remove(&id);
Expand Down Expand Up @@ -602,6 +607,13 @@ impl Client {
self.send_packet(HeldItemChange { slot });
}

pub fn change_gamemode(&self, gamemode: Gamemode) {
self.send_packet(ChangeGameState {
reason: StateReason::ChangeGameMode,
value: gamemode as u8 as f32,
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we change the protocol to take Gamemode and implement write on game mode?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ChangeGameState requires it to be f64, so I did it in a different way.

})
}

fn register_entity(&self, network_id: NetworkId) {
self.sent_entities.borrow_mut().insert(network_id);
}
Expand Down
2 changes: 2 additions & 0 deletions feather/server/src/systems.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
mod block;
mod chat;
mod entity;
mod gamemode;
mod particle;
mod player_join;
mod player_leave;
Expand Down Expand Up @@ -36,6 +37,7 @@ pub fn register(server: Server, game: &mut Game, systems: &mut SystemExecutor<Ga
chat::register(game, systems);
particle::register(systems);
plugin_message::register(systems);
gamemode::register(systems);

systems.group::<Server>().add_system(tick_clients);
}
Expand Down
226 changes: 226 additions & 0 deletions feather/server/src/systems/gamemode.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,226 @@
use std::collections::HashMap;

use base::Gamemode;
use common::Game;
use ecs::{SysResult, SystemExecutor};
use quill_common::components::{
CanBuild, CanCreativeFly, CreativeFlying, CreativeFlyingSpeed, Instabreak, Invulnerable,
PreviousGamemode, WalkSpeed,
};
use quill_common::events::{
BuildingAbilityChangeEvent, CreativeFlyingEvent, FlyingAbilityChangeEvent, GamemodeEvent,
InstabreakChangeEvent, InvulnerabilityChangeEvent,
};

use crate::{ClientId, Server};
use base::anvil::player::PlayerAbilities;

pub fn register(systems: &mut SystemExecutor<Game>) {
systems.group::<Server>().add_system(gamemode_change);
}

fn gamemode_change(game: &mut Game, server: &mut Server) -> SysResult {
let mut may_fly_changes = HashMap::new();
Comment thread
Iaiao marked this conversation as resolved.
Outdated
let mut fly_changes = HashMap::new();
let mut instabreak_changes = HashMap::new();
let mut build_changes = HashMap::new();
let mut invulnerability_changes = HashMap::new();
for (
entity,
(
event,
&client_id,
&walk_speed,
&fly_speed,
mut may_fly,
mut is_flying,
mut instabreak,
mut may_build,
mut invulnerable,
gamemode,
prev_gamemode,
),
) in game
.ecs
.query::<(
&GamemodeEvent,
Comment thread
Defman marked this conversation as resolved.
&ClientId,
&WalkSpeed,
&CreativeFlyingSpeed,
&mut CanCreativeFly,
&mut CreativeFlying,
&mut Instabreak,
&mut CanBuild,
&mut Invulnerable,
&mut Gamemode,
&mut PreviousGamemode,
)>()
.iter()
{
if **event == *gamemode {
continue;
}
*prev_gamemode = PreviousGamemode(Some(*gamemode));
*gamemode = **event;
match gamemode {
Gamemode::Creative => {
if !**instabreak {
instabreak_changes.insert(entity, true);
instabreak.0 = true;
}
if !**may_fly {
may_fly_changes.insert(entity, true);
may_fly.0 = true;
}
if !**may_build {
build_changes.insert(entity, true);
may_build.0 = true;
}
if !**invulnerable {
invulnerability_changes.insert(entity, true);
invulnerable.0 = true;
}
}
Gamemode::Spectator => {
if !**is_flying {
fly_changes.insert(entity, true);
is_flying.0 = true;
}
if **instabreak {
instabreak_changes.insert(entity, false);
instabreak.0 = false;
}
if !**may_fly {
may_fly_changes.insert(entity, true);
may_fly.0 = true;
}
if **may_build {
build_changes.insert(entity, false);
may_build.0 = false;
}
if !**invulnerable {
invulnerability_changes.insert(entity, true);
invulnerable.0 = true;
}
}
Gamemode::Survival => {
if **is_flying {
fly_changes.insert(entity, false);
is_flying.0 = false;
}
if **instabreak {
instabreak_changes.insert(entity, false);
instabreak.0 = false;
}
if **may_fly {
may_fly_changes.insert(entity, false);
may_fly.0 = false;
}
if !**may_build {
build_changes.insert(entity, true);
may_build.0 = true;
}
if **invulnerable {
invulnerability_changes.insert(entity, false);
invulnerable.0 = false;
}
}
Gamemode::Adventure => {
if **is_flying {
fly_changes.insert(entity, false);
is_flying.0 = false;
}
if **instabreak {
instabreak_changes.insert(entity, false);
instabreak.0 = false;
}
if **may_fly {
may_fly_changes.insert(entity, false);
may_fly.0 = false;
}
if **may_build {
build_changes.insert(entity, false);
may_build.0 = false;
}
if **invulnerable {
invulnerability_changes.insert(entity, false);
invulnerable.0 = false;
}
}
}
server
.clients
.get(client_id)
.unwrap()
.change_gamemode(**event);
server
.clients
.get(client_id)
.unwrap()
.send_abilities(&PlayerAbilities {
walk_speed,
fly_speed,
may_fly: *may_fly,
is_flying: *is_flying,
may_build: *may_build,
instabreak: *instabreak,
invulnerable: *invulnerable,
});
}
for (entity, flying) in fly_changes {
Comment thread
Defman marked this conversation as resolved.
if flying {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This if statement is redundant, just create CreativeFlyingEvent with the value of flying?

game.ecs
.insert_entity_event(entity, CreativeFlyingEvent::new(true))
.unwrap();
} else {
game.ecs
.insert_entity_event(entity, CreativeFlyingEvent::new(false))
.unwrap();
}
}
for (entity, instabreak) in instabreak_changes {
if instabreak {
game.ecs
.insert_entity_event(entity, InstabreakChangeEvent(true))
.unwrap();
} else {
game.ecs
.insert_entity_event(entity, InstabreakChangeEvent(false))
.unwrap();
}
}
for (entity, may_fly) in may_fly_changes {
if may_fly {
game.ecs
.insert_entity_event(entity, FlyingAbilityChangeEvent(true))
.unwrap();
} else {
game.ecs
.insert_entity_event(entity, FlyingAbilityChangeEvent(false))
.unwrap();
}
}
for (entity, build) in build_changes {
if build {
game.ecs
.insert_entity_event(entity, BuildingAbilityChangeEvent(true))
.unwrap();
} else {
game.ecs
.insert_entity_event(entity, BuildingAbilityChangeEvent(false))
.unwrap();
}
}
for (entity, invulnerable) in invulnerability_changes {
if invulnerable {
game.ecs
.insert_entity_event(entity, InvulnerabilityChangeEvent(true))
.unwrap();
} else {
game.ecs
.insert_entity_event(entity, InvulnerabilityChangeEvent(false))
.unwrap();
}
}
Ok(())
}
3 changes: 3 additions & 0 deletions feather/server/src/systems/player_join.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ use quill_common::components::{
CanBuild, CanCreativeFly, CreativeFlying, CreativeFlyingSpeed, Health, Instabreak,
Invulnerable, PreviousGamemode, WalkSpeed,
};
use quill_common::events::GamemodeEvent;
use quill_common::{components::Name, entity_init::EntityInit};

use crate::{ClientId, NetworkId, Server};
Expand Down Expand Up @@ -131,6 +132,8 @@ fn accept_new_player(game: &mut Game, server: &mut Server, client_id: ClientId)
.add(abilities.instabreak)
.add(abilities.invulnerable);

builder.add(GamemodeEvent(gamemode));

game.spawn_entity(builder);

broadcast_player_join(game, client.username());
Expand Down
12 changes: 11 additions & 1 deletion feather/server/src/systems/tablist.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use common::{
Game,
};
use ecs::{SysResult, SystemExecutor};
use quill_common::events::GamemodeEvent;
use quill_common::{components::Name, entities::Player};
use uuid::Uuid;

Expand All @@ -15,7 +16,8 @@ pub fn register(systems: &mut SystemExecutor<Game>) {
systems
.group::<Server>()
.add_system(remove_tablist_players)
.add_system(add_tablist_players);
.add_system(add_tablist_players)
.add_system(change_tablist_player_gamemode);
}

fn remove_tablist_players(game: &mut Game, server: &mut Server) -> SysResult {
Expand Down Expand Up @@ -62,3 +64,11 @@ fn add_tablist_players(game: &mut Game, server: &mut Server) -> SysResult {
}
Ok(())
}

fn change_tablist_player_gamemode(game: &mut Game, server: &mut Server) -> SysResult {
for (_, (event, &uuid)) in game.ecs.query::<(&GamemodeEvent, &Uuid)>().iter() {
// Change this player's gamemode in players' tablists
server.broadcast_with(|client| client.change_player_tablist_gamemode(uuid, **event));
}
Ok(())
}
12 changes: 10 additions & 2 deletions quill/common/src/component.rs
Original file line number Diff line number Diff line change
Expand Up @@ -198,8 +198,11 @@ host_component_enum! {
CanBuild = 1020,
Instabreak = 1021,
Invulnerable = 1022,


GamemodeEvent = 1023,
InstabreakChangeEvent = 1024,
FlyingAbilityChangeEvent = 1025,
BuildingAbilityChangeEvent = 1026,
InvulnerabilityChangeEvent = 1027,
}
}

Expand Down Expand Up @@ -363,3 +366,8 @@ bincode_component_impl!(BlockInteractEvent);
bincode_component_impl!(CreativeFlyingEvent);
bincode_component_impl!(SneakEvent);
bincode_component_impl!(SprintEvent);
bincode_component_impl!(GamemodeEvent);
bincode_component_impl!(InstabreakChangeEvent);
bincode_component_impl!(FlyingAbilityChangeEvent);
bincode_component_impl!(BuildingAbilityChangeEvent);
bincode_component_impl!(InvulnerabilityChangeEvent);
11 changes: 7 additions & 4 deletions quill/common/src/events.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
pub use block_interact::{BlockInteractEvent, BlockPlacementEvent};
pub use change::{
BuildingAbilityChangeEvent, CreativeFlyingEvent, FlyingAbilityChangeEvent, GamemodeEvent,
InstabreakChangeEvent, InvulnerabilityChangeEvent, SneakEvent, SprintEvent,
};
pub use interact_entity::InteractEntityEvent;

mod block_interact;
mod change;
mod interact_entity;

pub use block_interact::{BlockInteractEvent, BlockPlacementEvent};
pub use change::{CreativeFlyingEvent, SneakEvent, SprintEvent};
pub use interact_entity::InteractEntityEvent;
20 changes: 19 additions & 1 deletion quill/common/src/events/change.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
/*
All events in this file are triggerd when there is a change in a certain value.
All events in this file are triggered when there is a change in a certain value.
*/

use derive_more::Deref;
use libcraft_core::Gamemode;
use serde::{Deserialize, Serialize};

#[derive(Debug, Serialize, Deserialize, Clone)]
Expand Down Expand Up @@ -42,3 +44,19 @@ impl SprintEvent {
}
}
}

/// This event is called when a player's gamemode is changed and every time the player joins.
#[derive(Debug, Serialize, Deserialize, Clone, Deref)]
pub struct GamemodeEvent(pub Gamemode);

#[derive(Debug, Serialize, Deserialize, Clone, Deref)]
pub struct InstabreakChangeEvent(pub bool);

#[derive(Debug, Serialize, Deserialize, Clone, Deref)]
pub struct FlyingAbilityChangeEvent(pub bool);

#[derive(Debug, Serialize, Deserialize, Clone, Deref)]
pub struct BuildingAbilityChangeEvent(pub bool);

#[derive(Debug, Serialize, Deserialize, Clone, Deref)]
pub struct InvulnerabilityChangeEvent(pub bool);