Addressed review issues

This commit is contained in:
Joshua Barretto 2020-09-21 21:10:32 +01:00
parent 388a899a7f
commit 0ca42857fa
7 changed files with 79 additions and 45 deletions

View File

@ -16,7 +16,7 @@ fn criterion_benchmark(c: &mut Criterion) {
// Setup: Create chunk and fill it (dense) for z in [140, 220).
let mut chunk = TerrainChunk::new(
MIN_Z,
Block::new(BlockKind::Rock, Default::default()),
Block::new(BlockKind::Rock, Rgb::zero()),
Block::empty(),
TerrainChunkMeta::void(),
);
@ -29,7 +29,7 @@ fn criterion_benchmark(c: &mut Criterion) {
),
) {
chunk
.set(pos, Block::new(BlockKind::Rock, Default::default()))
.set(pos, Block::new(BlockKind::Rock, Rgb::zero()))
.unwrap();
}
@ -118,7 +118,7 @@ fn criterion_benchmark(c: &mut Criterion) {
MAX_Z,
),
) {
let _ = chunk.set(pos, Block::new(BlockKind::Rock, Default::default()));
let _ = chunk.set(pos, Block::new(BlockKind::Rock, Rgb::zero()));
}
})
});

View File

@ -45,18 +45,32 @@ make_case_elim!(
// Covers all other cases (we sometimes have bizarrely coloured misc blocks, and also we
// often want to experiment with new kinds of block without allocating them a
// dedicated block kind.
Misc = 0xFF,
Misc = 0xFE,
}
);
impl BlockKind {
#[inline]
pub const fn is_air(&self) -> bool { matches!(self, BlockKind::Air) }
/// Determine whether the block kind is a gas or a liquid. This does not
/// consider any sprites that may occupy the block (the definition of
/// fluid is 'a substance that deforms to fit containers')
#[inline]
pub const fn is_fluid(&self) -> bool { *self as u8 & 0xF0 == 0x00 }
#[inline]
pub const fn is_liquid(&self) -> bool { self.is_fluid() && !self.is_air() }
/// Determine whether the block is filled (i.e: fully solid). Right now,
/// this is the opposite of being a fluid.
#[inline]
pub const fn is_filled(&self) -> bool { !self.is_fluid() }
/// Determine whether the block has an RGB color storaged in the attribute
/// fields.
#[inline]
pub const fn has_color(&self) -> bool { self.is_filled() }
}
impl fmt::Display for BlockKind {
@ -76,7 +90,6 @@ impl<'a> TryFrom<&'a str> for BlockKind {
}
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
#[repr(packed)]
pub struct Block {
kind: BlockKind,
attr: [u8; 3],
@ -114,14 +127,23 @@ impl Block {
}
}
pub const fn air(sprite: SpriteKind) -> Self {
Self {
kind: BlockKind::Air,
attr: [sprite as u8, 0, 0],
}
}
#[inline]
pub fn get_color(&self) -> Option<Rgb<u8>> {
if self.is_filled() {
if self.has_color() {
Some(self.attr.into())
} else {
None
}
}
#[inline]
pub fn get_sprite(&self) -> Option<SpriteKind> {
if !self.is_filled() {
SpriteKind::from_u8(self.attr[0])
@ -130,6 +152,7 @@ impl Block {
}
}
#[inline]
pub fn get_ori(&self) -> Option<u8> {
if self.get_sprite()?.has_ori() {
// TODO: Formalise this a bit better
@ -139,6 +162,7 @@ impl Block {
}
}
#[inline]
pub fn get_glow(&self) -> Option<u8> {
// TODO: When we have proper volumetric lighting
// match self.get_sprite()? {
@ -149,39 +173,46 @@ impl Block {
None
}
#[inline]
pub fn is_solid(&self) -> bool {
self.get_sprite()
.map(|s| s.solid_height().is_some())
.unwrap_or(true)
}
#[inline]
pub fn is_explodable(&self) -> bool {
match self.kind() {
BlockKind::Leaves | BlockKind::Grass | BlockKind::WeakRock => true,
// Explodable means that the terrain sprite will get removed anyway, so is good for
// empty fluids TODO: Handle the case of terrain sprites we don't want to
// have explode
// Explodable means that the terrain sprite will get removed anyway, so all is good for
// empty fluids.
// TODO: Handle the case of terrain sprites we don't want to have explode
_ => true,
}
}
#[inline]
pub fn is_collectible(&self) -> bool {
self.get_sprite()
.map(|s| s.is_collectible())
.unwrap_or(false)
}
#[inline]
pub fn is_opaque(&self) -> bool { self.kind().is_filled() }
#[inline]
pub fn solid_height(&self) -> f32 {
self.get_sprite()
.map(|s| s.solid_height().unwrap_or(0.0))
.unwrap_or(1.0)
}
#[inline]
pub fn kind(&self) -> BlockKind { self.kind }
/// If this block is a fluid, replace its sprite.
#[inline]
pub fn with_sprite(mut self, sprite: SpriteKind) -> Self {
if !self.is_filled() {
self.attr[0] = sprite as u8;
@ -190,14 +221,18 @@ impl Block {
}
/// If this block can have orientation, give it a new orientation.
pub fn with_ori(mut self, ori: u8) -> Self {
#[inline]
pub fn with_ori(mut self, ori: u8) -> Option<Self> {
if self.get_sprite().map(|s| s.has_ori()).unwrap_or(false) {
self.attr[1] = (self.attr[1] & !0b111) | (ori & 0b111);
Some(self)
} else {
None
}
self
}
/// Remove the terrain sprite or solid aspects of a block
#[inline]
pub fn into_vacant(self) -> Self {
if self.is_fluid() {
Block::new(self.kind(), Rgb::zero())

View File

@ -14,7 +14,7 @@ use common::{
sync::{Uid, UidAllocator, WorldSyncExt},
sys::combat::BLOCK_ANGLE,
terrain::{Block, TerrainGrid},
vol::{ReadVol, Vox},
vol::ReadVol,
};
use comp::item::Reagent;
use rand::prelude::*;
@ -572,7 +572,7 @@ pub fn handle_explosion(
.until(|block| block.is_liquid() || rand::random::<f32>() < 0.05)
.for_each(|block: &Block, pos| {
if block.is_explodable() {
block_change.set(pos, Block::empty());
block_change.set(pos, block.into_vacant());
}
})
.cast();

View File

@ -506,23 +506,23 @@ pub fn block_from_structure(
)),
// None of these BlockKinds has an orientation, so we just use zero for the other color
// bits.
StructureBlock::Liana => Some(Block::empty().with_sprite(SpriteKind::Liana)),
StructureBlock::Liana => Some(Block::air(SpriteKind::Liana)),
StructureBlock::Fruit => Some(if field.get(pos + structure_pos) % 24 == 0 {
Block::empty().with_sprite(SpriteKind::Beehive)
Block::air(SpriteKind::Beehive)
} else if field.get(pos + structure_pos + 1) % 3 == 0 {
Block::empty().with_sprite(SpriteKind::Apple)
Block::air(SpriteKind::Apple)
} else {
Block::empty()
}),
StructureBlock::Coconut => Some(if field.get(pos + structure_pos) % 3 > 0 {
Block::empty()
} else {
Block::empty().with_sprite(SpriteKind::Coconut)
Block::air(SpriteKind::Coconut)
}),
StructureBlock::Chest => Some(if structure_seed % 10 < 7 {
Block::empty()
} else {
Block::empty().with_sprite(SpriteKind::Chest)
Block::air(SpriteKind::Chest)
}),
// We interpolate all these BlockKinds as needed.
StructureBlock::TemperateLeaves

View File

@ -593,7 +593,7 @@ impl Floor {
let floor_sprite = if RandomField::new(7331).chance(Vec3::from(pos), 0.00005) {
BlockMask::new(
Block::empty().with_sprite(
Block::air(
match (RandomField::new(1337).get(Vec3::from(pos)) / 2) % 20 {
0 => SpriteKind::Apple,
1 => SpriteKind::VeloriteFrag,
@ -609,7 +609,7 @@ impl Floor {
{
let room = &self.rooms[*room];
if RandomField::new(room.seed).chance(Vec3::from(pos), room.loot_density * 0.5) {
BlockMask::new(Block::empty().with_sprite(SpriteKind::Chest), 1)
BlockMask::new(Block::air(SpriteKind::Chest), 1)
} else {
empty
}

View File

@ -296,16 +296,15 @@ impl Archetype for House {
let empty = BlockMask::nothing();
let internal = BlockMask::new(Block::empty(), internal_layer);
let end_window = BlockMask::new(
Block::empty().with_sprite(attr.window).with_ori(match ori {
Ori::East => 2,
Ori::North => 0,
}),
Block::air(attr.window)
.with_ori(match ori {
Ori::East => 2,
Ori::North => 0,
})
.unwrap(),
structural_layer,
);
let fire = BlockMask::new(
Block::empty().with_sprite(SpriteKind::Ember),
foundation_layer,
);
let fire = BlockMask::new(Block::air(SpriteKind::Ember), foundation_layer);
let storey_height = 6;
let storey = ((z - 1) / storey_height).min(attr.levels - 1);
@ -436,16 +435,18 @@ impl Archetype for House {
// Doors on first floor only
if profile.y == foundation_height + 1 {
BlockMask::new(
Block::empty().with_sprite(SpriteKind::Door).with_ori(
match ori {
Ori::East => 2,
Ori::North => 0,
} + if bound_offset.x == (width - 1) / 2 {
0
} else {
4
},
),
Block::air(SpriteKind::Door)
.with_ori(
match ori {
Ori::East => 2,
Ori::North => 0,
} + if bound_offset.x == (width - 1) / 2 {
0
} else {
4
},
)
.unwrap(),
structural_layer,
)
} else {
@ -558,7 +559,7 @@ impl Archetype for House {
};
return Some(BlockMask::new(
Block::empty().with_sprite(furniture).with_ori(edge_ori),
Block::air(furniture).with_ori(edge_ori).unwrap(),
internal_layer,
));
} else {
@ -587,9 +588,7 @@ impl Archetype for House {
};
Some(BlockMask::new(
Block::empty()
.with_sprite(ornament)
.with_ori((edge_ori + 4) % 8),
Block::air(ornament).with_ori((edge_ori + 4) % 8).unwrap(),
internal_layer,
))
} else {

View File

@ -150,12 +150,12 @@ impl Archetype for Keep {
stone_color.2 + brick_tex,
);
let window = BlockMask::new(
Block::empty()
.with_sprite(SpriteKind::Window1)
Block::air(SpriteKind::Window1)
.with_ori(match ori {
Ori::East => 2,
Ori::North => 0,
}),
})
.unwrap(),
normal_layer,
);
let floor = make_block(