feat: initial village support
This commit is contained in:
parent
30303a8cbd
commit
5b8eab0f56
@ -25,14 +25,23 @@ pub struct WeightedEntryStruct {
|
||||
#[derive(Deserialize)]
|
||||
pub struct StructurePlacementStruct {
|
||||
/// Optional frequency-reduction method name applied before placement.
|
||||
frequency_reduction_method: Option<String>,
|
||||
pub frequency_reduction_method: Option<String>,
|
||||
/// Optional probability (0–1) that a candidate chunk actually spawns the structure.
|
||||
frequency: Option<f32>,
|
||||
pub frequency: Option<f32>,
|
||||
/// Per-structure salt mixed into the placement RNG seed.
|
||||
salt: u32,
|
||||
pub salt: u32,
|
||||
/// Optional exclusion zone to prevent this structure from generating near others.
|
||||
pub exclusion_zone: Option<ExclusionZoneStruct>,
|
||||
/// The specific placement algorithm and its parameters.
|
||||
#[serde(flatten)]
|
||||
r#type: StructurePlacementTypeStruct,
|
||||
pub r#type: StructurePlacementTypeStruct,
|
||||
}
|
||||
|
||||
/// Deserialized exclusion zone configuration.
|
||||
#[derive(Deserialize)]
|
||||
pub struct ExclusionZoneStruct {
|
||||
pub other_set: String,
|
||||
pub chunk_count: i32,
|
||||
}
|
||||
|
||||
/// Deserialized placement algorithm for a structure set.
|
||||
@ -70,10 +79,30 @@ pub struct StructureStruct {
|
||||
pub biomes: String,
|
||||
/// Generation step during which this structure is placed.
|
||||
pub step: String,
|
||||
/// Optional jigsaw start pool.
|
||||
pub start_pool: Option<String>,
|
||||
/// Optional jigsaw size (depth).
|
||||
pub size: Option<i32>,
|
||||
/// Optional terrain adaptation (bearding).
|
||||
pub terrain_adaptation: Option<String>,
|
||||
/// Optional jigsaw start height.
|
||||
pub start_height: Option<serde_json::Value>,
|
||||
/// Optional heightmap to project the start to.
|
||||
pub project_start_to_heightmap: Option<String>,
|
||||
/// Optional max distance from center.
|
||||
pub max_distance_from_center: Option<i32>,
|
||||
/// Optional liquid settings.
|
||||
pub liquid_settings: Option<String>,
|
||||
/// Optional dimension padding.
|
||||
pub dimension_padding: Option<i32>,
|
||||
/// Critical for villages to appropriately truncate long village streets.
|
||||
pub use_expansion_hack: Option<bool>,
|
||||
/// Defines the generation behavior (e.g. "minecraft:jigsaw").
|
||||
#[serde(rename = "type")]
|
||||
pub structure_type: String,
|
||||
}
|
||||
|
||||
impl ToTokens for StructureSetStruct {
|
||||
/// Emits a `StructureSet { … }` struct literal token stream for the wrapped structure set.
|
||||
fn to_tokens(&self, tokens: &mut TokenStream) {
|
||||
let placement = &self.placement;
|
||||
let structures = &self.structures;
|
||||
@ -88,7 +117,6 @@ impl ToTokens for StructureSetStruct {
|
||||
}
|
||||
|
||||
impl ToTokens for WeightedEntryStruct {
|
||||
/// Emits a `WeightedEntry { … }` struct literal token stream for the wrapped entry.
|
||||
fn to_tokens(&self, tokens: &mut TokenStream) {
|
||||
let structure = structure_key_to_token(&self.structure);
|
||||
let weight = self.weight;
|
||||
@ -103,7 +131,6 @@ impl ToTokens for WeightedEntryStruct {
|
||||
}
|
||||
|
||||
impl ToTokens for StructurePlacementStruct {
|
||||
/// Emits a `StructurePlacement { … }` struct literal token stream for the wrapped placement config.
|
||||
fn to_tokens(&self, tokens: &mut TokenStream) {
|
||||
let frequency_reduction = if let Some(method) = &self.frequency_reduction_method {
|
||||
let method_token = frequency_reduction_to_token(method);
|
||||
@ -118,6 +145,17 @@ impl ToTokens for StructurePlacementStruct {
|
||||
quote!(None)
|
||||
};
|
||||
|
||||
let exclusion_zone = if let Some(ez) = &self.exclusion_zone {
|
||||
let other_set = &ez.other_set;
|
||||
let chunk_count = ez.chunk_count;
|
||||
quote!(Some(ExclusionZone {
|
||||
other_set: #other_set,
|
||||
chunk_count: #chunk_count,
|
||||
}))
|
||||
} else {
|
||||
quote!(None)
|
||||
};
|
||||
|
||||
let salt = self.salt;
|
||||
let placement_type = &self.r#type;
|
||||
|
||||
@ -126,6 +164,7 @@ impl ToTokens for StructurePlacementStruct {
|
||||
frequency_reduction_method: #frequency_reduction,
|
||||
frequency: #frequency,
|
||||
salt: #salt,
|
||||
exclusion_zone: #exclusion_zone,
|
||||
placement_type: #placement_type,
|
||||
}
|
||||
));
|
||||
@ -133,7 +172,6 @@ impl ToTokens for StructurePlacementStruct {
|
||||
}
|
||||
|
||||
impl ToTokens for StructurePlacementTypeStruct {
|
||||
/// Emits a `StructurePlacementType` variant token stream for the wrapped placement algorithm.
|
||||
fn to_tokens(&self, tokens: &mut TokenStream) {
|
||||
match self {
|
||||
Self::RandomSpread {
|
||||
@ -176,15 +214,85 @@ impl ToTokens for StructurePlacementTypeStruct {
|
||||
}
|
||||
|
||||
impl ToTokens for StructureStruct {
|
||||
/// Emits a `Structure { … }` struct literal token stream for the wrapped structure entry.
|
||||
fn to_tokens(&self, tokens: &mut TokenStream) {
|
||||
let biomes = &self.biomes;
|
||||
let step = generation_step_to_token(&self.step);
|
||||
let start_pool = if let Some(pool) = &self.start_pool {
|
||||
quote!(Some(#pool))
|
||||
} else {
|
||||
quote!(None)
|
||||
};
|
||||
let size = if let Some(s) = self.size {
|
||||
quote!(Some(#s))
|
||||
} else {
|
||||
quote!(None)
|
||||
};
|
||||
let terrain_adaptation = if let Some(ta) = &self.terrain_adaptation {
|
||||
let ta_token = terrain_adaptation_to_token(ta);
|
||||
quote!(#ta_token)
|
||||
} else {
|
||||
quote!(TerrainAdaptation::None)
|
||||
};
|
||||
let project_start_to_heightmap = if let Some(ps) = &self.project_start_to_heightmap {
|
||||
quote!(Some(#ps))
|
||||
} else {
|
||||
quote!(None)
|
||||
};
|
||||
let max_distance_from_center = if let Some(m) = self.max_distance_from_center {
|
||||
quote!(Some(#m))
|
||||
} else {
|
||||
quote!(None)
|
||||
};
|
||||
let liquid_settings = if let Some(ls) = &self.liquid_settings {
|
||||
quote!(Some(#ls))
|
||||
} else {
|
||||
quote!(None)
|
||||
};
|
||||
let dimension_padding = if let Some(dp) = self.dimension_padding {
|
||||
quote!(Some(#dp))
|
||||
} else {
|
||||
quote!(None)
|
||||
};
|
||||
let use_expansion_hack = if let Some(hack) = self.use_expansion_hack {
|
||||
quote!(Some(#hack))
|
||||
} else {
|
||||
quote!(None)
|
||||
};
|
||||
|
||||
let structure_type = structure_type_to_token(&self.structure_type);
|
||||
|
||||
let start_height = if let Some(sh) = &self.start_height {
|
||||
if let Some(abs) = sh.get("absolute") {
|
||||
let abs_val = abs.as_i64().unwrap() as i16;
|
||||
quote!(Some(#abs_val))
|
||||
} else if let Some(min_inc) = sh.get("min_inclusive") {
|
||||
if let Some(abs) = min_inc.get("absolute") {
|
||||
let abs_val = abs.as_i64().unwrap() as i16;
|
||||
quote!(Some(#abs_val))
|
||||
} else {
|
||||
quote!(None)
|
||||
}
|
||||
} else {
|
||||
quote!(None)
|
||||
}
|
||||
} else {
|
||||
quote!(None)
|
||||
};
|
||||
|
||||
tokens.extend(quote!(
|
||||
Structure {
|
||||
biomes: #biomes,
|
||||
step: #step,
|
||||
start_pool: #start_pool,
|
||||
size: #size,
|
||||
terrain_adaptation: #terrain_adaptation,
|
||||
start_height: #start_height,
|
||||
project_start_to_heightmap: #project_start_to_heightmap,
|
||||
max_distance_from_center: #max_distance_from_center,
|
||||
liquid_settings: #liquid_settings,
|
||||
dimension_padding: #dimension_padding,
|
||||
use_expansion_hack: #use_expansion_hack,
|
||||
structure_type: #structure_type,
|
||||
}
|
||||
));
|
||||
}
|
||||
@ -192,10 +300,38 @@ impl ToTokens for StructureStruct {
|
||||
|
||||
// Helper functions
|
||||
|
||||
/// Converts a structure registry key to the corresponding `StructureKeys` enum variant token stream.
|
||||
///
|
||||
/// # Arguments
|
||||
/// – `key` – structure registry name with or without the `minecraft:` prefix.
|
||||
fn structure_type_to_token(st: &str) -> TokenStream {
|
||||
match st {
|
||||
"minecraft:jigsaw" => quote!(StructureType::Jigsaw),
|
||||
"minecraft:buried_treasure" => quote!(StructureType::BuriedTreasure),
|
||||
"minecraft:desert_pyramid" => quote!(StructureType::DesertPyramid),
|
||||
"minecraft:end_city" => quote!(StructureType::EndCity),
|
||||
"minecraft:fortress" => quote!(StructureType::Fortress),
|
||||
"minecraft:igloo" => quote!(StructureType::Igloo),
|
||||
"minecraft:jungle_temple" => quote!(StructureType::JungleTemple),
|
||||
"minecraft:woodland_mansion" => quote!(StructureType::WoodlandMansion),
|
||||
"minecraft:mineshaft" => quote!(StructureType::Mineshaft),
|
||||
"minecraft:ocean_monument" => quote!(StructureType::OceanMonument),
|
||||
"minecraft:nether_fossil" => quote!(StructureType::NetherFossil),
|
||||
"minecraft:ocean_ruin" => quote!(StructureType::OceanRuin),
|
||||
"minecraft:ruined_portal" => quote!(StructureType::RuinedPortal),
|
||||
"minecraft:shipwreck" => quote!(StructureType::Shipwreck),
|
||||
"minecraft:stronghold" => quote!(StructureType::Stronghold),
|
||||
"minecraft:swamp_hut" => quote!(StructureType::SwampHut),
|
||||
_ => quote!(StructureType::Unknown),
|
||||
}
|
||||
}
|
||||
|
||||
fn terrain_adaptation_to_token(ta: &str) -> TokenStream {
|
||||
match ta {
|
||||
"beard_thin" => quote!(TerrainAdaptation::BeardThin),
|
||||
"beard_box" => quote!(TerrainAdaptation::BeardBox),
|
||||
"bury" => quote!(TerrainAdaptation::Bury),
|
||||
"encapsulate" => quote!(TerrainAdaptation::Encapsulate),
|
||||
_ => quote!(TerrainAdaptation::None),
|
||||
}
|
||||
}
|
||||
|
||||
fn structure_key_to_token(key: &str) -> TokenStream {
|
||||
let stripped = key.strip_prefix("minecraft:").unwrap_or(key);
|
||||
|
||||
@ -238,10 +374,6 @@ fn structure_key_to_token(key: &str) -> TokenStream {
|
||||
}
|
||||
}
|
||||
|
||||
/// Converts a frequency-reduction method string to its `FrequencyReductionMethod` variant token stream.
|
||||
///
|
||||
/// # Arguments
|
||||
/// – `method` – one of `"default"`, `"legacy_type_1"`, `"legacy_type_2"`, or `"legacy_type_3"`.
|
||||
fn frequency_reduction_to_token(method: &str) -> TokenStream {
|
||||
match method {
|
||||
"default" => quote!(FrequencyReductionMethod::Default),
|
||||
@ -252,10 +384,6 @@ fn frequency_reduction_to_token(method: &str) -> TokenStream {
|
||||
}
|
||||
}
|
||||
|
||||
/// Converts a spread type string to its `SpreadType` variant token stream.
|
||||
///
|
||||
/// # Arguments
|
||||
/// – `spread` – `"linear"` or `"triangular"`.
|
||||
fn spread_type_to_token(spread: &str) -> TokenStream {
|
||||
match spread {
|
||||
"linear" => quote!(SpreadType::Linear),
|
||||
@ -264,10 +392,6 @@ fn spread_type_to_token(spread: &str) -> TokenStream {
|
||||
}
|
||||
}
|
||||
|
||||
/// Converts a generation step name to its `GenerationStep` variant token stream.
|
||||
///
|
||||
/// # Arguments
|
||||
/// – `step` – the generation step name as it appears in the JSON (e.g., `"surface_structures"`).
|
||||
fn generation_step_to_token(step: &str) -> TokenStream {
|
||||
match step {
|
||||
"raw_generation" => quote!(GenerationStep::RawGeneration),
|
||||
@ -389,10 +513,16 @@ pub fn build() -> TokenStream {
|
||||
pub weight: u32,
|
||||
}
|
||||
|
||||
pub struct ExclusionZone {
|
||||
pub other_set: &'static str,
|
||||
pub chunk_count: i32,
|
||||
}
|
||||
|
||||
pub struct StructurePlacement {
|
||||
pub frequency_reduction_method: Option<FrequencyReductionMethod>,
|
||||
pub frequency: Option<f32>,
|
||||
pub salt: u32,
|
||||
pub exclusion_zone: Option<ExclusionZone>,
|
||||
pub placement_type: StructurePlacementType,
|
||||
}
|
||||
|
||||
@ -440,9 +570,49 @@ pub fn build() -> TokenStream {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
pub enum TerrainAdaptation {
|
||||
None,
|
||||
BeardThin,
|
||||
BeardBox,
|
||||
Bury,
|
||||
Encapsulate,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
pub enum StructureType {
|
||||
Jigsaw,
|
||||
BuriedTreasure,
|
||||
DesertPyramid,
|
||||
EndCity,
|
||||
Fortress,
|
||||
Igloo,
|
||||
JungleTemple,
|
||||
WoodlandMansion,
|
||||
Mineshaft,
|
||||
OceanMonument,
|
||||
NetherFossil,
|
||||
OceanRuin,
|
||||
RuinedPortal,
|
||||
Shipwreck,
|
||||
Stronghold,
|
||||
SwampHut,
|
||||
Unknown,
|
||||
}
|
||||
|
||||
pub struct Structure {
|
||||
pub biomes: &'static str,
|
||||
pub step: GenerationStep,
|
||||
pub start_pool: Option<&'static str>,
|
||||
pub size: Option<i32>,
|
||||
pub terrain_adaptation: TerrainAdaptation,
|
||||
pub start_height: Option<i16>,
|
||||
pub project_start_to_heightmap: Option<&'static str>,
|
||||
pub max_distance_from_center: Option<i32>,
|
||||
pub liquid_settings: Option<&'static str>,
|
||||
pub dimension_padding: Option<i32>,
|
||||
pub use_expansion_hack: Option<bool>,
|
||||
pub structure_type: StructureType,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
@ -505,4 +675,4 @@ pub fn build() -> TokenStream {
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -1,13 +1,15 @@
|
||||
//! Block rotation and mirroring transformations for structure templates.
|
||||
//! Block rotation and mirroring transformations.
|
||||
//!
|
||||
//! These transformations are used to rotate and mirror structure templates
|
||||
//! These transformations are used to rotate and mirror blocks
|
||||
//! when placing them in the world, matching vanilla Minecraft behavior.
|
||||
|
||||
use pumpkin_util::math::vector3::Vector3;
|
||||
use serde::Deserialize;
|
||||
|
||||
/// Rotation around the Y axis in 90-degree increments.
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
|
||||
pub enum BlockRotation {
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default, Deserialize)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub enum Rotation {
|
||||
/// No rotation (0 degrees)
|
||||
#[default]
|
||||
None,
|
||||
@ -19,7 +21,7 @@ pub enum BlockRotation {
|
||||
CounterClockwise90,
|
||||
}
|
||||
|
||||
impl BlockRotation {
|
||||
impl Rotation {
|
||||
/// Returns all possible rotations.
|
||||
#[must_use]
|
||||
pub const fn values() -> [Self; 4] {
|
||||
@ -151,9 +153,27 @@ impl BlockRotation {
|
||||
/// Combines this rotation with another rotation.
|
||||
#[must_use]
|
||||
pub const fn then(&self, other: Self) -> Self {
|
||||
let a = *self as u8;
|
||||
let b = other as u8;
|
||||
Self::from_index((a + b) % 4)
|
||||
match self {
|
||||
Self::None => other,
|
||||
Self::Clockwise90 => match other {
|
||||
Self::None => Self::Clockwise90,
|
||||
Self::Clockwise90 => Self::Rotate180,
|
||||
Self::Rotate180 => Self::CounterClockwise90,
|
||||
Self::CounterClockwise90 => Self::None,
|
||||
},
|
||||
Self::Rotate180 => match other {
|
||||
Self::None => Self::Rotate180,
|
||||
Self::Clockwise90 => Self::CounterClockwise90,
|
||||
Self::Rotate180 => Self::None,
|
||||
Self::CounterClockwise90 => Self::Clockwise90,
|
||||
},
|
||||
Self::CounterClockwise90 => match other {
|
||||
Self::None => Self::CounterClockwise90,
|
||||
Self::Clockwise90 => Self::None,
|
||||
Self::Rotate180 => Self::Clockwise90,
|
||||
Self::CounterClockwise90 => Self::Rotate180,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the inverse of this rotation.
|
||||
@ -178,8 +198,9 @@ impl BlockRotation {
|
||||
}
|
||||
|
||||
/// Mirror transformation for structure templates.
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
|
||||
pub enum BlockMirror {
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default, Deserialize)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub enum Mirror {
|
||||
/// No mirroring
|
||||
#[default]
|
||||
None,
|
||||
@ -189,7 +210,7 @@ pub enum BlockMirror {
|
||||
FrontBack,
|
||||
}
|
||||
|
||||
impl BlockMirror {
|
||||
impl Mirror {
|
||||
/// Returns all possible mirrors.
|
||||
#[must_use]
|
||||
pub const fn values() -> [Self; 3] {
|
||||
@ -246,20 +267,20 @@ impl BlockMirror {
|
||||
|
||||
/// Returns the rotation needed to achieve this mirror from a base rotation.
|
||||
#[must_use]
|
||||
pub const fn get_rotation(&self, rotation: BlockRotation) -> BlockRotation {
|
||||
pub const fn get_rotation(&self, rotation: Rotation) -> Rotation {
|
||||
match self {
|
||||
Self::None => rotation,
|
||||
Self::LeftRight => match rotation {
|
||||
BlockRotation::None => BlockRotation::None,
|
||||
BlockRotation::Clockwise90 => BlockRotation::CounterClockwise90,
|
||||
BlockRotation::Rotate180 => BlockRotation::Rotate180,
|
||||
BlockRotation::CounterClockwise90 => BlockRotation::Clockwise90,
|
||||
Rotation::None => Rotation::None,
|
||||
Rotation::Clockwise90 => Rotation::CounterClockwise90,
|
||||
Rotation::Rotate180 => Rotation::Rotate180,
|
||||
Rotation::CounterClockwise90 => Rotation::Clockwise90,
|
||||
},
|
||||
Self::FrontBack => match rotation {
|
||||
BlockRotation::None => BlockRotation::Rotate180,
|
||||
BlockRotation::Clockwise90 => BlockRotation::Clockwise90,
|
||||
BlockRotation::Rotate180 => BlockRotation::None,
|
||||
BlockRotation::CounterClockwise90 => BlockRotation::CounterClockwise90,
|
||||
Rotation::None => Rotation::Rotate180,
|
||||
Rotation::Clockwise90 => Rotation::Clockwise90,
|
||||
Rotation::Rotate180 => Rotation::None,
|
||||
Rotation::CounterClockwise90 => Rotation::CounterClockwise90,
|
||||
},
|
||||
}
|
||||
}
|
||||
@ -267,82 +288,6 @@ impl BlockMirror {
|
||||
|
||||
/// Leaks a string to get a 'static str.
|
||||
/// This is used for non-standard property values that aren't covered by static strings.
|
||||
fn leak_str(s: &str) -> &'static str {
|
||||
pub fn leak_str(s: &str) -> &'static str {
|
||||
s.to_string().leak()
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_rotation_transform_pos() {
|
||||
let size = Vector3::new(3, 5, 4); // 3 wide, 5 tall, 4 deep
|
||||
let pos = Vector3::new(0, 2, 0);
|
||||
|
||||
// No rotation: position unchanged
|
||||
assert_eq!(BlockRotation::None.transform_pos(pos, size), pos);
|
||||
|
||||
// Clockwise 90: (x, y, z) -> (size.z - 1 - z, y, x)
|
||||
assert_eq!(
|
||||
BlockRotation::Clockwise90.transform_pos(pos, size),
|
||||
Vector3::new(3, 2, 0)
|
||||
);
|
||||
|
||||
// 180: (x, y, z) -> (size.x - 1 - x, y, size.z - 1 - z)
|
||||
assert_eq!(
|
||||
BlockRotation::Rotate180.transform_pos(pos, size),
|
||||
Vector3::new(2, 2, 3)
|
||||
);
|
||||
|
||||
// Counter-clockwise 90: (x, y, z) -> (z, y, size.x - 1 - x)
|
||||
assert_eq!(
|
||||
BlockRotation::CounterClockwise90.transform_pos(pos, size),
|
||||
Vector3::new(0, 2, 2)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_rotation_facing() {
|
||||
assert_eq!(BlockRotation::Clockwise90.rotate_facing("north"), "east");
|
||||
assert_eq!(BlockRotation::Clockwise90.rotate_facing("east"), "south");
|
||||
assert_eq!(BlockRotation::Rotate180.rotate_facing("north"), "south");
|
||||
assert_eq!(
|
||||
BlockRotation::CounterClockwise90.rotate_facing("north"),
|
||||
"west"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_mirror_facing() {
|
||||
assert_eq!(BlockMirror::LeftRight.mirror_facing("east"), "west");
|
||||
assert_eq!(BlockMirror::LeftRight.mirror_facing("north"), "north");
|
||||
assert_eq!(BlockMirror::FrontBack.mirror_facing("north"), "south");
|
||||
assert_eq!(BlockMirror::FrontBack.mirror_facing("east"), "east");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_rotation_inverse() {
|
||||
for rotation in BlockRotation::values() {
|
||||
let inverse = rotation.inverse();
|
||||
let combined = rotation.then(inverse);
|
||||
assert_eq!(combined, BlockRotation::None);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_transform_size() {
|
||||
let size = Vector3::new(3, 5, 7);
|
||||
|
||||
assert_eq!(BlockRotation::None.transform_size(size), size);
|
||||
assert_eq!(
|
||||
BlockRotation::Clockwise90.transform_size(size),
|
||||
Vector3::new(7, 5, 3)
|
||||
);
|
||||
assert_eq!(BlockRotation::Rotate180.transform_size(size), size);
|
||||
assert_eq!(
|
||||
BlockRotation::CounterClockwise90.transform_size(size),
|
||||
Vector3::new(7, 5, 3)
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -159,6 +159,24 @@ impl Block {
|
||||
pub const fn is_air(&self) -> bool {
|
||||
self.default_state.is_air()
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn mirror(
|
||||
&self,
|
||||
state_id: u16,
|
||||
_mirror: crate::block_rotation::Mirror,
|
||||
) -> &'static BlockState {
|
||||
BlockState::from_id(state_id)
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn rotate(
|
||||
&self,
|
||||
state_id: u16,
|
||||
_rotation: crate::block_rotation::Rotation,
|
||||
) -> &'static BlockState {
|
||||
BlockState::from_id(state_id)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
|
||||
@ -94,9 +94,25 @@ impl SpreadType {
|
||||
}
|
||||
}
|
||||
}
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
pub enum TerrainAdaptation {
|
||||
None,
|
||||
BeardThin,
|
||||
BeardBox,
|
||||
Bury,
|
||||
Encapsulate,
|
||||
}
|
||||
pub struct Structure {
|
||||
pub biomes: &'static str,
|
||||
pub step: GenerationStep,
|
||||
pub start_pool: Option<&'static str>,
|
||||
pub size: Option<i32>,
|
||||
pub terrain_adaptation: TerrainAdaptation,
|
||||
pub start_height: Option<i16>,
|
||||
pub project_start_to_heightmap: Option<&'static str>,
|
||||
pub max_distance_from_center: Option<i32>,
|
||||
pub liquid_settings: Option<&'static str>,
|
||||
pub dimension_padding: Option<i32>,
|
||||
}
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
pub enum GenerationStep {
|
||||
@ -131,138 +147,410 @@ impl Structure {
|
||||
pub const ANCIENT_CITY: Self = Structure {
|
||||
biomes: "#minecraft:has_structure/ancient_city",
|
||||
step: GenerationStep::UndergroundDecoration,
|
||||
start_pool: Some("minecraft:ancient_city/city_center"),
|
||||
size: Some(7i32),
|
||||
terrain_adaptation: TerrainAdaptation::BeardBox,
|
||||
start_height: Some(-27i16),
|
||||
project_start_to_heightmap: None,
|
||||
max_distance_from_center: Some(116i32),
|
||||
liquid_settings: None,
|
||||
dimension_padding: None,
|
||||
};
|
||||
pub const BASTION_REMNANT: Self = Structure {
|
||||
biomes: "#minecraft:has_structure/bastion_remnant",
|
||||
step: GenerationStep::SurfaceStructures,
|
||||
start_pool: Some("minecraft:bastion/starts"),
|
||||
size: Some(6i32),
|
||||
terrain_adaptation: TerrainAdaptation::None,
|
||||
start_height: Some(33i16),
|
||||
project_start_to_heightmap: None,
|
||||
max_distance_from_center: Some(80i32),
|
||||
liquid_settings: None,
|
||||
dimension_padding: None,
|
||||
};
|
||||
pub const BURIED_TREASURE: Self = Structure {
|
||||
biomes: "#minecraft:has_structure/buried_treasure",
|
||||
step: GenerationStep::UndergroundStructures,
|
||||
start_pool: None,
|
||||
size: None,
|
||||
terrain_adaptation: TerrainAdaptation::None,
|
||||
start_height: None,
|
||||
project_start_to_heightmap: None,
|
||||
max_distance_from_center: None,
|
||||
liquid_settings: None,
|
||||
dimension_padding: None,
|
||||
};
|
||||
pub const DESERT_PYRAMID: Self = Structure {
|
||||
biomes: "#minecraft:has_structure/desert_pyramid",
|
||||
step: GenerationStep::SurfaceStructures,
|
||||
start_pool: None,
|
||||
size: None,
|
||||
terrain_adaptation: TerrainAdaptation::None,
|
||||
start_height: None,
|
||||
project_start_to_heightmap: None,
|
||||
max_distance_from_center: None,
|
||||
liquid_settings: None,
|
||||
dimension_padding: None,
|
||||
};
|
||||
pub const END_CITY: Self = Structure {
|
||||
biomes: "#minecraft:has_structure/end_city",
|
||||
step: GenerationStep::SurfaceStructures,
|
||||
start_pool: None,
|
||||
size: None,
|
||||
terrain_adaptation: TerrainAdaptation::None,
|
||||
start_height: None,
|
||||
project_start_to_heightmap: None,
|
||||
max_distance_from_center: None,
|
||||
liquid_settings: None,
|
||||
dimension_padding: None,
|
||||
};
|
||||
pub const FORTRESS: Self = Structure {
|
||||
biomes: "#minecraft:has_structure/nether_fortress",
|
||||
step: GenerationStep::UndergroundDecoration,
|
||||
start_pool: None,
|
||||
size: None,
|
||||
terrain_adaptation: TerrainAdaptation::None,
|
||||
start_height: None,
|
||||
project_start_to_heightmap: None,
|
||||
max_distance_from_center: None,
|
||||
liquid_settings: None,
|
||||
dimension_padding: None,
|
||||
};
|
||||
pub const IGLOO: Self = Structure {
|
||||
biomes: "#minecraft:has_structure/igloo",
|
||||
step: GenerationStep::SurfaceStructures,
|
||||
start_pool: None,
|
||||
size: None,
|
||||
terrain_adaptation: TerrainAdaptation::None,
|
||||
start_height: None,
|
||||
project_start_to_heightmap: None,
|
||||
max_distance_from_center: None,
|
||||
liquid_settings: None,
|
||||
dimension_padding: None,
|
||||
};
|
||||
pub const JUNGLE_PYRAMID: Self = Structure {
|
||||
biomes: "#minecraft:has_structure/jungle_temple",
|
||||
step: GenerationStep::SurfaceStructures,
|
||||
start_pool: None,
|
||||
size: None,
|
||||
terrain_adaptation: TerrainAdaptation::None,
|
||||
start_height: None,
|
||||
project_start_to_heightmap: None,
|
||||
max_distance_from_center: None,
|
||||
liquid_settings: None,
|
||||
dimension_padding: None,
|
||||
};
|
||||
pub const MANSION: Self = Structure {
|
||||
biomes: "#minecraft:has_structure/woodland_mansion",
|
||||
step: GenerationStep::SurfaceStructures,
|
||||
start_pool: None,
|
||||
size: None,
|
||||
terrain_adaptation: TerrainAdaptation::None,
|
||||
start_height: None,
|
||||
project_start_to_heightmap: None,
|
||||
max_distance_from_center: None,
|
||||
liquid_settings: None,
|
||||
dimension_padding: None,
|
||||
};
|
||||
pub const MINESHAFT: Self = Structure {
|
||||
biomes: "#minecraft:has_structure/mineshaft",
|
||||
step: GenerationStep::UndergroundStructures,
|
||||
start_pool: None,
|
||||
size: None,
|
||||
terrain_adaptation: TerrainAdaptation::None,
|
||||
start_height: None,
|
||||
project_start_to_heightmap: None,
|
||||
max_distance_from_center: None,
|
||||
liquid_settings: None,
|
||||
dimension_padding: None,
|
||||
};
|
||||
pub const MINESHAFT_MESA: Self = Structure {
|
||||
biomes: "#minecraft:has_structure/mineshaft_mesa",
|
||||
step: GenerationStep::UndergroundStructures,
|
||||
start_pool: None,
|
||||
size: None,
|
||||
terrain_adaptation: TerrainAdaptation::None,
|
||||
start_height: None,
|
||||
project_start_to_heightmap: None,
|
||||
max_distance_from_center: None,
|
||||
liquid_settings: None,
|
||||
dimension_padding: None,
|
||||
};
|
||||
pub const MONUMENT: Self = Structure {
|
||||
biomes: "#minecraft:has_structure/ocean_monument",
|
||||
step: GenerationStep::SurfaceStructures,
|
||||
start_pool: None,
|
||||
size: None,
|
||||
terrain_adaptation: TerrainAdaptation::None,
|
||||
start_height: None,
|
||||
project_start_to_heightmap: None,
|
||||
max_distance_from_center: None,
|
||||
liquid_settings: None,
|
||||
dimension_padding: None,
|
||||
};
|
||||
pub const NETHER_FOSSIL: Self = Structure {
|
||||
biomes: "#minecraft:has_structure/nether_fossil",
|
||||
step: GenerationStep::UndergroundDecoration,
|
||||
start_pool: None,
|
||||
size: None,
|
||||
terrain_adaptation: TerrainAdaptation::BeardThin,
|
||||
start_height: None,
|
||||
project_start_to_heightmap: None,
|
||||
max_distance_from_center: None,
|
||||
liquid_settings: None,
|
||||
dimension_padding: None,
|
||||
};
|
||||
pub const OCEAN_RUIN_COLD: Self = Structure {
|
||||
biomes: "#minecraft:has_structure/ocean_ruin_cold",
|
||||
step: GenerationStep::SurfaceStructures,
|
||||
start_pool: None,
|
||||
size: None,
|
||||
terrain_adaptation: TerrainAdaptation::None,
|
||||
start_height: None,
|
||||
project_start_to_heightmap: None,
|
||||
max_distance_from_center: None,
|
||||
liquid_settings: None,
|
||||
dimension_padding: None,
|
||||
};
|
||||
pub const OCEAN_RUIN_WARM: Self = Structure {
|
||||
biomes: "#minecraft:has_structure/ocean_ruin_warm",
|
||||
step: GenerationStep::SurfaceStructures,
|
||||
start_pool: None,
|
||||
size: None,
|
||||
terrain_adaptation: TerrainAdaptation::None,
|
||||
start_height: None,
|
||||
project_start_to_heightmap: None,
|
||||
max_distance_from_center: None,
|
||||
liquid_settings: None,
|
||||
dimension_padding: None,
|
||||
};
|
||||
pub const PILLAGER_OUTPOST: Self = Structure {
|
||||
biomes: "#minecraft:has_structure/pillager_outpost",
|
||||
step: GenerationStep::SurfaceStructures,
|
||||
start_pool: Some("minecraft:pillager_outpost/base_plates"),
|
||||
size: Some(7i32),
|
||||
terrain_adaptation: TerrainAdaptation::BeardThin,
|
||||
start_height: Some(0i16),
|
||||
project_start_to_heightmap: Some("WORLD_SURFACE_WG"),
|
||||
max_distance_from_center: Some(80i32),
|
||||
liquid_settings: None,
|
||||
dimension_padding: None,
|
||||
};
|
||||
pub const RUINED_PORTAL: Self = Structure {
|
||||
biomes: "#minecraft:has_structure/ruined_portal_standard",
|
||||
step: GenerationStep::SurfaceStructures,
|
||||
start_pool: None,
|
||||
size: None,
|
||||
terrain_adaptation: TerrainAdaptation::None,
|
||||
start_height: None,
|
||||
project_start_to_heightmap: None,
|
||||
max_distance_from_center: None,
|
||||
liquid_settings: None,
|
||||
dimension_padding: None,
|
||||
};
|
||||
pub const RUINED_PORTAL_DESERT: Self = Structure {
|
||||
biomes: "#minecraft:has_structure/ruined_portal_desert",
|
||||
step: GenerationStep::SurfaceStructures,
|
||||
start_pool: None,
|
||||
size: None,
|
||||
terrain_adaptation: TerrainAdaptation::None,
|
||||
start_height: None,
|
||||
project_start_to_heightmap: None,
|
||||
max_distance_from_center: None,
|
||||
liquid_settings: None,
|
||||
dimension_padding: None,
|
||||
};
|
||||
pub const RUINED_PORTAL_JUNGLE: Self = Structure {
|
||||
biomes: "#minecraft:has_structure/ruined_portal_jungle",
|
||||
step: GenerationStep::SurfaceStructures,
|
||||
start_pool: None,
|
||||
size: None,
|
||||
terrain_adaptation: TerrainAdaptation::None,
|
||||
start_height: None,
|
||||
project_start_to_heightmap: None,
|
||||
max_distance_from_center: None,
|
||||
liquid_settings: None,
|
||||
dimension_padding: None,
|
||||
};
|
||||
pub const RUINED_PORTAL_MOUNTAIN: Self = Structure {
|
||||
biomes: "#minecraft:has_structure/ruined_portal_mountain",
|
||||
step: GenerationStep::SurfaceStructures,
|
||||
start_pool: None,
|
||||
size: None,
|
||||
terrain_adaptation: TerrainAdaptation::None,
|
||||
start_height: None,
|
||||
project_start_to_heightmap: None,
|
||||
max_distance_from_center: None,
|
||||
liquid_settings: None,
|
||||
dimension_padding: None,
|
||||
};
|
||||
pub const RUINED_PORTAL_NETHER: Self = Structure {
|
||||
biomes: "#minecraft:has_structure/ruined_portal_nether",
|
||||
step: GenerationStep::SurfaceStructures,
|
||||
start_pool: None,
|
||||
size: None,
|
||||
terrain_adaptation: TerrainAdaptation::None,
|
||||
start_height: None,
|
||||
project_start_to_heightmap: None,
|
||||
max_distance_from_center: None,
|
||||
liquid_settings: None,
|
||||
dimension_padding: None,
|
||||
};
|
||||
pub const RUINED_PORTAL_OCEAN: Self = Structure {
|
||||
biomes: "#minecraft:has_structure/ruined_portal_ocean",
|
||||
step: GenerationStep::SurfaceStructures,
|
||||
start_pool: None,
|
||||
size: None,
|
||||
terrain_adaptation: TerrainAdaptation::None,
|
||||
start_height: None,
|
||||
project_start_to_heightmap: None,
|
||||
max_distance_from_center: None,
|
||||
liquid_settings: None,
|
||||
dimension_padding: None,
|
||||
};
|
||||
pub const RUINED_PORTAL_SWAMP: Self = Structure {
|
||||
biomes: "#minecraft:has_structure/ruined_portal_swamp",
|
||||
step: GenerationStep::SurfaceStructures,
|
||||
start_pool: None,
|
||||
size: None,
|
||||
terrain_adaptation: TerrainAdaptation::None,
|
||||
start_height: None,
|
||||
project_start_to_heightmap: None,
|
||||
max_distance_from_center: None,
|
||||
liquid_settings: None,
|
||||
dimension_padding: None,
|
||||
};
|
||||
pub const SHIPWRECK: Self = Structure {
|
||||
biomes: "#minecraft:has_structure/shipwreck",
|
||||
step: GenerationStep::SurfaceStructures,
|
||||
start_pool: None,
|
||||
size: None,
|
||||
terrain_adaptation: TerrainAdaptation::None,
|
||||
start_height: None,
|
||||
project_start_to_heightmap: None,
|
||||
max_distance_from_center: None,
|
||||
liquid_settings: None,
|
||||
dimension_padding: None,
|
||||
};
|
||||
pub const SHIPWRECK_BEACHED: Self = Structure {
|
||||
biomes: "#minecraft:has_structure/shipwreck_beached",
|
||||
step: GenerationStep::SurfaceStructures,
|
||||
start_pool: None,
|
||||
size: None,
|
||||
terrain_adaptation: TerrainAdaptation::None,
|
||||
start_height: None,
|
||||
project_start_to_heightmap: None,
|
||||
max_distance_from_center: None,
|
||||
liquid_settings: None,
|
||||
dimension_padding: None,
|
||||
};
|
||||
pub const STRONGHOLD: Self = Structure {
|
||||
biomes: "#minecraft:has_structure/stronghold",
|
||||
step: GenerationStep::SurfaceStructures,
|
||||
start_pool: None,
|
||||
size: None,
|
||||
terrain_adaptation: TerrainAdaptation::Bury,
|
||||
start_height: None,
|
||||
project_start_to_heightmap: None,
|
||||
max_distance_from_center: None,
|
||||
liquid_settings: None,
|
||||
dimension_padding: None,
|
||||
};
|
||||
pub const SWAMP_HUT: Self = Structure {
|
||||
biomes: "#minecraft:has_structure/swamp_hut",
|
||||
step: GenerationStep::SurfaceStructures,
|
||||
start_pool: None,
|
||||
size: None,
|
||||
terrain_adaptation: TerrainAdaptation::None,
|
||||
start_height: None,
|
||||
project_start_to_heightmap: None,
|
||||
max_distance_from_center: None,
|
||||
liquid_settings: None,
|
||||
dimension_padding: None,
|
||||
};
|
||||
pub const TRAIL_RUINS: Self = Structure {
|
||||
biomes: "#minecraft:has_structure/trail_ruins",
|
||||
step: GenerationStep::UndergroundStructures,
|
||||
start_pool: Some("minecraft:trail_ruins/tower"),
|
||||
size: Some(7i32),
|
||||
terrain_adaptation: TerrainAdaptation::Bury,
|
||||
start_height: Some(-15i16),
|
||||
project_start_to_heightmap: Some("WORLD_SURFACE_WG"),
|
||||
max_distance_from_center: Some(80i32),
|
||||
liquid_settings: None,
|
||||
dimension_padding: None,
|
||||
};
|
||||
pub const TRIAL_CHAMBERS: Self = Structure {
|
||||
biomes: "#minecraft:has_structure/trial_chambers",
|
||||
step: GenerationStep::UndergroundStructures,
|
||||
start_pool: Some("minecraft:trial_chambers/chamber/end"),
|
||||
size: Some(20i32),
|
||||
terrain_adaptation: TerrainAdaptation::Encapsulate,
|
||||
start_height: Some(-40i16),
|
||||
project_start_to_heightmap: None,
|
||||
max_distance_from_center: Some(116i32),
|
||||
liquid_settings: Some("ignore_waterlogging"),
|
||||
dimension_padding: Some(10i32),
|
||||
};
|
||||
pub const VILLAGE_DESERT: Self = Structure {
|
||||
biomes: "#minecraft:has_structure/village_desert",
|
||||
step: GenerationStep::SurfaceStructures,
|
||||
start_pool: Some("minecraft:village/desert/town_centers"),
|
||||
size: Some(6i32),
|
||||
terrain_adaptation: TerrainAdaptation::BeardThin,
|
||||
start_height: Some(0i16),
|
||||
project_start_to_heightmap: Some("WORLD_SURFACE_WG"),
|
||||
max_distance_from_center: Some(80i32),
|
||||
liquid_settings: None,
|
||||
dimension_padding: None,
|
||||
};
|
||||
pub const VILLAGE_PLAINS: Self = Structure {
|
||||
biomes: "#minecraft:has_structure/village_plains",
|
||||
step: GenerationStep::SurfaceStructures,
|
||||
start_pool: Some("minecraft:village/plains/town_centers"),
|
||||
size: Some(6i32),
|
||||
terrain_adaptation: TerrainAdaptation::BeardThin,
|
||||
start_height: Some(0i16),
|
||||
project_start_to_heightmap: Some("WORLD_SURFACE_WG"),
|
||||
max_distance_from_center: Some(80i32),
|
||||
liquid_settings: None,
|
||||
dimension_padding: None,
|
||||
};
|
||||
pub const VILLAGE_SAVANNA: Self = Structure {
|
||||
biomes: "#minecraft:has_structure/village_savanna",
|
||||
step: GenerationStep::SurfaceStructures,
|
||||
start_pool: Some("minecraft:village/savanna/town_centers"),
|
||||
size: Some(6i32),
|
||||
terrain_adaptation: TerrainAdaptation::BeardThin,
|
||||
start_height: Some(0i16),
|
||||
project_start_to_heightmap: Some("WORLD_SURFACE_WG"),
|
||||
max_distance_from_center: Some(80i32),
|
||||
liquid_settings: None,
|
||||
dimension_padding: None,
|
||||
};
|
||||
pub const VILLAGE_SNOWY: Self = Structure {
|
||||
biomes: "#minecraft:has_structure/village_snowy",
|
||||
step: GenerationStep::SurfaceStructures,
|
||||
start_pool: Some("minecraft:village/snowy/town_centers"),
|
||||
size: Some(6i32),
|
||||
terrain_adaptation: TerrainAdaptation::BeardThin,
|
||||
start_height: Some(0i16),
|
||||
project_start_to_heightmap: Some("WORLD_SURFACE_WG"),
|
||||
max_distance_from_center: Some(80i32),
|
||||
liquid_settings: None,
|
||||
dimension_padding: None,
|
||||
};
|
||||
pub const VILLAGE_TAIGA: Self = Structure {
|
||||
biomes: "#minecraft:has_structure/village_taiga",
|
||||
step: GenerationStep::SurfaceStructures,
|
||||
start_pool: Some("minecraft:village/taiga/town_centers"),
|
||||
size: Some(6i32),
|
||||
terrain_adaptation: TerrainAdaptation::BeardThin,
|
||||
start_height: Some(0i16),
|
||||
project_start_to_heightmap: Some("WORLD_SURFACE_WG"),
|
||||
max_distance_from_center: Some(80i32),
|
||||
liquid_settings: None,
|
||||
dimension_padding: None,
|
||||
};
|
||||
#[must_use]
|
||||
pub const fn get(key: &StructureKeys) -> &'static Self {
|
||||
|
||||
@ -287,6 +287,8 @@ pub mod recipe_remainder;
|
||||
#[cfg(feature = "block")]
|
||||
mod block_direction;
|
||||
#[cfg(feature = "block")]
|
||||
pub mod block_rotation;
|
||||
#[cfg(feature = "block")]
|
||||
pub mod block_state;
|
||||
#[cfg(feature = "block")]
|
||||
mod blocks;
|
||||
@ -298,6 +300,8 @@ pub use block_direction::FacingExt;
|
||||
#[cfg(feature = "block")]
|
||||
pub use block_direction::HorizontalFacingExt;
|
||||
#[cfg(feature = "block")]
|
||||
pub use block_rotation::{Mirror, Rotation};
|
||||
#[cfg(feature = "block")]
|
||||
pub use block_state::BlockState;
|
||||
#[cfg(feature = "block")]
|
||||
pub use block_state::BlockStateRef;
|
||||
|
||||
14
pumpkin-protocol/src/java/server/play/jigsaw_generate.rs
Normal file
14
pumpkin-protocol/src/java/server/play/jigsaw_generate.rs
Normal file
@ -0,0 +1,14 @@
|
||||
use pumpkin_data::packet::serverbound::PLAY_JIGSAW_GENERATE;
|
||||
use pumpkin_macros::java_packet;
|
||||
use pumpkin_util::math::position::BlockPos;
|
||||
use serde::Deserialize;
|
||||
|
||||
use crate::codec::var_int::VarInt;
|
||||
|
||||
#[derive(Deserialize)]
|
||||
#[java_packet(PLAY_JIGSAW_GENERATE)]
|
||||
pub struct SJigsawGenerate {
|
||||
pub pos: BlockPos,
|
||||
pub levels: VarInt,
|
||||
pub keep_jigsaws: bool,
|
||||
}
|
||||
@ -15,6 +15,7 @@ mod cookie_response;
|
||||
mod custom_click_action;
|
||||
mod custom_payload;
|
||||
mod interact;
|
||||
mod jigsaw_generate;
|
||||
mod keep_alive;
|
||||
mod move_vehicle;
|
||||
mod paddle_boat;
|
||||
@ -39,6 +40,7 @@ mod set_beacon;
|
||||
mod set_command_block;
|
||||
mod set_creative_slot;
|
||||
mod set_held_item;
|
||||
mod set_jigsaw_block;
|
||||
mod swing_arm;
|
||||
mod update_sign;
|
||||
mod use_item;
|
||||
@ -61,6 +63,7 @@ pub use cookie_response::*;
|
||||
pub use custom_click_action::*;
|
||||
pub use custom_payload::*;
|
||||
pub use interact::*;
|
||||
pub use jigsaw_generate::*;
|
||||
pub use keep_alive::*;
|
||||
pub use move_vehicle::*;
|
||||
pub use paddle_boat::*;
|
||||
@ -85,6 +88,7 @@ pub use set_beacon::*;
|
||||
pub use set_command_block::*;
|
||||
pub use set_creative_slot::*;
|
||||
pub use set_held_item::*;
|
||||
pub use set_jigsaw_block::*;
|
||||
pub use swing_arm::*;
|
||||
pub use update_sign::*;
|
||||
pub use use_item::*;
|
||||
|
||||
19
pumpkin-protocol/src/java/server/play/set_jigsaw_block.rs
Normal file
19
pumpkin-protocol/src/java/server/play/set_jigsaw_block.rs
Normal file
@ -0,0 +1,19 @@
|
||||
use pumpkin_data::packet::serverbound::PLAY_SET_JIGSAW_BLOCK;
|
||||
use pumpkin_macros::java_packet;
|
||||
use pumpkin_util::math::position::BlockPos;
|
||||
use serde::Deserialize;
|
||||
|
||||
use crate::codec::var_int::VarInt;
|
||||
|
||||
#[derive(Deserialize)]
|
||||
#[java_packet(PLAY_SET_JIGSAW_BLOCK)]
|
||||
pub struct SSetJigsawBlock {
|
||||
pub pos: BlockPos,
|
||||
pub name: String,
|
||||
pub target: String,
|
||||
pub pool: String,
|
||||
pub final_state: String,
|
||||
pub joint: String,
|
||||
pub selection_priority: VarInt,
|
||||
pub placement_priority: VarInt,
|
||||
}
|
||||
@ -143,6 +143,30 @@ impl BlockDirection {
|
||||
_ => Self::West,
|
||||
}
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub const fn opposite(&self) -> Self {
|
||||
match self {
|
||||
Self::Down => Self::Up,
|
||||
Self::Up => Self::Down,
|
||||
Self::North => Self::South,
|
||||
Self::South => Self::North,
|
||||
Self::West => Self::East,
|
||||
Self::East => Self::West,
|
||||
}
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub const fn to_vector(&self) -> crate::math::vector3::Vector3<i32> {
|
||||
match self {
|
||||
Self::Down => crate::math::vector3::Vector3::new(0, -1, 0),
|
||||
Self::Up => crate::math::vector3::Vector3::new(0, 1, 0),
|
||||
Self::North => crate::math::vector3::Vector3::new(0, 0, -1),
|
||||
Self::South => crate::math::vector3::Vector3::new(0, 0, 1),
|
||||
Self::West => crate::math::vector3::Vector3::new(-1, 0, 0),
|
||||
Self::East => crate::math::vector3::Vector3::new(1, 0, 0),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A mutable slice split into three parts: the element at the split index, the start, and the end.
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
pumpkin-world/assets/structures/bastion/blocks/air.nbt
Normal file
BIN
pumpkin-world/assets/structures/bastion/blocks/air.nbt
Normal file
Binary file not shown.
BIN
pumpkin-world/assets/structures/bastion/blocks/gold.nbt
Normal file
BIN
pumpkin-world/assets/structures/bastion/blocks/gold.nbt
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
pumpkin-world/assets/structures/bastion/bridge/legs/leg_0.nbt
Normal file
BIN
pumpkin-world/assets/structures/bastion/bridge/legs/leg_0.nbt
Normal file
Binary file not shown.
BIN
pumpkin-world/assets/structures/bastion/bridge/legs/leg_1.nbt
Normal file
BIN
pumpkin-world/assets/structures/bastion/bridge/legs/leg_1.nbt
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user