mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Merge branch 'zesterer/toggle-light-sprites' into 'master'
Added the ability to toggle light sources on and off See merge request veloren/veloren!4267
This commit is contained in:
commit
92a8bc2806
@ -44,6 +44,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
- Potion of Agility
|
- Potion of Agility
|
||||||
- A way for servers to specify must-accept rules for players
|
- A way for servers to specify must-accept rules for players
|
||||||
- A flag argument type for commands
|
- A flag argument type for commands
|
||||||
|
- The ability to turn lamp-like sprites on and off
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
|
@ -40,6 +40,7 @@ hud-zoom_lock_indicator-remind = Zoom locked
|
|||||||
hud-zoom_lock_indicator-enable = Camera zoom locked
|
hud-zoom_lock_indicator-enable = Camera zoom locked
|
||||||
hud-zoom_lock_indicator-disable = Camera zoom unlocked
|
hud-zoom_lock_indicator-disable = Camera zoom unlocked
|
||||||
hud-activate = Activate
|
hud-activate = Activate
|
||||||
|
hud-deactivate = Deactivate
|
||||||
hud-collect = Collect
|
hud-collect = Collect
|
||||||
hud-pick_up = Pick up
|
hud-pick_up = Pick up
|
||||||
hud-open = Open
|
hud-open = Open
|
||||||
|
@ -1419,6 +1419,12 @@ impl Client {
|
|||||||
self.send_msg(ClientGeneral::ControlEvent(ControlEvent::DisableLantern));
|
self.send_msg(ClientGeneral::ControlEvent(ControlEvent::DisableLantern));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn toggle_sprite_light(&mut self, pos: VolumePos, enable: bool) {
|
||||||
|
self.control_action(ControlAction::InventoryAction(
|
||||||
|
InventoryAction::ToggleSpriteLight(pos, enable),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
pub fn remove_buff(&mut self, buff_id: BuffKind) {
|
pub fn remove_buff(&mut self, buff_id: BuffKind) {
|
||||||
self.send_msg(ClientGeneral::ControlEvent(ControlEvent::RemoveBuff(
|
self.send_msg(ClientGeneral::ControlEvent(ControlEvent::RemoveBuff(
|
||||||
buff_id,
|
buff_id,
|
||||||
|
@ -40,6 +40,9 @@ pub enum InventoryAction {
|
|||||||
Use(Slot),
|
Use(Slot),
|
||||||
Sort,
|
Sort,
|
||||||
Collect(Vec3<i32>),
|
Collect(Vec3<i32>),
|
||||||
|
// TODO: Not actually inventory-related: refactor to allow sprite interaction without
|
||||||
|
// inventory manipulation!
|
||||||
|
ToggleSpriteLight(VolumePos, bool),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
|
@ -4,6 +4,7 @@ pub const MAX_MOUNT_RANGE: f32 = 5.0;
|
|||||||
pub const MAX_SPRITE_MOUNT_RANGE: f32 = 2.0;
|
pub const MAX_SPRITE_MOUNT_RANGE: f32 = 2.0;
|
||||||
pub const MAX_TRADE_RANGE: f32 = 20.0;
|
pub const MAX_TRADE_RANGE: f32 = 20.0;
|
||||||
pub const MAX_NPCINTERACT_RANGE: f32 = 30.0;
|
pub const MAX_NPCINTERACT_RANGE: f32 = 30.0;
|
||||||
|
pub const MAX_INTERACT_RANGE: f32 = 5.0;
|
||||||
|
|
||||||
pub const GRAVITY: f32 = 25.0;
|
pub const GRAVITY: f32 = 25.0;
|
||||||
pub const FRIC_GROUND: f32 = 0.15;
|
pub const FRIC_GROUND: f32 = 0.15;
|
||||||
|
@ -338,6 +338,11 @@ pub enum ServerEvent {
|
|||||||
entity: EcsEntity,
|
entity: EcsEntity,
|
||||||
portal: EcsEntity,
|
portal: EcsEntity,
|
||||||
},
|
},
|
||||||
|
ToggleSpriteLight {
|
||||||
|
entity: EcsEntity,
|
||||||
|
pos: Vec3<i32>,
|
||||||
|
enable: bool,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct EventBus<E> {
|
pub struct EventBus<E> {
|
||||||
|
@ -117,8 +117,19 @@ impl CharacterBehavior for Data {
|
|||||||
sprite_pos: self.static_data.sprite_pos,
|
sprite_pos: self.static_data.sprite_pos,
|
||||||
required_item: inv_slot,
|
required_item: inv_slot,
|
||||||
};
|
};
|
||||||
output_events
|
|
||||||
.emit_server(ServerEvent::InventoryManip(data.entity, inv_manip));
|
match self.static_data.sprite_kind {
|
||||||
|
SpriteInteractKind::ToggleLight(enable) => {
|
||||||
|
output_events.emit_server(ServerEvent::ToggleSpriteLight {
|
||||||
|
entity: data.entity,
|
||||||
|
pos: self.static_data.sprite_pos,
|
||||||
|
enable,
|
||||||
|
})
|
||||||
|
},
|
||||||
|
_ => output_events
|
||||||
|
.emit_server(ServerEvent::InventoryManip(data.entity, inv_manip)),
|
||||||
|
}
|
||||||
|
|
||||||
if matches!(self.static_data.sprite_kind, SpriteInteractKind::Unlock) {
|
if matches!(self.static_data.sprite_kind, SpriteInteractKind::Unlock) {
|
||||||
output_events.emit_local(LocalEvent::CreateOutcome(
|
output_events.emit_local(LocalEvent::CreateOutcome(
|
||||||
Outcome::SpriteUnlocked {
|
Outcome::SpriteUnlocked {
|
||||||
@ -157,6 +168,7 @@ pub enum SpriteInteractKind {
|
|||||||
Collectible,
|
Collectible,
|
||||||
Unlock,
|
Unlock,
|
||||||
Fallback,
|
Fallback,
|
||||||
|
ToggleLight(bool),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<SpriteKind> for Option<SpriteInteractKind> {
|
impl From<SpriteKind> for Option<SpriteInteractKind> {
|
||||||
@ -233,6 +245,11 @@ impl SpriteInteractKind {
|
|||||||
Duration::from_secs_f32(1.0),
|
Duration::from_secs_f32(1.0),
|
||||||
Duration::from_secs_f32(0.3),
|
Duration::from_secs_f32(0.3),
|
||||||
),
|
),
|
||||||
|
Self::ToggleLight(_) => (
|
||||||
|
Duration::from_secs_f32(0.1),
|
||||||
|
Duration::from_secs_f32(0.2),
|
||||||
|
Duration::from_secs_f32(0.1),
|
||||||
|
),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,6 +20,7 @@ use crate::{
|
|||||||
},
|
},
|
||||||
consts::{FRIC_GROUND, GRAVITY, MAX_PICKUP_RANGE},
|
consts::{FRIC_GROUND, GRAVITY, MAX_PICKUP_RANGE},
|
||||||
event::{LocalEvent, ServerEvent},
|
event::{LocalEvent, ServerEvent},
|
||||||
|
mounting::Volume,
|
||||||
outcome::Outcome,
|
outcome::Outcome,
|
||||||
states::{behavior::JoinData, utils::CharacterState::Idle, *},
|
states::{behavior::JoinData, utils::CharacterState::Idle, *},
|
||||||
terrain::{Block, TerrainGrid, UnlockKind},
|
terrain::{Block, TerrainGrid, UnlockKind},
|
||||||
@ -1140,6 +1141,29 @@ pub fn handle_manipulate_loadout(
|
|||||||
let inv_manip = InventoryManip::Use(slot);
|
let inv_manip = InventoryManip::Use(slot);
|
||||||
output_events.emit_server(ServerEvent::InventoryManip(data.entity, inv_manip));
|
output_events.emit_server(ServerEvent::InventoryManip(data.entity, inv_manip));
|
||||||
},
|
},
|
||||||
|
InventoryAction::ToggleSpriteLight(pos, enable) => {
|
||||||
|
if matches!(pos.kind, Volume::Terrain) {
|
||||||
|
let sprite_interact = sprite_interact::SpriteInteractKind::ToggleLight(enable);
|
||||||
|
|
||||||
|
let (buildup_duration, use_duration, recover_duration) =
|
||||||
|
sprite_interact.durations();
|
||||||
|
|
||||||
|
update.character = CharacterState::SpriteInteract(sprite_interact::Data {
|
||||||
|
static_data: sprite_interact::StaticData {
|
||||||
|
buildup_duration,
|
||||||
|
use_duration,
|
||||||
|
recover_duration,
|
||||||
|
sprite_pos: pos.pos,
|
||||||
|
sprite_kind: sprite_interact,
|
||||||
|
was_wielded: data.character.is_wield(),
|
||||||
|
was_sneak: data.character.is_stealthy(),
|
||||||
|
required_item: None,
|
||||||
|
},
|
||||||
|
timer: Duration::default(),
|
||||||
|
stage_section: StageSection::Buildup,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -156,50 +156,44 @@ impl Block {
|
|||||||
|
|
||||||
/* Constructors */
|
/* Constructors */
|
||||||
|
|
||||||
// TODO: Rename to `filled`
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub const fn new(kind: BlockKind, color: Rgb<u8>) -> Self {
|
pub(super) const fn from_raw(kind: BlockKind, data: [u8; 3]) -> Self { Self { kind, data } }
|
||||||
// TODO: we should probably assert this, overwriting the data fields with a
|
|
||||||
// colour is bad news
|
|
||||||
/*
|
|
||||||
#[cfg(debug_assertions)]
|
|
||||||
assert!(kind.is_filled());
|
|
||||||
*/
|
|
||||||
|
|
||||||
Self {
|
// TODO: Rename to `filled`, make caller guarantees stronger
|
||||||
kind,
|
#[inline]
|
||||||
// Colours are only valid for non-fluids
|
#[track_caller]
|
||||||
data: if kind.is_filled() {
|
pub const fn new(kind: BlockKind, color: Rgb<u8>) -> Self {
|
||||||
[color.r, color.g, color.b]
|
if kind.is_filled() {
|
||||||
} else {
|
Self::from_raw(kind, [color.r, color.g, color.b])
|
||||||
[0; 3]
|
} else {
|
||||||
},
|
// Works because `SpriteKind::Empty` has no attributes
|
||||||
|
let data = (SpriteKind::Empty as u32).to_be_bytes();
|
||||||
|
Self::from_raw(kind, [data[1], data[2], data[3]])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Only valid if `block_kind` is unfilled, so this is just a private utility
|
// Only valid if `block_kind` is unfilled, so this is just a private utility
|
||||||
// method
|
// method
|
||||||
#[inline]
|
#[inline]
|
||||||
const fn unfilled(kind: BlockKind, sprite: SpriteKind) -> Self {
|
pub fn unfilled(kind: BlockKind, sprite: SpriteKind) -> Self {
|
||||||
#[cfg(debug_assertions)]
|
#[cfg(debug_assertions)]
|
||||||
assert!(!kind.is_filled());
|
assert!(!kind.is_filled());
|
||||||
|
|
||||||
let sprite_bytes = (sprite as u32).to_be_bytes();
|
Self::from_raw(kind, sprite.to_initial_bytes())
|
||||||
|
|
||||||
Self {
|
|
||||||
kind,
|
|
||||||
data: [sprite_bytes[1], sprite_bytes[2], sprite_bytes[3]],
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub const fn air(sprite: SpriteKind) -> Self { Self::unfilled(BlockKind::Air, sprite) }
|
pub fn air(sprite: SpriteKind) -> Self { Self::unfilled(BlockKind::Air, sprite) }
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub const fn empty() -> Self { Self::air(SpriteKind::Empty) }
|
pub const fn empty() -> Self {
|
||||||
|
// Works because `SpriteKind::Empty` has no attributes
|
||||||
|
let data = (SpriteKind::Empty as u32).to_be_bytes();
|
||||||
|
Self::from_raw(BlockKind::Air, [data[1], data[2], data[3]])
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub const fn water(sprite: SpriteKind) -> Self { Self::unfilled(BlockKind::Water, sprite) }
|
pub fn water(sprite: SpriteKind) -> Self { Self::unfilled(BlockKind::Water, sprite) }
|
||||||
|
|
||||||
/* Sprite decoding */
|
/* Sprite decoding */
|
||||||
|
|
||||||
@ -258,6 +252,9 @@ impl Block {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
pub(super) const fn data(&self) -> [u8; 3] { self.data }
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub(super) const fn with_data(mut self, data: [u8; 3]) -> Self {
|
pub(super) const fn with_data(mut self, data: [u8; 3]) -> Self {
|
||||||
self.data = data;
|
self.data = data;
|
||||||
@ -377,13 +374,13 @@ impl Block {
|
|||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn get_glow(&self) -> Option<u8> {
|
pub fn get_glow(&self) -> Option<u8> {
|
||||||
match self.kind() {
|
let glow_level = match self.kind() {
|
||||||
BlockKind::Lava => Some(24),
|
BlockKind::Lava => 24,
|
||||||
BlockKind::GlowingRock | BlockKind::GlowingWeakRock => Some(10),
|
BlockKind::GlowingRock | BlockKind::GlowingWeakRock => 10,
|
||||||
BlockKind::GlowingMushroom => Some(20),
|
BlockKind::GlowingMushroom => 20,
|
||||||
_ => match self.get_sprite()? {
|
_ => match self.get_sprite()? {
|
||||||
SpriteKind::StreetLamp | SpriteKind::StreetLampTall => Some(24),
|
SpriteKind::StreetLamp | SpriteKind::StreetLampTall => 24,
|
||||||
SpriteKind::Ember | SpriteKind::FireBlock => Some(20),
|
SpriteKind::Ember | SpriteKind::FireBlock => 20,
|
||||||
SpriteKind::WallLamp
|
SpriteKind::WallLamp
|
||||||
| SpriteKind::WallLampSmall
|
| SpriteKind::WallLampSmall
|
||||||
| SpriteKind::WallSconce
|
| SpriteKind::WallSconce
|
||||||
@ -391,8 +388,8 @@ impl Block {
|
|||||||
| SpriteKind::ChristmasOrnament
|
| SpriteKind::ChristmasOrnament
|
||||||
| SpriteKind::CliffDecorBlock
|
| SpriteKind::CliffDecorBlock
|
||||||
| SpriteKind::Orb
|
| SpriteKind::Orb
|
||||||
| SpriteKind::Candle => Some(16),
|
| SpriteKind::Candle => 16,
|
||||||
SpriteKind::DiamondLight => Some(30),
|
SpriteKind::DiamondLight => 30,
|
||||||
SpriteKind::Velorite
|
SpriteKind::Velorite
|
||||||
| SpriteKind::VeloriteFrag
|
| SpriteKind::VeloriteFrag
|
||||||
| SpriteKind::CavernGrassBlueShort
|
| SpriteKind::CavernGrassBlueShort
|
||||||
@ -400,12 +397,12 @@ impl Block {
|
|||||||
| SpriteKind::CavernGrassBlueLong
|
| SpriteKind::CavernGrassBlueLong
|
||||||
| SpriteKind::CavernLillypadBlue
|
| SpriteKind::CavernLillypadBlue
|
||||||
| SpriteKind::CavernMycelBlue
|
| SpriteKind::CavernMycelBlue
|
||||||
| SpriteKind::CeilingMushroom => Some(6),
|
| SpriteKind::CeilingMushroom => 6,
|
||||||
SpriteKind::CaveMushroom
|
SpriteKind::CaveMushroom
|
||||||
| SpriteKind::CookingPot
|
| SpriteKind::CookingPot
|
||||||
| SpriteKind::CrystalHigh
|
| SpriteKind::CrystalHigh
|
||||||
| SpriteKind::CrystalLow => Some(10),
|
| SpriteKind::CrystalLow => 10,
|
||||||
SpriteKind::SewerMushroom => Some(16),
|
SpriteKind::SewerMushroom => 16,
|
||||||
SpriteKind::Amethyst
|
SpriteKind::Amethyst
|
||||||
| SpriteKind::Ruby
|
| SpriteKind::Ruby
|
||||||
| SpriteKind::Sapphire
|
| SpriteKind::Sapphire
|
||||||
@ -417,14 +414,23 @@ impl Block {
|
|||||||
| SpriteKind::DiamondSmall
|
| SpriteKind::DiamondSmall
|
||||||
| SpriteKind::RubySmall
|
| SpriteKind::RubySmall
|
||||||
| SpriteKind::EmeraldSmall
|
| SpriteKind::EmeraldSmall
|
||||||
| SpriteKind::SapphireSmall => Some(3),
|
| SpriteKind::SapphireSmall => 3,
|
||||||
SpriteKind::Lantern => Some(24),
|
SpriteKind::Lantern => 24,
|
||||||
SpriteKind::SeashellLantern | SpriteKind::GlowIceCrystal => Some(16),
|
SpriteKind::SeashellLantern | SpriteKind::GlowIceCrystal => 16,
|
||||||
SpriteKind::SeaDecorEmblem => Some(12),
|
SpriteKind::SeaDecorEmblem => 12,
|
||||||
SpriteKind::SeaDecorBlock | SpriteKind::HaniwaKeyDoor => Some(10),
|
SpriteKind::SeaDecorBlock | SpriteKind::HaniwaKeyDoor => 10,
|
||||||
SpriteKind::Mine => Some(2),
|
SpriteKind::Mine => 2,
|
||||||
_ => None,
|
_ => return None,
|
||||||
},
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
if self
|
||||||
|
.get_attr::<sprite::LightEnabled>()
|
||||||
|
.map_or(true, |l| l.0)
|
||||||
|
{
|
||||||
|
Some(glow_level)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -625,6 +631,11 @@ impl Block {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Apply a light toggle to this block, if possible
|
||||||
|
pub fn with_toggle_light(self, enable: bool) -> Option<Self> {
|
||||||
|
self.with_attr(sprite::LightEnabled(enable)).ok()
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn kind(&self) -> BlockKind { self.kind }
|
pub fn kind(&self) -> BlockKind { self.kind }
|
||||||
|
|
||||||
@ -648,7 +659,7 @@ impl Block {
|
|||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn into_vacant(self) -> Self {
|
pub fn into_vacant(self) -> Self {
|
||||||
if self.is_fluid() {
|
if self.is_fluid() {
|
||||||
Block::new(self.kind(), Rgb::zero())
|
Block::unfilled(self.kind(), SpriteKind::Empty)
|
||||||
} else {
|
} else {
|
||||||
// FIXME: Figure out if there's some sensible way to determine what medium to
|
// FIXME: Figure out if there's some sensible way to determine what medium to
|
||||||
// replace a filled block with if it's removed.
|
// replace a filled block with if it's removed.
|
||||||
@ -675,24 +686,3 @@ impl Block {
|
|||||||
|
|
||||||
const _: () = assert!(core::mem::size_of::<BlockKind>() == 1);
|
const _: () = assert!(core::mem::size_of::<BlockKind>() == 1);
|
||||||
const _: () = assert!(core::mem::size_of::<Block>() == 4);
|
const _: () = assert!(core::mem::size_of::<Block>() == 4);
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests {
|
|
||||||
use super::*;
|
|
||||||
use strum::IntoEnumIterator;
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn convert_u32() {
|
|
||||||
for bk in BlockKind::iter() {
|
|
||||||
let block = Block::new(bk, Rgb::new(165, 90, 204)); // Pretty unique bit patterns
|
|
||||||
if bk.is_filled() {
|
|
||||||
assert_eq!(Block::from_u32(block.to_u32()), Some(block));
|
|
||||||
} else {
|
|
||||||
assert_eq!(
|
|
||||||
Block::from_u32(block.to_u32()),
|
|
||||||
Some(Block::new(bk, Rgb::zero())),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -286,7 +286,7 @@ impl TerrainChunk {
|
|||||||
pub fn water(sea_level: i32) -> TerrainChunk {
|
pub fn water(sea_level: i32) -> TerrainChunk {
|
||||||
TerrainChunk::new(
|
TerrainChunk::new(
|
||||||
sea_level,
|
sea_level,
|
||||||
Block::new(BlockKind::Water, Rgb::zero()),
|
Block::water(SpriteKind::Empty),
|
||||||
Block::air(SpriteKind::Empty),
|
Block::air(SpriteKind::Empty),
|
||||||
TerrainChunkMeta::void(),
|
TerrainChunkMeta::void(),
|
||||||
)
|
)
|
||||||
|
@ -120,18 +120,12 @@ sprites! {
|
|||||||
DungeonChest4 = 0x35,
|
DungeonChest4 = 0x35,
|
||||||
DungeonChest5 = 0x36,
|
DungeonChest5 = 0x36,
|
||||||
CoralChest = 0x37,
|
CoralChest = 0x37,
|
||||||
HaniwaUrn = 0x38,
|
HaniwaUrn = 0x38,
|
||||||
CommonLockedChest = 0x39,
|
CommonLockedChest = 0x39,
|
||||||
ChestBuried = 0x3A,
|
ChestBuried = 0x3A,
|
||||||
Crate = 0x3B,
|
Crate = 0x3B,
|
||||||
Barrel = 0x3C,
|
Barrel = 0x3C,
|
||||||
CrateBlock = 0x3D,
|
CrateBlock = 0x3D,
|
||||||
// Standalone lights
|
|
||||||
Lantern = 0x40,
|
|
||||||
StreetLamp = 0x41,
|
|
||||||
StreetLampTall = 0x42,
|
|
||||||
SeashellLantern = 0x43,
|
|
||||||
FireBowlGround = 0x44,
|
|
||||||
// Wall
|
// Wall
|
||||||
HangingBasket = 0x50,
|
HangingBasket = 0x50,
|
||||||
HangingSign = 0x51,
|
HangingSign = 0x51,
|
||||||
@ -355,21 +349,42 @@ sprites! {
|
|||||||
SeaDecorPillar = 0x1E,
|
SeaDecorPillar = 0x1E,
|
||||||
MagicalSeal = 0x1F,
|
MagicalSeal = 0x1F,
|
||||||
},
|
},
|
||||||
|
Lamp = 7 has Ori, LightEnabled {
|
||||||
|
// Standalone lights
|
||||||
|
Lantern = 0,
|
||||||
|
StreetLamp = 1,
|
||||||
|
StreetLampTall = 2,
|
||||||
|
SeashellLantern = 3,
|
||||||
|
FireBowlGround = 4,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
attributes! {
|
attributes! {
|
||||||
Ori { bits: 4, err: Infallible, from: |bits| Ok(Self(bits as u8)), into: |Ori(x)| x as u16 },
|
Ori { bits: 4, err: Infallible, from: |bits| Ok(Self(bits as u8)), into: |Ori(x)| x as u16 },
|
||||||
Growth { bits: 4, err: Infallible, from: |bits| Ok(Self(bits as u8)), into: |Growth(x)| x as u16 },
|
Growth { bits: 4, err: Infallible, from: |bits| Ok(Self(bits as u8)), into: |Growth(x)| x as u16 },
|
||||||
|
LightEnabled { bits: 1, err: Infallible, from: |bits| Ok(Self(bits == 1)), into: |LightEnabled(x)| x as u16 },
|
||||||
}
|
}
|
||||||
|
|
||||||
// The orientation of the sprite, 0..8
|
// The orientation of the sprite, 0..16
|
||||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
#[derive(Copy, Clone, Default, Debug, PartialEq, Eq)]
|
||||||
pub struct Ori(pub u8);
|
pub struct Ori(pub u8);
|
||||||
|
|
||||||
// The growth of the plant, 0..16
|
// The growth of the plant, 0..16
|
||||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||||
pub struct Growth(pub u8);
|
pub struct Growth(pub u8);
|
||||||
|
|
||||||
|
impl Default for Growth {
|
||||||
|
fn default() -> Self { Self(15) }
|
||||||
|
}
|
||||||
|
|
||||||
|
// Whether a light has been toggled on or off.
|
||||||
|
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||||
|
pub struct LightEnabled(pub bool);
|
||||||
|
|
||||||
|
impl Default for LightEnabled {
|
||||||
|
fn default() -> Self { Self(true) }
|
||||||
|
}
|
||||||
|
|
||||||
impl SpriteKind {
|
impl SpriteKind {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn solid_height(&self) -> Option<f32> {
|
pub fn solid_height(&self) -> Option<f32> {
|
||||||
|
@ -158,6 +158,15 @@ macro_rules! sprites {
|
|||||||
},)*
|
},)*
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline] pub(super) fn to_initial_bytes(self) -> [u8; 3] {
|
||||||
|
let sprite_bytes = (self as u32).to_be_bytes();
|
||||||
|
let block = Block::from_raw(super::BlockKind::Air, [sprite_bytes[1], sprite_bytes[2], sprite_bytes[3]]);
|
||||||
|
match self.category() {
|
||||||
|
$(Category::$category_name => block$($(.with_attr($attr::default()).unwrap())*)?,)*
|
||||||
|
}
|
||||||
|
.data()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -170,12 +179,14 @@ pub enum AttributeError<E> {
|
|||||||
Attribute(E),
|
Attribute(E),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait Attribute: Sized {
|
pub trait Attribute: Default + Sized {
|
||||||
/// The unique index assigned to this attribute, used to index offset arrays
|
/// The unique index assigned to this attribute, used to index offset
|
||||||
|
/// arrays.
|
||||||
const INDEX: usize;
|
const INDEX: usize;
|
||||||
/// The number of bits required to represent this attribute
|
/// The number of bits required to represent this attribute.
|
||||||
const BITS: u8;
|
const BITS: u8;
|
||||||
type Error;
|
/// The error that might occur when decoding the attribute from bits.
|
||||||
|
type Error: core::fmt::Debug;
|
||||||
fn from_bits(bits: u16) -> Result<Self, Self::Error>;
|
fn from_bits(bits: u16) -> Result<Self, Self::Error>;
|
||||||
fn into_bits(self) -> u16;
|
fn into_bits(self) -> u16;
|
||||||
}
|
}
|
||||||
|
@ -15,7 +15,7 @@ use common::{
|
|||||||
Inventory, LootOwner, Pos, SkillGroupKind,
|
Inventory, LootOwner, Pos, SkillGroupKind,
|
||||||
},
|
},
|
||||||
consts::{
|
consts::{
|
||||||
MAX_MOUNT_RANGE, MAX_NPCINTERACT_RANGE, MAX_SPRITE_MOUNT_RANGE,
|
MAX_INTERACT_RANGE, MAX_MOUNT_RANGE, MAX_NPCINTERACT_RANGE, MAX_SPRITE_MOUNT_RANGE,
|
||||||
SOUND_TRAVEL_DIST_PER_VOLUME,
|
SOUND_TRAVEL_DIST_PER_VOLUME,
|
||||||
},
|
},
|
||||||
event::EventBus,
|
event::EventBus,
|
||||||
@ -194,7 +194,7 @@ pub fn handle_mount_volume(server: &mut Server, rider: EcsEntity, volume_pos: Vo
|
|||||||
block,
|
block,
|
||||||
rider,
|
rider,
|
||||||
}).is_ok();
|
}).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>();
|
||||||
if let Some(rider_entity) = uid_allocator.uid_entity(rider)
|
if let Some(rider_entity) = uid_allocator.uid_entity(rider)
|
||||||
@ -469,3 +469,27 @@ pub fn handle_tame_pet(server: &mut Server, pet_entity: EcsEntity, owner_entity:
|
|||||||
// showing taming success?
|
// showing taming success?
|
||||||
tame_pet(server.state.ecs(), pet_entity, owner_entity);
|
tame_pet(server.state.ecs(), pet_entity, owner_entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn handle_toggle_sprite_light(
|
||||||
|
server: &mut Server,
|
||||||
|
entity: EcsEntity,
|
||||||
|
pos: Vec3<i32>,
|
||||||
|
enable: bool,
|
||||||
|
) {
|
||||||
|
let state = server.state_mut();
|
||||||
|
// TODO: Implement toggling lights on volume entities
|
||||||
|
if let Some(entity_pos) = state.ecs().read_storage::<Pos>().get(entity)
|
||||||
|
&& entity_pos.0.distance_squared(pos.as_()) < MAX_INTERACT_RANGE.powi(2)
|
||||||
|
&& state.can_set_block(pos)
|
||||||
|
{
|
||||||
|
if let Some(new_block) = state
|
||||||
|
.terrain()
|
||||||
|
.get(pos)
|
||||||
|
.ok()
|
||||||
|
.and_then(|block| block.with_toggle_light(enable))
|
||||||
|
{
|
||||||
|
state.set_block(pos, new_block);
|
||||||
|
// TODO: Emit outcome
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -26,7 +26,7 @@ use group_manip::handle_group;
|
|||||||
use information::handle_site_info;
|
use information::handle_site_info;
|
||||||
use interaction::{
|
use interaction::{
|
||||||
handle_create_sprite, handle_lantern, handle_mine_block, handle_mount, handle_npc_interaction,
|
handle_create_sprite, handle_lantern, handle_mine_block, handle_mount, handle_npc_interaction,
|
||||||
handle_set_pet_stay, handle_sound, handle_unmount,
|
handle_set_pet_stay, handle_sound, handle_toggle_sprite_light, handle_unmount,
|
||||||
};
|
};
|
||||||
use inventory_manip::handle_inventory;
|
use inventory_manip::handle_inventory;
|
||||||
use invite::{handle_invite, handle_invite_response};
|
use invite::{handle_invite, handle_invite_response};
|
||||||
@ -305,6 +305,11 @@ impl Server {
|
|||||||
ServerEvent::StartTeleporting { entity, portal } => {
|
ServerEvent::StartTeleporting { entity, portal } => {
|
||||||
handle_start_teleporting(self, entity, portal)
|
handle_start_teleporting(self, entity, portal)
|
||||||
},
|
},
|
||||||
|
ServerEvent::ToggleSpriteLight {
|
||||||
|
entity,
|
||||||
|
pos,
|
||||||
|
enable,
|
||||||
|
} => handle_toggle_sprite_light(self, entity, pos, enable),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2161,6 +2161,11 @@ impl Hud {
|
|||||||
Some(GameInput::Interact),
|
Some(GameInput::Interact),
|
||||||
i18n.get_msg("hud-read").to_string(),
|
i18n.get_msg("hud-read").to_string(),
|
||||||
)],
|
)],
|
||||||
|
// TODO: change to turn on/turn off?
|
||||||
|
BlockInteraction::LightToggle(enable) => vec![(
|
||||||
|
Some(GameInput::Interact),
|
||||||
|
i18n.get_msg(if *enable { "hud-activate" } else { "hud-deactivate" }).to_string(),
|
||||||
|
)],
|
||||||
};
|
};
|
||||||
|
|
||||||
// This is only done once per frame, so it's not a performance issue
|
// This is only done once per frame, so it's not a performance issue
|
||||||
|
@ -294,7 +294,7 @@ pub fn generate_mesh<'a>(
|
|||||||
let d = d + 2;
|
let d = d + 2;
|
||||||
let flat = {
|
let flat = {
|
||||||
let mut volume = vol.cached();
|
let mut volume = vol.cached();
|
||||||
const AIR: Block = Block::air(common::terrain::sprite::SpriteKind::Empty);
|
const AIR: Block = Block::empty();
|
||||||
// TODO: Once we can manage it sensibly, consider using something like
|
// TODO: Once we can manage it sensibly, consider using something like
|
||||||
// Option<Block> instead of just assuming air.
|
// Option<Block> instead of just assuming air.
|
||||||
let mut flat = vec![AIR; (w * h * d) as usize];
|
let mut flat = vec![AIR; (w * h * d) as usize];
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use crate::hud::CraftingTab;
|
use crate::hud::CraftingTab;
|
||||||
use common::{
|
use common::{
|
||||||
terrain::{Block, BlockKind, SpriteKind},
|
terrain::{sprite, Block, BlockKind, SpriteKind},
|
||||||
vol::ReadVol,
|
vol::ReadVol,
|
||||||
};
|
};
|
||||||
use common_base::span;
|
use common_base::span;
|
||||||
@ -16,6 +16,7 @@ pub enum Interaction {
|
|||||||
Craft(CraftingTab),
|
Craft(CraftingTab),
|
||||||
Mount,
|
Mount,
|
||||||
Read,
|
Read,
|
||||||
|
LightToggle(bool),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum FireplaceType {
|
pub enum FireplaceType {
|
||||||
@ -138,80 +139,96 @@ impl BlocksOfInterest {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
BlockKind::Snow | BlockKind::Ice if rng.gen_range(0..16) == 0 => snow.push(pos),
|
BlockKind::Snow | BlockKind::Ice if rng.gen_range(0..16) == 0 => snow.push(pos),
|
||||||
_ => match block.get_sprite() {
|
_ => {
|
||||||
Some(SpriteKind::Ember) => {
|
if let Some(sprite) = block.get_sprite() {
|
||||||
fires.push(pos);
|
if sprite.category() == sprite::Category::Lamp {
|
||||||
smokers.push(SmokerProperties::new(pos, FireplaceType::House));
|
if let Ok(sprite::LightEnabled(enabled)) = block.get_attr() {
|
||||||
},
|
interactables.push((pos, Interaction::LightToggle(!enabled)));
|
||||||
// Offset positions to account for block height.
|
}
|
||||||
// TODO: Is this a good idea?
|
|
||||||
Some(SpriteKind::StreetLamp) => fire_bowls.push(pos + Vec3::unit_z() * 2),
|
|
||||||
Some(SpriteKind::FireBowlGround) => fire_bowls.push(pos + Vec3::unit_z()),
|
|
||||||
Some(SpriteKind::StreetLampTall) => fire_bowls.push(pos + Vec3::unit_z() * 4),
|
|
||||||
Some(SpriteKind::WallSconce) => fire_bowls.push(pos + Vec3::unit_z()),
|
|
||||||
Some(SpriteKind::Beehive) => beehives.push(pos),
|
|
||||||
Some(SpriteKind::CrystalHigh) => fireflies.push(pos),
|
|
||||||
Some(SpriteKind::Reed) => {
|
|
||||||
reeds.push(pos);
|
|
||||||
fireflies.push(pos);
|
|
||||||
if rng.gen_range(0..12) == 0 {
|
|
||||||
frogs.push(pos);
|
|
||||||
}
|
}
|
||||||
},
|
|
||||||
Some(SpriteKind::CaveMushroom) => fireflies.push(pos),
|
if block.is_mountable() {
|
||||||
Some(SpriteKind::PinkFlower) => flowers.push(pos),
|
interactables.push((pos, Interaction::Mount));
|
||||||
Some(SpriteKind::PurpleFlower) => flowers.push(pos),
|
}
|
||||||
Some(SpriteKind::RedFlower) => flowers.push(pos),
|
|
||||||
Some(SpriteKind::WhiteFlower) => flowers.push(pos),
|
match sprite {
|
||||||
Some(SpriteKind::YellowFlower) => flowers.push(pos),
|
SpriteKind::Ember => {
|
||||||
Some(SpriteKind::Sunflower) => flowers.push(pos),
|
fires.push(pos);
|
||||||
Some(SpriteKind::CraftingBench) => {
|
smokers.push(SmokerProperties::new(pos, FireplaceType::House));
|
||||||
interactables.push((pos, Interaction::Craft(CraftingTab::All)))
|
},
|
||||||
},
|
// Offset positions to account for block height.
|
||||||
Some(SpriteKind::SmokeDummy) => {
|
// TODO: Is this a good idea?
|
||||||
smokers.push(SmokerProperties::new(pos, FireplaceType::Workshop));
|
SpriteKind::StreetLamp => fire_bowls.push(pos + Vec3::unit_z() * 2),
|
||||||
},
|
SpriteKind::FireBowlGround => fire_bowls.push(pos + Vec3::unit_z()),
|
||||||
Some(SpriteKind::Forge) => interactables
|
SpriteKind::StreetLampTall => fire_bowls.push(pos + Vec3::unit_z() * 4),
|
||||||
.push((pos, Interaction::Craft(CraftingTab::ProcessedMaterial))),
|
SpriteKind::WallSconce => fire_bowls.push(pos + Vec3::unit_z()),
|
||||||
Some(SpriteKind::TanningRack) => interactables
|
SpriteKind::Beehive => beehives.push(pos),
|
||||||
.push((pos, Interaction::Craft(CraftingTab::ProcessedMaterial))),
|
SpriteKind::CrystalHigh => fireflies.push(pos),
|
||||||
Some(SpriteKind::SpinningWheel) => {
|
SpriteKind::Reed => {
|
||||||
interactables.push((pos, Interaction::Craft(CraftingTab::All)))
|
reeds.push(pos);
|
||||||
},
|
fireflies.push(pos);
|
||||||
Some(SpriteKind::Loom) => {
|
if rng.gen_range(0..12) == 0 {
|
||||||
interactables.push((pos, Interaction::Craft(CraftingTab::All)))
|
frogs.push(pos);
|
||||||
},
|
}
|
||||||
Some(SpriteKind::Cauldron) => {
|
},
|
||||||
fires.push(pos);
|
SpriteKind::CaveMushroom => fireflies.push(pos),
|
||||||
interactables.push((pos, Interaction::Craft(CraftingTab::Potion)))
|
SpriteKind::PinkFlower => flowers.push(pos),
|
||||||
},
|
SpriteKind::PurpleFlower => flowers.push(pos),
|
||||||
Some(SpriteKind::Anvil) => {
|
SpriteKind::RedFlower => flowers.push(pos),
|
||||||
interactables.push((pos, Interaction::Craft(CraftingTab::Weapon)))
|
SpriteKind::WhiteFlower => flowers.push(pos),
|
||||||
},
|
SpriteKind::YellowFlower => flowers.push(pos),
|
||||||
Some(SpriteKind::CookingPot) => {
|
SpriteKind::Sunflower => flowers.push(pos),
|
||||||
fires.push(pos);
|
SpriteKind::CraftingBench => {
|
||||||
interactables.push((pos, Interaction::Craft(CraftingTab::Food)))
|
interactables.push((pos, Interaction::Craft(CraftingTab::All)))
|
||||||
},
|
},
|
||||||
Some(SpriteKind::DismantlingBench) => {
|
SpriteKind::SmokeDummy => {
|
||||||
fires.push(pos);
|
smokers.push(SmokerProperties::new(pos, FireplaceType::Workshop));
|
||||||
interactables.push((pos, Interaction::Craft(CraftingTab::Dismantle)))
|
},
|
||||||
},
|
SpriteKind::Forge => interactables
|
||||||
Some(SpriteKind::RepairBench) => {
|
.push((pos, Interaction::Craft(CraftingTab::ProcessedMaterial))),
|
||||||
interactables.push((pos, Interaction::Craft(CraftingTab::All)))
|
SpriteKind::TanningRack => interactables
|
||||||
},
|
.push((pos, Interaction::Craft(CraftingTab::ProcessedMaterial))),
|
||||||
Some(SpriteKind::OneWayWall) => one_way_walls.push((
|
SpriteKind::SpinningWheel => {
|
||||||
pos,
|
interactables.push((pos, Interaction::Craft(CraftingTab::All)))
|
||||||
Vec2::unit_y()
|
},
|
||||||
.rotated_z(
|
SpriteKind::Loom => {
|
||||||
std::f32::consts::PI * 0.25 * block.get_ori().unwrap_or(0) as f32,
|
interactables.push((pos, Interaction::Craft(CraftingTab::All)))
|
||||||
)
|
},
|
||||||
.with_z(0.0),
|
SpriteKind::Cauldron => {
|
||||||
)),
|
fires.push(pos);
|
||||||
Some(SpriteKind::Sign | SpriteKind::HangingSign) => {
|
interactables.push((pos, Interaction::Craft(CraftingTab::Potion)))
|
||||||
interactables.push((pos, Interaction::Read))
|
},
|
||||||
},
|
SpriteKind::Anvil => {
|
||||||
_ if block.is_mountable() => interactables.push((pos, Interaction::Mount)),
|
interactables.push((pos, Interaction::Craft(CraftingTab::Weapon)))
|
||||||
_ => {},
|
},
|
||||||
|
SpriteKind::CookingPot => {
|
||||||
|
fires.push(pos);
|
||||||
|
interactables.push((pos, Interaction::Craft(CraftingTab::Food)))
|
||||||
|
},
|
||||||
|
SpriteKind::DismantlingBench => {
|
||||||
|
fires.push(pos);
|
||||||
|
interactables
|
||||||
|
.push((pos, Interaction::Craft(CraftingTab::Dismantle)))
|
||||||
|
},
|
||||||
|
SpriteKind::RepairBench => {
|
||||||
|
interactables.push((pos, Interaction::Craft(CraftingTab::All)))
|
||||||
|
},
|
||||||
|
SpriteKind::OneWayWall => one_way_walls.push((
|
||||||
|
pos,
|
||||||
|
Vec2::unit_y()
|
||||||
|
.rotated_z(
|
||||||
|
std::f32::consts::PI
|
||||||
|
* 0.25
|
||||||
|
* block.get_ori().unwrap_or(0) as f32,
|
||||||
|
)
|
||||||
|
.with_z(0.0),
|
||||||
|
)),
|
||||||
|
SpriteKind::Sign | SpriteKind::HangingSign => {
|
||||||
|
interactables.push((pos, Interaction::Read))
|
||||||
|
},
|
||||||
|
_ => {},
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
if block.collectible_id().is_some() {
|
if block.collectible_id().is_some() {
|
||||||
|
@ -10,7 +10,7 @@ use client::Client;
|
|||||||
use common::{
|
use common::{
|
||||||
comp,
|
comp,
|
||||||
comp::{ship::figuredata::VOXEL_COLLIDER_MANIFEST, tool::ToolKind, Collider, Content},
|
comp::{ship::figuredata::VOXEL_COLLIDER_MANIFEST, tool::ToolKind, Collider, Content},
|
||||||
consts::{MAX_PICKUP_RANGE, MAX_SPRITE_MOUNT_RANGE, TELEPORTER_RADIUS},
|
consts::{MAX_INTERACT_RANGE, MAX_PICKUP_RANGE, MAX_SPRITE_MOUNT_RANGE, TELEPORTER_RADIUS},
|
||||||
link::Is,
|
link::Is,
|
||||||
mounting::{Mount, Rider, VolumePos, VolumeRider},
|
mounting::{Mount, Rider, VolumePos, VolumeRider},
|
||||||
terrain::{Block, TerrainGrid, UnlockKind},
|
terrain::{Block, TerrainGrid, UnlockKind},
|
||||||
@ -36,6 +36,7 @@ pub enum BlockInteraction {
|
|||||||
Mine(ToolKind),
|
Mine(ToolKind),
|
||||||
Mount,
|
Mount,
|
||||||
Read(Content),
|
Read(Content),
|
||||||
|
LightToggle(bool),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
@ -105,6 +106,7 @@ impl Interactable {
|
|||||||
},
|
},
|
||||||
Interaction::Craft(tab) => BlockInteraction::Craft(tab),
|
Interaction::Craft(tab) => BlockInteraction::Craft(tab),
|
||||||
Interaction::Mount => BlockInteraction::Mount,
|
Interaction::Mount => BlockInteraction::Mount,
|
||||||
|
Interaction::LightToggle(enable) => BlockInteraction::LightToggle(enable),
|
||||||
};
|
};
|
||||||
Some(Self::Block(block, volume_pos, block_interaction))
|
Some(Self::Block(block, volume_pos, block_interaction))
|
||||||
}
|
}
|
||||||
@ -341,8 +343,9 @@ pub(super) fn select_interactable(
|
|||||||
.filter(|(wpos, volume_pos, interaction)| {
|
.filter(|(wpos, volume_pos, interaction)| {
|
||||||
match interaction {
|
match interaction {
|
||||||
Interaction::Mount => !is_volume_rider.contains(player_entity)
|
Interaction::Mount => !is_volume_rider.contains(player_entity)
|
||||||
&& wpos.distance_squared(player_pos) < MAX_SPRITE_MOUNT_RANGE * MAX_SPRITE_MOUNT_RANGE
|
&& wpos.distance_squared(player_pos) < MAX_SPRITE_MOUNT_RANGE.powi(2)
|
||||||
&& !is_volume_rider.join().any(|is_volume_rider| is_volume_rider.pos == *volume_pos),
|
&& !is_volume_rider.join().any(|is_volume_rider| is_volume_rider.pos == *volume_pos),
|
||||||
|
Interaction::LightToggle(_) => wpos.distance_squared(player_pos) < MAX_INTERACT_RANGE.powi(2),
|
||||||
_ => true,
|
_ => true,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -1042,6 +1042,9 @@ impl PlayState for SessionState {
|
|||||||
// currently supported
|
// currently supported
|
||||||
common::mounting::Volume::Entity(_) => {},
|
common::mounting::Volume::Entity(_) => {},
|
||||||
},
|
},
|
||||||
|
BlockInteraction::LightToggle(enable) => {
|
||||||
|
client.toggle_sprite_light(*pos, *enable);
|
||||||
|
},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Interactable::Entity(entity) => {
|
Interactable::Entity(entity) => {
|
||||||
|
@ -47,7 +47,7 @@ pub struct Colors {
|
|||||||
pub vein: (u8, u8, u8),
|
pub vein: (u8, u8, u8),
|
||||||
}
|
}
|
||||||
|
|
||||||
const EMPTY_AIR: Block = Block::air(SpriteKind::Empty);
|
const EMPTY_AIR: Block = Block::empty();
|
||||||
|
|
||||||
pub struct PathLocals {
|
pub struct PathLocals {
|
||||||
pub riverless_alt: f32,
|
pub riverless_alt: f32,
|
||||||
|
@ -167,7 +167,7 @@ impl Archetype for Keep {
|
|||||||
make_block(colors.pole.0, colors.pole.1, colors.pole.2).with_priority(important_layer);
|
make_block(colors.pole.0, colors.pole.1, colors.pole.2).with_priority(important_layer);
|
||||||
let flag =
|
let flag =
|
||||||
make_block(flag_color.0, flag_color.1, flag_color.2).with_priority(important_layer);
|
make_block(flag_color.0, flag_color.1, flag_color.2).with_priority(important_layer);
|
||||||
const AIR: Block = Block::air(SpriteKind::Empty);
|
const AIR: Block = Block::empty();
|
||||||
const EMPTY: BlockMask = BlockMask::nothing();
|
const EMPTY: BlockMask = BlockMask::nothing();
|
||||||
let internal = BlockMask::new(AIR, internal_layer);
|
let internal = BlockMask::new(AIR, internal_layer);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user