mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
update toolchain to nightly-2024-01-17
This commit is contained in:
parent
6743386c4e
commit
6ebbb89d4d
@ -235,7 +235,7 @@ impl BotClient {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
let c = list.characters.get(0).unwrap();
|
let c = list.characters.first().unwrap();
|
||||||
if let Some(id) = c.character.id {
|
if let Some(id) = c.character.id {
|
||||||
client.request_character(id, common::ViewDistances {
|
client.request_character(id, common::ViewDistances {
|
||||||
terrain: 5,
|
terrain: 5,
|
||||||
|
@ -15,6 +15,7 @@ pub struct PathEntry<S> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<S: Eq> PartialEq for PathEntry<S> {
|
impl<S: Eq> PartialEq for PathEntry<S> {
|
||||||
|
#[allow(clippy::unconditional_recursion)] // false positive as we use .node
|
||||||
fn eq(&self, other: &PathEntry<S>) -> bool { self.node.eq(&other.node) }
|
fn eq(&self, other: &PathEntry<S>) -> bool { self.node.eq(&other.node) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -35,7 +35,7 @@ where
|
|||||||
// Grab all comments from old file
|
// Grab all comments from old file
|
||||||
let source = fs::File::open(from.join(&path))?;
|
let source = fs::File::open(from.join(&path))?;
|
||||||
let mut comments = Vec::new();
|
let mut comments = Vec::new();
|
||||||
for line in BufReader::new(source).lines().flatten() {
|
for line in BufReader::new(source).lines().map_while(Result::ok) {
|
||||||
if let Some(idx) = line.find("//") {
|
if let Some(idx) = line.find("//") {
|
||||||
let comment = &line[idx..line.len()];
|
let comment = &line[idx..line.len()];
|
||||||
comments.push(comment.to_owned());
|
comments.push(comment.to_owned());
|
||||||
|
@ -307,7 +307,9 @@ pub mod figuredata {
|
|||||||
let dyna = base_structure.vol.map_into(|cell| {
|
let dyna = base_structure.vol.map_into(|cell| {
|
||||||
if let Some(i) = cell {
|
if let Some(i) = cell {
|
||||||
let color = base_structure.palette[u8::from(i) as usize];
|
let color = base_structure.palette[u8::from(i) as usize];
|
||||||
if let Some(block) = spec.custom_indices.get(&i.get()) && index == 0 {
|
if let Some(block) = spec.custom_indices.get(&i.get())
|
||||||
|
&& index == 0
|
||||||
|
{
|
||||||
block.to_block(color)
|
block.to_block(color)
|
||||||
} else {
|
} else {
|
||||||
Block::new(BlockKind::Misc, color)
|
Block::new(BlockKind::Misc, color)
|
||||||
|
@ -943,7 +943,6 @@ impl Inventory {
|
|||||||
/// account whether there will be free space in the inventory for the
|
/// account whether there will be free space in the inventory for the
|
||||||
/// loadout item once any slots that were provided by it have been
|
/// loadout item once any slots that were provided by it have been
|
||||||
/// removed.
|
/// removed.
|
||||||
#[allow(clippy::blocks_in_if_conditions)]
|
|
||||||
pub fn can_swap(&self, inv_slot_id: InvSlotId, equip_slot: EquipSlot) -> bool {
|
pub fn can_swap(&self, inv_slot_id: InvSlotId, equip_slot: EquipSlot) -> bool {
|
||||||
// Check if loadout slot can hold item
|
// Check if loadout slot can hold item
|
||||||
if !self.get(inv_slot_id).map_or(true, |item| {
|
if !self.get(inv_slot_id).map_or(true, |item| {
|
||||||
@ -1004,10 +1003,11 @@ impl Inventory {
|
|||||||
let (slots_mut, recently_unequipped_items) =
|
let (slots_mut, recently_unequipped_items) =
|
||||||
self.slots_mut_with_mutable_recently_unequipped_items();
|
self.slots_mut_with_mutable_recently_unequipped_items();
|
||||||
slots_mut.filter_map(|slot| slot.as_mut()).for_each(|item| {
|
slots_mut.filter_map(|slot| slot.as_mut()).for_each(|item| {
|
||||||
if item.durability_lost()
|
if item
|
||||||
.map_or(false, |dur| dur < Item::MAX_DURABILITY)
|
.durability_lost()
|
||||||
|
.map_or(false, |dur| dur < Item::MAX_DURABILITY)
|
||||||
&& let Some((_unequip_time, count)) =
|
&& let Some((_unequip_time, count)) =
|
||||||
recently_unequipped_items.get_mut(&item.item_definition_id())
|
recently_unequipped_items.get_mut(&item.item_definition_id())
|
||||||
&& *count > 0
|
&& *count > 0
|
||||||
{
|
{
|
||||||
*count -= 1;
|
*count -= 1;
|
||||||
|
@ -506,8 +506,8 @@ impl SkillSet {
|
|||||||
let prerequisites_met = this.prerequisites_met(skill);
|
let prerequisites_met = this.prerequisites_met(skill);
|
||||||
// Check that skill is not yet at max level
|
// Check that skill is not yet at max level
|
||||||
if !matches!(this.skills.get(&skill), Some(level) if *level == skill.max_level()) {
|
if !matches!(this.skills.get(&skill), Some(level) if *level == skill.max_level()) {
|
||||||
if let Some(skill_group) = this.skill_groups.get(&skill_group_kind) &&
|
if let Some(skill_group) = this.skill_groups.get(&skill_group_kind)
|
||||||
this.skill_group_accessible_if_exists(skill_group_kind)
|
&& this.skill_group_accessible_if_exists(skill_group_kind)
|
||||||
{
|
{
|
||||||
if prerequisites_met {
|
if prerequisites_met {
|
||||||
if let Some(new_available_sp) = skill_group
|
if let Some(new_available_sp) = skill_group
|
||||||
@ -521,8 +521,9 @@ impl SkillSet {
|
|||||||
// NOTE: Verified to exist previously when we accessed
|
// NOTE: Verified to exist previously when we accessed
|
||||||
// this.skill_groups (assuming a non-pathological implementation of
|
// this.skill_groups (assuming a non-pathological implementation of
|
||||||
// ToOwned).
|
// ToOwned).
|
||||||
let skill_group = this.skill_groups.get_mut(&skill_group_kind)
|
let skill_group = this.skill_groups.get_mut(&skill_group_kind).expect(
|
||||||
.expect("Verified to exist when we previously accessed this.skill_groups");
|
"Verified to exist when we previously accessed this.skill_groups",
|
||||||
|
);
|
||||||
skill_group.available_sp = new_available_sp;
|
skill_group.available_sp = new_available_sp;
|
||||||
skill_group.ordered_skills.push(skill);
|
skill_group.ordered_skills.push(skill);
|
||||||
match skill {
|
match skill {
|
||||||
|
@ -605,24 +605,36 @@ pub fn handle_orientation(
|
|||||||
(a.to_quat().into_vec4() - b.to_quat().into_vec4()).reduce(|a, b| a.abs() + b.abs())
|
(a.to_quat().into_vec4() - b.to_quat().into_vec4()).reduce(|a, b| a.abs() + b.abs())
|
||||||
}
|
}
|
||||||
|
|
||||||
let (tilt_ori, efficiency) = if let Body::Ship(ship) = data.body && ship.has_wheels() {
|
let (tilt_ori, efficiency) = if let Body::Ship(ship) = data.body
|
||||||
let height_at = |rpos| data
|
&& ship.has_wheels()
|
||||||
.terrain
|
{
|
||||||
.ray(
|
let height_at = |rpos| {
|
||||||
data.pos.0 + rpos + Vec3::unit_z() * 4.0,
|
data.terrain
|
||||||
data.pos.0 + rpos - Vec3::unit_z() * 4.0,
|
.ray(
|
||||||
)
|
data.pos.0 + rpos + Vec3::unit_z() * 4.0,
|
||||||
.until(Block::is_solid)
|
data.pos.0 + rpos - Vec3::unit_z() * 4.0,
|
||||||
.cast()
|
)
|
||||||
.0;
|
.until(Block::is_solid)
|
||||||
|
.cast()
|
||||||
|
.0
|
||||||
|
};
|
||||||
|
|
||||||
// Do some cheap raycasting with the ground to determine the appropriate orientation for the vehicle
|
// Do some cheap raycasting with the ground to determine the appropriate
|
||||||
let x_diff = (height_at(data.ori.to_horizontal().right().to_vec() * 3.0) - height_at(data.ori.to_horizontal().right().to_vec() * -3.0)) / 10.0;
|
// orientation for the vehicle
|
||||||
let y_diff = (height_at(data.ori.to_horizontal().look_dir().to_vec() * -4.5) - height_at(data.ori.to_horizontal().look_dir().to_vec() * 4.5)) / 10.0;
|
let x_diff = (height_at(data.ori.to_horizontal().right().to_vec() * 3.0)
|
||||||
|
- height_at(data.ori.to_horizontal().right().to_vec() * -3.0))
|
||||||
|
/ 10.0;
|
||||||
|
let y_diff = (height_at(data.ori.to_horizontal().look_dir().to_vec() * -4.5)
|
||||||
|
- height_at(data.ori.to_horizontal().look_dir().to_vec() * 4.5))
|
||||||
|
/ 10.0;
|
||||||
|
|
||||||
(
|
(
|
||||||
Quaternion::rotation_y(x_diff.atan()) * Quaternion::rotation_x(y_diff.atan()),
|
Quaternion::rotation_y(x_diff.atan()) * Quaternion::rotation_x(y_diff.atan()),
|
||||||
(data.vel.0 - data.physics.ground_vel).xy().magnitude().max(3.0) * efficiency,
|
(data.vel.0 - data.physics.ground_vel)
|
||||||
|
.xy()
|
||||||
|
.magnitude()
|
||||||
|
.max(3.0)
|
||||||
|
* efficiency,
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
(Quaternion::identity(), efficiency)
|
(Quaternion::identity(), efficiency)
|
||||||
|
@ -161,7 +161,7 @@ pub(crate) fn load_base_structure<B: Default>(
|
|||||||
mut to_block: impl FnMut(Rgb<u8>) -> B,
|
mut to_block: impl FnMut(Rgb<u8>) -> B,
|
||||||
) -> BaseStructure<B> {
|
) -> BaseStructure<B> {
|
||||||
let mut palette = std::array::from_fn(|_| B::default());
|
let mut palette = std::array::from_fn(|_| B::default());
|
||||||
if let Some(model) = dot_vox_data.models.get(0) {
|
if let Some(model) = dot_vox_data.models.first() {
|
||||||
for (i, col) in dot_vox_data
|
for (i, col) in dot_vox_data
|
||||||
.palette
|
.palette
|
||||||
.iter()
|
.iter()
|
||||||
|
@ -864,15 +864,18 @@ impl<'a> PhysicsData<'a> {
|
|||||||
character_state.map_or(false, |cs| matches!(cs, CharacterState::Climb(_)));
|
character_state.map_or(false, |cs| matches!(cs, CharacterState::Climb(_)));
|
||||||
|
|
||||||
let friction_factor = |vel: Vec3<f32>| {
|
let friction_factor = |vel: Vec3<f32>| {
|
||||||
if let Some(Body::Ship(ship)) = body && ship.has_wheels() {
|
if let Some(Body::Ship(ship)) = body
|
||||||
vel
|
&& ship.has_wheels()
|
||||||
.try_normalized()
|
{
|
||||||
.and_then(|dir| Some(orientations.get(entity)?.right().dot(dir).abs()))
|
vel.try_normalized()
|
||||||
.unwrap_or(1.0)
|
.and_then(|dir| {
|
||||||
.max(0.2)
|
Some(orientations.get(entity)?.right().dot(dir).abs())
|
||||||
} else {
|
})
|
||||||
1.0
|
.unwrap_or(1.0)
|
||||||
}
|
.max(0.2)
|
||||||
|
} else {
|
||||||
|
1.0
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
match &collider {
|
match &collider {
|
||||||
|
@ -7,8 +7,6 @@ pub use retrieve::*;
|
|||||||
|
|
||||||
use std::convert::TryInto;
|
use std::convert::TryInto;
|
||||||
|
|
||||||
pub use retrieve::*;
|
|
||||||
|
|
||||||
pub use plugin_api as api;
|
pub use plugin_api as api;
|
||||||
pub use plugin_derive::*;
|
pub use plugin_derive::*;
|
||||||
|
|
||||||
|
@ -110,11 +110,7 @@ fn rugged_ser_enum_map<
|
|||||||
map: &EnumMap<K, V>,
|
map: &EnumMap<K, V>,
|
||||||
ser: S,
|
ser: S,
|
||||||
) -> Result<S::Ok, S::Error> {
|
) -> Result<S::Ok, S::Error> {
|
||||||
ser.collect_map(
|
ser.collect_map(map.iter().filter(|(_, v)| v != &&V::from(DEFAULT)))
|
||||||
map.iter()
|
|
||||||
.filter(|(_, v)| v != &&V::from(DEFAULT))
|
|
||||||
.map(|(k, v)| (k, v)),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn rugged_de_enum_map<
|
fn rugged_de_enum_map<
|
||||||
|
@ -337,8 +337,10 @@ impl NpcLinks {
|
|||||||
if Actor::Npc(mount) == rider {
|
if Actor::Npc(mount) == rider {
|
||||||
return Err(MountingError::MountSelf);
|
return Err(MountingError::MountSelf);
|
||||||
}
|
}
|
||||||
if let Actor::Npc(rider) = rider && self.mount_map.contains_key(rider) {
|
if let Actor::Npc(rider) = rider
|
||||||
return Err(MountingError::RiderIsMounted);
|
&& self.mount_map.contains_key(rider)
|
||||||
|
{
|
||||||
|
return Err(MountingError::RiderIsMounted);
|
||||||
}
|
}
|
||||||
if self.rider_map.contains_key(&Actor::Npc(mount)) {
|
if self.rider_map.contains_key(&Actor::Npc(mount)) {
|
||||||
return Err(MountingError::MountIsRiding);
|
return Err(MountingError::MountIsRiding);
|
||||||
|
@ -1,10 +1,7 @@
|
|||||||
#![feature(
|
#![feature(
|
||||||
never_type,
|
never_type,
|
||||||
try_blocks,
|
try_blocks,
|
||||||
generator_trait,
|
|
||||||
generators,
|
|
||||||
trait_alias,
|
trait_alias,
|
||||||
trait_upcasting,
|
|
||||||
control_flow_enum,
|
control_flow_enum,
|
||||||
let_chains,
|
let_chains,
|
||||||
binary_heap_drain_sorted,
|
binary_heap_drain_sorted,
|
||||||
|
@ -61,23 +61,33 @@ impl Rule for Migrate {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reassign NPCs to sites if their old one was deleted. If they were already homeless, no need to do anything.
|
// Reassign NPCs to sites if their old one was deleted. If they were already
|
||||||
|
// homeless, no need to do anything.
|
||||||
for npc in data.npcs.values_mut() {
|
for npc in data.npcs.values_mut() {
|
||||||
if let Some(home) = npc.home
|
if let Some(home) = npc.home
|
||||||
&& !data.sites.contains_key(home)
|
&& !data.sites.contains_key(home)
|
||||||
{
|
{
|
||||||
// Choose the closest habitable site as the new home for the NPC
|
// Choose the closest habitable site as the new home for the NPC
|
||||||
npc.home = data.sites.sites
|
npc.home = data
|
||||||
|
.sites
|
||||||
|
.sites
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|(_, site)| {
|
.filter(|(_, site)| {
|
||||||
// TODO: This is a bit silly, but needs to wait on the removal of site1
|
// TODO: This is a bit silly, but needs to wait on the removal of site1
|
||||||
site.world_site.map_or(false, |ws| matches!(&ctx.index.sites.get(ws).kind, SiteKind::Refactor(_)
|
site.world_site.map_or(false, |ws| {
|
||||||
| SiteKind::CliffTown(_)
|
matches!(
|
||||||
| SiteKind::SavannahPit(_)
|
&ctx.index.sites.get(ws).kind,
|
||||||
| SiteKind::CoastalTown(_)
|
SiteKind::Refactor(_)
|
||||||
| SiteKind::DesertCity(_)))
|
| SiteKind::CliffTown(_)
|
||||||
|
| SiteKind::SavannahPit(_)
|
||||||
|
| SiteKind::CoastalTown(_)
|
||||||
|
| SiteKind::DesertCity(_)
|
||||||
|
)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.min_by_key(|(_, site)| {
|
||||||
|
site.wpos.as_().distance_squared(npc.wpos.xy()) as i32
|
||||||
})
|
})
|
||||||
.min_by_key(|(_, site)| site.wpos.as_().distance_squared(npc.wpos.xy()) as i32)
|
|
||||||
.map(|(site_id, _)| site_id);
|
.map(|(site_id, _)| site_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -594,25 +594,46 @@ fn talk_to<S: State>(tgt: Actor, _subject: Option<Subject>) -> impl Action<S> +
|
|||||||
&& let Some(current_site) = ctx.state.data().sites.get(current_site)
|
&& let Some(current_site) = ctx.state.data().sites.get(current_site)
|
||||||
&& let Some(mention_site) = current_site.nearby_sites_by_size.choose(&mut ctx.rng)
|
&& let Some(mention_site) = current_site.nearby_sites_by_size.choose(&mut ctx.rng)
|
||||||
&& let Some(mention_site) = ctx.state.data().sites.get(*mention_site)
|
&& let Some(mention_site) = ctx.state.data().sites.get(*mention_site)
|
||||||
&& let Some(mention_site_name) = mention_site.world_site
|
&& let Some(mention_site_name) = mention_site
|
||||||
|
.world_site
|
||||||
.map(|ws| ctx.index.sites.get(ws).name().to_string())
|
.map(|ws| ctx.index.sites.get(ws).name().to_string())
|
||||||
{
|
{
|
||||||
Content::localized_with_args("npc-speech-tell_site", [
|
Content::localized_with_args("npc-speech-tell_site", [
|
||||||
("site", Content::Plain(mention_site_name)),
|
("site", Content::Plain(mention_site_name)),
|
||||||
("dir", Direction::from_dir(mention_site.wpos.as_() - ctx.npc.wpos.xy()).localize_npc()),
|
(
|
||||||
("dist", Distance::from_length(mention_site.wpos.as_().distance(ctx.npc.wpos.xy()) as i32).localize_npc()),
|
"dir",
|
||||||
|
Direction::from_dir(mention_site.wpos.as_() - ctx.npc.wpos.xy())
|
||||||
|
.localize_npc(),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"dist",
|
||||||
|
Distance::from_length(
|
||||||
|
mention_site.wpos.as_().distance(ctx.npc.wpos.xy()) as i32
|
||||||
|
)
|
||||||
|
.localize_npc(),
|
||||||
|
),
|
||||||
])
|
])
|
||||||
// Mention nearby monsters
|
// Mention nearby monsters
|
||||||
} else if ctx.rng.gen_bool(0.3)
|
} else if ctx.rng.gen_bool(0.3)
|
||||||
&& let Some(monster) = ctx.state.data().npcs
|
&& let Some(monster) = ctx
|
||||||
|
.state
|
||||||
|
.data()
|
||||||
|
.npcs
|
||||||
.values()
|
.values()
|
||||||
.filter(|other| matches!(&other.role, Role::Monster))
|
.filter(|other| matches!(&other.role, Role::Monster))
|
||||||
.min_by_key(|other| other.wpos.xy().distance(ctx.npc.wpos.xy()) as i32)
|
.min_by_key(|other| other.wpos.xy().distance(ctx.npc.wpos.xy()) as i32)
|
||||||
{
|
{
|
||||||
Content::localized_with_args("npc-speech-tell_monster", [
|
Content::localized_with_args("npc-speech-tell_monster", [
|
||||||
("body", monster.body.localize_npc()),
|
("body", monster.body.localize_npc()),
|
||||||
("dir", Direction::from_dir(monster.wpos.xy() - ctx.npc.wpos.xy()).localize_npc()),
|
(
|
||||||
("dist", Distance::from_length(monster.wpos.xy().distance(ctx.npc.wpos.xy()) as i32).localize_npc()),
|
"dir",
|
||||||
|
Direction::from_dir(monster.wpos.xy() - ctx.npc.wpos.xy()).localize_npc(),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"dist",
|
||||||
|
Distance::from_length(monster.wpos.xy().distance(ctx.npc.wpos.xy()) as i32)
|
||||||
|
.localize_npc(),
|
||||||
|
),
|
||||||
])
|
])
|
||||||
} else {
|
} else {
|
||||||
ctx.npc.personality.get_generic_comment(&mut ctx.rng)
|
ctx.npc.personality.get_generic_comment(&mut ctx.rng)
|
||||||
|
@ -33,11 +33,18 @@ fn on_mount_volume(ctx: EventCtx<SimulateNpcs, OnMountVolume>) {
|
|||||||
let data = &mut *ctx.state.data_mut();
|
let data = &mut *ctx.state.data_mut();
|
||||||
|
|
||||||
// TODO: Add actor to riders.
|
// TODO: Add actor to riders.
|
||||||
if let VolumePos { kind: Volume::Entity(vehicle), .. } = ctx.event.pos
|
if let VolumePos {
|
||||||
|
kind: Volume::Entity(vehicle),
|
||||||
|
..
|
||||||
|
} = ctx.event.pos
|
||||||
&& let Some(link) = data.npcs.mounts.get_steerer_link(vehicle)
|
&& let Some(link) = data.npcs.mounts.get_steerer_link(vehicle)
|
||||||
&& let Actor::Npc(driver) = link.rider
|
&& let Actor::Npc(driver) = link.rider
|
||||||
&& let Some(driver) = data.npcs.get_mut(driver) {
|
&& let Some(driver) = data.npcs.get_mut(driver)
|
||||||
driver.controller.actions.push(NpcAction::Say(Some(ctx.event.actor), comp::Content::localized("npc-speech-welcome-aboard")))
|
{
|
||||||
|
driver.controller.actions.push(NpcAction::Say(
|
||||||
|
Some(ctx.event.actor),
|
||||||
|
comp::Content::localized("npc-speech-welcome-aboard"),
|
||||||
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -104,14 +104,14 @@ fn on_tick(ctx: EventCtx<SyncNpcs, OnTick>) {
|
|||||||
{
|
{
|
||||||
if let Some(site) = data.sites.get_mut(current_site) {
|
if let Some(site) = data.sites.get_mut(current_site) {
|
||||||
// TODO: Sites should have an inbox and their own AI code
|
// TODO: Sites should have an inbox and their own AI code
|
||||||
site.known_reports.extend(npc.known_reports
|
site.known_reports.extend(npc.known_reports.iter().copied());
|
||||||
.iter()
|
npc.inbox.extend(
|
||||||
.copied());
|
site.known_reports
|
||||||
npc.inbox.extend(site.known_reports
|
.iter()
|
||||||
.iter()
|
.copied()
|
||||||
.copied()
|
.filter(|report| !npc.known_reports.contains(report))
|
||||||
.filter(|report| !npc.known_reports.contains(report))
|
.map(NpcInput::Report),
|
||||||
.map(NpcInput::Report));
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1 +1 @@
|
|||||||
nightly-2023-09-28
|
nightly-2024-01-17
|
||||||
|
@ -221,7 +221,9 @@ impl ChatForwarder {
|
|||||||
while let Some(msg) = self.chat_r.recv().await {
|
while let Some(msg) = self.chat_r.recv().await {
|
||||||
let drop_older_than = msg.time.sub(self.keep_duration);
|
let drop_older_than = msg.time.sub(self.keep_duration);
|
||||||
let mut messages = self.messages.lock().await;
|
let mut messages = self.messages.lock().await;
|
||||||
while let Some(msg) = messages.front() && msg.time < drop_older_than {
|
while let Some(msg) = messages.front()
|
||||||
|
&& msg.time < drop_older_than
|
||||||
|
{
|
||||||
messages.pop_front();
|
messages.pop_front();
|
||||||
}
|
}
|
||||||
messages.push_back(msg);
|
messages.push_back(msg);
|
||||||
|
@ -549,7 +549,9 @@ pub fn handle_destroy(server: &mut Server, entity: EcsEntity, last_change: Healt
|
|||||||
|
|
||||||
// TODO: Do we need to do this if `should_delete` is true?
|
// TODO: Do we need to do this if `should_delete` is true?
|
||||||
// Modify durability on all equipped items
|
// Modify durability on all equipped items
|
||||||
if !resists_durability && let Some(mut inventory) = state.ecs().write_storage::<Inventory>().get_mut(entity) {
|
if !resists_durability
|
||||||
|
&& let Some(mut inventory) = state.ecs().write_storage::<Inventory>().get_mut(entity)
|
||||||
|
{
|
||||||
let ecs = state.ecs();
|
let ecs = state.ecs();
|
||||||
let ability_map = ecs.read_resource::<AbilityMap>();
|
let ability_map = ecs.read_resource::<AbilityMap>();
|
||||||
let msm = ecs.read_resource::<MaterialStatManifest>();
|
let msm = ecs.read_resource::<MaterialStatManifest>();
|
||||||
@ -1406,7 +1408,9 @@ pub fn handle_parry_hook(
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some(attacker) = attacker && matches!(source, AttackSource::Melee){
|
if let Some(attacker) = attacker
|
||||||
|
&& matches!(source, AttackSource::Melee)
|
||||||
|
{
|
||||||
// When attacker is parried, add the parried debuff for 2 seconds, which slows
|
// When attacker is parried, add the parried debuff for 2 seconds, which slows
|
||||||
// them
|
// them
|
||||||
let data = buff::BuffData::new(1.0, Some(Secs(2.0)));
|
let data = buff::BuffData::new(1.0, Some(Secs(2.0)));
|
||||||
|
@ -99,10 +99,12 @@ pub fn handle_npc_interaction(
|
|||||||
})
|
})
|
||||||
};
|
};
|
||||||
|
|
||||||
if within_range && let Some(agent) = state
|
if within_range
|
||||||
.ecs()
|
&& let Some(agent) = state
|
||||||
.write_storage::<comp::Agent>()
|
.ecs()
|
||||||
.get_mut(npc_entity) && agent.target.is_none()
|
.write_storage::<comp::Agent>()
|
||||||
|
.get_mut(npc_entity)
|
||||||
|
&& agent.target.is_none()
|
||||||
{
|
{
|
||||||
if let Some(interactor_uid) = state.ecs().uid_from_entity(interactor) {
|
if let Some(interactor_uid) = state.ecs().uid_from_entity(interactor) {
|
||||||
agent
|
agent
|
||||||
@ -179,21 +181,28 @@ pub fn handle_mount_volume(server: &mut Server, rider: EcsEntity, volume_pos: Vo
|
|||||||
);
|
);
|
||||||
|
|
||||||
if let Some((mat, _, block)) = block_transform
|
if let Some((mat, _, block)) = block_transform
|
||||||
&& let Some(mount_offset) = block.mount_offset() {
|
&& let Some(mount_offset) = block.mount_offset()
|
||||||
|
{
|
||||||
let mount_pos = (mat * mount_offset.0.with_w(1.0)).xyz();
|
let mount_pos = (mat * mount_offset.0.with_w(1.0)).xyz();
|
||||||
let within_range = {
|
let within_range = {
|
||||||
let positions = state.ecs().read_storage::<Pos>();
|
let positions = state.ecs().read_storage::<Pos>();
|
||||||
positions.get(rider).map_or(false, |pos| pos.0.distance_squared(mount_pos) < MAX_SPRITE_MOUNT_RANGE.powi(2))
|
positions.get(rider).map_or(false, |pos| {
|
||||||
|
pos.0.distance_squared(mount_pos) < MAX_SPRITE_MOUNT_RANGE.powi(2)
|
||||||
|
})
|
||||||
};
|
};
|
||||||
|
|
||||||
let maybe_uid = state.ecs().read_storage::<Uid>().get(rider).copied();
|
let maybe_uid = state.ecs().read_storage::<Uid>().get(rider).copied();
|
||||||
|
|
||||||
if let Some(rider) = maybe_uid && within_range {
|
if let Some(rider) = maybe_uid
|
||||||
let _link_successful = state.link(VolumeMounting {
|
&& within_range
|
||||||
pos: volume_pos,
|
{
|
||||||
block,
|
let _link_successful = state
|
||||||
rider,
|
.link(VolumeMounting {
|
||||||
}).is_ok();
|
pos: volume_pos,
|
||||||
|
block,
|
||||||
|
rider,
|
||||||
|
})
|
||||||
|
.is_ok();
|
||||||
#[cfg(feature = "worldgen")]
|
#[cfg(feature = "worldgen")]
|
||||||
if _link_successful {
|
if _link_successful {
|
||||||
let uid_allocator = state.ecs().read_resource::<IdMaps>();
|
let uid_allocator = state.ecs().read_resource::<IdMaps>();
|
||||||
@ -202,13 +211,20 @@ pub fn handle_mount_volume(server: &mut Server, rider: EcsEntity, volume_pos: Vo
|
|||||||
&& let Some(volume_pos) = volume_pos.try_map_entity(|uid| {
|
&& let Some(volume_pos) = volume_pos.try_map_entity(|uid| {
|
||||||
let entity = uid_allocator.uid_entity(uid)?;
|
let entity = uid_allocator.uid_entity(uid)?;
|
||||||
state.read_storage::<RtSimEntity>().get(entity).map(|v| v.0)
|
state.read_storage::<RtSimEntity>().get(entity).map(|v| v.0)
|
||||||
}) {
|
})
|
||||||
state.ecs().write_resource::<RtSim>().hook_character_mount_volume(
|
{
|
||||||
|
state
|
||||||
|
.ecs()
|
||||||
|
.write_resource::<RtSim>()
|
||||||
|
.hook_character_mount_volume(
|
||||||
&state.ecs().read_resource::<Arc<world::World>>(),
|
&state.ecs().read_resource::<Arc<world::World>>(),
|
||||||
state.ecs().read_resource::<world::IndexOwned>().as_index_ref(),
|
state
|
||||||
|
.ecs()
|
||||||
|
.read_resource::<world::IndexOwned>()
|
||||||
|
.as_index_ref(),
|
||||||
volume_pos,
|
volume_pos,
|
||||||
rider_actor,
|
rider_actor,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -53,7 +53,7 @@ pub fn snuff_lantern(storage: &mut WriteStorage<LightEmitter>, entity: EcsEntity
|
|||||||
storage.remove(entity);
|
storage.remove(entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(clippy::blocks_in_if_conditions)]
|
#[allow(clippy::blocks_in_conditions)]
|
||||||
pub fn handle_inventory(server: &mut Server, entity: EcsEntity, manip: comp::InventoryManip) {
|
pub fn handle_inventory(server: &mut Server, entity: EcsEntity, manip: comp::InventoryManip) {
|
||||||
let state = server.state_mut();
|
let state = server.state_mut();
|
||||||
|
|
||||||
|
@ -101,8 +101,8 @@ pub fn handle_exit_ingame(server: &mut Server, entity: EcsEntity, skip_persisten
|
|||||||
state.mut_resource::<IdMaps>().remap_entity(uid, new_entity);
|
state.mut_resource::<IdMaps>().remap_entity(uid, new_entity);
|
||||||
|
|
||||||
let ecs = state.ecs();
|
let ecs = state.ecs();
|
||||||
// Note, we use `delete_entity_common` directly to avoid `delete_entity_recorded` from
|
// Note, we use `delete_entity_common` directly to avoid
|
||||||
// making any changes to the group.
|
// `delete_entity_recorded` from making any changes to the group.
|
||||||
if let Some(group) = maybe_group {
|
if let Some(group) = maybe_group {
|
||||||
let mut group_manager = ecs.write_resource::<group::GroupManager>();
|
let mut group_manager = ecs.write_resource::<group::GroupManager>();
|
||||||
if group_manager
|
if group_manager
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#![deny(unsafe_code)]
|
#![deny(unsafe_code)]
|
||||||
#![allow(
|
#![allow(
|
||||||
clippy::option_map_unit_fn,
|
clippy::option_map_unit_fn,
|
||||||
|
clippy::blocks_in_conditions,
|
||||||
clippy::needless_pass_by_ref_mut //until we find a better way for specs
|
clippy::needless_pass_by_ref_mut //until we find a better way for specs
|
||||||
)]
|
)]
|
||||||
#![deny(clippy::clone_on_ref_ptr)]
|
#![deny(clippy::clone_on_ref_ptr)]
|
||||||
|
@ -89,15 +89,13 @@ pub fn handle_inbox_talk(bdata: &mut BehaviorData) -> bool {
|
|||||||
let by_entity = get_entity_by_id(by, read_data);
|
let by_entity = get_entity_by_id(by, read_data);
|
||||||
|
|
||||||
if let Some(rtsim_outbox) = &mut agent.rtsim_outbox {
|
if let Some(rtsim_outbox) = &mut agent.rtsim_outbox {
|
||||||
if let Subject::Regular
|
if let Subject::Regular | Subject::Mood | Subject::Work = subject
|
||||||
| Subject::Mood
|
|
||||||
| Subject::Work = subject
|
|
||||||
&& let Some(by_entity) = by_entity
|
&& let Some(by_entity) = by_entity
|
||||||
&& let Some(actor) = read_data.presences
|
&& let Some(actor) = read_data
|
||||||
|
.presences
|
||||||
.get(by_entity)
|
.get(by_entity)
|
||||||
.and_then(|p| p.kind.character_id().map(Actor::Character))
|
.and_then(|p| p.kind.character_id().map(Actor::Character))
|
||||||
.or_else(|| Some(Actor::Npc(read_data.rtsim_entities
|
.or_else(|| Some(Actor::Npc(read_data.rtsim_entities.get(by_entity)?.0)))
|
||||||
.get(by_entity)?.0)))
|
|
||||||
{
|
{
|
||||||
rtsim_outbox.push_back(NpcInput::Interaction(actor, subject));
|
rtsim_outbox.push_back(NpcInput::Interaction(actor, subject));
|
||||||
return false;
|
return false;
|
||||||
|
@ -334,8 +334,22 @@ impl<'a> System<'a> for Sys {
|
|||||||
);
|
);
|
||||||
|
|
||||||
if include_all_comps && let Some(&pos) = maybe_pos {
|
if include_all_comps && let Some(&pos) = maybe_pos {
|
||||||
let send_now = should_sync_client_physics(entity, &player_physics_settings, &players, &force_updates, is_rider);
|
let send_now = should_sync_client_physics(
|
||||||
add_physics_components(send_now, &mut comp_sync_package, uid, pos, last_pos, ori, vel);
|
entity,
|
||||||
|
&player_physics_settings,
|
||||||
|
&players,
|
||||||
|
&force_updates,
|
||||||
|
is_rider,
|
||||||
|
);
|
||||||
|
add_physics_components(
|
||||||
|
send_now,
|
||||||
|
&mut comp_sync_package,
|
||||||
|
uid,
|
||||||
|
pos,
|
||||||
|
last_pos,
|
||||||
|
ori,
|
||||||
|
vel,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if !comp_sync_package.is_empty() {
|
if !comp_sync_package.is_empty() {
|
||||||
|
@ -77,11 +77,13 @@ impl Sys {
|
|||||||
match msg {
|
match msg {
|
||||||
// Request spectator state
|
// Request spectator state
|
||||||
ClientGeneral::Spectate(requested_view_distances) => {
|
ClientGeneral::Spectate(requested_view_distances) => {
|
||||||
if let Some(admin) = admins.get(entity) && admin.0 >= AdminRole::Moderator {
|
if let Some(admin) = admins.get(entity)
|
||||||
|
&& admin.0 >= AdminRole::Moderator
|
||||||
|
{
|
||||||
send_join_messages()?;
|
send_join_messages()?;
|
||||||
|
|
||||||
server_emitter.emit(ServerEvent::InitSpectator(entity, requested_view_distances));
|
server_emitter
|
||||||
|
.emit(ServerEvent::InitSpectator(entity, requested_view_distances));
|
||||||
} else {
|
} else {
|
||||||
debug!("dropped Spectate msg from unprivileged client")
|
debug!("dropped Spectate msg from unprivileged client")
|
||||||
}
|
}
|
||||||
@ -96,8 +98,7 @@ impl Sys {
|
|||||||
// this.
|
// this.
|
||||||
if presences.contains(entity) {
|
if presences.contains(entity) {
|
||||||
debug!("player already ingame, aborting");
|
debug!("player already ingame, aborting");
|
||||||
} else if character_updater.has_pending_database_action(character_id)
|
} else if character_updater.has_pending_database_action(character_id) {
|
||||||
{
|
|
||||||
debug!("player recently logged out pending persistence, aborting");
|
debug!("player recently logged out pending persistence, aborting");
|
||||||
client.send(ServerGeneral::CharacterDataLoadResult(Err(
|
client.send(ServerGeneral::CharacterDataLoadResult(Err(
|
||||||
"You have recently logged out, please wait a few seconds and try again"
|
"You have recently logged out, please wait a few seconds and try again"
|
||||||
@ -171,19 +172,35 @@ impl Sys {
|
|||||||
body,
|
body,
|
||||||
character_updater,
|
character_updater,
|
||||||
start_site.and_then(|site_idx| {
|
start_site.and_then(|site_idx| {
|
||||||
// TODO: This corresponds to the ID generation logic in `world/src/lib.rs`
|
// TODO: This corresponds to the ID generation logic in
|
||||||
// Really, we should have a way to consistently refer to sites, but that's a job for rtsim2
|
// `world/src/lib.rs`. Really, we should have
|
||||||
// and the site changes that it will require. Until then, this code is very hacky.
|
// a way to consistently refer to sites, but that's a job for rtsim2
|
||||||
world.civs().sites.iter()
|
// and the site changes that it will require. Until then, this code is
|
||||||
|
// very hacky.
|
||||||
|
world
|
||||||
|
.civs()
|
||||||
|
.sites
|
||||||
|
.iter()
|
||||||
.find(|(_, site)| site.site_tmp.map(|i| i.id()) == Some(site_idx))
|
.find(|(_, site)| site.site_tmp.map(|i| i.id()) == Some(site_idx))
|
||||||
.map(Some)
|
.map(Some)
|
||||||
.unwrap_or_else(|| {
|
.unwrap_or_else(|| {
|
||||||
error!("Tried to create character with starting site index {}, but such a site does not exist", site_idx);
|
error!(
|
||||||
|
"Tried to create character with starting site index {}, \
|
||||||
|
but such a site does not exist",
|
||||||
|
site_idx
|
||||||
|
);
|
||||||
None
|
None
|
||||||
})
|
})
|
||||||
.map(|(_, site)| {
|
.map(|(_, site)| {
|
||||||
let wpos2d = TerrainChunkSize::center_wpos(site.center);
|
let wpos2d = TerrainChunkSize::center_wpos(site.center);
|
||||||
Waypoint::new(world.find_accessible_pos(index.as_index_ref(), wpos2d, false), time)
|
Waypoint::new(
|
||||||
|
world.find_accessible_pos(
|
||||||
|
index.as_index_ref(),
|
||||||
|
wpos2d,
|
||||||
|
false,
|
||||||
|
),
|
||||||
|
time,
|
||||||
|
)
|
||||||
})
|
})
|
||||||
}),
|
}),
|
||||||
) {
|
) {
|
||||||
|
@ -85,8 +85,12 @@ impl Sys {
|
|||||||
ClientGeneral::SetViewDistance(view_distances) => {
|
ClientGeneral::SetViewDistance(view_distances) => {
|
||||||
let clamped_vds = view_distances.clamp(settings.max_view_distance);
|
let clamped_vds = view_distances.clamp(settings.max_view_distance);
|
||||||
|
|
||||||
presence.terrain_view_distance.set_target(clamped_vds.terrain, time_for_vd_changes);
|
presence
|
||||||
presence.entity_view_distance.set_target(clamped_vds.entity, time_for_vd_changes);
|
.terrain_view_distance
|
||||||
|
.set_target(clamped_vds.terrain, time_for_vd_changes);
|
||||||
|
presence
|
||||||
|
.entity_view_distance
|
||||||
|
.set_target(clamped_vds.entity, time_for_vd_changes);
|
||||||
|
|
||||||
// Correct client if its requested VD is too high.
|
// Correct client if its requested VD is too high.
|
||||||
if view_distances.terrain != clamped_vds.terrain {
|
if view_distances.terrain != clamped_vds.terrain {
|
||||||
@ -101,7 +105,9 @@ impl Sys {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
ClientGeneral::ControlEvent(event) => {
|
ClientGeneral::ControlEvent(event) => {
|
||||||
if presence.kind.controlling_char() && let Some(controller) = controller {
|
if presence.kind.controlling_char()
|
||||||
|
&& let Some(controller) = controller
|
||||||
|
{
|
||||||
// Skip respawn if client entity is alive
|
// Skip respawn if client entity is alive
|
||||||
let skip_respawn = matches!(event, ControlEvent::Respawn)
|
let skip_respawn = matches!(event, ControlEvent::Respawn)
|
||||||
&& healths.get(entity).map_or(true, |h| !h.is_dead);
|
&& healths.get(entity).map_or(true, |h| !h.is_dead);
|
||||||
@ -118,9 +124,15 @@ impl Sys {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
ClientGeneral::PlayerPhysics { pos, vel, ori, force_counter } => {
|
ClientGeneral::PlayerPhysics {
|
||||||
|
pos,
|
||||||
|
vel,
|
||||||
|
ori,
|
||||||
|
force_counter,
|
||||||
|
} => {
|
||||||
if presence.kind.controlling_char()
|
if presence.kind.controlling_char()
|
||||||
&& force_update.map_or(true, |force_update| force_update.counter() == force_counter)
|
&& force_update
|
||||||
|
.map_or(true, |force_update| force_update.counter() == force_counter)
|
||||||
&& healths.get(entity).map_or(true, |h| !h.is_dead)
|
&& healths.get(entity).map_or(true, |h| !h.is_dead)
|
||||||
&& is_rider.get(entity).is_none()
|
&& is_rider.get(entity).is_none()
|
||||||
&& is_volume_rider.get(entity).is_none()
|
&& is_volume_rider.get(entity).is_none()
|
||||||
@ -146,10 +158,12 @@ impl Sys {
|
|||||||
let new_block = old_block.into_vacant();
|
let new_block = old_block.into_vacant();
|
||||||
// Take the rare writes lock as briefly as possible.
|
// Take the rare writes lock as briefly as possible.
|
||||||
let mut guard = rare_writes.lock();
|
let mut guard = rare_writes.lock();
|
||||||
let _was_set = guard.block_changes.try_set(pos, new_block).is_some();
|
let _was_set =
|
||||||
|
guard.block_changes.try_set(pos, new_block).is_some();
|
||||||
#[cfg(feature = "persistent_world")]
|
#[cfg(feature = "persistent_world")]
|
||||||
if _was_set {
|
if _was_set {
|
||||||
if let Some(terrain_persistence) = guard._terrain_persistence.as_mut()
|
if let Some(terrain_persistence) =
|
||||||
|
guard._terrain_persistence.as_mut()
|
||||||
{
|
{
|
||||||
terrain_persistence.set_block(pos, new_block);
|
terrain_persistence.set_block(pos, new_block);
|
||||||
}
|
}
|
||||||
@ -173,10 +187,12 @@ impl Sys {
|
|||||||
{
|
{
|
||||||
// Take the rare writes lock as briefly as possible.
|
// Take the rare writes lock as briefly as possible.
|
||||||
let mut guard = rare_writes.lock();
|
let mut guard = rare_writes.lock();
|
||||||
let _was_set = guard.block_changes.try_set(pos, new_block).is_some();
|
let _was_set =
|
||||||
|
guard.block_changes.try_set(pos, new_block).is_some();
|
||||||
#[cfg(feature = "persistent_world")]
|
#[cfg(feature = "persistent_world")]
|
||||||
if _was_set {
|
if _was_set {
|
||||||
if let Some(terrain_persistence) = guard._terrain_persistence.as_mut()
|
if let Some(terrain_persistence) =
|
||||||
|
guard._terrain_persistence.as_mut()
|
||||||
{
|
{
|
||||||
terrain_persistence.set_block(pos, new_block);
|
terrain_persistence.set_block(pos, new_block);
|
||||||
}
|
}
|
||||||
@ -188,9 +204,12 @@ impl Sys {
|
|||||||
},
|
},
|
||||||
ClientGeneral::UnlockSkill(skill) => {
|
ClientGeneral::UnlockSkill(skill) => {
|
||||||
// FIXME: How do we want to handle the error? Probably not by swallowing it.
|
// FIXME: How do we want to handle the error? Probably not by swallowing it.
|
||||||
let _ = skill_set.as_mut().map(|skill_set| {
|
let _ = skill_set
|
||||||
SkillSet::unlock_skill_cow(skill_set, skill, |skill_set| skill_set.to_mut())
|
.as_mut()
|
||||||
}).transpose();
|
.map(|skill_set| {
|
||||||
|
SkillSet::unlock_skill_cow(skill_set, skill, |skill_set| skill_set.to_mut())
|
||||||
|
})
|
||||||
|
.transpose();
|
||||||
},
|
},
|
||||||
ClientGeneral::RequestSiteInfo(id) => {
|
ClientGeneral::RequestSiteInfo(id) => {
|
||||||
server_emitter.emit(ServerEvent::RequestSiteInfo { entity, id });
|
server_emitter.emit(ServerEvent::RequestSiteInfo { entity, id });
|
||||||
@ -211,7 +230,10 @@ impl Sys {
|
|||||||
server_emitter.emit(ServerEvent::UpdateMapMarker { entity, update });
|
server_emitter.emit(ServerEvent::UpdateMapMarker { entity, update });
|
||||||
},
|
},
|
||||||
ClientGeneral::SpectatePosition(pos) => {
|
ClientGeneral::SpectatePosition(pos) => {
|
||||||
if let Some(admin) = maybe_admin && admin.0 >= AdminRole::Moderator && presence.kind == PresenceKind::Spectator {
|
if let Some(admin) = maybe_admin
|
||||||
|
&& admin.0 >= AdminRole::Moderator
|
||||||
|
&& presence.kind == PresenceKind::Spectator
|
||||||
|
{
|
||||||
if let Some(position) = position {
|
if let Some(position) = position {
|
||||||
position.0 = pos;
|
position.0 = pos;
|
||||||
}
|
}
|
||||||
|
@ -59,7 +59,9 @@ impl<'a> System<'a> for Sys {
|
|||||||
|
|
||||||
for (pet_entity, owner_pos) in lost_pets.iter() {
|
for (pet_entity, owner_pos) in lost_pets.iter() {
|
||||||
let stay = agn.get(*pet_entity).and_then(|x| x.stay_pos).is_some();
|
let stay = agn.get(*pet_entity).and_then(|x| x.stay_pos).is_some();
|
||||||
if let Some(pet_pos) = positions.get_mut(*pet_entity) && !stay{
|
if let Some(pet_pos) = positions.get_mut(*pet_entity)
|
||||||
|
&& !stay
|
||||||
|
{
|
||||||
// Move the pets to their owner's position
|
// Move the pets to their owner's position
|
||||||
// TODO: Create a teleportation event to handle this instead of
|
// TODO: Create a teleportation event to handle this instead of
|
||||||
// processing the entity position move here
|
// processing the entity position move here
|
||||||
|
@ -41,7 +41,7 @@ impl<'a> System<'a> for Sys {
|
|||||||
const ORIGIN: Origin = Origin::Server;
|
const ORIGIN: Origin = Origin::Server;
|
||||||
const PHASE: Phase = Phase::Create;
|
const PHASE: Phase = Phase::Create;
|
||||||
|
|
||||||
#[allow(clippy::blocks_in_if_conditions)] // TODO: Pending review in #587
|
#[allow(clippy::blocks_in_conditions)] // TODO: Pending review in #587
|
||||||
fn run(
|
fn run(
|
||||||
_job: &mut Job<Self>,
|
_job: &mut Job<Self>,
|
||||||
(
|
(
|
||||||
|
@ -22,6 +22,7 @@ use super::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
enum WeatherJobState {
|
enum WeatherJobState {
|
||||||
|
#[allow(dead_code)]
|
||||||
Working(SlowJob),
|
Working(SlowJob),
|
||||||
Idle(WeatherSim),
|
Idle(WeatherSim),
|
||||||
None,
|
None,
|
||||||
@ -108,7 +109,8 @@ impl<'a> System<'a> for Sys {
|
|||||||
|
|
||||||
if let Some(weather_job) = to_update {
|
if let Some(weather_job) = to_update {
|
||||||
if matches!(weather_job.state, WeatherJobState::Working(_))
|
if matches!(weather_job.state, WeatherJobState::Working(_))
|
||||||
&& let Ok((new_grid, new_lightning_cells, sim)) = weather_job.weather_rx.try_recv() {
|
&& let Ok((new_grid, new_lightning_cells, sim)) = weather_job.weather_rx.try_recv()
|
||||||
|
{
|
||||||
*grid = new_grid;
|
*grid = new_grid;
|
||||||
*lightning_cells = new_lightning_cells;
|
*lightning_cells = new_lightning_cells;
|
||||||
let mut lazy_msg = None;
|
let mut lazy_msg = None;
|
||||||
@ -121,7 +123,6 @@ impl<'a> System<'a> for Sys {
|
|||||||
lazy_msg.as_ref().map(|msg| client.send_prepared(msg));
|
lazy_msg.as_ref().map(|msg| client.send_prepared(msg));
|
||||||
}
|
}
|
||||||
weather_job.state = WeatherJobState::Idle(sim);
|
weather_job.state = WeatherJobState::Idle(sim);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if matches!(weather_job.state, WeatherJobState::Idle(_)) {
|
if matches!(weather_job.state, WeatherJobState::Idle(_)) {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
pub use ::vek::{
|
pub use ::vek::{
|
||||||
bezier::repr_simd::*, geom::repr_simd::*, mat::repr_simd::column_major::Mat4, ops::*,
|
geom::repr_simd::*, mat::repr_simd::column_major::Mat4, ops::*, quaternion::repr_simd::*,
|
||||||
quaternion::repr_simd::*, transform::repr_simd::*, transition::*, vec::repr_simd::*,
|
transform::repr_simd::*, transition::*, vec::repr_simd::*,
|
||||||
};
|
};
|
||||||
/*pub use ::vek::{
|
/*pub use ::vek::{
|
||||||
bezier::repr_c::*, geom::repr_c::*, mat::repr_c::column_major::Mat4, ops::*,
|
bezier::repr_c::*, geom::repr_c::*, mat::repr_c::column_major::Mat4, ops::*,
|
||||||
|
@ -134,7 +134,9 @@ pub fn localize_chat_message(
|
|||||||
let message_format = |from: &Uid, content: &Content, group: Option<&String>| {
|
let message_format = |from: &Uid, content: &Content, group: Option<&String>| {
|
||||||
let alias = name_format_or_complex(true, from);
|
let alias = name_format_or_complex(true, from);
|
||||||
|
|
||||||
let name = if let Some(pi) = info.player_info.get(from).cloned() && show_char_name {
|
let name = if let Some(pi) = info.player_info.get(from).cloned()
|
||||||
|
&& show_char_name
|
||||||
|
{
|
||||||
pi.character.map(|c| c.name)
|
pi.character.map(|c| c.name)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
|
@ -36,6 +36,7 @@ impl OggSound {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(clippy::implied_bounds_in_impls)]
|
||||||
pub fn load_ogg(specifier: &str) -> impl Source + Iterator<Item = i16> {
|
pub fn load_ogg(specifier: &str) -> impl Source + Iterator<Item = i16> {
|
||||||
OggSound::load_or_insert_with(specifier, |error| {
|
OggSound::load_or_insert_with(specifier, |error| {
|
||||||
warn!(?specifier, ?error, "Failed to load sound");
|
warn!(?specifier, ?error, "Failed to load sound");
|
||||||
|
@ -27,7 +27,7 @@ impl<'a> System<'a> for Sys {
|
|||||||
const ORIGIN: Origin = Origin::Frontend("voxygen");
|
const ORIGIN: Origin = Origin::Frontend("voxygen");
|
||||||
const PHASE: Phase = Phase::Create;
|
const PHASE: Phase = Phase::Create;
|
||||||
|
|
||||||
#[allow(clippy::blocks_in_if_conditions)] // TODO: Pending review in #587
|
#[allow(clippy::blocks_in_conditions)] // TODO: Pending review in #587
|
||||||
fn run(
|
fn run(
|
||||||
_job: &mut Job<Self>,
|
_job: &mut Job<Self>,
|
||||||
(entities, my_entity, dt, pos, healths, mut hp_floater_lists): Self::SystemData,
|
(entities, my_entity, dt, pos, healths, mut hp_floater_lists): Self::SystemData,
|
||||||
|
@ -719,7 +719,7 @@ impl<'a> Widget for Chat<'a> {
|
|||||||
// Update the history
|
// Update the history
|
||||||
// Don't add if this is identical to the last message in the history
|
// Don't add if this is identical to the last message in the history
|
||||||
s.history_pos = 0;
|
s.history_pos = 0;
|
||||||
if s.history.get(0).map_or(true, |h| h != &msg) {
|
if s.history.front().map_or(true, |h| h != &msg) {
|
||||||
s.history.push_front(msg.clone());
|
s.history.push_front(msg.clone());
|
||||||
s.history.truncate(self.history_max);
|
s.history.truncate(self.history_max);
|
||||||
}
|
}
|
||||||
|
@ -148,7 +148,7 @@ impl<'a> Widget for Group<'a> {
|
|||||||
//TODO: Disband groups when there's only one member in them
|
//TODO: Disband groups when there's only one member in them
|
||||||
//TODO: Always send health, energy, level and position of group members to the
|
//TODO: Always send health, energy, level and position of group members to the
|
||||||
// client
|
// client
|
||||||
#[allow(clippy::blocks_in_if_conditions)] // TODO: Pending review in #587
|
#[allow(clippy::blocks_in_conditions)] // TODO: Pending review in #587
|
||||||
fn update(self, args: widget::UpdateArgs<Self>) -> Self::Event {
|
fn update(self, args: widget::UpdateArgs<Self>) -> Self::Event {
|
||||||
common_base::prof_span!("Group::update");
|
common_base::prof_span!("Group::update");
|
||||||
let widget::UpdateArgs { state, ui, .. } = args;
|
let widget::UpdateArgs { state, ui, .. } = args;
|
||||||
|
@ -2042,9 +2042,14 @@ impl Hud {
|
|||||||
&& let Some((mat, _, _)) = pos.get_block_and_transform(
|
&& let Some((mat, _, _)) = pos.get_block_and_transform(
|
||||||
&ecs.read_resource(),
|
&ecs.read_resource(),
|
||||||
&ecs.read_resource(),
|
&ecs.read_resource(),
|
||||||
|e| ecs.read_storage::<vcomp::Interpolated>().get(e).map(|interpolated| (comp::Pos(interpolated.pos), interpolated.ori)),
|
|e| {
|
||||||
|
ecs.read_storage::<vcomp::Interpolated>()
|
||||||
|
.get(e)
|
||||||
|
.map(|interpolated| (comp::Pos(interpolated.pos), interpolated.ori))
|
||||||
|
},
|
||||||
&ecs.read_storage(),
|
&ecs.read_storage(),
|
||||||
) {
|
)
|
||||||
|
{
|
||||||
let overitem_id = overitem_walker.next(
|
let overitem_id = overitem_walker.next(
|
||||||
&mut self.ids.overitems,
|
&mut self.ids.overitems,
|
||||||
&mut ui_widgets.widget_id_generator(),
|
&mut ui_widgets.widget_id_generator(),
|
||||||
@ -2129,7 +2134,12 @@ impl Hud {
|
|||||||
BlockInteraction::Mount => {
|
BlockInteraction::Mount => {
|
||||||
let key = match block.get_sprite() {
|
let key = match block.get_sprite() {
|
||||||
Some(SpriteKind::Helm) => "hud-steer",
|
Some(SpriteKind::Helm) => "hud-steer",
|
||||||
Some(SpriteKind::Bed | SpriteKind::Bedroll | SpriteKind::BedrollSnow | SpriteKind::BedrollPirate) => "hud-lay",
|
Some(
|
||||||
|
SpriteKind::Bed
|
||||||
|
| SpriteKind::Bedroll
|
||||||
|
| SpriteKind::BedrollSnow
|
||||||
|
| SpriteKind::BedrollPirate,
|
||||||
|
) => "hud-lay",
|
||||||
_ => "hud-sit",
|
_ => "hud-sit",
|
||||||
};
|
};
|
||||||
vec![(Some(GameInput::Mount), i18n.get_msg(key).to_string())]
|
vec![(Some(GameInput::Mount), i18n.get_msg(key).to_string())]
|
||||||
@ -2141,7 +2151,12 @@ impl Hud {
|
|||||||
// TODO: change to turn on/turn off?
|
// TODO: change to turn on/turn off?
|
||||||
BlockInteraction::LightToggle(enable) => vec![(
|
BlockInteraction::LightToggle(enable) => vec![(
|
||||||
Some(GameInput::Interact),
|
Some(GameInput::Interact),
|
||||||
i18n.get_msg(if *enable { "hud-activate" } else { "hud-deactivate" }).to_string(),
|
i18n.get_msg(if *enable {
|
||||||
|
"hud-activate"
|
||||||
|
} else {
|
||||||
|
"hud-deactivate"
|
||||||
|
})
|
||||||
|
.to_string(),
|
||||||
)],
|
)],
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -2170,7 +2185,11 @@ impl Hud {
|
|||||||
// TODO: Handle this better. The items returned from `try_reclaim_from_block`
|
// TODO: Handle this better. The items returned from `try_reclaim_from_block`
|
||||||
// are based on rng. We probably want some function to get only gauranteed items
|
// are based on rng. We probably want some function to get only gauranteed items
|
||||||
// from `LootSpec`.
|
// from `LootSpec`.
|
||||||
else if let Some((amount, mut item)) = Item::try_reclaim_from_block(*block).into_iter().flatten().next() {
|
else if let Some((amount, mut item)) = Item::try_reclaim_from_block(*block)
|
||||||
|
.into_iter()
|
||||||
|
.flatten()
|
||||||
|
.next()
|
||||||
|
{
|
||||||
item.set_amount(amount.clamp(1, item.max_amount()))
|
item.set_amount(amount.clamp(1, item.max_amount()))
|
||||||
.expect("amount >= 1 and <= max_amount is always a valid amount");
|
.expect("amount >= 1 and <= max_amount is always a valid amount");
|
||||||
make_overitem(
|
make_overitem(
|
||||||
@ -2250,7 +2269,8 @@ impl Hud {
|
|||||||
"hud-activate"
|
"hud-activate"
|
||||||
} else {
|
} else {
|
||||||
"hud-use"
|
"hud-use"
|
||||||
}).to_string(),
|
})
|
||||||
|
.to_string(),
|
||||||
)],
|
)],
|
||||||
)
|
)
|
||||||
.x_y(0.0, 100.0)
|
.x_y(0.0, 100.0)
|
||||||
|
@ -7,7 +7,6 @@
|
|||||||
)]
|
)]
|
||||||
#![deny(clippy::clone_on_ref_ptr)]
|
#![deny(clippy::clone_on_ref_ptr)]
|
||||||
#![feature(
|
#![feature(
|
||||||
array_methods,
|
|
||||||
extract_if,
|
extract_if,
|
||||||
trait_alias,
|
trait_alias,
|
||||||
option_get_or_insert_default,
|
option_get_or_insert_default,
|
||||||
|
@ -498,7 +498,7 @@ impl Controls {
|
|||||||
self.selected = client
|
self.selected = client
|
||||||
.character_list()
|
.character_list()
|
||||||
.characters
|
.characters
|
||||||
.get(0)
|
.first()
|
||||||
.and_then(|i| i.character.id);
|
.and_then(|i| i.character.id);
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -76,6 +76,7 @@ impl ClientInit {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
let mut mismatched_server_info = None;
|
let mut mismatched_server_info = None;
|
||||||
|
#[allow(clippy::blocks_in_conditions)]
|
||||||
match Client::new(
|
match Client::new(
|
||||||
connection_args.clone(),
|
connection_args.clone(),
|
||||||
Arc::clone(&runtime2),
|
Arc::clone(&runtime2),
|
||||||
|
@ -63,7 +63,7 @@ where
|
|||||||
|vol: &mut V, pos: Vec3<i32>| vol.get(pos).map_or(true, |vox| !vox.is_filled());
|
|vol: &mut V, pos: Vec3<i32>| vol.get(pos).map_or(true, |vox| !vox.is_filled());
|
||||||
let should_draw = |vol: &mut V, pos: Vec3<i32>, delta: Vec3<i32>, uv| {
|
let should_draw = |vol: &mut V, pos: Vec3<i32>, delta: Vec3<i32>, uv| {
|
||||||
should_draw_greedy(pos, delta, uv, |vox| {
|
should_draw_greedy(pos, delta, uv, |vox| {
|
||||||
vol.get(vox).map(|vox| *vox).unwrap_or_else(|_| Cell::Empty)
|
vol.get(vox).copied().unwrap_or(Cell::Empty)
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
let create_opaque = |atlas_pos, pos, norm| {
|
let create_opaque = |atlas_pos, pos, norm| {
|
||||||
@ -167,9 +167,7 @@ where
|
|||||||
let get_opacity = |vol: &mut V, pos: Vec3<i32>| vol.get(pos).map_or(true, |vox| vox.is_fluid());
|
let get_opacity = |vol: &mut V, pos: Vec3<i32>| vol.get(pos).map_or(true, |vox| vox.is_fluid());
|
||||||
let should_draw = |vol: &mut V, pos: Vec3<i32>, delta: Vec3<i32>, _uv| {
|
let should_draw = |vol: &mut V, pos: Vec3<i32>, delta: Vec3<i32>, _uv| {
|
||||||
super::terrain::should_draw_greedy(pos, delta, |vox| {
|
super::terrain::should_draw_greedy(pos, delta, |vox| {
|
||||||
vol.get(vox)
|
vol.get(vox).copied().unwrap_or_else(|_| Block::empty())
|
||||||
.map(|vox| *vox)
|
|
||||||
.unwrap_or_else(|_| Block::empty())
|
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -271,7 +269,7 @@ where
|
|||||||
for y in -1..greedy_size.y + 1 {
|
for y in -1..greedy_size.y + 1 {
|
||||||
for z in -1..greedy_size.z + 1 {
|
for z in -1..greedy_size.z + 1 {
|
||||||
let wpos = lower_bound + Vec3::new(x, y, z);
|
let wpos = lower_bound + Vec3::new(x, y, z);
|
||||||
let block = vol.get(wpos).map(|b| *b).unwrap_or_else(|_| Cell::Empty);
|
let block = vol.get(wpos).copied().unwrap_or(Cell::Empty);
|
||||||
flat[i] = block;
|
flat[i] = block;
|
||||||
i += 1;
|
i += 1;
|
||||||
}
|
}
|
||||||
@ -395,7 +393,7 @@ where
|
|||||||
|vol: &mut V, pos: Vec3<i32>| vol.get(pos).map_or(true, |vox| !vox.is_filled());
|
|vol: &mut V, pos: Vec3<i32>| vol.get(pos).map_or(true, |vox| !vox.is_filled());
|
||||||
let should_draw = |vol: &mut V, pos: Vec3<i32>, delta: Vec3<i32>, uv| {
|
let should_draw = |vol: &mut V, pos: Vec3<i32>, delta: Vec3<i32>, uv| {
|
||||||
should_draw_greedy(pos, delta, uv, |vox| {
|
should_draw_greedy(pos, delta, uv, |vox| {
|
||||||
vol.get(vox).map(|vox| *vox).unwrap_or_else(|_| Cell::Empty)
|
vol.get(vox).copied().unwrap_or(Cell::Empty)
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
let create_opaque = |_atlas_pos, pos: Vec3<f32>, norm| ParticleVertex::new(pos, norm);
|
let create_opaque = |_atlas_pos, pos: Vec3<f32>, norm| ParticleVertex::new(pos, norm);
|
||||||
|
@ -305,7 +305,7 @@ pub fn generate_mesh<'a>(
|
|||||||
let wpos = range.min + Vec3::new(x, y, z);
|
let wpos = range.min + Vec3::new(x, y, z);
|
||||||
let block = volume
|
let block = volume
|
||||||
.get(wpos)
|
.get(wpos)
|
||||||
.map(|b| *b)
|
.copied()
|
||||||
// TODO: Replace with None or some other more reasonable value,
|
// TODO: Replace with None or some other more reasonable value,
|
||||||
// since it's not clear this will work properly with liquid.
|
// since it's not clear this will work properly with liquid.
|
||||||
.unwrap_or(AIR);
|
.unwrap_or(AIR);
|
||||||
|
@ -205,6 +205,7 @@ struct ArmorVoxSpec {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
|
#[allow(dead_code)]
|
||||||
enum ModularComponentSpec {
|
enum ModularComponentSpec {
|
||||||
/// item id, offset from origin to mount point
|
/// item id, offset from origin to mount point
|
||||||
Damage((String, [i32; 3])),
|
Damage((String, [i32; 3])),
|
||||||
|
@ -173,7 +173,9 @@ pub(super) fn select_interactable(
|
|||||||
// interactable. We are only returning the mineable air
|
// interactable. We are only returning the mineable air
|
||||||
// elements (e.g. minerals). The mineable weakrock are used
|
// elements (e.g. minerals). The mineable weakrock are used
|
||||||
// in the terrain selected_pos, but is not an interactable.
|
// in the terrain selected_pos, but is not an interactable.
|
||||||
if let Some(mine_tool) = b.mine_tool() && b.is_air() {
|
if let Some(mine_tool) = b.mine_tool()
|
||||||
|
&& b.is_air()
|
||||||
|
{
|
||||||
Some(Interactable::Block(
|
Some(Interactable::Block(
|
||||||
b,
|
b,
|
||||||
VolumePos::terrain(t.position_int()),
|
VolumePos::terrain(t.position_int()),
|
||||||
|
@ -990,8 +990,15 @@ impl PlayState for SessionState {
|
|||||||
))
|
))
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if let Some(pet_entity) = close_pet && client.state().read_storage::<Is<Mount>>().get(pet_entity).is_none() {
|
if let Some(pet_entity) = close_pet
|
||||||
let is_staying = client.state()
|
&& client
|
||||||
|
.state()
|
||||||
|
.read_storage::<Is<Mount>>()
|
||||||
|
.get(pet_entity)
|
||||||
|
.is_none()
|
||||||
|
{
|
||||||
|
let is_staying = client
|
||||||
|
.state()
|
||||||
.read_component_copied::<CharacterActivity>(pet_entity)
|
.read_component_copied::<CharacterActivity>(pet_entity)
|
||||||
.map_or(false, |activity| activity.is_pet_staying);
|
.map_or(false, |activity| activity.is_pet_staying);
|
||||||
client.set_pet_stay(pet_entity, !is_staying);
|
client.set_pet_stay(pet_entity, !is_staying);
|
||||||
|
@ -73,11 +73,10 @@ impl SingleplayerState {
|
|||||||
let mut settings = server::Settings::singleplayer(&server_data_dir);
|
let mut settings = server::Settings::singleplayer(&server_data_dir);
|
||||||
let editable_settings = server::EditableSettings::singleplayer(&server_data_dir);
|
let editable_settings = server::EditableSettings::singleplayer(&server_data_dir);
|
||||||
|
|
||||||
let file_opts = if let Some(gen_opts) = &world.gen_opts && !world.is_generated {
|
let file_opts = if let Some(gen_opts) = &world.gen_opts
|
||||||
server::FileOpts::Save(
|
&& !world.is_generated
|
||||||
world.map_path.clone(),
|
{
|
||||||
gen_opts.clone(),
|
server::FileOpts::Save(world.map_path.clone(), gen_opts.clone())
|
||||||
)
|
|
||||||
} else {
|
} else {
|
||||||
if !world.is_generated && world.gen_opts.is_none() {
|
if !world.is_generated && world.gen_opts.is_none() {
|
||||||
world.copy_default_world();
|
world.copy_default_world();
|
||||||
@ -114,6 +113,7 @@ impl SingleplayerState {
|
|||||||
|
|
||||||
let builder = thread::Builder::new().name("singleplayer-server-thread".into());
|
let builder = thread::Builder::new().name("singleplayer-server-thread".into());
|
||||||
let runtime = Arc::clone(runtime);
|
let runtime = Arc::clone(runtime);
|
||||||
|
#[allow(clippy::blocks_in_conditions)]
|
||||||
let thread = builder
|
let thread = builder
|
||||||
.spawn(move || {
|
.spawn(move || {
|
||||||
trace!("starting singleplayer server thread");
|
trace!("starting singleplayer server thread");
|
||||||
|
@ -593,6 +593,7 @@ where
|
|||||||
fn style(&self) -> Self::Style {}
|
fn style(&self) -> Self::Style {}
|
||||||
|
|
||||||
/// Update the state of the Slot.
|
/// Update the state of the Slot.
|
||||||
|
#[allow(clippy::useless_asref)] // false positive
|
||||||
fn update(mut self, args: widget::UpdateArgs<Self>) -> Self::Event {
|
fn update(mut self, args: widget::UpdateArgs<Self>) -> Self::Event {
|
||||||
let widget::UpdateArgs {
|
let widget::UpdateArgs {
|
||||||
id,
|
id,
|
||||||
|
@ -538,6 +538,7 @@ impl Window {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(clippy::get_first)]
|
||||||
pub fn fetch_events(&mut self) -> Vec<Event> {
|
pub fn fetch_events(&mut self) -> Vec<Event> {
|
||||||
span!(_guard, "fetch_events", "Window::fetch_events");
|
span!(_guard, "fetch_events", "Window::fetch_events");
|
||||||
// Refresh ui size (used when changing playstates)
|
// Refresh ui size (used when changing playstates)
|
||||||
|
@ -660,7 +660,7 @@ impl<'a, NN: NearestNeighbor, const N: u32> VoxelImageEncoding for PaletteEncodi
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn histogram_to_dictionary(histogram: &HashMap<Vec<u8>, usize>, dictionary: &mut Vec<u8>) {
|
fn histogram_to_dictionary(histogram: &HashMap<Vec<u8>, usize>, dictionary: &mut [u8]) {
|
||||||
let mut tmp: Vec<(Vec<u8>, usize)> = histogram.iter().map(|(k, v)| (k.clone(), *v)).collect();
|
let mut tmp: Vec<(Vec<u8>, usize)> = histogram.iter().map(|(k, v)| (k.clone(), *v)).collect();
|
||||||
tmp.sort_by_key(|(_, count)| *count);
|
tmp.sort_by_key(|(_, count)| *count);
|
||||||
debug!("{:?}", tmp.last());
|
debug!("{:?}", tmp.last());
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
#![allow(incomplete_features)]
|
#![allow(incomplete_features)]
|
||||||
#![allow(
|
#![allow(
|
||||||
clippy::option_map_unit_fn,
|
clippy::option_map_unit_fn,
|
||||||
clippy::blocks_in_if_conditions,
|
clippy::blocks_in_conditions,
|
||||||
clippy::identity_op,
|
clippy::identity_op,
|
||||||
clippy::needless_pass_by_ref_mut //until we find a better way for specs
|
clippy::needless_pass_by_ref_mut //until we find a better way for specs
|
||||||
)]
|
)]
|
||||||
|
@ -648,13 +648,16 @@ impl Floor {
|
|||||||
),
|
),
|
||||||
RoomKind::Peaceful | RoomKind::LavaPlatforming => {},
|
RoomKind::Peaceful | RoomKind::LavaPlatforming => {},
|
||||||
}
|
}
|
||||||
} else if let Some(Tile::UpStair(_, _)) = is_boss_tile && tile_wcenter.xy() == wpos2d {
|
} else if let Some(Tile::UpStair(_, _)) = is_boss_tile
|
||||||
|
&& tile_wcenter.xy() == wpos2d
|
||||||
|
{
|
||||||
// Create one teleporter at the top of the "stairs" and one at the botton
|
// Create one teleporter at the top of the "stairs" and one at the botton
|
||||||
let bottom_pos = tile_wcenter.map(|v| v as f32) ;
|
let bottom_pos = tile_wcenter.map(|v| v as f32);
|
||||||
let top_pos =
|
let top_pos =
|
||||||
(tile_wcenter + Vec3::unit_z() * self.total_depth()).map(|v| v as f32);
|
(tile_wcenter + Vec3::unit_z() * self.total_depth()).map(|v| v as f32);
|
||||||
|
|
||||||
// Move both a bit to the side to prevent teleportation loop, ideally we'd have the portals at another location
|
// Move both a bit to the side to prevent teleportation loop, ideally we'd have
|
||||||
|
// the portals at another location
|
||||||
supplement.add_entity(EntityInfo::at(top_pos).into_special(
|
supplement.add_entity(EntityInfo::at(top_pos).into_special(
|
||||||
SpecialEntity::Teleporter(PortalData {
|
SpecialEntity::Teleporter(PortalData {
|
||||||
target: bottom_pos + Vec3::unit_x() * 5.,
|
target: bottom_pos + Vec3::unit_x() * 5.,
|
||||||
@ -1187,7 +1190,9 @@ impl Floor {
|
|||||||
|
|
||||||
if let Some(room) = room.map(|i| self.rooms.get(*i)) {
|
if let Some(room) = room.map(|i| self.rooms.get(*i)) {
|
||||||
height = height.min(room.height);
|
height = height.min(room.height);
|
||||||
if let Tile::UpStair(_, kind) = tile && !self.final_level {
|
if let Tile::UpStair(_, kind) = tile
|
||||||
|
&& !self.final_level
|
||||||
|
{
|
||||||
// Construct the staircase that connects this tile to the matching DownStair
|
// Construct the staircase that connects this tile to the matching DownStair
|
||||||
// tile on the floor above (or to the surface if this is the top floor), and a
|
// tile on the floor above (or to the surface if this is the top floor), and a
|
||||||
// hollow bounding box to place air in
|
// hollow bounding box to place air in
|
||||||
@ -1203,10 +1208,13 @@ impl Floor {
|
|||||||
StairsKind::WallSpiral => Primitive::Aabb(aabb),
|
StairsKind::WallSpiral => Primitive::Aabb(aabb),
|
||||||
});
|
});
|
||||||
|
|
||||||
painter.fill(painter.prim(match kind {
|
painter.fill(
|
||||||
StairsKind::WallSpiral => Primitive::Aabb(outer_aabb),
|
painter.prim(match kind {
|
||||||
StairsKind::Spiral => Primitive::Cylinder(outer_aabb),
|
StairsKind::WallSpiral => Primitive::Aabb(outer_aabb),
|
||||||
}), Fill::Block(stone_wall));
|
StairsKind::Spiral => Primitive::Cylinder(outer_aabb),
|
||||||
|
}),
|
||||||
|
Fill::Block(stone_wall),
|
||||||
|
);
|
||||||
|
|
||||||
let stair = painter.prim(Primitive::sampling(bb, match kind {
|
let stair = painter.prim(Primitive::sampling(bb, match kind {
|
||||||
StairsKind::Spiral => spiral_staircase(center, radius, 0.5, 9.0),
|
StairsKind::Spiral => spiral_staircase(center, radius, 0.5, 9.0),
|
||||||
|
@ -1499,7 +1499,9 @@ impl Structure for Tavern {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if let Some(door) = wall.door_bounds() && !matches!(kinds, (Some(RoomKind::Garden), Some(RoomKind::Garden))) {
|
if let Some(door) = wall.door_bounds()
|
||||||
|
&& !matches!(kinds, (Some(RoomKind::Garden), Some(RoomKind::Garden)))
|
||||||
|
{
|
||||||
let orth = wall.to_dir.orthogonal();
|
let orth = wall.to_dir.orthogonal();
|
||||||
painter
|
painter
|
||||||
.aabb(aabb(Aabb {
|
.aabb(aabb(Aabb {
|
||||||
|
Loading…
Reference in New Issue
Block a user