Skip to content

Commit

Permalink
Flowers and crafting improvements
Browse files Browse the repository at this point in the history
  • Loading branch information
drey7925 committed Jan 1, 2024
1 parent 9b5de4d commit 34b66e8
Show file tree
Hide file tree
Showing 20 changed files with 359 additions and 31 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 3 additions & 5 deletions perovskite_game_api/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,11 @@ smallvec = "1.11.2"
regex = "1.10.2"

serenity = { version = "0.12.0", optional = true }
image = { version = "0.24.7", optional = true }
image = { version = "0.24.7" }
petgraph = "0.6.4"

[features]
default = ["default_game", "colors", "agriculture", "circuits", "discord"]
default = ["default_game", "agriculture", "circuits", "discord"]
# When enabled, re-exports selected from perovskite_server. These are subject to change
# in the current version.
unstable_api = []
Expand All @@ -69,9 +70,6 @@ circuits = []
# dirt and other interactions
agriculture = ["default_game"]

# Provides a unified definition for colored blocks, so different plugins can interoperate with dyes and related.
# Still a WIP
colors = ["dep:image"]

# If enabled, server will detect deadlocks and log them.
deadlock_detection = ["perovskite_server/deadlock_detection"]
Expand Down
2 changes: 1 addition & 1 deletion perovskite_game_api/src/blocks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ impl DroppedItem {
Ok(BlockInteractionResult {
item_stacks: closure(),
tool_wear: match rule {
Some(rule) => rule.tool_wear(block_type)?,
Some(rule) => rule.computed_tool_wear(block_type)?,
None => 0,
},
})
Expand Down
6 changes: 1 addition & 5 deletions perovskite_game_api/src/circuits/simple_blocks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -264,14 +264,10 @@ pub(crate) fn register_simple_blocks(builder: &mut crate::game_builder::GameBuil
off: oscillator_off_block.id,
})),
);
#[cfg(feature = "colors")]
{
register_colored_lamps(builder)?;
}
register_colored_lamps(builder)?;
Ok(())
}

#[cfg(feature = "colors")]
fn register_colored_lamps(builder: &mut crate::game_builder::GameBuilder) -> Result<()> {
use crate::game_builder::{BlockName, TextureName};

Expand Down
2 changes: 1 addition & 1 deletion perovskite_game_api/src/default_game/basic_blocks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -403,7 +403,7 @@ pub(crate) fn register_basic_blocks(game_builder: &mut GameBuilder) -> Result<()
quantity_type: Some(QuantityType::Stack(256)),
},
},
shapeless: false,
shapeless: true,
metadata: (),
});

Expand Down
130 changes: 123 additions & 7 deletions perovskite_game_api/src/default_game/foliage.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,21 @@
use anyhow::Result;
use perovskite_core::protocol::items::item_stack::QuantityType;
use perovskite_core::protocol::{
blocks::{block_type_def::PhysicsInfo, Empty},
items::item_stack::QuantityType,
};
use perovskite_server::game_state::{blocks::BlockType, items::ItemStack};

use crate::{
blocks::{BlockBuilder, CubeAppearanceBuilder, PlantLikeAppearanceBuilder},
game_builder::{GameBuilder, StaticBlockName, StaticItemName, StaticTextureName},
game_builder::{GameBuilder, StaticBlockName, StaticItemName, StaticTextureName, TextureName},
include_texture_bytes,
};

use super::{block_groups, item_groups, recipes::RecipeSlot, shaped_blocks, DefaultGameBuilder};

pub mod wood_groups {
pub mod foliage_groups {
pub const MAPLE: &str = "maple";
pub const FLOWERS: &str = "flowers";
}

pub const MAPLE_TREE: StaticBlockName = StaticBlockName("default:maple_tree");
Expand Down Expand Up @@ -46,9 +51,9 @@ pub(crate) fn register_foliage(builder: &mut GameBuilder) -> Result<()> {
BlockBuilder::new(MAPLE_TREE)
.add_block_group(block_groups::TREE_TRUNK)
.add_block_group(block_groups::FIBROUS)
.add_block_group(wood_groups::MAPLE)
.add_block_group(foliage_groups::MAPLE)
.add_item_group(item_groups::TREE_TRUNK)
.add_item_group(wood_groups::MAPLE)
.add_item_group(foliage_groups::MAPLE)
.set_cube_appearance(CubeAppearanceBuilder::new().set_individual_textures(
MAPLE_TREE_SIDE_TEX,
MAPLE_TREE_SIDE_TEX,
Expand Down Expand Up @@ -79,9 +84,9 @@ pub(crate) fn register_foliage(builder: &mut GameBuilder) -> Result<()> {
BlockBuilder::new(MAPLE_PLANKS)
.add_block_group(block_groups::WOOD_PLANKS)
.add_block_group(block_groups::FIBROUS)
.add_block_group(wood_groups::MAPLE)
.add_block_group(foliage_groups::MAPLE)
.add_item_group(item_groups::WOOD_PLANKS)
.add_item_group(wood_groups::MAPLE)
.add_item_group(foliage_groups::MAPLE)
.set_cube_appearance(CubeAppearanceBuilder::new().set_single_texture(MAPLE_PLANKS_TEX))
.set_display_name("Maple planks"),
)?;
Expand All @@ -101,6 +106,7 @@ pub(crate) fn register_foliage(builder: &mut GameBuilder) -> Result<()> {
STICK_ITEM.0.to_string(),
4,
Some(QuantityType::Stack(256)),
true,
);

builder.register_crafting_recipe(
Expand All @@ -118,6 +124,7 @@ pub(crate) fn register_foliage(builder: &mut GameBuilder) -> Result<()> {
MAPLE_PLANKS.0.to_string(),
4,
Some(QuantityType::Stack(256)),
true,
);

builder.add_block(
Expand Down Expand Up @@ -148,5 +155,114 @@ pub(crate) fn register_foliage(builder: &mut GameBuilder) -> Result<()> {
shaped_blocks::make_stairs(builder, &maple_planks, true)?;
shaped_blocks::make_slab(builder, &maple_trunk, true)?;
shaped_blocks::make_stairs(builder, &maple_trunk, true)?;

register_flowers(builder)?;

Ok(())
}

fn register_flowers(builder: &mut GameBuilder) -> Result<()> {
for &(block, texture, display_name, color, tex_bytes) in TERRESTRIAL_FLOWERS
.iter()
.chain([WHITE_LOTUS_DEF, PURPLE_LOTUS_DEF].iter())
{
builder.register_texture_bytes(texture, tex_bytes)?;

builder.add_block(
BlockBuilder::new(block)
.set_plant_like_appearance(PlantLikeAppearanceBuilder::new().set_texture(texture))
.set_display_name(display_name)
.set_inventory_texture(texture)
.set_allow_light_propagation(true)
.add_modifier(Box::new(|block: &mut BlockType| {
block.client_info.physics_info = Some(PhysicsInfo::Air(Empty {}));
})),
)?;
builder.register_crafting_recipe(
[
RecipeSlot::Exact(block.0.to_string()),
RecipeSlot::Empty,
RecipeSlot::Empty,
RecipeSlot::Empty,
RecipeSlot::Empty,
RecipeSlot::Empty,
RecipeSlot::Empty,
RecipeSlot::Empty,
RecipeSlot::Empty,
],
color.dye_item_name(),
1,
Some(QuantityType::Stack(256)),
true,
);
}
Ok(())
}

type FlowerDef = (
StaticBlockName,
StaticTextureName,
&'static str,
crate::colors::Color,
&'static [u8],
);

pub(crate) const WHITE_LOTUS_DEF: FlowerDef = (
StaticBlockName("default:white_lotus"),
StaticTextureName("default:white_lotus"),
"White lotus",
crate::colors::Color::White,
include_bytes!("textures/tall_grass.png"),
);
pub(crate) const PURPLE_LOTUS_DEF: FlowerDef = (
StaticBlockName("default:purple_lotus"),
StaticTextureName("default:purple_lotus"),
"Purple lotus",
crate::colors::Color::Purple,
include_bytes!("textures/tall_grass.png"),
);

pub(crate) const TERRESTRIAL_FLOWERS: &[FlowerDef] = &[
(
StaticBlockName("default:rose"),
StaticTextureName("default:rose"),
"Rose",
crate::colors::Color::Pink,
include_bytes!("textures/flowers/rose.png"),
),
(
StaticBlockName("default:carnation"),
StaticTextureName("default:carnation"),
"Carnation",
crate::colors::Color::Red,
include_bytes!("textures/flowers/carnation.png"),
),
(
StaticBlockName("default:dandelion"),
StaticTextureName("default:dandelion"),
"Dandelion",
crate::colors::Color::Yellow,
include_bytes!("textures/flowers/dandelion.png"),
),
(
StaticBlockName("default:calendula"),
StaticTextureName("default:calendula"),
"Calendula",
crate::colors::Color::Orange,
include_bytes!("textures/flowers/calendula.png"),
),
(
StaticBlockName("default:cornflower"),
StaticTextureName("default:cornflower"),
"Cornflower",
crate::colors::Color::Blue,
include_bytes!("textures/flowers/cornflower.png"),
),
(
StaticBlockName("default:lavender"),
StaticTextureName("default:lavender"),
"Lavender",
crate::colors::Color::Purple,
include_bytes!("textures/flowers/lavender.png"),
),
];
2 changes: 1 addition & 1 deletion perovskite_game_api/src/default_game/furnace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -375,7 +375,7 @@ fn furnace_dig_handler(
Ok(BlockInteractionResult {
item_stacks: vec![ctx.items().get_item(FURNACE.0).unwrap().singleton_stack()],
tool_wear: match rule {
Some(rule) => rule.tool_wear(block_type)?,
Some(rule) => rule.computed_tool_wear(block_type)?,
None => 0,
},
})
Expand Down
80 changes: 78 additions & 2 deletions perovskite_game_api/src/default_game/mapgen/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,28 +11,38 @@ use perovskite_server::game_state::{
game_map::MapChunk,
mapgen::MapgenInterface,
};
use rand::seq::SliceRandom;

use super::{
basic_blocks::{DESERT_SAND, DESERT_STONE, DIRT, DIRT_WITH_GRASS, SAND, STONE, WATER},
foliage::{CACTUS, MAPLE_LEAVES, MAPLE_TREE},
foliage::{CACTUS, MAPLE_LEAVES, MAPLE_TREE, TALL_GRASS, TERRESTRIAL_FLOWERS},
};

const ELEVATION_FINE_INPUT_SCALE: f64 = 1.0 / 60.0;
const ELEVATION_FINE_OUTPUT_SCALE: f64 = 10.0;
const ELEVATION_COARSE_INPUT_SCALE: f64 = 1.0 / 800.0;
const ELEVATION_COARSE_OUTPUT_SCALE: f64 = 60.0;
const ELEVATION_OFFSET: f64 = 20.0;

const TREE_DENSITY_INPUT_SCALE: f64 = 1.0 / 240.0;
const TREE_DENSITY_OUTPUT_SCALE: f64 = 0.0625;
const TREE_DENSITY_OUTPUT_OFFSET: f64 = 0.03125;
const CACTUS_DENSITY_INPUT_SCALE: f64 = 1.0 / 120.0;
const CACTUS_DENSITY_OUTPUT_SCALE: f64 = 0.03125;
const CACTUS_DENSITY_OUTPUT_OFFSET: f64 = 0.03125;

const TALL_GRASS_DENSITY_INPUT_SCALE: f64 = 1.0 / 120.0;
const TALL_GRASS_DENSITY_OUTPUT_SCALE: f64 = 0.03125;
const TALL_GRASS_DENSITY_OUTPUT_OFFSET: f64 = 0.03125;

const FLOWER_DENSITY_INPUT_SCALE: f64 = 1.0 / 240.0;
const FLOWER_DENSITY_OUTPUT_SCALE: f64 = 0.03125;
const FLOWER_DENSITY_OUTPUT_OFFSET: f64 = 0.03125;

const BEACH_TENDENCY_INPUT_SCALE: f64 = 1.0 / 240.0;
const DESERT_TENDENCY_INPUT_SCALE: f64 = 1.0 / 480.0;

// Next seed offset: 7
// Next seed offset: 9

#[derive(Clone, Copy, Debug)]
enum Biome {
Expand Down Expand Up @@ -175,10 +185,16 @@ struct DefaultMapgen {
maple_tree: BlockTypeHandle,
maple_leaves: BlockTypeHandle,
cactus: BlockTypeHandle,
tall_grass: BlockTypeHandle,
flowers: Vec<BlockTypeHandle>,

elevation_noise: ElevationNoise,
tree_density_noise: noise::Billow<noise::SuperSimplex>,

flower_density_noise: noise::Billow<noise::SuperSimplex>,
cactus_density_noise: noise::Billow<noise::SuperSimplex>,
tall_grass_density_noise: noise::Billow<noise::SuperSimplex>,

biome_noise: BiomeNoise,
cave_noise: CaveNoise,
ores: Vec<(OreDefinition, noise::SuperSimplex)>,
Expand Down Expand Up @@ -317,6 +333,42 @@ impl DefaultMapgen {
if tree_value < tree_cutoff {
self.make_tree(chunk_coord, chunk, x, y, z);
}

let flower_value =
self.fast_uniform_2d(x, z, self.seed.wrapping_add(3));
let flower_cutoff = self.flower_density_noise.get([
(x as f64) * FLOWER_DENSITY_INPUT_SCALE,
(z as f64) * FLOWER_DENSITY_INPUT_SCALE,
]) * FLOWER_DENSITY_OUTPUT_SCALE
+ FLOWER_DENSITY_OUTPUT_OFFSET;
if flower_value < flower_cutoff {
self.make_simple_foliage(
chunk_coord,
chunk,
x,
y,
z,
*self.flowers.choose(&mut rand::thread_rng()).unwrap(),
);
}

let tall_grass_value =
self.fast_uniform_2d(x, z, self.seed.wrapping_add(4));
let tall_grass_cutoff = self.flower_density_noise.get([
(x as f64) * FLOWER_DENSITY_INPUT_SCALE,
(z as f64) * FLOWER_DENSITY_INPUT_SCALE,
]) * FLOWER_DENSITY_OUTPUT_SCALE
+ FLOWER_DENSITY_OUTPUT_OFFSET;
if tall_grass_value < tall_grass_cutoff {
self.make_simple_foliage(
chunk_coord,
chunk,
x,
y,
z,
self.tall_grass,
);
}
}
Biome::Desert => {
let cactus_value =
Expand Down Expand Up @@ -463,6 +515,21 @@ impl DefaultMapgen {
gen_ore()
}
}

fn make_simple_foliage(
&self,
chunk_coord: ChunkCoordinate,
chunk: &mut MapChunk,
x: i32,
y: i32,
z: i32,
block: BlockId,
) {
let coord = BlockCoordinate::new(x, y + 1, z);
if coord.chunk() == chunk_coord {
chunk.set_block(coord.offset(), block, None);
}
}
}

pub(crate) fn build_mapgen(
Expand All @@ -486,12 +553,21 @@ pub(crate) fn build_mapgen(
.unwrap(),
maple_tree: blocks.get_by_name(MAPLE_TREE.0).expect("maple_tree"),
maple_leaves: blocks.get_by_name(MAPLE_LEAVES.0).expect("maple_leaves"),
tall_grass: blocks.get_by_name(TALL_GRASS.0).expect("tall_grass"),

flowers: TERRESTRIAL_FLOWERS
.iter()
.map(|f| blocks.get_by_name(f.0 .0).expect("flower missing"))
.collect(),

cactus: blocks.get_by_name(CACTUS.0).expect("cactus"),

elevation_noise: ElevationNoise::new(seed),
biome_noise: BiomeNoise::new(seed),
cave_noise: CaveNoise::new(seed),
tree_density_noise: noise::Billow::new(seed.wrapping_add(2)),
flower_density_noise: noise::Billow::new(seed.wrapping_add(7)),
tall_grass_density_noise: noise::Billow::new(seed.wrapping_add(8)),
cactus_density_noise: noise::Billow::new(seed.wrapping_add(5)),
ores: ores
.into_iter()
Expand Down
Loading

0 comments on commit 34b66e8

Please sign in to comment.