mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Add a toggle to negotiate the use of server-authoritative physics.
This commit is contained in:
parent
d6f4537d39
commit
50d0314a75
@ -48,6 +48,7 @@
|
|||||||
"hud.settings.free_look_behavior": "Free look behavior",
|
"hud.settings.free_look_behavior": "Free look behavior",
|
||||||
"hud.settings.auto_walk_behavior": "Auto walk behavior",
|
"hud.settings.auto_walk_behavior": "Auto walk behavior",
|
||||||
"hud.settings.camera_clamp_behavior": "Camera clamp behavior",
|
"hud.settings.camera_clamp_behavior": "Camera clamp behavior",
|
||||||
|
"hud.settings.player_physics_behavior": "Player physics behavior",
|
||||||
"hud.settings.stop_auto_walk_on_input": "Stop auto walk on movement",
|
"hud.settings.stop_auto_walk_on_input": "Stop auto walk on movement",
|
||||||
"hud.settings.auto_camera": "Auto camera",
|
"hud.settings.auto_camera": "Auto camera",
|
||||||
"hud.settings.reset_gameplay": "Reset to Defaults",
|
"hud.settings.reset_gameplay": "Reset to Defaults",
|
||||||
|
@ -786,7 +786,8 @@ impl Client {
|
|||||||
| ClientGeneral::UnlockSkill(_)
|
| ClientGeneral::UnlockSkill(_)
|
||||||
| ClientGeneral::RefundSkill(_)
|
| ClientGeneral::RefundSkill(_)
|
||||||
| ClientGeneral::RequestSiteInfo(_)
|
| ClientGeneral::RequestSiteInfo(_)
|
||||||
| ClientGeneral::UnlockSkillGroup(_) => &mut self.in_game_stream,
|
| ClientGeneral::UnlockSkillGroup(_)
|
||||||
|
| ClientGeneral::RequestPlayerPhysics { .. } => &mut self.in_game_stream,
|
||||||
//Only in game, terrain
|
//Only in game, terrain
|
||||||
ClientGeneral::TerrainChunkRequest { .. } => &mut self.terrain_stream,
|
ClientGeneral::TerrainChunkRequest { .. } => &mut self.terrain_stream,
|
||||||
//Always possible
|
//Always possible
|
||||||
@ -800,6 +801,12 @@ impl Client {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn request_player_physics(&mut self, server_authoritative: bool) {
|
||||||
|
self.send_msg(ClientGeneral::RequestPlayerPhysics {
|
||||||
|
server_authoritative,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
fn send_msg<S>(&mut self, msg: S)
|
fn send_msg<S>(&mut self, msg: S)
|
||||||
where
|
where
|
||||||
S: Into<ClientMsg>,
|
S: Into<ClientMsg>,
|
||||||
|
@ -81,6 +81,9 @@ pub enum ClientGeneral {
|
|||||||
//Always possible
|
//Always possible
|
||||||
ChatMsg(String),
|
ChatMsg(String),
|
||||||
Terminate,
|
Terminate,
|
||||||
|
RequestPlayerPhysics {
|
||||||
|
server_authoritative: bool,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ClientMsg {
|
impl ClientMsg {
|
||||||
@ -117,7 +120,8 @@ impl ClientMsg {
|
|||||||
| ClientGeneral::UnlockSkill(_)
|
| ClientGeneral::UnlockSkill(_)
|
||||||
| ClientGeneral::RefundSkill(_)
|
| ClientGeneral::RefundSkill(_)
|
||||||
| ClientGeneral::RequestSiteInfo(_)
|
| ClientGeneral::RequestSiteInfo(_)
|
||||||
| ClientGeneral::UnlockSkillGroup(_) => {
|
| ClientGeneral::UnlockSkillGroup(_)
|
||||||
|
| ClientGeneral::RequestPlayerPhysics { .. } => {
|
||||||
c_type == ClientType::Game && presence.is_some()
|
c_type == ClientType::Game && presence.is_some()
|
||||||
},
|
},
|
||||||
//Always possible
|
//Always possible
|
||||||
|
@ -32,3 +32,36 @@ pub enum GameMode {
|
|||||||
/// server
|
/// server
|
||||||
#[derive(Copy, Clone, Default, Debug)]
|
#[derive(Copy, Clone, Default, Debug)]
|
||||||
pub struct PlayerEntity(pub Option<Entity>);
|
pub struct PlayerEntity(pub Option<Entity>);
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub struct PlayerPhysicsSetting {
|
||||||
|
/// true if the client wants server-authoratative physics (e.g. to use
|
||||||
|
/// airships properly)
|
||||||
|
pub client_optin: bool,
|
||||||
|
/// true if the server is forcing server-authoratative physics (e.g. as
|
||||||
|
/// punishment for wallhacking)
|
||||||
|
pub server_optout: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for PlayerPhysicsSetting {
|
||||||
|
fn default() -> PlayerPhysicsSetting {
|
||||||
|
PlayerPhysicsSetting {
|
||||||
|
client_optin: false,
|
||||||
|
server_optout: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PlayerPhysicsSetting {
|
||||||
|
pub fn server_authoritative(&self) -> bool { self.client_optin || self.server_optout }
|
||||||
|
|
||||||
|
pub fn client_authoritative(&self) -> bool { !self.server_authoritative() }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// List of which players are using client-authoratative vs server-authoratative
|
||||||
|
/// physics, as a stop-gap until we can use server-authoratative physics for
|
||||||
|
/// everyone
|
||||||
|
#[derive(Clone, Default, Debug)]
|
||||||
|
pub struct PlayerPhysicsSettings {
|
||||||
|
pub settings: hashbrown::HashMap<uuid::Uuid, PlayerPhysicsSetting>,
|
||||||
|
}
|
||||||
|
@ -10,7 +10,7 @@ use common::{
|
|||||||
event::{EventBus, LocalEvent, ServerEvent},
|
event::{EventBus, LocalEvent, ServerEvent},
|
||||||
outcome::Outcome,
|
outcome::Outcome,
|
||||||
region::RegionMap,
|
region::RegionMap,
|
||||||
resources::{DeltaTime, GameMode, PlayerEntity, Time, TimeOfDay},
|
resources::{DeltaTime, GameMode, PlayerEntity, PlayerPhysicsSettings, Time, TimeOfDay},
|
||||||
slowjob::SlowJobPool,
|
slowjob::SlowJobPool,
|
||||||
terrain::{Block, TerrainChunk, TerrainGrid},
|
terrain::{Block, TerrainChunk, TerrainGrid},
|
||||||
time::DayPeriod,
|
time::DayPeriod,
|
||||||
@ -278,6 +278,7 @@ impl State {
|
|||||||
ecs.insert(SysMetrics::default());
|
ecs.insert(SysMetrics::default());
|
||||||
ecs.insert(PhysicsMetrics::default());
|
ecs.insert(PhysicsMetrics::default());
|
||||||
ecs.insert(Trades::default());
|
ecs.insert(Trades::default());
|
||||||
|
ecs.insert(PlayerPhysicsSettings::default());
|
||||||
|
|
||||||
// Load plugins from asset directory
|
// Load plugins from asset directory
|
||||||
#[cfg(feature = "plugins")]
|
#[cfg(feature = "plugins")]
|
||||||
|
@ -5,10 +5,10 @@ use crate::{
|
|||||||
Tick,
|
Tick,
|
||||||
};
|
};
|
||||||
use common::{
|
use common::{
|
||||||
comp::{Collider, ForceUpdate, Inventory, InventoryUpdate, Last, Ori, Pos, Vel},
|
comp::{Collider, ForceUpdate, Inventory, InventoryUpdate, Last, Ori, Player, Pos, Vel},
|
||||||
outcome::Outcome,
|
outcome::Outcome,
|
||||||
region::{Event as RegionEvent, RegionMap},
|
region::{Event as RegionEvent, RegionMap},
|
||||||
resources::TimeOfDay,
|
resources::{PlayerPhysicsSettings, TimeOfDay},
|
||||||
terrain::TerrainChunkSize,
|
terrain::TerrainChunkSize,
|
||||||
uid::Uid,
|
uid::Uid,
|
||||||
vol::RectVolSize,
|
vol::RectVolSize,
|
||||||
@ -45,6 +45,8 @@ impl<'a> System<'a> for Sys {
|
|||||||
WriteStorage<'a, InventoryUpdate>,
|
WriteStorage<'a, InventoryUpdate>,
|
||||||
Write<'a, DeletedEntities>,
|
Write<'a, DeletedEntities>,
|
||||||
Write<'a, Vec<Outcome>>,
|
Write<'a, Vec<Outcome>>,
|
||||||
|
Read<'a, PlayerPhysicsSettings>,
|
||||||
|
ReadStorage<'a, Player>,
|
||||||
TrackedComps<'a>,
|
TrackedComps<'a>,
|
||||||
ReadTrackers<'a>,
|
ReadTrackers<'a>,
|
||||||
);
|
);
|
||||||
@ -76,6 +78,8 @@ impl<'a> System<'a> for Sys {
|
|||||||
mut inventory_updates,
|
mut inventory_updates,
|
||||||
mut deleted_entities,
|
mut deleted_entities,
|
||||||
mut outcomes,
|
mut outcomes,
|
||||||
|
player_physics_settings,
|
||||||
|
players,
|
||||||
tracked_comps,
|
tracked_comps,
|
||||||
trackers,
|
trackers,
|
||||||
): Self::SystemData,
|
): Self::SystemData,
|
||||||
@ -201,22 +205,28 @@ impl<'a> System<'a> for Sys {
|
|||||||
for (client, _, client_entity, client_pos) in &mut subscribers {
|
for (client, _, client_entity, client_pos) in &mut subscribers {
|
||||||
let mut comp_sync_package = CompSyncPackage::new();
|
let mut comp_sync_package = CompSyncPackage::new();
|
||||||
|
|
||||||
for (_, entity, &uid, (&pos, last_pos), vel, ori, force_update, collider) in (
|
for (_, entity, &uid, (&pos, last_pos), vel, ori, force_update, collider, player) in
|
||||||
region.entities(),
|
(
|
||||||
&entities,
|
region.entities(),
|
||||||
&uids,
|
&entities,
|
||||||
(&positions, last_pos.mask().maybe()),
|
&uids,
|
||||||
(&velocities, last_vel.mask().maybe()).maybe(),
|
(&positions, last_pos.mask().maybe()),
|
||||||
(&orientations, last_vel.mask().maybe()).maybe(),
|
(&velocities, last_vel.mask().maybe()).maybe(),
|
||||||
force_updates.mask().maybe(),
|
(&orientations, last_vel.mask().maybe()).maybe(),
|
||||||
colliders.maybe(),
|
force_updates.mask().maybe(),
|
||||||
)
|
colliders.maybe(),
|
||||||
.join()
|
players.maybe(),
|
||||||
|
)
|
||||||
|
.join()
|
||||||
{
|
{
|
||||||
|
let player_physics_setting = player
|
||||||
|
.and_then(|p| player_physics_settings.settings.get(&p.uuid()).cloned())
|
||||||
|
.unwrap_or_default();
|
||||||
// Decide how regularly to send physics updates.
|
// Decide how regularly to send physics updates.
|
||||||
let send_now = if client_entity == &entity {
|
let send_now = if client_entity == &entity {
|
||||||
// Don't send client physics updates about itself unless force update is set
|
// Don't send client physics updates about itself unless force update is set
|
||||||
force_update.is_some() || true
|
// or the client is subject to server-authoritative physics
|
||||||
|
force_update.is_some() || player_physics_setting.server_authoritative()
|
||||||
} else if matches!(collider, Some(Collider::Voxel { .. })) {
|
} else if matches!(collider, Some(Collider::Voxel { .. })) {
|
||||||
// Things with a voxel collider (airships, etc.) need to have very stable
|
// Things with a voxel collider (airships, etc.) need to have very stable
|
||||||
// physics so we always send updated for these where
|
// physics so we always send updated for these where
|
||||||
|
@ -1,7 +1,10 @@
|
|||||||
use crate::{client::Client, presence::Presence, Settings};
|
use crate::{client::Client, presence::Presence, Settings};
|
||||||
use common::{
|
use common::{
|
||||||
comp::{CanBuild, ControlEvent, Controller, ForceUpdate, Health, Ori, Pos, SkillSet, Vel},
|
comp::{
|
||||||
|
CanBuild, ControlEvent, Controller, ForceUpdate, Health, Ori, Player, Pos, SkillSet, Vel,
|
||||||
|
},
|
||||||
event::{EventBus, ServerEvent},
|
event::{EventBus, ServerEvent},
|
||||||
|
resources::PlayerPhysicsSettings,
|
||||||
terrain::TerrainGrid,
|
terrain::TerrainGrid,
|
||||||
vol::ReadVol,
|
vol::ReadVol,
|
||||||
};
|
};
|
||||||
@ -30,6 +33,8 @@ impl Sys {
|
|||||||
controllers: &mut WriteStorage<'_, Controller>,
|
controllers: &mut WriteStorage<'_, Controller>,
|
||||||
settings: &Read<'_, Settings>,
|
settings: &Read<'_, Settings>,
|
||||||
build_areas: &Read<'_, BuildAreas>,
|
build_areas: &Read<'_, BuildAreas>,
|
||||||
|
player_physics_settings: &mut Write<'_, PlayerPhysicsSettings>,
|
||||||
|
maybe_player: &Option<&Player>,
|
||||||
msg: ClientGeneral,
|
msg: ClientGeneral,
|
||||||
) -> Result<(), crate::error::Error> {
|
) -> Result<(), crate::error::Error> {
|
||||||
let presence = match maybe_presence {
|
let presence = match maybe_presence {
|
||||||
@ -40,6 +45,12 @@ impl Sys {
|
|||||||
return Ok(());
|
return Ok(());
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
let player_physics_setting = maybe_player.map(|p| {
|
||||||
|
player_physics_settings
|
||||||
|
.settings
|
||||||
|
.entry(p.uuid())
|
||||||
|
.or_default()
|
||||||
|
});
|
||||||
match msg {
|
match msg {
|
||||||
// Go back to registered state (char selection screen)
|
// Go back to registered state (char selection screen)
|
||||||
ClientGeneral::ExitInGame => {
|
ClientGeneral::ExitInGame => {
|
||||||
@ -93,14 +104,15 @@ impl Sys {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
ClientGeneral::PlayerPhysics { pos, vel, ori } => {
|
ClientGeneral::PlayerPhysics { pos, vel, ori } => {
|
||||||
/*if matches!(presence.kind, PresenceKind::Character(_))
|
if matches!(presence.kind, PresenceKind::Character(_))
|
||||||
&& force_updates.get(entity).is_none()
|
&& force_updates.get(entity).is_none()
|
||||||
&& healths.get(entity).map_or(true, |h| !h.is_dead)
|
&& healths.get(entity).map_or(true, |h| !h.is_dead)
|
||||||
|
&& player_physics_setting.map_or(true, |s| s.client_authoritative())
|
||||||
{
|
{
|
||||||
let _ = positions.insert(entity, pos);
|
let _ = positions.insert(entity, pos);
|
||||||
let _ = velocities.insert(entity, vel);
|
let _ = velocities.insert(entity, vel);
|
||||||
let _ = orientations.insert(entity, ori);
|
let _ = orientations.insert(entity, ori);
|
||||||
}*/
|
}
|
||||||
},
|
},
|
||||||
ClientGeneral::BreakBlock(pos) => {
|
ClientGeneral::BreakBlock(pos) => {
|
||||||
if let Some(comp_can_build) = can_build.get(entity) {
|
if let Some(comp_can_build) = can_build.get(entity) {
|
||||||
@ -156,6 +168,13 @@ impl Sys {
|
|||||||
ClientGeneral::RequestSiteInfo(id) => {
|
ClientGeneral::RequestSiteInfo(id) => {
|
||||||
server_emitter.emit(ServerEvent::RequestSiteInfo { entity, id });
|
server_emitter.emit(ServerEvent::RequestSiteInfo { entity, id });
|
||||||
},
|
},
|
||||||
|
ClientGeneral::RequestPlayerPhysics {
|
||||||
|
server_authoritative,
|
||||||
|
} => {
|
||||||
|
if let Some(setting) = player_physics_setting {
|
||||||
|
setting.client_optin = server_authoritative;
|
||||||
|
}
|
||||||
|
},
|
||||||
_ => tracing::error!("not a client_in_game msg"),
|
_ => tracing::error!("not a client_in_game msg"),
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -184,6 +203,8 @@ impl<'a> System<'a> for Sys {
|
|||||||
WriteStorage<'a, Controller>,
|
WriteStorage<'a, Controller>,
|
||||||
Read<'a, Settings>,
|
Read<'a, Settings>,
|
||||||
Read<'a, BuildAreas>,
|
Read<'a, BuildAreas>,
|
||||||
|
Write<'a, PlayerPhysicsSettings>,
|
||||||
|
ReadStorage<'a, Player>,
|
||||||
);
|
);
|
||||||
|
|
||||||
const NAME: &'static str = "msg::in_game";
|
const NAME: &'static str = "msg::in_game";
|
||||||
@ -209,12 +230,19 @@ impl<'a> System<'a> for Sys {
|
|||||||
mut controllers,
|
mut controllers,
|
||||||
settings,
|
settings,
|
||||||
build_areas,
|
build_areas,
|
||||||
|
mut player_physics_settings,
|
||||||
|
players,
|
||||||
): Self::SystemData,
|
): Self::SystemData,
|
||||||
) {
|
) {
|
||||||
let mut server_emitter = server_event_bus.emitter();
|
let mut server_emitter = server_event_bus.emitter();
|
||||||
|
|
||||||
for (entity, client, mut maybe_presence) in
|
for (entity, client, mut maybe_presence, player) in (
|
||||||
(&entities, &mut clients, (&mut presences).maybe()).join()
|
&entities,
|
||||||
|
&mut clients,
|
||||||
|
(&mut presences).maybe(),
|
||||||
|
players.maybe(),
|
||||||
|
)
|
||||||
|
.join()
|
||||||
{
|
{
|
||||||
let _ = super::try_recv_all(client, 2, |client, msg| {
|
let _ = super::try_recv_all(client, 2, |client, msg| {
|
||||||
Self::handle_client_in_game_msg(
|
Self::handle_client_in_game_msg(
|
||||||
@ -234,6 +262,8 @@ impl<'a> System<'a> for Sys {
|
|||||||
&mut controllers,
|
&mut controllers,
|
||||||
&settings,
|
&settings,
|
||||||
&build_areas,
|
&build_areas,
|
||||||
|
&mut player_physics_settings,
|
||||||
|
&player,
|
||||||
msg,
|
msg,
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
|
@ -44,6 +44,8 @@ widget_ids! {
|
|||||||
auto_walk_behavior_list,
|
auto_walk_behavior_list,
|
||||||
camera_clamp_behavior_text,
|
camera_clamp_behavior_text,
|
||||||
camera_clamp_behavior_list,
|
camera_clamp_behavior_list,
|
||||||
|
player_physics_behavior_text,
|
||||||
|
player_physics_behavior_list,
|
||||||
stop_auto_walk_on_input_button,
|
stop_auto_walk_on_input_button,
|
||||||
stop_auto_walk_on_input_label,
|
stop_auto_walk_on_input_label,
|
||||||
auto_camera_button,
|
auto_camera_button,
|
||||||
@ -438,6 +440,43 @@ impl<'a> Widget for Gameplay<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Player physics behavior
|
||||||
|
Text::new(
|
||||||
|
&self
|
||||||
|
.localized_strings
|
||||||
|
.get("hud.settings.player_physics_behavior"),
|
||||||
|
)
|
||||||
|
.down_from(state.ids.auto_walk_behavior_list, 10.0)
|
||||||
|
.right_from(state.ids.camera_clamp_behavior_text, 118.0)
|
||||||
|
.font_size(self.fonts.cyri.scale(14))
|
||||||
|
.font_id(self.fonts.cyri.conrod_id)
|
||||||
|
.color(TEXT_COLOR)
|
||||||
|
.set(state.ids.player_physics_behavior_text, ui);
|
||||||
|
|
||||||
|
let player_physics_selected =
|
||||||
|
self.global_state.settings.gameplay.player_physics_behavior as usize;
|
||||||
|
|
||||||
|
if let Some(clicked) = DropDownList::new(
|
||||||
|
&["Client-authoritative", "Server-authoritative"],
|
||||||
|
Some(player_physics_selected),
|
||||||
|
)
|
||||||
|
.w_h(200.0, 30.0)
|
||||||
|
.color(MENU_BG)
|
||||||
|
.label_color(TEXT_COLOR)
|
||||||
|
.label_font_id(self.fonts.cyri.conrod_id)
|
||||||
|
.down_from(state.ids.player_physics_behavior_text, 8.0)
|
||||||
|
.set(state.ids.player_physics_behavior_list, ui)
|
||||||
|
{
|
||||||
|
match clicked {
|
||||||
|
0 => events.push(ChangePlayerPhysicsBehavior {
|
||||||
|
server_authoritative: false,
|
||||||
|
}),
|
||||||
|
_ => events.push(ChangePlayerPhysicsBehavior {
|
||||||
|
server_authoritative: true,
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Stop autowalk on input toggle
|
// Stop autowalk on input toggle
|
||||||
let stop_auto_walk_on_input_toggle = ToggleButton::new(
|
let stop_auto_walk_on_input_toggle = ToggleButton::new(
|
||||||
self.global_state.settings.gameplay.stop_auto_walk_on_input,
|
self.global_state.settings.gameplay.stop_auto_walk_on_input,
|
||||||
|
@ -88,6 +88,9 @@ impl SessionState {
|
|||||||
scene
|
scene
|
||||||
.camera_mut()
|
.camera_mut()
|
||||||
.set_fov_deg(global_state.settings.graphics.fov);
|
.set_fov_deg(global_state.settings.graphics.fov);
|
||||||
|
client
|
||||||
|
.borrow_mut()
|
||||||
|
.request_player_physics(global_state.settings.gameplay.player_physics_behavior);
|
||||||
let hud = Hud::new(global_state, &client.borrow());
|
let hud = Hud::new(global_state, &client.borrow());
|
||||||
let walk_forward_dir = scene.camera().forward_xy();
|
let walk_forward_dir = scene.camera().forward_xy();
|
||||||
let walk_right_dir = scene.camera().right_xy();
|
let walk_right_dir = scene.camera().right_xy();
|
||||||
|
@ -46,6 +46,7 @@ pub enum Gameplay {
|
|||||||
ChangeFreeLookBehavior(PressBehavior),
|
ChangeFreeLookBehavior(PressBehavior),
|
||||||
ChangeAutoWalkBehavior(PressBehavior),
|
ChangeAutoWalkBehavior(PressBehavior),
|
||||||
ChangeCameraClampBehavior(PressBehavior),
|
ChangeCameraClampBehavior(PressBehavior),
|
||||||
|
ChangePlayerPhysicsBehavior { server_authoritative: bool },
|
||||||
ChangeStopAutoWalkOnInput(bool),
|
ChangeStopAutoWalkOnInput(bool),
|
||||||
ChangeAutoCamera(bool),
|
ChangeAutoCamera(bool),
|
||||||
|
|
||||||
@ -224,6 +225,15 @@ impl SettingsChange {
|
|||||||
Gameplay::ChangeCameraClampBehavior(behavior) => {
|
Gameplay::ChangeCameraClampBehavior(behavior) => {
|
||||||
settings.gameplay.camera_clamp_behavior = behavior;
|
settings.gameplay.camera_clamp_behavior = behavior;
|
||||||
},
|
},
|
||||||
|
Gameplay::ChangePlayerPhysicsBehavior {
|
||||||
|
server_authoritative,
|
||||||
|
} => {
|
||||||
|
settings.gameplay.player_physics_behavior = server_authoritative;
|
||||||
|
session_state
|
||||||
|
.client
|
||||||
|
.borrow_mut()
|
||||||
|
.request_player_physics(server_authoritative);
|
||||||
|
},
|
||||||
Gameplay::ChangeStopAutoWalkOnInput(state) => {
|
Gameplay::ChangeStopAutoWalkOnInput(state) => {
|
||||||
settings.gameplay.stop_auto_walk_on_input = state;
|
settings.gameplay.stop_auto_walk_on_input = state;
|
||||||
},
|
},
|
||||||
|
@ -14,6 +14,7 @@ pub struct GameplaySettings {
|
|||||||
pub free_look_behavior: PressBehavior,
|
pub free_look_behavior: PressBehavior,
|
||||||
pub auto_walk_behavior: PressBehavior,
|
pub auto_walk_behavior: PressBehavior,
|
||||||
pub camera_clamp_behavior: PressBehavior,
|
pub camera_clamp_behavior: PressBehavior,
|
||||||
|
pub player_physics_behavior: bool,
|
||||||
pub stop_auto_walk_on_input: bool,
|
pub stop_auto_walk_on_input: bool,
|
||||||
pub auto_camera: bool,
|
pub auto_camera: bool,
|
||||||
}
|
}
|
||||||
@ -30,6 +31,7 @@ impl Default for GameplaySettings {
|
|||||||
free_look_behavior: PressBehavior::Toggle,
|
free_look_behavior: PressBehavior::Toggle,
|
||||||
auto_walk_behavior: PressBehavior::Toggle,
|
auto_walk_behavior: PressBehavior::Toggle,
|
||||||
camera_clamp_behavior: PressBehavior::Toggle,
|
camera_clamp_behavior: PressBehavior::Toggle,
|
||||||
|
player_physics_behavior: false,
|
||||||
stop_auto_walk_on_input: true,
|
stop_auto_walk_on_input: true,
|
||||||
auto_camera: false,
|
auto_camera: false,
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user